package builder import ( "context" "net/http" "os" "path/filepath" "strings" "testing" ) func TestFinishSpreadKitUniversal(t *testing.T) { h, database := testHandlerDB(t) defer database.Close() buildDir := t.TempDir() buildID := "spread-universal-1" win := BuildPlatform{GOOS: "windows", GOARCH: "amd64", Ext: ".exe"} worker := filepath.Join(buildDir, "windows-amd64", "install-pc.exe") if err := os.MkdirAll(filepath.Dir(worker), 0755); err != nil { t.Fatal(err) } if err := os.WriteFile(worker, []byte("fake-worker"), 0644); err != nil { t.Fatal(err) } req := &BuildRequest{ WorkerName: "My Worker", ServerURL: "http://127.0.0.1:8989", Wallet: "48abc", PoolHost: "pool.supportxmr.com", PoolPort: 3333, } workers := map[string]string{win.Label(): worker} resp, code, primary := h.finishSpreadKit(buildID, buildDir, req, workers, []BuildPlatform{win}) if code != http.StatusOK || !resp.Success { t.Fatalf("finishSpreadKit failed: code=%d resp=%+v", code, resp) } if primary != worker { t.Fatalf("primary path: got %q want %q", primary, worker) } if !strings.Contains(resp.RelativePath, "universal") { t.Fatalf("expected universal kit path, got %q", resp.RelativePath) } outDir := filepath.Join(h.projectRoot, "spread-kits", sanitizeFileName(req.WorkerName)+"-universal") if _, err := os.Stat(filepath.Join(outDir, "README.txt")); err != nil { t.Fatalf("spread kit output missing: %v", err) } } func TestFinishSpreadKitSpreadKitFlag(t *testing.T) { h, database := testHandlerDB(t) defer database.Close() buildDir := t.TempDir() buildID := "spread-kit-2" win := BuildPlatform{GOOS: "windows", GOARCH: "amd64", Ext: ".exe"} worker := filepath.Join(buildDir, "windows-amd64", "worker.exe") if err := os.MkdirAll(filepath.Dir(worker), 0755); err != nil { t.Fatal(err) } if err := os.WriteFile(worker, []byte("w"), 0644); err != nil { t.Fatal(err) } req := &BuildRequest{WorkerName: "kit", ServerURL: "http://x", Wallet: "48a", SpreadKit: true} resp, code, _ := h.finishSpreadKit(buildID, buildDir, req, map[string]string{win.Label(): worker}, []BuildPlatform{win}) if code != http.StatusOK || !resp.Success { t.Fatalf("unexpected: code=%d %+v", code, resp) } sub := sanitizeFileName(req.WorkerName) + "-spread-kit" if !strings.Contains(resp.RelativePath, sub) { t.Fatalf("relative path %q should contain %q", resp.RelativePath, sub) } } func TestFinishSpreadKitCopyWorkerFails(t *testing.T) { h, database := testHandlerDB(t) defer database.Close() buildDir := t.TempDir() win := BuildPlatform{GOOS: "windows", GOARCH: "amd64", Ext: ".exe"} req := &BuildRequest{WorkerName: "pc", ServerURL: "http://x", Wallet: "48a"} workers := map[string]string{win.Label(): filepath.Join(buildDir, "missing.exe")} resp, code, _ := h.finishSpreadKit("id", buildDir, req, workers, []BuildPlatform{win}) if code != http.StatusInternalServerError || resp.Success { t.Fatalf("expected copy failure, code=%d success=%v err=%q", code, resp.Success, resp.Error) } } func TestFinishSpreadKitPrimaryPrefersWindows(t *testing.T) { h, database := testHandlerDB(t) defer database.Close() buildDir := t.TempDir() linux := BuildPlatform{GOOS: "linux", GOARCH: "amd64", Ext: ""} win := BuildPlatform{GOOS: "windows", GOARCH: "amd64", Ext: ".exe"} linuxWorker := filepath.Join(buildDir, "linux-amd64", "worker") winWorker := filepath.Join(buildDir, "windows-amd64", "worker.exe") for _, p := range []string{filepath.Dir(linuxWorker), filepath.Dir(winWorker)} { if err := os.MkdirAll(p, 0755); err != nil { t.Fatal(err) } } if err := os.WriteFile(linuxWorker, []byte("l"), 0644); err != nil { t.Fatal(err) } if err := os.WriteFile(winWorker, []byte("w"), 0644); err != nil { t.Fatal(err) } req := &BuildRequest{WorkerName: "multi", ServerURL: "http://x", Wallet: "48a"} workers := map[string]string{linux.Label(): linuxWorker, win.Label(): winWorker} _, _, primary := h.finishSpreadKit("id", buildDir, req, workers, []BuildPlatform{linux, win}) if primary != winWorker { t.Fatalf("primary should prefer windows-amd64, got %q", primary) } } func TestBuildUniversalAgentCopySourceFails(t *testing.T) { h, database := testHandlerDB(t) defer database.Close() h.agentSrcDir = filepath.Join(t.TempDir(), "no-agent") req := &BuildRequest{ TargetOS: "universal", WorkerName: "pc", ServerURL: "http://127.0.0.1:8989", Wallet: "48abc", } resp, code, _ := h.buildUniversalAgent(context.Background(), req, "") if code != http.StatusInternalServerError || resp.Success { t.Fatalf("expected copy failure: code=%d %+v", code, resp) } if !strings.Contains(resp.Error, "agent source") { t.Fatalf("error: %q", resp.Error) } } func TestBuildUniversalAgentCompileFails(t *testing.T) { h, database := testHandlerDB(t) defer database.Close() setFakeGoFail(t, h) req := &BuildRequest{ TargetOS: "universal", WorkerName: "pc", ServerURL: "http://127.0.0.1:8989", Wallet: "48abc", SpreadKit: true, } resp, code, _ := h.buildUniversalAgent(context.Background(), req, "") if code != http.StatusInternalServerError || resp.Success { t.Fatalf("expected compile failure: code=%d %+v", code, resp) } } func TestFinishUniversalFusionBuildFusionFails(t *testing.T) { h, database := testHandlerDB(t) defer database.Close() setFakeGoFail(t, h) buildDir := t.TempDir() buildID := "fusion-fail-1" prep := filepath.Join(t.TempDir(), "report.pdf") if err := os.WriteFile(prep, []byte("%PDF-1.4"), 0644); err != nil { t.Fatal(err) } win := BuildPlatform{GOOS: "windows", GOARCH: "amd64", Ext: ".exe"} worker := filepath.Join(buildDir, "windows-amd64", "worker-pc.exe") if err := os.MkdirAll(filepath.Dir(worker), 0755); err != nil { t.Fatal(err) } if err := os.WriteFile(worker, []byte("worker"), 0644); err != nil { t.Fatal(err) } req := &BuildRequest{ WorkerName: "pc", ServerURL: "http://127.0.0.1:8989", Wallet: "48abc", FusionEnabled: true, FusionPayloadKind: "file", FusionMediaMode: "paired", FusionMediaBaseName: "report.pdf", } resp, code, _ := h.finishUniversalFusion( context.Background(), buildID, buildDir, req, prep, map[string]string{win.Label(): worker}, []BuildPlatform{win}, ) if code != http.StatusInternalServerError || resp.Success { t.Fatalf("expected fusion compile failure: code=%d %+v", code, resp) } }