diff options
Diffstat (limited to 'src/runtime/coverage/ts_test.go')
-rw-r--r-- | src/runtime/coverage/ts_test.go | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/src/runtime/coverage/ts_test.go b/src/runtime/coverage/ts_test.go new file mode 100644 index 0000000..b4c6e97 --- /dev/null +++ b/src/runtime/coverage/ts_test.go @@ -0,0 +1,207 @@ +// 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 coverage + +import ( + "encoding/json" + "internal/coverage" + "internal/goexperiment" + "internal/testenv" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" + _ "unsafe" +) + +//go:linkname testing_testGoCoverDir testing.testGoCoverDir +func testing_testGoCoverDir() string + +func testGoCoverDir(t *testing.T) string { + tgcd := testing_testGoCoverDir() + if tgcd != "" { + return tgcd + } + return t.TempDir() +} + +// TestTestSupport does a basic verification of the functionality in +// runtime/coverage.processCoverTestDir (doing this here as opposed to +// relying on other test paths will provide a better signal when +// running "go test -cover" for this package). +func TestTestSupport(t *testing.T) { + if !goexperiment.CoverageRedesign { + return + } + if testing.CoverMode() == "" { + return + } + tgcd := testGoCoverDir(t) + t.Logf("testing.testGoCoverDir() returns %s mode=%s\n", + tgcd, testing.CoverMode()) + + textfile := filepath.Join(t.TempDir(), "file.txt") + var sb strings.Builder + err := processCoverTestDirInternal(tgcd, textfile, + testing.CoverMode(), "", &sb) + if err != nil { + t.Fatalf("bad: %v", err) + } + + // Check for existence of text file. + if inf, err := os.Open(textfile); err != nil { + t.Fatalf("problems opening text file %s: %v", textfile, err) + } else { + inf.Close() + } + + // Check for percent output with expected tokens. + strout := sb.String() + want := "of statements" + if !strings.Contains(strout, want) { + t.Logf("output from run: %s\n", strout) + t.Fatalf("percent output missing token: %q", want) + } +} + +var funcInvoked bool + +//go:noinline +func thisFunctionOnlyCalledFromSnapshotTest(n int) int { + if funcInvoked { + panic("bad") + } + funcInvoked = true + + // Contents here not especially important, just so long as we + // have some statements. + t := 0 + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + t += i ^ j + } + } + return t +} + +// Tests runtime/coverage.snapshot() directly. Note that if +// coverage is not enabled, the hook is designed to just return +// zero. +func TestCoverageSnapshot(t *testing.T) { + C1 := snapshot() + thisFunctionOnlyCalledFromSnapshotTest(15) + C2 := snapshot() + cond := "C1 > C2" + val := C1 > C2 + if testing.CoverMode() != "" { + cond = "C1 >= C2" + val = C1 >= C2 + } + t.Logf("%f %f\n", C1, C2) + if val { + t.Errorf("erroneous snapshots, %s = true C1=%f C2=%f", + cond, C1, C2) + } +} + +const hellogo = ` +package main + +func main() { + println("hello") +} +` + +// Returns a pair F,T where F is a meta-data file generated from +// "hello.go" above, and T is a token to look for that should be +// present in the coverage report from F. +func genAuxMeta(t *testing.T, dstdir string) (string, string) { + // Do a GOCOVERDIR=<tmp> go run hello.go + src := filepath.Join(dstdir, "hello.go") + if err := os.WriteFile(src, []byte(hellogo), 0777); err != nil { + t.Fatalf("write failed: %v", err) + } + args := []string{"run", "-covermode=" + testing.CoverMode(), src} + cmd := exec.Command(testenv.GoToolPath(t), args...) + cmd.Env = updateGoCoverDir(os.Environ(), dstdir, true) + if b, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("go run failed (%v): %s", err, b) + } + + // Pick out the generated meta-data file. + files, err := os.ReadDir(dstdir) + if err != nil { + t.Fatalf("reading %s: %v", dstdir, err) + } + for _, f := range files { + if strings.HasPrefix(f.Name(), "covmeta") { + return filepath.Join(dstdir, f.Name()), "hello.go:" + } + } + t.Fatalf("could not locate generated meta-data file") + return "", "" +} + +func TestAuxMetaDataFiles(t *testing.T) { + if !goexperiment.CoverageRedesign { + return + } + if testing.CoverMode() == "" { + return + } + testenv.MustHaveGoRun(t) + tgcd := testGoCoverDir(t) + t.Logf("testing.testGoCoverDir() returns %s mode=%s\n", + tgcd, testing.CoverMode()) + + td := t.TempDir() + + // Manufacture a new, separate meta-data file not related to this + // test. Contents are not important, just so long as the + // packages/paths are different. + othermetadir := filepath.Join(td, "othermeta") + if err := os.Mkdir(othermetadir, 0777); err != nil { + t.Fatalf("mkdir failed: %v", err) + } + mfile, token := genAuxMeta(t, othermetadir) + + // Write a metafiles file. + metafiles := filepath.Join(tgcd, coverage.MetaFilesFileName) + mfc := coverage.MetaFileCollection{ + ImportPaths: []string{"command-line-arguments"}, + MetaFileFragments: []string{mfile}, + } + jdata, err := json.Marshal(mfc) + if err != nil { + t.Fatalf("marshal MetaFileCollection: %v", err) + } + if err := os.WriteFile(metafiles, jdata, 0666); err != nil { + t.Fatalf("write failed: %v", err) + } + + // Kick off guts of test. + var sb strings.Builder + textfile := filepath.Join(td, "file2.txt") + err = processCoverTestDirInternal(tgcd, textfile, + testing.CoverMode(), "", &sb) + if err != nil { + t.Fatalf("bad: %v", err) + } + if err = os.Remove(metafiles); err != nil { + t.Fatalf("removing metafiles file: %v", err) + } + + // Look for the expected things in the coverage profile. + contents, err := os.ReadFile(textfile) + strc := string(contents) + if err != nil { + t.Fatalf("problems reading text file %s: %v", textfile, err) + } + if !strings.Contains(strc, token) { + t.Logf("content: %s\n", string(contents)) + t.Fatalf("cov profile does not contain aux meta content %q", token) + } +} |