Files
玉澜andCursor a1f8ecb7f0 test(coverage): cover empty allowlist path in filterBlocksByFiles
Hit the nil-allowlist early return so the platform changed-statement gate
reaches 100% after shared-file overall baseline filtering.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-06 13:33:36 +08:00

688 lines
24 KiB
Go

// Copyright 2026 Alibaba Group
// Licensed under the Apache License, Version 2.0 (the "License");
package main
import (
"bytes"
"errors"
"os"
"os/exec"
"path/filepath"
"reflect"
"strings"
"testing"
)
func TestRun(t *testing.T) {
profile := filepath.Join(t.TempDir(), "coverage.out")
body := "mode: atomic\nexample.com/project/internal/a.go:10.1,12.2 5 1\n"
if err := os.WriteFile(profile, []byte(body), 0o600); err != nil {
t.Fatal(err)
}
args := []string{
"--overall-profile", profile,
"--diff-profile", profile,
"--base-ref", "base",
"--module", "example.com/project",
"--baseline-overall", "100",
"--target", "80",
"--enforce-overall-target=true",
}
loader := func(ref string) (map[string][]lineRange, error) {
if ref != "base" {
t.Fatalf("base ref=%q", ref)
}
return map[string][]lineRange{"internal/a.go": {{Start: 10, End: 12}}}, nil
}
var stdout, stderr bytes.Buffer
if code := run(args, &stdout, &stderr, loader, nil); code != 0 {
t.Fatalf("run code=%d stderr=%s", code, stderr.String())
}
if !strings.Contains(stdout.String(), "overall coverage: 100.0000%") || !strings.Contains(stdout.String(), "changed code coverage: 100.0000%") {
t.Fatalf("unexpected output %q", stdout.String())
}
stderr.Reset()
if code := run(nil, &stdout, &stderr, loader, nil); code != 2 {
t.Fatalf("missing arguments code=%d, want 2", code)
}
stderr.Reset()
badLoader := func(string) (map[string][]lineRange, error) { return nil, errors.New("diff failed") }
if code := run(args, &stdout, &stderr, badLoader, nil); code != 2 || !strings.Contains(stderr.String(), "diff failed") {
t.Fatalf("loader failure code=%d stderr=%q", code, stderr.String())
}
}
func TestRunDefaultsToFullChangedCodeCoverage(t *testing.T) {
profile := filepath.Join(t.TempDir(), "coverage.out")
partialBody := "mode: atomic\n" +
"example.com/project/internal/a.go:10.1,12.2 9 1\n" +
"example.com/project/internal/a.go:13.1,13.2 1 0\n"
if err := os.WriteFile(profile, []byte(partialBody), 0o600); err != nil {
t.Fatal(err)
}
args := []string{
"--changed-only",
"--diff-profile", profile,
"--base-ref", "base",
"--module", "example.com/project",
}
loader := func(string) (map[string][]lineRange, error) {
return map[string][]lineRange{"internal/a.go": {{Start: 10, End: 13}}}, nil
}
var stdout, stderr bytes.Buffer
if code := run(args, &stdout, &stderr, loader, nil); code != 1 {
t.Fatalf("run code=%d, want 1; stdout=%s stderr=%s", code, stdout.String(), stderr.String())
}
if !strings.Contains(stderr.String(), "changed code coverage 90.0000% is below target 100.0000%") {
t.Fatalf("default target was not enforced: %q", stderr.String())
}
fullBody := "mode: atomic\n" +
"example.com/project/internal/a.go:10.1,12.2 9 1\n" +
"example.com/project/internal/a.go:13.1,13.2 1 1\n"
if err := os.WriteFile(profile, []byte(fullBody), 0o600); err != nil {
t.Fatal(err)
}
stdout.Reset()
stderr.Reset()
if code := run(args, &stdout, &stderr, loader, nil); code != 0 {
t.Fatalf("100%% changed coverage code=%d; stdout=%s stderr=%s", code, stdout.String(), stderr.String())
}
}
func TestCrossPlatformCoverageRunEvaluatesBaselineProfileWithCandidateCoverageModel(t *testing.T) {
profile := filepath.Join(t.TempDir(), "coverage.out")
body := "mode: atomic\n" +
"example.com/project/internal/a.go:10.1,12.2 5 0\n" +
"example.com/project/internal/a.go:10.1,12.2 5 1\n" +
"example.com/project/internal/a.go:20.1,22.2 5 0\n"
if err := os.WriteFile(profile, []byte(body), 0o600); err != nil {
t.Fatal(err)
}
baseline := filepath.Join(t.TempDir(), "baseline.out")
baselineBody := body + "example.com/project/internal/deleted.go:1.1,2.2 100 1\n"
if err := os.WriteFile(baseline, []byte(baselineBody), 0o600); err != nil {
t.Fatal(err)
}
args := []string{
"--overall-profile", profile,
"--baseline-profile", baseline,
"--diff-profile", profile,
"--base-ref", "base",
"--module", "example.com/project",
}
loader := func(string) (map[string][]lineRange, error) {
return map[string][]lineRange{}, nil
}
var stdout, stderr bytes.Buffer
if code := run(args, &stdout, &stderr, loader, nil); code != 0 {
t.Fatalf("run code=%d stderr=%s", code, stderr.String())
}
// Candidate overall stays 50%; merge-base ignores the deleted 100%-covered
// package so non-regression compares the shared file set only.
if !strings.Contains(stdout.String(), "overall coverage: 50.0000% (merge-base 50.0000%") {
t.Fatalf("shared-file baseline comparison failed: %q", stdout.String())
}
}
func TestRunFailsClosedWhenBaselineProfileIsMissing(t *testing.T) {
profile := filepath.Join(t.TempDir(), "coverage.out")
body := "mode: atomic\nexample.com/project/internal/a.go:10.1,12.2 5 1\n"
if err := os.WriteFile(profile, []byte(body), 0o600); err != nil {
t.Fatal(err)
}
args := []string{
"--overall-profile", profile,
"--baseline-profile", filepath.Join(t.TempDir(), "missing.out"),
"--diff-profile", profile,
"--base-ref", "base",
"--module", "example.com/project",
}
loader := func(string) (map[string][]lineRange, error) {
return map[string][]lineRange{}, nil
}
var stdout, stderr bytes.Buffer
if code := run(args, &stdout, &stderr, loader, nil); code != 2 {
t.Fatalf("missing baseline profile code=%d, want 2; stdout=%s stderr=%s", code, stdout.String(), stderr.String())
}
if !strings.Contains(stderr.String(), "open coverage profile") {
t.Fatalf("missing baseline profile did not fail closed: %q", stderr.String())
}
}
func TestRunRejectsConflictingBaselineSources(t *testing.T) {
args := []string{
"--overall-profile", "candidate.out",
"--baseline-profile", "baseline.out",
"--baseline-overall", "100",
"--diff-profile", "candidate.out",
"--base-ref", "base",
"--module", "example.com/project",
}
var stdout, stderr bytes.Buffer
if code := run(args, &stdout, &stderr, nil, nil); code != 2 {
t.Fatalf("conflicting baseline sources code=%d, want 2; stdout=%s stderr=%s", code, stdout.String(), stderr.String())
}
if !strings.Contains(stderr.String(), "either --baseline-profile or --baseline-overall, not both") {
t.Fatalf("conflicting baseline sources were not rejected clearly: %q", stderr.String())
}
}
func TestCrossPlatformCoverageRunUnionsRepeatedOverallProfiles(t *testing.T) {
dir := t.TempDir()
uncovered := filepath.Join(dir, "uncovered.out")
covered := filepath.Join(dir, "covered.out")
if err := os.WriteFile(uncovered, []byte("mode: atomic\nexample.com/project/internal/a.go:10.1,12.2 5 0\n"), 0o600); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(covered, []byte("mode: atomic\nexample.com/project/internal/a.go:10.1,12.2 5 1\n"), 0o600); err != nil {
t.Fatal(err)
}
args := []string{
"--overall-profile", uncovered,
"--overall-profile", covered,
"--diff-profile", uncovered,
"--diff-profile", covered,
"--base-ref", "base",
"--module", "example.com/project",
"--baseline-overall", "100",
"--target", "80",
}
loader := func(string) (map[string][]lineRange, error) {
return map[string][]lineRange{"internal/a.go": {{Start: 10, End: 12}}}, nil
}
var stdout, stderr bytes.Buffer
if code := run(args, &stdout, &stderr, loader, nil); code != 0 {
t.Fatalf("run code=%d stderr=%s", code, stderr.String())
}
if !strings.Contains(stdout.String(), "overall coverage: 100.0000%") || !strings.Contains(stdout.String(), "changed code coverage: 100.0000%") {
t.Fatalf("repeated profiles were not unioned: %q", stdout.String())
}
}
func TestRunChangedOnlyWithBuildableScope(t *testing.T) {
profile := filepath.Join(t.TempDir(), "coverage.out")
body := "mode: atomic\nexample.com/project/internal/a.go:10.1,12.2 5 1\n"
if err := os.WriteFile(profile, []byte(body), 0o600); err != nil {
t.Fatal(err)
}
args := []string{
"--changed-only",
"--scope-buildable",
"--diff-profile", profile,
"--base-ref", "base",
"--module", "example.com/project",
"--target", "80",
}
loader := func(string) (map[string][]lineRange, error) {
return map[string][]lineRange{
"internal/a.go": {{Start: 10, End: 12}},
"internal/a_windows.go": {{Start: 1, End: 3}},
}, nil
}
buildableLoader := func() (map[string]bool, error) {
return map[string]bool{"internal/a.go": true}, nil
}
var stdout, stderr bytes.Buffer
if code := run(args, &stdout, &stderr, loader, buildableLoader); code != 0 {
t.Fatalf("run code=%d stderr=%s", code, stderr.String())
}
if strings.Contains(stdout.String(), "overall coverage") || !strings.Contains(stdout.String(), "changed code coverage: 100.0000%") {
t.Fatalf("unexpected changed-only output %q", stdout.String())
}
missingProfileScope := func() (map[string]bool, error) {
return map[string]bool{"internal/a.go": true, "internal/a_windows.go": true}, nil
}
stdout.Reset()
stderr.Reset()
if code := run(args, &stdout, &stderr, loader, missingProfileScope); code != 1 || !strings.Contains(stderr.String(), "internal/a_windows.go") {
t.Fatalf("missing native profile code=%d stderr=%q", code, stderr.String())
}
brokenScope := func() (map[string]bool, error) { return nil, errors.New("go list failed") }
stdout.Reset()
stderr.Reset()
if code := run(args, &stdout, &stderr, loader, brokenScope); code != 2 || !strings.Contains(stderr.String(), "go list failed") {
t.Fatalf("scope failure code=%d stderr=%q", code, stderr.String())
}
}
func TestReadProfiles(t *testing.T) {
path := filepath.Join(t.TempDir(), "coverage.out")
if err := os.WriteFile(path, []byte("mode: set\nexample.com/project/internal/a.go:1.1,2.2 3 1\n"), 0o600); err != nil {
t.Fatal(err)
}
blocks, err := readProfiles([]string{path}, "example.com/project")
if err != nil {
t.Fatal(err)
}
if len(blocks) != 1 ||
blocks[0].File != "internal/a.go" ||
blocks[0].StartColumn != 1 ||
blocks[0].EndColumn != 2 ||
blocks[0].Statements != 3 {
t.Fatalf("blocks=%v", blocks)
}
if _, err := readProfiles([]string{filepath.Join(t.TempDir(), "missing")}, "example.com/project"); err == nil {
t.Fatal("missing profile should fail")
}
}
func TestParseChangedLinesRejectsInvalidHunk(t *testing.T) {
_, err := parseChangedLines([]byte("+++ b/internal/a.go\n@@ invalid @@\n"))
if err == nil {
t.Fatal("invalid hunk should fail")
}
}
func TestGitChangedLines(t *testing.T) {
repository := t.TempDir()
runGit := func(args ...string) string {
t.Helper()
command := exec.Command("git", args...)
command.Dir = repository
output, err := command.CombinedOutput()
if err != nil {
t.Fatalf("git %v: %v\n%s", args, err, output)
}
return strings.TrimSpace(string(output))
}
runGit("init")
runGit("config", "user.email", "coverage@example.com")
runGit("config", "user.name", "Coverage Test")
path := filepath.Join(repository, "a.go")
if err := os.WriteFile(path, []byte("package sample\n"), 0o600); err != nil {
t.Fatal(err)
}
runGit("add", "a.go")
runGit("commit", "-m", "base")
base := runGit("rev-parse", "HEAD")
if err := os.WriteFile(path, []byte("package sample\n\nfunc added() int { return 1 }\n"), 0o600); err != nil {
t.Fatal(err)
}
runGit("add", "a.go")
runGit("commit", "-m", "change")
if err := os.WriteFile(path, []byte("package sample\n\nfunc added() int { return 1 }\nfunc workingTree() int { return 2 }\n"), 0o600); err != nil {
t.Fatal(err)
}
previous, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
if err := os.Chdir(repository); err != nil {
t.Fatal(err)
}
t.Cleanup(func() { _ = os.Chdir(previous) })
changed, err := gitChangedLines(base)
if err != nil {
t.Fatal(err)
}
if len(changed["a.go"]) == 0 {
t.Fatalf("changed lines=%v", changed)
}
last := changed["a.go"][len(changed["a.go"])-1]
if last.End < 4 {
t.Fatalf("working-tree line was not included: %v", changed["a.go"])
}
}
func TestParseChangedLines(t *testing.T) {
diff := []byte("diff --git a/internal/a.go b/internal/a.go\n+++ b/internal/a.go\n@@ -1,0 +2,3 @@\n+one\n+two\n+three\n" +
"diff --git a/internal/a_test.go b/internal/a_test.go\n+++ b/internal/a_test.go\n@@ -0,0 +1,2 @@\n+test\n")
got, err := parseChangedLines(diff)
if err != nil {
t.Fatal(err)
}
want := map[string][]lineRange{"internal/a.go": {{Start: 2, End: 4}}}
if !reflect.DeepEqual(got, want) {
t.Fatalf("parseChangedLines() = %#v, want %#v", got, want)
}
}
func TestFilterChangedFiles(t *testing.T) {
changed := map[string][]lineRange{
"internal/a.go": {{Start: 1, End: 2}},
"internal/a_windows.go": {{Start: 3, End: 4}},
}
got := filterChangedFiles(changed, map[string]bool{"internal/a_windows.go": true})
want := map[string][]lineRange{"internal/a_windows.go": {{Start: 3, End: 4}}}
if !reflect.DeepEqual(got, want) {
t.Fatalf("filterChangedFiles() = %#v, want %#v", got, want)
}
}
func TestEvaluateAllowsNonRegressionAndCoveredChanges(t *testing.T) {
result := evaluate(gateInput{
Overall: []coverageBlock{
{File: "internal/a.go", Statements: 8, Count: 1},
{File: "internal/a.go", Statements: 2, Count: 0},
},
Diff: []coverageBlock{
{File: "internal/a.go", StartLine: 10, EndLine: 12, Statements: 4, Count: 1},
{File: "internal/a.go", StartLine: 20, EndLine: 22, Statements: 1, Count: 0},
},
Changed: map[string][]lineRange{"internal/a.go": {{Start: 10, End: 22}}},
BaselineOverall: 80,
Target: 80,
})
if len(result.Failures) != 0 {
t.Fatalf("unexpected failures: %v", result.Failures)
}
if result.ChangedCoverage != 80 {
t.Fatalf("changed coverage = %.1f, want 80", result.ChangedCoverage)
}
}
func TestCrossPlatformCoverageUnionsDuplicateCrossPackageCoverageBlocks(t *testing.T) {
duplicate := coverageBlock{File: "internal/a.go", StartLine: 10, EndLine: 12, Statements: 4}
covered := duplicate
covered.Count = 3
result := evaluate(gateInput{
Overall: []coverageBlock{duplicate, covered},
Diff: []coverageBlock{duplicate, covered},
Changed: map[string][]lineRange{"internal/a.go": {{Start: 10, End: 12}}},
Target: 80,
})
if len(result.Failures) != 0 {
t.Fatalf("duplicate blocks should be unioned: %v", result.Failures)
}
if result.Overall != 100 || result.ChangedCoverage != 100 || result.ChangedStatements != 4 {
t.Fatalf("result = %#v, want one fully covered four-statement block", result)
}
}
func TestCoverageKeepsDistinctBlocksOnTheSameLine(t *testing.T) {
result := evaluate(gateInput{
Diff: []coverageBlock{
{
File: "internal/a.go",
StartLine: 10,
StartColumn: 1,
EndLine: 10,
EndColumn: 5,
Statements: 1,
Count: 1,
},
{
File: "internal/a.go",
StartLine: 10,
StartColumn: 6,
EndLine: 10,
EndColumn: 10,
Statements: 1,
Count: 0,
},
},
Changed: map[string][]lineRange{"internal/a.go": {{Start: 10, End: 10}}},
Target: 100,
ChangedOnly: true,
})
if result.ChangedCoverage != 50 || result.ChangedStatements != 2 {
t.Fatalf("same-line blocks were collapsed: %#v", result)
}
if len(result.Failures) != 1 ||
!strings.Contains(result.Failures[0], "changed code coverage 50.0000% is below target 100.0000%") {
t.Fatalf("same-line uncovered block did not fail the gate: %v", result.Failures)
}
}
func TestEvaluateAllowsMeasurementTolerance(t *testing.T) {
result := evaluate(gateInput{
Overall: []coverageBlock{{Statements: 403, Count: 1}, {Statements: 597, Count: 0}},
Changed: map[string][]lineRange{},
BaselineOverall: 40.4,
OverallTolerance: 0.1,
Target: 80,
})
if len(result.Failures) != 0 {
t.Fatalf("measurement tolerance should allow 40.3%% vs 40.4%%: %v", result.Failures)
}
}
func TestCrossPlatformCoverageFilterBlocksByFilesDropsDeletedPackages(t *testing.T) {
if filtered := filterBlocksByFiles([]coverageBlock{{File: "internal/keep.go", Statements: 1, Count: 1}}, nil); filtered != nil {
t.Fatalf("empty allowlist = %#v, want nil", filtered)
}
baseline := []coverageBlock{
{File: "internal/keep.go", StartLine: 1, EndLine: 10, Statements: 50, Count: 1},
{File: "internal/keep.go", StartLine: 11, EndLine: 20, Statements: 50, Count: 0},
{File: "internal/deleted.go", StartLine: 1, EndLine: 40, Statements: 100, Count: 1},
}
currentFiles := profileFiles([]coverageBlock{
{File: "internal/keep.go", StartLine: 1, EndLine: 8, Statements: 40, Count: 1},
})
filtered := filterBlocksByFiles(baseline, currentFiles)
got := coveragePercent(filtered)
if got != 50 {
t.Fatalf("shared-file baseline = %.4f%%, want 50%% (deleted 100%%-covered package excluded)", got)
}
if len(profileFiles(filtered)) != 1 || !profileFiles(filtered)["internal/keep.go"] {
t.Fatalf("filtered files = %#v, want only keep.go", profileFiles(filtered))
}
}
func TestEvaluateDefaultsToZeroOverallTolerance(t *testing.T) {
result := evaluate(gateInput{
Overall: []coverageBlock{{Statements: 403, Count: 1}, {Statements: 597, Count: 0}},
Changed: map[string][]lineRange{},
BaselineOverall: 40.4,
OverallTolerance: 0,
Target: 100,
})
if len(result.Failures) != 1 ||
!strings.Contains(result.Failures[0], "overall coverage regressed from 40.4000% to 40.3000%") {
t.Fatalf("zero-tolerance regression failures = %v", result.Failures)
}
}
func TestEvaluateRejectsRegressionHiddenByOneDecimalRounding(t *testing.T) {
result := evaluate(gateInput{
Overall: []coverageBlock{
{Statements: 1999, Count: 1},
{Statements: 1, Count: 0},
},
Changed: map[string][]lineRange{},
BaselineOverall: 100,
Target: 100,
})
if len(result.Failures) != 1 ||
!strings.Contains(result.Failures[0], "overall coverage regressed from 100.0000% to 99.9500%") {
t.Fatalf("sub-tenth regression failures = %v", result.Failures)
}
}
func TestEvaluateRejectsChangedCoverageBelow100WithoutRounding(t *testing.T) {
result := evaluate(gateInput{
Diff: []coverageBlock{
{File: "internal/a.go", StartLine: 1, EndLine: 1999, Statements: 1999, Count: 1},
{File: "internal/a.go", StartLine: 2000, EndLine: 2000, Statements: 1, Count: 0},
},
Changed: map[string][]lineRange{"internal/a.go": {{Start: 1, End: 2000}}},
Target: 100,
ChangedOnly: true,
})
if len(result.Failures) != 1 ||
!strings.Contains(result.Failures[0], "changed code coverage 99.9500% is below target 100.0000%") {
t.Fatalf("sub-100 changed-code failures = %v", result.Failures)
}
}
func TestEvaluateFailsClosed(t *testing.T) {
result := evaluate(gateInput{
Overall: []coverageBlock{
{File: "internal/base.go", StartLine: 1, EndLine: 2, Statements: 10, Count: 1},
{File: "internal/base.go", StartLine: 3, EndLine: 4, Statements: 10, Count: 0},
},
Diff: []coverageBlock{{File: "internal/a.go", StartLine: 1, EndLine: 2, Statements: 2, Count: 0}},
Changed: map[string][]lineRange{"internal/a.go": {{Start: 1, End: 2}}, "internal/missing.go": {{Start: 1, End: 1}}},
BaselineOverall: 54.2,
Target: 80,
})
if len(result.Failures) != 3 {
t.Fatalf("got failures %v, want overall, changed-code, and missing-profile failures", result.Failures)
}
}
func TestEvaluateOverallTargetCanBeEnabled(t *testing.T) {
result := evaluate(gateInput{
Overall: []coverageBlock{{Statements: 60, Count: 1}, {Statements: 40, Count: 0}},
Diff: []coverageBlock{},
Changed: map[string][]lineRange{},
BaselineOverall: 54.2,
Target: 80,
EnforceOverall: true,
})
if len(result.Failures) != 1 {
t.Fatalf("failures = %v, want overall target failure", result.Failures)
}
}
func TestExemptNonExecutableFiles(t *testing.T) {
changed := map[string][]lineRange{
"internal/cli/gen.go": {{Start: 1, End: 5}},
"internal/cli/doc.go": {{Start: 1, End: 2}},
"internal/cli/code.go": {{Start: 10, End: 12}},
}
filtered, exempted := exemptNonExecutableFiles(changed, func(path string) bool {
return path == "internal/cli/code.go"
})
want := map[string][]lineRange{"internal/cli/code.go": {{Start: 10, End: 12}}}
if !reflect.DeepEqual(filtered, want) {
t.Fatalf("filtered = %#v, want %#v", filtered, want)
}
// 豁免列表按字典序返回,供调用方日志化而非静默丢弃。
if !reflect.DeepEqual(exempted, []string{"internal/cli/doc.go", "internal/cli/gen.go"}) {
t.Fatalf("exempted = %v, want sorted exempted paths", exempted)
}
}
func TestFileHasExecutableStatements(t *testing.T) {
dir := t.TempDir()
write := func(name, source string) string {
path := filepath.Join(dir, name)
if err := os.WriteFile(path, []byte(source), 0o600); err != nil {
t.Fatal(err)
}
return path
}
cases := []struct {
name string
path string
want bool
}{
{
name: "pragma-only file has no executable statements",
path: write("gen.go", "// Comment only.\npackage cli\n\n//go:generate echo hi\n"),
want: false,
},
{
name: "function body counts as executable",
path: write("code.go", "package cli\n\nfunc f() int { return 1 }\n"),
want: true,
},
{
name: "empty function body is not executable",
path: write("empty.go", "package cli\n\nfunc f() {}\n"),
want: false,
},
{
name: "package-level function literal counts as executable",
path: write("lit.go", "package cli\n\nvar f = func() int { return 1 }\n"),
want: true,
},
{
name: "missing file stays conservative",
path: filepath.Join(dir, "nonexistent.go"),
want: true,
},
{
name: "unparsable file stays conservative",
path: write("broken.go", "package cli\n\nfunc {{{\n"),
want: true,
},
}
for _, tc := range cases {
if got := fileHasExecutableStatements(tc.path); got != tc.want {
t.Errorf("%s: fileHasExecutableStatements() = %v, want %v", tc.name, got, tc.want)
}
}
}
func TestRunLogsExemptedNonExecutableFiles(t *testing.T) {
dir := t.TempDir()
pragmaOnly := filepath.Join(dir, "gen.go")
if err := os.WriteFile(pragmaOnly, []byte("// pragma carrier\npackage cli\n\n//go:generate echo hi\n"), 0o600); err != nil {
t.Fatal(err)
}
profile := filepath.Join(dir, "coverage.out")
body := "mode: atomic\nexample.com/project/internal/a.go:10.1,12.2 5 1\n"
if err := os.WriteFile(profile, []byte(body), 0o600); err != nil {
t.Fatal(err)
}
args := []string{
"--overall-profile", profile,
"--diff-profile", profile,
"--base-ref", "base",
"--module", "example.com/project",
"--baseline-overall", "100",
"--target", "80",
}
loader := func(string) (map[string][]lineRange, error) {
return map[string][]lineRange{
"internal/a.go": {{Start: 10, End: 12}},
pragmaOnly: {{Start: 1, End: 4}},
}, nil
}
var stdout, stderr bytes.Buffer
if code := run(args, &stdout, &stderr, loader, nil); code != 0 {
t.Fatalf("run code=%d stderr=%s", code, stderr.String())
}
if !strings.Contains(stderr.String(), "exempting "+pragmaOnly) {
t.Fatalf("stderr = %q, want exemption log for pragma-only file", stderr.String())
}
}
func TestCrossPlatformCoveragePhysicalPath(t *testing.T) {
real := t.TempDir()
link := filepath.Join(t.TempDir(), "link")
if err := os.Symlink(real, link); err != nil {
t.Fatalf("symlink: %v", err)
}
expected, err := filepath.EvalSymlinks(real)
if err != nil {
t.Fatalf("EvalSymlinks(real): %v", err)
}
if got := physicalPath(link); got != expected {
t.Fatalf("physicalPath(%q) = %q, want %q", link, got, expected)
}
missing := filepath.Join(t.TempDir(), "missing")
if got := physicalPath(missing); got != missing {
t.Fatalf("physicalPath(%q) = %q, want path returned unchanged", missing, got)
}
}
func TestCrossPlatformCoverageGoListBuildableFilesIncludesSelfPackage(t *testing.T) {
buildable, err := goListBuildableFiles()
if err != nil {
t.Fatalf("goListBuildableFiles: %v", err)
}
if !buildable["scripts/policy/coverage-gate/main.go"] {
t.Fatalf("buildable files missing self package; sample keys: %v", firstKeys(buildable, 3))
}
}
func firstKeys(m map[string]bool, n int) []string {
keys := make([]string, 0, n)
for key := range m {
keys = append(keys, key)
if len(keys) == n {
break
}
}
return keys
}