package releasekit import ( "errors" "testing" "gitea.maximumdirect.net/eric/ReleaseKit/internal/validation" ) func TestCandidateRequestMapsGoValidation(t *testing.T) { limit := int64(4096) request := candidateRequest(ReleaseRequest{ Validation: ValidationSpec{Go: GoValidationSpec{ Race: true, FullVet: true, CompileTargets: []Target{{OS: "linux", Arch: "amd64"}, {OS: "darwin", Arch: "arm64"}}, }, GoFormat: true, ModuleDistribution: ModuleDistributionValidationSpec{WorkspaceFiles: true, LocalReplacements: true}, FileSize: &FileSizeValidationSpec{LimitBytes: &limit, Exclusions: []string{"assets"}}}, }) if !request.Validation.Race || !request.Validation.FullVet || !request.Validation.GoFormat || !request.Validation.ModuleDistribution.WorkspaceFiles || !request.Validation.ModuleDistribution.LocalReplacements { t.Fatalf("candidate request validation = %#v, want race, full vet, formatting, and distribution checks enabled", request.Validation) } if request.Validation.FileSize == nil || request.Validation.FileSize.LimitBytes == nil || *request.Validation.FileSize.LimitBytes != limit || len(request.Validation.FileSize.Exclusions) != 1 || request.Validation.FileSize.Exclusions[0] != "assets" { t.Fatalf("candidate request file size = %#v, want configured limit and exclusions", request.Validation.FileSize) } want := []validation.Target{{OS: "linux", Arch: "amd64"}, {OS: "darwin", Arch: "arm64"}} if len(request.Validation.CompileTargets) != len(want) { t.Fatalf("candidate request compile targets = %#v, want %#v", request.Validation.CompileTargets, want) } for index := range want { if request.Validation.CompileTargets[index] != want[index] { t.Fatalf("candidate request compile targets = %#v, want %#v", request.Validation.CompileTargets, want) } } } func TestCandidateRequestPreservesFileSizeObjectSelection(t *testing.T) { disabled := candidateRequest(ReleaseRequest{}) enabled := candidateRequest(ReleaseRequest{Validation: ValidationSpec{FileSize: &FileSizeValidationSpec{}}}) if disabled.Validation.FileSize != nil { t.Fatalf("omitted FileSize = %#v, want disabled", disabled.Validation.FileSize) } if enabled.Validation.FileSize == nil || enabled.Validation.FileSize.LimitBytes != nil { t.Fatalf("empty FileSize = %#v, want enabled default selection", enabled.Validation.FileSize) } } func TestValidationErrorPreservesLocalReplacementsIdentityAndFinding(t *testing.T) { cause := errors.New("module declaration could not be read") got := convertValidationError(&validation.Failure{ Check: validation.LocalReplacements, Findings: []validation.Finding{{ Path: "nested/go.mod", Line: 4, Target: "../local", Directive: "replace", Message: "filesystem module replacement is committed", }}, Cause: cause, }) var validationError *ValidationError if !errors.As(got, &validationError) || validationError.Check != "local-replacements" { t.Fatalf("converted error = %#v, want local-replacements identity", got) } if len(validationError.Findings) != 1 || validationError.Findings[0].Path != "nested/go.mod" || validationError.Findings[0].Line != 4 || validationError.Findings[0].Target != "../local" || validationError.Findings[0].Directive != "replace" { t.Fatalf("converted findings = %#v, want path, line, target, and directive", validationError.Findings) } if !errors.Is(got, cause) { t.Fatalf("converted error = %v, want cause preserved", got) } } func TestValidationErrorPreservesFileSizeMeasurement(t *testing.T) { got := convertValidationError(&validation.Failure{ Check: validation.FileSize, Findings: []validation.Finding{{Path: "assets/bundle.bin", Message: "committed file exceeds the selected size limit"}}, Measurement: &validation.FileSizeMeasurement{Bytes: 12, LimitBytes: 10}, }) var validationError *ValidationError if !errors.As(got, &validationError) || validationError.Check != "file-size" { t.Fatalf("converted error = %#v, want file-size identity", got) } if validationError.Measurement == nil || validationError.Measurement.Bytes != 12 || validationError.Measurement.LimitBytes != 10 { t.Fatalf("converted measurement = %#v, want 12 bytes against 10", validationError.Measurement) } } func TestValidationErrorPreservesGoVetIdentity(t *testing.T) { cause := errors.New("vet failed") got := convertValidationError(&validation.Failure{Check: validation.GoVet, Cause: cause}) var validationError *ValidationError if !errors.As(got, &validationError) || validationError.Check != "go-vet" { t.Fatalf("converted error = %#v, want go-vet validation identity", got) } if !errors.Is(got, cause) { t.Fatalf("converted error = %v, want cause preserved", got) } } func TestValidationErrorPreservesGoFormatIdentityAndFindings(t *testing.T) { cause := errors.New("format parser failed") got := convertValidationError(&validation.Failure{ Check: validation.GoFormat, Findings: []validation.Finding{{ Path: "vendor/example/bad.go", Message: "committed Go source cannot be formatted", }}, Cause: cause, }) var validationError *ValidationError if !errors.As(got, &validationError) || validationError.Check != "go-format" { t.Fatalf("converted error = %#v, want go-format validation identity", got) } if len(validationError.Findings) != 1 || validationError.Findings[0].Path != "vendor/example/bad.go" { t.Fatalf("converted findings = %#v, want vendor path", validationError.Findings) } if !errors.Is(got, cause) { t.Fatalf("converted error = %v, want parser cause preserved", got) } } func TestValidationErrorPreservesWorkspaceFilesIdentity(t *testing.T) { got := convertValidationError(&validation.Failure{ Check: validation.WorkspaceFiles, Findings: []validation.Finding{{ Path: "nested/go.work.sum", Message: "workspace file is committed in the candidate", }}, }) var validationError *ValidationError if !errors.As(got, &validationError) || validationError.Check != "workspace-files" { t.Fatalf("converted error = %#v, want workspace-files validation identity", got) } if len(validationError.Findings) != 1 || validationError.Findings[0].Path != "nested/go.work.sum" { t.Fatalf("converted findings = %#v, want nested workspace path", validationError.Findings) } }