1
2
3
4
5 package test
6
7 import (
8 "fmt"
9 "internal/coverage"
10 "internal/coverage/decodemeta"
11 "internal/coverage/encodemeta"
12 "internal/coverage/slicewriter"
13 "io"
14 "os"
15 "path/filepath"
16 "testing"
17 )
18
19 func cmpFuncDesc(want, got coverage.FuncDesc) string {
20 swant := fmt.Sprintf("%+v", want)
21 sgot := fmt.Sprintf("%+v", got)
22 if swant == sgot {
23 return ""
24 }
25 return fmt.Sprintf("wanted %q got %q", swant, sgot)
26 }
27
28 func TestMetaDataEmptyPackage(t *testing.T) {
29
30
31 p := "empty/package"
32 pn := "package"
33 mp := "m"
34 b, err := encodemeta.NewCoverageMetaDataBuilder(p, pn, mp)
35 if err != nil {
36 t.Fatalf("making builder: %v", err)
37 }
38 drws := &slicewriter.WriteSeeker{}
39 b.Emit(drws)
40 drws.Seek(0, io.SeekStart)
41 dec, err := decodemeta.NewCoverageMetaDataDecoder(drws.BytesWritten(), false)
42 if err != nil {
43 t.Fatalf("making decoder: %v", err)
44 }
45 nf := dec.NumFuncs()
46 if nf != 0 {
47 t.Errorf("dec.NumFuncs(): got %d want %d", nf, 0)
48 }
49 pp := dec.PackagePath()
50 if pp != p {
51 t.Errorf("dec.PackagePath(): got %s want %s", pp, p)
52 }
53 ppn := dec.PackageName()
54 if ppn != pn {
55 t.Errorf("dec.PackageName(): got %s want %s", ppn, pn)
56 }
57 pmp := dec.ModulePath()
58 if pmp != mp {
59 t.Errorf("dec.ModulePath(): got %s want %s", pmp, mp)
60 }
61 }
62
63 func TestMetaDataEncoderDecoder(t *testing.T) {
64
65 pp := "foo/bar/pkg"
66 pn := "pkg"
67 mp := "barmod"
68 b, err := encodemeta.NewCoverageMetaDataBuilder(pp, pn, mp)
69 if err != nil {
70 t.Fatalf("making builder: %v", err)
71 }
72 f1 := coverage.FuncDesc{
73 Funcname: "func",
74 Srcfile: "foo.go",
75 Units: []coverage.CoverableUnit{
76 coverage.CoverableUnit{StLine: 1, StCol: 2, EnLine: 3, EnCol: 4, NxStmts: 5},
77 coverage.CoverableUnit{StLine: 6, StCol: 7, EnLine: 8, EnCol: 9, NxStmts: 10},
78 },
79 }
80 idx := b.AddFunc(f1)
81 if idx != 0 {
82 t.Errorf("b.AddFunc(f1) got %d want %d", idx, 0)
83 }
84
85 f2 := coverage.FuncDesc{
86 Funcname: "xfunc",
87 Srcfile: "bar.go",
88 Units: []coverage.CoverableUnit{
89 coverage.CoverableUnit{StLine: 1, StCol: 2, EnLine: 3, EnCol: 4, NxStmts: 5},
90 coverage.CoverableUnit{StLine: 6, StCol: 7, EnLine: 8, EnCol: 9, NxStmts: 10},
91 coverage.CoverableUnit{StLine: 11, StCol: 12, EnLine: 13, EnCol: 14, NxStmts: 15},
92 },
93 }
94 idx = b.AddFunc(f2)
95 if idx != 1 {
96 t.Errorf("b.AddFunc(f2) got %d want %d", idx, 0)
97 }
98
99
100 drws := &slicewriter.WriteSeeker{}
101 b.Emit(drws)
102
103
104 drws.Seek(0, io.SeekStart)
105 dec, err := decodemeta.NewCoverageMetaDataDecoder(drws.BytesWritten(), false)
106 if err != nil {
107 t.Fatalf("NewCoverageMetaDataDecoder error: %v", err)
108 }
109 nf := dec.NumFuncs()
110 if nf != 2 {
111 t.Errorf("dec.NumFuncs(): got %d want %d", nf, 2)
112 }
113
114 gotpp := dec.PackagePath()
115 if gotpp != pp {
116 t.Errorf("packagepath: got %s want %s", gotpp, pp)
117 }
118 gotpn := dec.PackageName()
119 if gotpn != pn {
120 t.Errorf("packagename: got %s want %s", gotpn, pn)
121 }
122
123 cases := []coverage.FuncDesc{f1, f2}
124 for i := uint32(0); i < uint32(len(cases)); i++ {
125 var fn coverage.FuncDesc
126 if err := dec.ReadFunc(i, &fn); err != nil {
127 t.Fatalf("err reading function %d: %v", i, err)
128 }
129 res := cmpFuncDesc(cases[i], fn)
130 if res != "" {
131 t.Errorf("ReadFunc(%d): %s", i, res)
132 }
133 }
134 }
135
136 func createFuncs(i int) []coverage.FuncDesc {
137 res := []coverage.FuncDesc{}
138 lc := uint32(1)
139 for fi := 0; fi < i+1; fi++ {
140 units := []coverage.CoverableUnit{}
141 for ui := 0; ui < (fi+1)*(i+1); ui++ {
142 units = append(units,
143 coverage.CoverableUnit{StLine: lc, StCol: lc + 1,
144 EnLine: lc + 2, EnCol: lc + 3, NxStmts: lc + 4,
145 })
146 lc += 5
147 }
148 f := coverage.FuncDesc{
149 Funcname: fmt.Sprintf("func_%d_%d", i, fi),
150 Srcfile: fmt.Sprintf("foo_%d.go", i),
151 Units: units,
152 }
153 res = append(res, f)
154 }
155 return res
156 }
157
158 func createBlob(t *testing.T, i int) []byte {
159 nomodule := ""
160 b, err := encodemeta.NewCoverageMetaDataBuilder("foo/pkg", "pkg", nomodule)
161 if err != nil {
162 t.Fatalf("making builder: %v", err)
163 }
164
165 funcs := createFuncs(i)
166 for _, f := range funcs {
167 b.AddFunc(f)
168 }
169 drws := &slicewriter.WriteSeeker{}
170 b.Emit(drws)
171 return drws.BytesWritten()
172 }
173
174 func createMetaDataBlobs(t *testing.T, nb int) [][]byte {
175 res := [][]byte{}
176 for i := 0; i < nb; i++ {
177 res = append(res, createBlob(t, i))
178 }
179 return res
180 }
181
182 func TestMetaDataWriterReader(t *testing.T) {
183 d := t.TempDir()
184
185
186 mfpath := filepath.Join(d, "covmeta.hash.0")
187 of, err := os.OpenFile(mfpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
188 if err != nil {
189 t.Fatalf("opening covmeta: %v", err)
190 }
191
192 blobs := createMetaDataBlobs(t, 7)
193 gran := coverage.CtrGranularityPerBlock
194 mfw := encodemeta.NewCoverageMetaFileWriter(mfpath, of)
195 finalHash := [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
196 err = mfw.Write(finalHash, blobs, coverage.CtrModeAtomic, gran)
197 if err != nil {
198 t.Fatalf("writing meta-file: %v", err)
199 }
200 if err = of.Close(); err != nil {
201 t.Fatalf("closing meta-file: %v", err)
202 }
203
204
205
206 for k := 0; k < 2; k++ {
207 var fileView []byte
208
209 inf, err := os.Open(mfpath)
210 if err != nil {
211 t.Fatalf("open() on meta-file: %v", err)
212 }
213
214 if k != 0 {
215
216 fi, err := os.Stat(mfpath)
217 if err != nil {
218 t.Fatalf("stat() on meta-file: %v", err)
219 }
220 fileView = make([]byte, fi.Size())
221 if _, err := inf.Read(fileView); err != nil {
222 t.Fatalf("read() on meta-file: %v", err)
223 }
224 if _, err := inf.Seek(int64(0), io.SeekStart); err != nil {
225 t.Fatalf("seek() on meta-file: %v", err)
226 }
227 }
228
229 mfr, err := decodemeta.NewCoverageMetaFileReader(inf, fileView)
230 if err != nil {
231 t.Fatalf("k=%d NewCoverageMetaFileReader failed with: %v", k, err)
232 }
233 np := mfr.NumPackages()
234 if np != 7 {
235 t.Fatalf("k=%d wanted 7 packages got %d", k, np)
236 }
237 md := mfr.CounterMode()
238 wmd := coverage.CtrModeAtomic
239 if md != wmd {
240 t.Fatalf("k=%d wanted mode %d got %d", k, wmd, md)
241 }
242 gran := mfr.CounterGranularity()
243 wgran := coverage.CtrGranularityPerBlock
244 if gran != wgran {
245 t.Fatalf("k=%d wanted gran %d got %d", k, wgran, gran)
246 }
247
248 payload := []byte{}
249 for pi := 0; pi < int(np); pi++ {
250 var pd *decodemeta.CoverageMetaDataDecoder
251 var err error
252 pd, payload, err = mfr.GetPackageDecoder(uint32(pi), payload)
253 if err != nil {
254 t.Fatalf("GetPackageDecoder(%d) failed with: %v", pi, err)
255 }
256 efuncs := createFuncs(pi)
257 nf := pd.NumFuncs()
258 if len(efuncs) != int(nf) {
259 t.Fatalf("decoding pk %d wanted %d funcs got %d",
260 pi, len(efuncs), nf)
261 }
262 var f coverage.FuncDesc
263 for fi := 0; fi < int(nf); fi++ {
264 if err := pd.ReadFunc(uint32(fi), &f); err != nil {
265 t.Fatalf("ReadFunc(%d) pk %d got error %v",
266 fi, pi, err)
267 }
268 res := cmpFuncDesc(efuncs[fi], f)
269 if res != "" {
270 t.Errorf("ReadFunc(%d) pk %d: %s", fi, pi, res)
271 }
272 }
273 }
274 inf.Close()
275 }
276 }
277
278 func TestMetaDataDecodeLitFlagIssue57942(t *testing.T) {
279
280
281
282 pp := "foo/bar/pkg"
283 pn := "pkg"
284 mp := "barmod"
285 b, err := encodemeta.NewCoverageMetaDataBuilder(pp, pn, mp)
286 if err != nil {
287 t.Fatalf("making builder: %v", err)
288 }
289 const NF = 6
290 const NCU = 1
291 ln := uint32(10)
292 wantfds := []coverage.FuncDesc{}
293 for fi := uint32(0); fi < NF; fi++ {
294 fis := fmt.Sprintf("%d", fi)
295 fd := coverage.FuncDesc{
296 Funcname: "func" + fis,
297 Srcfile: "foo" + fis + ".go",
298 Units: []coverage.CoverableUnit{
299 coverage.CoverableUnit{StLine: ln + 1, StCol: 2, EnLine: ln + 3, EnCol: 4, NxStmts: fi + 2},
300 },
301 Lit: (fi % 2) == 0,
302 }
303 wantfds = append(wantfds, fd)
304 b.AddFunc(fd)
305 }
306
307
308 drws := &slicewriter.WriteSeeker{}
309 b.Emit(drws)
310
311
312 drws.Seek(0, io.SeekStart)
313 dec, err := decodemeta.NewCoverageMetaDataDecoder(drws.BytesWritten(), false)
314 if err != nil {
315 t.Fatalf("making decoder: %v", err)
316 }
317 nf := dec.NumFuncs()
318 if nf != NF {
319 t.Fatalf("decoder number of functions: got %d want %d", nf, NF)
320 }
321 var fn coverage.FuncDesc
322 for i := uint32(0); i < uint32(NF); i++ {
323 if err := dec.ReadFunc(i, &fn); err != nil {
324 t.Fatalf("err reading function %d: %v", i, err)
325 }
326 res := cmpFuncDesc(wantfds[i], fn)
327 if res != "" {
328 t.Errorf("ReadFunc(%d): %s", i, res)
329 }
330 }
331 }
332
View as plain text