1 # Test for bug where cached coverage profiles with -coverpkg can contain
2 # outdated line references when source files are modified.
3 # This reproduces the issue where coverage data from cache may reference
4 # lines that no longer exist in the updated source files.
5
6 [short] skip
7 [GODEBUG:gocacheverify=1] skip
8
9 # We're testing cache behavior, so start with a clean GOCACHE.
10 env GOCACHE=$WORK/cache
11
12 # Create a project structure with multiple packages
13 # proj/
14 # some_func.go
15 # some_func_test.go
16 # sub/
17 # sub.go
18 # sub_test.go
19 # sum/
20 # sum.go
21
22 # Switch to the proj directory
23 cd proj
24
25 # Run tests with -coverpkg to collect coverage for all packages
26 go test -coverpkg=proj/... -coverprofile=cover1.out ./...
27 stdout 'coverage:'
28
29 # Verify the first coverage profile exists and has expected content
30 exists cover1.out
31 grep -q 'proj/sub/sub.go:' cover1.out
32
33 # Run again to ensure caching works
34 go test -coverpkg=proj/... -coverprofile=cover1_cached.out ./...
35 stdout '\(cached\)'
36 stdout 'coverage:'
37
38 # Note: Due to the bug, cached coverage profiles may have duplicate entries.
39 # The duplicate entries are the entries for the previous file structure and the new file structure.
40
41 # Now modify sub.go to change line structure - this will invalidate
42 # the cache for the sub package but not for the proj package.
43 cp ../sub_modified.go sub/sub.go
44
45 # After modifying sub.go, we should not have both old and new line references.
46 go test -coverpkg=proj/... -coverprofile=cover2.out ./...
47 stdout 'coverage:'
48
49 # With the bug present, we would see duplicate entries for the same lines.
50 # With the bug fixed, there should be no duplicate or stale entries in the coverage profile.
51 grep 'proj/sub/sub.go:' cover2.out
52 # The fix should ensure that only the new line format exists, not the old one
53 grep 'proj/sub/sub.go:4.2,4.35' cover2.out
54 # This should fail if the stale coverage line exists (the bug is present)
55 ! grep 'proj/sub/sub.go:4.2,4.22' cover2.out
56
57 -- proj/go.mod --
58 module proj
59
60 go 1.21
61
62 -- proj/some_func.go --
63 package proj
64
65 import "proj/sum"
66
67 func SomeFunc(a, b int) int {
68 if a == 0 && b == 0 {
69 return 0
70 }
71 return sum.Sum(a, b)
72 }
73
74 -- proj/some_func_test.go --
75 package proj
76
77 import (
78 "testing"
79 )
80
81 func Test_SomeFunc(t *testing.T) {
82 t.Run("test1", func(t *testing.T) {
83 result := SomeFunc(1, 1)
84 if result != 2 {
85 t.Errorf("Expected 2, got %d", result)
86 }
87 })
88 }
89
90 -- proj/sub/sub.go --
91 package sub
92
93 func Sub(a, b int) int {
94 if a == 0 && b == 0 {
95 return 0
96 }
97 return a - b
98 }
99
100 -- proj/sub/sub_test.go --
101 package sub
102
103 import (
104 "testing"
105 )
106
107 func Test_Sub(t *testing.T) {
108 t.Run("test_sub1", func(t *testing.T) {
109 result := Sub(1, 1)
110 if result != 0 {
111 t.Errorf("Expected 0, got %d", result)
112 }
113 })
114 }
115
116 -- proj/sum/sum.go --
117 package sum
118
119 func Sum(a, b int) int {
120 if a == 0 {
121 return b
122 }
123 return a + b
124 }
125
126 -- sub_modified.go --
127 package sub
128
129 func Sub(a, b int) int {
130 if a == 0 && b == 0 || a == -100 {
131 return 0
132 }
133 return a - b
134 }
135
View as plain text