1
2
3
4
5 package test
6
7 import (
8 "fmt"
9 "internal/coverage"
10 "internal/coverage/decodecounter"
11 "internal/coverage/encodecounter"
12 "io"
13 "os"
14 "path/filepath"
15 "testing"
16 )
17
18 type ctrVis struct {
19 funcs []decodecounter.FuncPayload
20 }
21
22 func (v *ctrVis) VisitFuncs(f encodecounter.CounterVisitorFn) error {
23 for _, fn := range v.funcs {
24 if err := f(fn.PkgIdx, fn.FuncIdx, fn.Counters); err != nil {
25 return err
26 }
27 }
28 return nil
29 }
30
31 func mkfunc(p uint32, f uint32, c []uint32) decodecounter.FuncPayload {
32 return decodecounter.FuncPayload{
33 PkgIdx: p,
34 FuncIdx: f,
35 Counters: c,
36 }
37 }
38
39 func TestCounterDataWriterReader(t *testing.T) {
40 flavors := []coverage.CounterFlavor{
41 coverage.CtrRaw,
42 coverage.CtrULeb128,
43 }
44
45 isDead := func(fp decodecounter.FuncPayload) bool {
46 for _, v := range fp.Counters {
47 if v != 0 {
48 return false
49 }
50 }
51 return true
52 }
53
54 funcs := []decodecounter.FuncPayload{
55 mkfunc(0, 0, []uint32{13, 14, 15}),
56 mkfunc(0, 1, []uint32{16, 17}),
57 mkfunc(1, 0, []uint32{18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 976543, 7}),
58 }
59 writeVisitor := &ctrVis{funcs: funcs}
60
61 for kf, flav := range flavors {
62
63 t.Logf("testing flavor %d\n", flav)
64
65
66 d := t.TempDir()
67 cfpath := filepath.Join(d, fmt.Sprintf("covcounters.hash.0.%d", kf))
68 of, err := os.OpenFile(cfpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
69 if err != nil {
70 t.Fatalf("opening covcounters: %v", err)
71 }
72
73
74 cdfw := encodecounter.NewCoverageDataWriter(of, flav)
75 if cdfw == nil {
76 t.Fatalf("NewCoverageDataWriter failed")
77 }
78 finalHash := [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}
79 args := map[string]string{"argc": "3", "argv0": "arg0", "argv1": "arg1", "argv2": "arg_________2"}
80 if err := cdfw.Write(finalHash, args, writeVisitor); err != nil {
81 t.Fatalf("counter file Write failed: %v", err)
82 }
83 if err := of.Close(); err != nil {
84 t.Fatalf("closing covcounters: %v", err)
85 }
86 cdfw = nil
87
88
89 var cdr *decodecounter.CounterDataReader
90 inf, err := os.Open(cfpath)
91 defer func() {
92 if err := inf.Close(); err != nil {
93 t.Fatalf("close failed with: %v", err)
94 }
95 }()
96
97 if err != nil {
98 t.Fatalf("reopening covcounters file: %v", err)
99 }
100 if cdr, err = decodecounter.NewCounterDataReader(cfpath, inf); err != nil {
101 t.Fatalf("opening covcounters for read: %v", err)
102 }
103 decodedArgs := cdr.OsArgs()
104 aWant := "[arg0 arg1 arg_________2]"
105 aGot := fmt.Sprintf("%+v", decodedArgs)
106 if aWant != aGot {
107 t.Errorf("reading decoded args, got %s want %s", aGot, aWant)
108 }
109 for i := range funcs {
110 if isDead(funcs[i]) {
111 continue
112 }
113 var fp decodecounter.FuncPayload
114 if ok, err := cdr.NextFunc(&fp); err != nil {
115 t.Fatalf("reading func %d: %v", i, err)
116 } else if !ok {
117 t.Fatalf("reading func %d: bad return", i)
118 }
119 got := fmt.Sprintf("%+v", fp)
120 want := fmt.Sprintf("%+v", funcs[i])
121 if got != want {
122 t.Errorf("cdr.NextFunc iter %d\ngot %+v\nwant %+v", i, got, want)
123 }
124 }
125 var dummy decodecounter.FuncPayload
126 if ok, err := cdr.NextFunc(&dummy); err != nil {
127 t.Fatalf("reading func after loop: %v", err)
128 } else if ok {
129 t.Fatalf("reading func after loop: expected EOF")
130 }
131 }
132 }
133
134 func TestCounterDataAppendSegment(t *testing.T) {
135 d := t.TempDir()
136 cfpath := filepath.Join(d, "covcounters.hash2.0")
137 of, err := os.OpenFile(cfpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
138 if err != nil {
139 t.Fatalf("opening covcounters: %v", err)
140 }
141
142 const numSegments = 2
143
144
145 args := map[string]string{"argc": "1", "argv0": "prog.exe"}
146 allfuncs := [][]decodecounter.FuncPayload{}
147 ctrs := []uint32{}
148 q := uint32(0)
149 var cdfw *encodecounter.CoverageDataWriter
150 for idx := 0; idx < numSegments; idx++ {
151 args[fmt.Sprintf("seg%d", idx)] = "x"
152 q += 7
153 ctrs = append(ctrs, q)
154 funcs := []decodecounter.FuncPayload{}
155 for k := 0; k < idx+1; k++ {
156 c := make([]uint32, len(ctrs))
157 copy(c, ctrs)
158 funcs = append(funcs, mkfunc(uint32(idx), uint32(k), c))
159 }
160 allfuncs = append(allfuncs, funcs)
161
162 writeVisitor := &ctrVis{funcs: funcs}
163
164 if idx == 0 {
165
166 cdfw = encodecounter.NewCoverageDataWriter(of, coverage.CtrRaw)
167 if cdfw == nil {
168 t.Fatalf("NewCoverageDataWriter failed")
169 }
170 finalHash := [16]byte{1, 2}
171 if err := cdfw.Write(finalHash, args, writeVisitor); err != nil {
172 t.Fatalf("counter file Write failed: %v", err)
173 }
174 } else {
175 if err := cdfw.AppendSegment(args, writeVisitor); err != nil {
176 t.Fatalf("counter file AppendSegment failed: %v", err)
177 }
178 }
179 }
180 if err := of.Close(); err != nil {
181 t.Fatalf("closing covcounters: %v", err)
182 }
183
184
185 var cdr *decodecounter.CounterDataReader
186 inf, err := os.Open(cfpath)
187 defer func() {
188 if err := inf.Close(); err != nil {
189 t.Fatalf("close failed with: %v", err)
190 }
191 }()
192
193 if err != nil {
194 t.Fatalf("reopening covcounters file: %v", err)
195 }
196 if cdr, err = decodecounter.NewCounterDataReader(cfpath, inf); err != nil {
197 t.Fatalf("opening covcounters for read: %v", err)
198 }
199 ns := cdr.NumSegments()
200 if ns != numSegments {
201 t.Fatalf("got %d segments want %d", ns, numSegments)
202 }
203 if len(allfuncs) != numSegments {
204 t.Fatalf("expected %d got %d", numSegments, len(allfuncs))
205 }
206
207 for sidx := 0; sidx < int(ns); sidx++ {
208 if off, err := inf.Seek(0, io.SeekCurrent); err != nil {
209 t.Fatalf("Seek failed: %v", err)
210 } else {
211 t.Logf("sidx=%d off=%d\n", sidx, off)
212 }
213
214 if sidx != 0 {
215 if ok, err := cdr.BeginNextSegment(); err != nil {
216 t.Fatalf("BeginNextSegment failed: %v", err)
217 } else if !ok {
218 t.Fatalf("BeginNextSegment return %v on iter %d",
219 ok, sidx)
220 }
221 }
222 funcs := allfuncs[sidx]
223 for i := range funcs {
224 var fp decodecounter.FuncPayload
225 if ok, err := cdr.NextFunc(&fp); err != nil {
226 t.Fatalf("reading func %d: %v", i, err)
227 } else if !ok {
228 t.Fatalf("reading func %d: bad return", i)
229 }
230 got := fmt.Sprintf("%+v", fp)
231 want := fmt.Sprintf("%+v", funcs[i])
232 if got != want {
233 t.Errorf("cdr.NextFunc iter %d\ngot %+v\nwant %+v", i, got, want)
234 }
235 }
236 }
237 }
238
View as plain text