diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 19:23:18 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 19:23:18 +0000 |
commit | 43a123c1ae6613b3efeed291fa552ecd909d3acf (patch) | |
tree | fd92518b7024bc74031f78a1cf9e454b65e73665 /src/internal/coverage/test/roundtrip_test.go | |
parent | Initial commit. (diff) | |
download | golang-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/roundtrip_test.go')
-rw-r--r-- | src/internal/coverage/test/roundtrip_test.go | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/src/internal/coverage/test/roundtrip_test.go b/src/internal/coverage/test/roundtrip_test.go new file mode 100644 index 0000000..614f56e --- /dev/null +++ b/src/internal/coverage/test/roundtrip_test.go @@ -0,0 +1,331 @@ +// 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/decodemeta" + "internal/coverage/encodemeta" + "internal/coverage/slicewriter" + "io" + "os" + "path/filepath" + "testing" +) + +func cmpFuncDesc(want, got coverage.FuncDesc) string { + swant := fmt.Sprintf("%+v", want) + sgot := fmt.Sprintf("%+v", got) + if swant == sgot { + return "" + } + return fmt.Sprintf("wanted %q got %q", swant, sgot) +} + +func TestMetaDataEmptyPackage(t *testing.T) { + // Make sure that encoding/decoding works properly with packages + // that don't actually have any functions. + p := "empty/package" + pn := "package" + mp := "m" + b, err := encodemeta.NewCoverageMetaDataBuilder(p, pn, mp) + if err != nil { + t.Fatalf("making builder: %v", err) + } + drws := &slicewriter.WriteSeeker{} + b.Emit(drws) + drws.Seek(0, io.SeekStart) + dec, err := decodemeta.NewCoverageMetaDataDecoder(drws.BytesWritten(), false) + if err != nil { + t.Fatalf("making decoder: %v", err) + } + nf := dec.NumFuncs() + if nf != 0 { + t.Errorf("dec.NumFuncs(): got %d want %d", nf, 0) + } + pp := dec.PackagePath() + if pp != p { + t.Errorf("dec.PackagePath(): got %s want %s", pp, p) + } + ppn := dec.PackageName() + if ppn != pn { + t.Errorf("dec.PackageName(): got %s want %s", ppn, pn) + } + pmp := dec.ModulePath() + if pmp != mp { + t.Errorf("dec.ModulePath(): got %s want %s", pmp, mp) + } +} + +func TestMetaDataEncoderDecoder(t *testing.T) { + // Test encode path. + pp := "foo/bar/pkg" + pn := "pkg" + mp := "barmod" + b, err := encodemeta.NewCoverageMetaDataBuilder(pp, pn, mp) + if err != nil { + t.Fatalf("making builder: %v", err) + } + f1 := coverage.FuncDesc{ + Funcname: "func", + Srcfile: "foo.go", + Units: []coverage.CoverableUnit{ + coverage.CoverableUnit{StLine: 1, StCol: 2, EnLine: 3, EnCol: 4, NxStmts: 5}, + coverage.CoverableUnit{StLine: 6, StCol: 7, EnLine: 8, EnCol: 9, NxStmts: 10}, + }, + } + idx := b.AddFunc(f1) + if idx != 0 { + t.Errorf("b.AddFunc(f1) got %d want %d", idx, 0) + } + + f2 := coverage.FuncDesc{ + Funcname: "xfunc", + Srcfile: "bar.go", + Units: []coverage.CoverableUnit{ + coverage.CoverableUnit{StLine: 1, StCol: 2, EnLine: 3, EnCol: 4, NxStmts: 5}, + coverage.CoverableUnit{StLine: 6, StCol: 7, EnLine: 8, EnCol: 9, NxStmts: 10}, + coverage.CoverableUnit{StLine: 11, StCol: 12, EnLine: 13, EnCol: 14, NxStmts: 15}, + }, + } + idx = b.AddFunc(f2) + if idx != 1 { + t.Errorf("b.AddFunc(f2) got %d want %d", idx, 0) + } + + // Emit into a writer. + drws := &slicewriter.WriteSeeker{} + b.Emit(drws) + + // Test decode path. + drws.Seek(0, io.SeekStart) + dec, err := decodemeta.NewCoverageMetaDataDecoder(drws.BytesWritten(), false) + if err != nil { + t.Fatalf("NewCoverageMetaDataDecoder error: %v", err) + } + nf := dec.NumFuncs() + if nf != 2 { + t.Errorf("dec.NumFuncs(): got %d want %d", nf, 2) + } + + gotpp := dec.PackagePath() + if gotpp != pp { + t.Errorf("packagepath: got %s want %s", gotpp, pp) + } + gotpn := dec.PackageName() + if gotpn != pn { + t.Errorf("packagename: got %s want %s", gotpn, pn) + } + + cases := []coverage.FuncDesc{f1, f2} + for i := uint32(0); i < uint32(len(cases)); i++ { + var fn coverage.FuncDesc + if err := dec.ReadFunc(i, &fn); err != nil { + t.Fatalf("err reading function %d: %v", i, err) + } + res := cmpFuncDesc(cases[i], fn) + if res != "" { + t.Errorf("ReadFunc(%d): %s", i, res) + } + } +} + +func createFuncs(i int) []coverage.FuncDesc { + res := []coverage.FuncDesc{} + lc := uint32(1) + for fi := 0; fi < i+1; fi++ { + units := []coverage.CoverableUnit{} + for ui := 0; ui < (fi+1)*(i+1); ui++ { + units = append(units, + coverage.CoverableUnit{StLine: lc, StCol: lc + 1, + EnLine: lc + 2, EnCol: lc + 3, NxStmts: lc + 4, + }) + lc += 5 + } + f := coverage.FuncDesc{ + Funcname: fmt.Sprintf("func_%d_%d", i, fi), + Srcfile: fmt.Sprintf("foo_%d.go", i), + Units: units, + } + res = append(res, f) + } + return res +} + +func createBlob(t *testing.T, i int) []byte { + nomodule := "" + b, err := encodemeta.NewCoverageMetaDataBuilder("foo/pkg", "pkg", nomodule) + if err != nil { + t.Fatalf("making builder: %v", err) + } + + funcs := createFuncs(i) + for _, f := range funcs { + b.AddFunc(f) + } + drws := &slicewriter.WriteSeeker{} + b.Emit(drws) + return drws.BytesWritten() +} + +func createMetaDataBlobs(t *testing.T, nb int) [][]byte { + res := [][]byte{} + for i := 0; i < nb; i++ { + res = append(res, createBlob(t, i)) + } + return res +} + +func TestMetaDataWriterReader(t *testing.T) { + d := t.TempDir() + + // Emit a meta-file... + mfpath := filepath.Join(d, "covmeta.hash.0") + of, err := os.OpenFile(mfpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) + if err != nil { + t.Fatalf("opening covmeta: %v", err) + } + //t.Logf("meta-file path is %s", mfpath) + blobs := createMetaDataBlobs(t, 7) + gran := coverage.CtrGranularityPerBlock + mfw := encodemeta.NewCoverageMetaFileWriter(mfpath, of) + finalHash := [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} + err = mfw.Write(finalHash, blobs, coverage.CtrModeAtomic, gran) + if err != nil { + t.Fatalf("writing meta-file: %v", err) + } + if err = of.Close(); err != nil { + t.Fatalf("closing meta-file: %v", err) + } + + // ... then read it back in, first time without setting fileView, + // second time setting it. + for k := 0; k < 2; k++ { + var fileView []byte + + inf, err := os.Open(mfpath) + if err != nil { + t.Fatalf("open() on meta-file: %v", err) + } + + if k != 0 { + // Use fileview to exercise different paths in reader. + fi, err := os.Stat(mfpath) + if err != nil { + t.Fatalf("stat() on meta-file: %v", err) + } + fileView = make([]byte, fi.Size()) + if _, err := inf.Read(fileView); err != nil { + t.Fatalf("read() on meta-file: %v", err) + } + if _, err := inf.Seek(int64(0), io.SeekStart); err != nil { + t.Fatalf("seek() on meta-file: %v", err) + } + } + + mfr, err := decodemeta.NewCoverageMetaFileReader(inf, fileView) + if err != nil { + t.Fatalf("k=%d NewCoverageMetaFileReader failed with: %v", k, err) + } + np := mfr.NumPackages() + if np != 7 { + t.Fatalf("k=%d wanted 7 packages got %d", k, np) + } + md := mfr.CounterMode() + wmd := coverage.CtrModeAtomic + if md != wmd { + t.Fatalf("k=%d wanted mode %d got %d", k, wmd, md) + } + gran := mfr.CounterGranularity() + wgran := coverage.CtrGranularityPerBlock + if gran != wgran { + t.Fatalf("k=%d wanted gran %d got %d", k, wgran, gran) + } + + payload := []byte{} + for pi := 0; pi < int(np); pi++ { + var pd *decodemeta.CoverageMetaDataDecoder + var err error + pd, payload, err = mfr.GetPackageDecoder(uint32(pi), payload) + if err != nil { + t.Fatalf("GetPackageDecoder(%d) failed with: %v", pi, err) + } + efuncs := createFuncs(pi) + nf := pd.NumFuncs() + if len(efuncs) != int(nf) { + t.Fatalf("decoding pk %d wanted %d funcs got %d", + pi, len(efuncs), nf) + } + var f coverage.FuncDesc + for fi := 0; fi < int(nf); fi++ { + if err := pd.ReadFunc(uint32(fi), &f); err != nil { + t.Fatalf("ReadFunc(%d) pk %d got error %v", + fi, pi, err) + } + res := cmpFuncDesc(efuncs[fi], f) + if res != "" { + t.Errorf("ReadFunc(%d) pk %d: %s", fi, pi, res) + } + } + } + inf.Close() + } +} + +func TestMetaDataDecodeLitFlagIssue57942(t *testing.T) { + + // Encode a package with a few functions. The funcs alternate + // between regular functions and function literals. + pp := "foo/bar/pkg" + pn := "pkg" + mp := "barmod" + b, err := encodemeta.NewCoverageMetaDataBuilder(pp, pn, mp) + if err != nil { + t.Fatalf("making builder: %v", err) + } + const NF = 6 + const NCU = 1 + ln := uint32(10) + wantfds := []coverage.FuncDesc{} + for fi := uint32(0); fi < NF; fi++ { + fis := fmt.Sprintf("%d", fi) + fd := coverage.FuncDesc{ + Funcname: "func" + fis, + Srcfile: "foo" + fis + ".go", + Units: []coverage.CoverableUnit{ + coverage.CoverableUnit{StLine: ln + 1, StCol: 2, EnLine: ln + 3, EnCol: 4, NxStmts: fi + 2}, + }, + Lit: (fi % 2) == 0, + } + wantfds = append(wantfds, fd) + b.AddFunc(fd) + } + + // Emit into a writer. + drws := &slicewriter.WriteSeeker{} + b.Emit(drws) + + // Decode the result. + drws.Seek(0, io.SeekStart) + dec, err := decodemeta.NewCoverageMetaDataDecoder(drws.BytesWritten(), false) + if err != nil { + t.Fatalf("making decoder: %v", err) + } + nf := dec.NumFuncs() + if nf != NF { + t.Fatalf("decoder number of functions: got %d want %d", nf, NF) + } + var fn coverage.FuncDesc + for i := uint32(0); i < uint32(NF); i++ { + if err := dec.ReadFunc(i, &fn); err != nil { + t.Fatalf("err reading function %d: %v", i, err) + } + res := cmpFuncDesc(wantfds[i], fn) + if res != "" { + t.Errorf("ReadFunc(%d): %s", i, res) + } + } +} |