summaryrefslogtreecommitdiffstats
path: root/src/internal/coverage/test/counter_test.go
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-16 19:23:18 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-16 19:23:18 +0000
commit43a123c1ae6613b3efeed291fa552ecd909d3acf (patch)
treefd92518b7024bc74031f78a1cf9e454b65e73665 /src/internal/coverage/test/counter_test.go
parentInitial commit. (diff)
downloadgolang-1.20-upstream.tar.xz
golang-1.20-upstream.zip
Adding upstream version 1.20.14.upstream/1.20.14upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/internal/coverage/test/counter_test.go')
-rw-r--r--src/internal/coverage/test/counter_test.go241
1 files changed, 241 insertions, 0 deletions
diff --git a/src/internal/coverage/test/counter_test.go b/src/internal/coverage/test/counter_test.go
new file mode 100644
index 0000000..3fc111e
--- /dev/null
+++ b/src/internal/coverage/test/counter_test.go
@@ -0,0 +1,241 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package test
+
+import (
+ "fmt"
+ "internal/coverage"
+ "internal/coverage/decodecounter"
+ "internal/coverage/encodecounter"
+ "io"
+ "os"
+ "path/filepath"
+ "testing"
+)
+
+type ctrVis struct {
+ funcs []decodecounter.FuncPayload
+}
+
+func (v *ctrVis) NumFuncs() (int, error) {
+ return len(v.funcs), nil
+}
+
+func (v *ctrVis) VisitFuncs(f encodecounter.CounterVisitorFn) error {
+ for _, fn := range v.funcs {
+ if err := f(fn.PkgIdx, fn.FuncIdx, fn.Counters); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func mkfunc(p uint32, f uint32, c []uint32) decodecounter.FuncPayload {
+ return decodecounter.FuncPayload{
+ PkgIdx: p,
+ FuncIdx: f,
+ Counters: c,
+ }
+}
+
+func TestCounterDataWriterReader(t *testing.T) {
+ flavors := []coverage.CounterFlavor{
+ coverage.CtrRaw,
+ coverage.CtrULeb128,
+ }
+
+ isDead := func(fp decodecounter.FuncPayload) bool {
+ for _, v := range fp.Counters {
+ if v != 0 {
+ return false
+ }
+ }
+ return true
+ }
+
+ funcs := []decodecounter.FuncPayload{
+ mkfunc(0, 0, []uint32{13, 14, 15}),
+ mkfunc(0, 1, []uint32{16, 17}),
+ mkfunc(1, 0, []uint32{18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 976543, 7}),
+ }
+ writeVisitor := &ctrVis{funcs: funcs}
+
+ for kf, flav := range flavors {
+
+ t.Logf("testing flavor %d\n", flav)
+
+ // Open a counter data file in preparation for emitting data.
+ d := t.TempDir()
+ cfpath := filepath.Join(d, fmt.Sprintf("covcounters.hash.0.%d", kf))
+ of, err := os.OpenFile(cfpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
+ if err != nil {
+ t.Fatalf("opening covcounters: %v", err)
+ }
+
+ // Perform the encode and write.
+ cdfw := encodecounter.NewCoverageDataWriter(of, flav)
+ if cdfw == nil {
+ t.Fatalf("NewCoverageDataWriter failed")
+ }
+ finalHash := [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}
+ args := map[string]string{"argc": "3", "argv0": "arg0", "argv1": "arg1", "argv2": "arg_________2"}
+ if err := cdfw.Write(finalHash, args, writeVisitor); err != nil {
+ t.Fatalf("counter file Write failed: %v", err)
+ }
+ if err := of.Close(); err != nil {
+ t.Fatalf("closing covcounters: %v", err)
+ }
+ cdfw = nil
+
+ // Decode the same file.
+ var cdr *decodecounter.CounterDataReader
+ inf, err := os.Open(cfpath)
+ defer func() {
+ if err := inf.Close(); err != nil {
+ t.Fatalf("close failed with: %v", err)
+ }
+ }()
+
+ if err != nil {
+ t.Fatalf("reopening covcounters file: %v", err)
+ }
+ if cdr, err = decodecounter.NewCounterDataReader(cfpath, inf); err != nil {
+ t.Fatalf("opening covcounters for read: %v", err)
+ }
+ decodedArgs := cdr.OsArgs()
+ aWant := "[arg0 arg1 arg_________2]"
+ aGot := fmt.Sprintf("%+v", decodedArgs)
+ if aWant != aGot {
+ t.Errorf("reading decoded args, got %s want %s", aGot, aWant)
+ }
+ for i := range funcs {
+ if isDead(funcs[i]) {
+ continue
+ }
+ var fp decodecounter.FuncPayload
+ if ok, err := cdr.NextFunc(&fp); err != nil {
+ t.Fatalf("reading func %d: %v", i, err)
+ } else if !ok {
+ t.Fatalf("reading func %d: bad return", i)
+ }
+ got := fmt.Sprintf("%+v", fp)
+ want := fmt.Sprintf("%+v", funcs[i])
+ if got != want {
+ t.Errorf("cdr.NextFunc iter %d\ngot %+v\nwant %+v", i, got, want)
+ }
+ }
+ var dummy decodecounter.FuncPayload
+ if ok, err := cdr.NextFunc(&dummy); err != nil {
+ t.Fatalf("reading func after loop: %v", err)
+ } else if ok {
+ t.Fatalf("reading func after loop: expected EOF")
+ }
+ }
+}
+
+func TestCounterDataAppendSegment(t *testing.T) {
+ d := t.TempDir()
+ cfpath := filepath.Join(d, "covcounters.hash2.0")
+ of, err := os.OpenFile(cfpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
+ if err != nil {
+ t.Fatalf("opening covcounters: %v", err)
+ }
+
+ const numSegments = 2
+
+ // Write a counter with with multiple segments.
+ args := map[string]string{"argc": "1", "argv0": "prog.exe"}
+ allfuncs := [][]decodecounter.FuncPayload{}
+ ctrs := []uint32{}
+ q := uint32(0)
+ var cdfw *encodecounter.CoverageDataWriter
+ for idx := 0; idx < numSegments; idx++ {
+ args[fmt.Sprintf("seg%d", idx)] = "x"
+ q += 7
+ ctrs = append(ctrs, q)
+ funcs := []decodecounter.FuncPayload{}
+ for k := 0; k < idx+1; k++ {
+ c := make([]uint32, len(ctrs))
+ copy(c, ctrs)
+ funcs = append(funcs, mkfunc(uint32(idx), uint32(k), c))
+ }
+ allfuncs = append(allfuncs, funcs)
+
+ writeVisitor := &ctrVis{funcs: funcs}
+
+ if idx == 0 {
+ // Perform the encode and write.
+ cdfw = encodecounter.NewCoverageDataWriter(of, coverage.CtrRaw)
+ if cdfw == nil {
+ t.Fatalf("NewCoverageDataWriter failed")
+ }
+ finalHash := [16]byte{1, 2}
+ if err := cdfw.Write(finalHash, args, writeVisitor); err != nil {
+ t.Fatalf("counter file Write failed: %v", err)
+ }
+ } else {
+ if err := cdfw.AppendSegment(args, writeVisitor); err != nil {
+ t.Fatalf("counter file AppendSegment failed: %v", err)
+ }
+ }
+ }
+ if err := of.Close(); err != nil {
+ t.Fatalf("closing covcounters: %v", err)
+ }
+
+ // Read the result file.
+ var cdr *decodecounter.CounterDataReader
+ inf, err := os.Open(cfpath)
+ defer func() {
+ if err := inf.Close(); err != nil {
+ t.Fatalf("close failed with: %v", err)
+ }
+ }()
+
+ if err != nil {
+ t.Fatalf("reopening covcounters file: %v", err)
+ }
+ if cdr, err = decodecounter.NewCounterDataReader(cfpath, inf); err != nil {
+ t.Fatalf("opening covcounters for read: %v", err)
+ }
+ ns := cdr.NumSegments()
+ if ns != numSegments {
+ t.Fatalf("got %d segments want %d", ns, numSegments)
+ }
+ if len(allfuncs) != numSegments {
+ t.Fatalf("expected %d got %d", numSegments, len(allfuncs))
+ }
+
+ for sidx := 0; sidx < int(ns); sidx++ {
+ if off, err := inf.Seek(0, io.SeekCurrent); err != nil {
+ t.Fatalf("Seek failed: %v", err)
+ } else {
+ t.Logf("sidx=%d off=%d\n", sidx, off)
+ }
+
+ if sidx != 0 {
+ if ok, err := cdr.BeginNextSegment(); err != nil {
+ t.Fatalf("BeginNextSegment failed: %v", err)
+ } else if !ok {
+ t.Fatalf("BeginNextSegment return %v on iter %d",
+ ok, sidx)
+ }
+ }
+ funcs := allfuncs[sidx]
+ for i := range funcs {
+ var fp decodecounter.FuncPayload
+ if ok, err := cdr.NextFunc(&fp); err != nil {
+ t.Fatalf("reading func %d: %v", i, err)
+ } else if !ok {
+ t.Fatalf("reading func %d: bad return", i)
+ }
+ got := fmt.Sprintf("%+v", fp)
+ want := fmt.Sprintf("%+v", funcs[i])
+ if got != want {
+ t.Errorf("cdr.NextFunc iter %d\ngot %+v\nwant %+v", i, got, want)
+ }
+ }
+ }
+}