summaryrefslogtreecommitdiffstats
path: root/src/runtime/coverage/testdata
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/runtime/coverage/testdata
parentInitial commit. (diff)
downloadgolang-1.20-43a123c1ae6613b3efeed291fa552ecd909d3acf.tar.xz
golang-1.20-43a123c1ae6613b3efeed291fa552ecd909d3acf.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/runtime/coverage/testdata')
-rw-r--r--src/runtime/coverage/testdata/harness.go259
-rw-r--r--src/runtime/coverage/testdata/issue56006/repro.go26
-rw-r--r--src/runtime/coverage/testdata/issue56006/repro_test.go8
3 files changed, 293 insertions, 0 deletions
diff --git a/src/runtime/coverage/testdata/harness.go b/src/runtime/coverage/testdata/harness.go
new file mode 100644
index 0000000..5c87e4c
--- /dev/null
+++ b/src/runtime/coverage/testdata/harness.go
@@ -0,0 +1,259 @@
+// Copyright 2022 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 main
+
+import (
+ "flag"
+ "fmt"
+ "internal/coverage/slicewriter"
+ "io"
+ "io/ioutil"
+ "log"
+ "path/filepath"
+ "runtime/coverage"
+ "strings"
+)
+
+var verbflag = flag.Int("v", 0, "Verbose trace output level")
+var testpointflag = flag.String("tp", "", "Testpoint to run")
+var outdirflag = flag.String("o", "", "Output dir into which to emit")
+
+func emitToWriter() {
+ log.SetPrefix("emitToWriter: ")
+ var slwm slicewriter.WriteSeeker
+ if err := coverage.WriteMeta(&slwm); err != nil {
+ log.Fatalf("error: WriteMeta returns %v", err)
+ }
+ mf := filepath.Join(*outdirflag, "covmeta.0abcdef")
+ if err := ioutil.WriteFile(mf, slwm.BytesWritten(), 0666); err != nil {
+ log.Fatalf("error: writing %s: %v", mf, err)
+ }
+ var slwc slicewriter.WriteSeeker
+ if err := coverage.WriteCounters(&slwc); err != nil {
+ log.Fatalf("error: WriteCounters returns %v", err)
+ }
+ cf := filepath.Join(*outdirflag, "covcounters.0abcdef.99.77")
+ if err := ioutil.WriteFile(cf, slwc.BytesWritten(), 0666); err != nil {
+ log.Fatalf("error: writing %s: %v", cf, err)
+ }
+}
+
+func emitToDir() {
+ log.SetPrefix("emitToDir: ")
+ if err := coverage.WriteMetaDir(*outdirflag); err != nil {
+ log.Fatalf("error: WriteMetaDir returns %v", err)
+ }
+ if err := coverage.WriteCountersDir(*outdirflag); err != nil {
+ log.Fatalf("error: WriteCountersDir returns %v", err)
+ }
+}
+
+func emitToNonexistentDir() {
+ log.SetPrefix("emitToNonexistentDir: ")
+
+ want := []string{
+ "no such file or directory", // linux-ish
+ "system cannot find the file specified", // windows
+ "does not exist", // plan9
+ }
+
+ checkWant := func(which string, got string) {
+ found := false
+ for _, w := range want {
+ if strings.Contains(got, w) {
+ found = true
+ break
+ }
+ }
+ if !found {
+ log.Fatalf("%s emit to bad dir: got error:\n %v\nwanted error with one of:\n %+v", which, got, want)
+ }
+ }
+
+ // Mangle the output directory to produce something nonexistent.
+ mangled := *outdirflag + "_MANGLED"
+ if err := coverage.WriteMetaDir(mangled); err == nil {
+ log.Fatal("expected error from WriteMetaDir to nonexistent dir")
+ } else {
+ got := fmt.Sprintf("%v", err)
+ checkWant("meta data", got)
+ }
+
+ // Now try to emit counter data file to a bad dir.
+ if err := coverage.WriteCountersDir(mangled); err == nil {
+ log.Fatal("expected error emitting counter data to bad dir")
+ } else {
+ got := fmt.Sprintf("%v", err)
+ checkWant("counter data", got)
+ }
+}
+
+func emitToUnwritableDir() {
+ log.SetPrefix("emitToUnwritableDir: ")
+
+ want := "permission denied"
+
+ if err := coverage.WriteMetaDir(*outdirflag); err == nil {
+ log.Fatal("expected error from WriteMetaDir to unwritable dir")
+ } else {
+ got := fmt.Sprintf("%v", err)
+ if !strings.Contains(got, want) {
+ log.Fatalf("meta-data emit to unwritable dir: wanted error containing %q got %q", want, got)
+ }
+ }
+
+ // Similarly with writing counter data.
+ if err := coverage.WriteCountersDir(*outdirflag); err == nil {
+ log.Fatal("expected error emitting counter data to unwritable dir")
+ } else {
+ got := fmt.Sprintf("%v", err)
+ if !strings.Contains(got, want) {
+ log.Fatalf("emitting counter data to unwritable dir: wanted error containing %q got %q", want, got)
+ }
+ }
+}
+
+func emitToNilWriter() {
+ log.SetPrefix("emitToWriter: ")
+ want := "nil writer"
+ var bad io.WriteSeeker
+ if err := coverage.WriteMeta(bad); err == nil {
+ log.Fatal("expected error passing nil writer for meta emit")
+ } else {
+ got := fmt.Sprintf("%v", err)
+ if !strings.Contains(got, want) {
+ log.Fatalf("emitting meta-data passing nil writer: wanted error containing %q got %q", want, got)
+ }
+ }
+
+ if err := coverage.WriteCounters(bad); err == nil {
+ log.Fatal("expected error passing nil writer for counter emit")
+ } else {
+ got := fmt.Sprintf("%v", err)
+ if !strings.Contains(got, want) {
+ log.Fatalf("emitting counter data passing nil writer: wanted error containing %q got %q", want, got)
+ }
+ }
+}
+
+type failingWriter struct {
+ writeCount int
+ writeLimit int
+ slws slicewriter.WriteSeeker
+}
+
+func (f *failingWriter) Write(p []byte) (n int, err error) {
+ c := f.writeCount
+ f.writeCount++
+ if f.writeLimit < 0 || c < f.writeLimit {
+ return f.slws.Write(p)
+ }
+ return 0, fmt.Errorf("manufactured write error")
+}
+
+func (f *failingWriter) Seek(offset int64, whence int) (int64, error) {
+ return f.slws.Seek(offset, whence)
+}
+
+func (f *failingWriter) reset(lim int) {
+ f.writeCount = 0
+ f.writeLimit = lim
+ f.slws = slicewriter.WriteSeeker{}
+}
+
+func writeStressTest(tag string, testf func(testf *failingWriter) error) {
+ // Invoke the function initially without the write limit
+ // set, to capture the number of writes performed.
+ fw := &failingWriter{writeLimit: -1}
+ testf(fw)
+
+ // Now that we know how many writes are going to happen, run the
+ // function repeatedly, each time with a Write operation set to
+ // fail at a new spot. The goal here is to make sure that:
+ // A) an error is reported, and B) nothing crashes.
+ tot := fw.writeCount
+ for i := 0; i < tot; i++ {
+ fw.reset(i)
+ err := testf(fw)
+ if err == nil {
+ log.Fatalf("no error from write %d tag %s", i, tag)
+ }
+ }
+}
+
+func postClear() int {
+ return 42
+}
+
+func preClear() int {
+ return 42
+}
+
+// This test is designed to ensure that write errors are properly
+// handled by the code that writes out coverage data. It repeatedly
+// invokes the 'emit to writer' apis using a specially crafted writer
+// that captures the total number of expected writes, then replays the
+// execution N times with a manufactured write error at the
+// appropriate spot.
+func emitToFailingWriter() {
+ log.SetPrefix("emitToFailingWriter: ")
+
+ writeStressTest("emit-meta", func(f *failingWriter) error {
+ return coverage.WriteMeta(f)
+ })
+ writeStressTest("emit-counter", func(f *failingWriter) error {
+ return coverage.WriteCounters(f)
+ })
+}
+
+func emitWithCounterClear() {
+ log.SetPrefix("emitWitCounterClear: ")
+ preClear()
+ if err := coverage.ClearCounters(); err != nil {
+ log.Fatalf("clear failed: %v", err)
+ }
+ postClear()
+ if err := coverage.WriteMetaDir(*outdirflag); err != nil {
+ log.Fatalf("error: WriteMetaDir returns %v", err)
+ }
+ if err := coverage.WriteCountersDir(*outdirflag); err != nil {
+ log.Fatalf("error: WriteCountersDir returns %v", err)
+ }
+}
+
+func final() int {
+ println("I run last.")
+ return 43
+}
+
+func main() {
+ log.SetFlags(0)
+ flag.Parse()
+ if *testpointflag == "" {
+ log.Fatalf("error: no testpoint (use -tp flag)")
+ }
+ if *outdirflag == "" {
+ log.Fatalf("error: no output dir specified (use -o flag)")
+ }
+ switch *testpointflag {
+ case "emitToDir":
+ emitToDir()
+ case "emitToWriter":
+ emitToWriter()
+ case "emitToNonexistentDir":
+ emitToNonexistentDir()
+ case "emitToUnwritableDir":
+ emitToUnwritableDir()
+ case "emitToNilWriter":
+ emitToNilWriter()
+ case "emitToFailingWriter":
+ emitToFailingWriter()
+ case "emitWithCounterClear":
+ emitWithCounterClear()
+ default:
+ log.Fatalf("error: unknown testpoint %q", *testpointflag)
+ }
+ final()
+}
diff --git a/src/runtime/coverage/testdata/issue56006/repro.go b/src/runtime/coverage/testdata/issue56006/repro.go
new file mode 100644
index 0000000..60a4925
--- /dev/null
+++ b/src/runtime/coverage/testdata/issue56006/repro.go
@@ -0,0 +1,26 @@
+package main
+
+//go:noinline
+func blah(x int) int {
+ if x != 0 {
+ return x + 42
+ }
+ return x - 42
+}
+
+func main() {
+ go infloop()
+ println(blah(1) + blah(0))
+}
+
+var G int
+
+func infloop() {
+ for {
+ G += blah(1)
+ G += blah(0)
+ if G > 10000 {
+ G = 0
+ }
+ }
+}
diff --git a/src/runtime/coverage/testdata/issue56006/repro_test.go b/src/runtime/coverage/testdata/issue56006/repro_test.go
new file mode 100644
index 0000000..674d819
--- /dev/null
+++ b/src/runtime/coverage/testdata/issue56006/repro_test.go
@@ -0,0 +1,8 @@
+package main
+
+import "testing"
+
+func TestSomething(t *testing.T) {
+ go infloop()
+ println(blah(1) + blah(0))
+}