Source file src/internal/coverage/cfile/ts_test.go

     1  // Copyright 2022 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package cfile
     6  
     7  import (
     8  	"encoding/json"
     9  	"flag"
    10  	"internal/coverage"
    11  	"internal/goexperiment"
    12  	"internal/testenv"
    13  	"os"
    14  	"os/exec"
    15  	"path/filepath"
    16  	"strings"
    17  	"testing"
    18  	_ "unsafe"
    19  )
    20  
    21  func testGoCoverDir(t *testing.T) string {
    22  	if f := flag.Lookup("test.gocoverdir"); f != nil {
    23  		if dir := f.Value.String(); dir != "" {
    24  			return dir
    25  		}
    26  	}
    27  	return t.TempDir()
    28  }
    29  
    30  // TestTestSupport does a basic verification of the functionality in
    31  // ProcessCoverTestDir (doing this here as opposed to
    32  // relying on other test paths will provide a better signal when
    33  // running "go test -cover" for this package).
    34  func TestTestSupport(t *testing.T) {
    35  	if !goexperiment.CoverageRedesign {
    36  		return
    37  	}
    38  	if testing.CoverMode() == "" {
    39  		return
    40  	}
    41  	tgcd := testGoCoverDir(t)
    42  	t.Logf("testing.testGoCoverDir() returns %s mode=%s\n",
    43  		tgcd, testing.CoverMode())
    44  
    45  	textfile := filepath.Join(t.TempDir(), "file.txt")
    46  	var sb strings.Builder
    47  	err := ProcessCoverTestDir(tgcd, textfile,
    48  		testing.CoverMode(), "", &sb, nil)
    49  	if err != nil {
    50  		t.Fatalf("bad: %v", err)
    51  	}
    52  
    53  	// Check for existence of text file.
    54  	if inf, err := os.Open(textfile); err != nil {
    55  		t.Fatalf("problems opening text file %s: %v", textfile, err)
    56  	} else {
    57  		inf.Close()
    58  	}
    59  
    60  	// Check for percent output with expected tokens.
    61  	strout := sb.String()
    62  	want := "of statements"
    63  	if !strings.Contains(strout, want) {
    64  		t.Logf("output from run: %s\n", strout)
    65  		t.Fatalf("percent output missing token: %q", want)
    66  	}
    67  }
    68  
    69  // Kicks off a sub-test to verify that Snapshot() works properly.
    70  // We do this as a separate shell-out, so as to avoid potential
    71  // interactions with -coverpkg. For example, if you do
    72  //
    73  //	$ cd `go env GOROOT`
    74  //	$ cd src/internal/coverage
    75  //	$ go test -coverpkg=internal/coverage/decodecounter ./...
    76  //	...
    77  //	$
    78  //
    79  // The previous version of this test could fail due to the fact
    80  // that "cfile" itself was not being instrumented, as in the
    81  // scenario above.
    82  func TestCoverageSnapshot(t *testing.T) {
    83  	testenv.MustHaveGoRun(t)
    84  	args := []string{"test", "-tags", "SELECT_USING_THIS_TAG",
    85  		"-cover", "-run=TestCoverageSnapshotImpl", "internal/coverage/cfile"}
    86  	cmd := exec.Command(testenv.GoToolPath(t), args...)
    87  	if b, err := cmd.CombinedOutput(); err != nil {
    88  		t.Fatalf("go test failed (%v): %s", err, b)
    89  	}
    90  }
    91  
    92  const hellogo = `
    93  package main
    94  
    95  func main() {
    96    println("hello")
    97  }
    98  `
    99  
   100  // Returns a pair F,T where F is a meta-data file generated from
   101  // "hello.go" above, and T is a token to look for that should be
   102  // present in the coverage report from F.
   103  func genAuxMeta(t *testing.T, dstdir string) (string, string) {
   104  	// Do a GOCOVERDIR=<tmp> go run hello.go
   105  	src := filepath.Join(dstdir, "hello.go")
   106  	if err := os.WriteFile(src, []byte(hellogo), 0777); err != nil {
   107  		t.Fatalf("write failed: %v", err)
   108  	}
   109  	args := []string{"run", "-covermode=" + testing.CoverMode(), src}
   110  	cmd := exec.Command(testenv.GoToolPath(t), args...)
   111  	cmd.Env = updateGoCoverDir(os.Environ(), dstdir, true)
   112  	if b, err := cmd.CombinedOutput(); err != nil {
   113  		t.Fatalf("go run failed (%v): %s", err, b)
   114  	}
   115  
   116  	// Pick out the generated meta-data file.
   117  	files, err := os.ReadDir(dstdir)
   118  	if err != nil {
   119  		t.Fatalf("reading %s: %v", dstdir, err)
   120  	}
   121  	for _, f := range files {
   122  		if strings.HasPrefix(f.Name(), "covmeta") {
   123  			return filepath.Join(dstdir, f.Name()), "hello.go:"
   124  		}
   125  	}
   126  	t.Fatalf("could not locate generated meta-data file")
   127  	return "", ""
   128  }
   129  
   130  func TestAuxMetaDataFiles(t *testing.T) {
   131  	if !goexperiment.CoverageRedesign {
   132  		return
   133  	}
   134  	if testing.CoverMode() == "" {
   135  		return
   136  	}
   137  	testenv.MustHaveGoRun(t)
   138  	tgcd := testGoCoverDir(t)
   139  	t.Logf("testing.testGoCoverDir() returns %s mode=%s\n",
   140  		tgcd, testing.CoverMode())
   141  
   142  	td := t.TempDir()
   143  
   144  	// Manufacture a new, separate meta-data file not related to this
   145  	// test. Contents are not important, just so long as the
   146  	// packages/paths are different.
   147  	othermetadir := filepath.Join(td, "othermeta")
   148  	if err := os.Mkdir(othermetadir, 0777); err != nil {
   149  		t.Fatalf("mkdir failed: %v", err)
   150  	}
   151  	mfile, token := genAuxMeta(t, othermetadir)
   152  
   153  	// Write a metafiles file.
   154  	metafiles := filepath.Join(tgcd, coverage.MetaFilesFileName)
   155  	mfc := coverage.MetaFileCollection{
   156  		ImportPaths:       []string{"command-line-arguments"},
   157  		MetaFileFragments: []string{mfile},
   158  	}
   159  	jdata, err := json.Marshal(mfc)
   160  	if err != nil {
   161  		t.Fatalf("marshal MetaFileCollection: %v", err)
   162  	}
   163  	if err := os.WriteFile(metafiles, jdata, 0666); err != nil {
   164  		t.Fatalf("write failed: %v", err)
   165  	}
   166  
   167  	// Kick off guts of test.
   168  	var sb strings.Builder
   169  	textfile := filepath.Join(td, "file2.txt")
   170  	err = ProcessCoverTestDir(tgcd, textfile,
   171  		testing.CoverMode(), "", &sb, nil)
   172  	if err != nil {
   173  		t.Fatalf("bad: %v", err)
   174  	}
   175  	if err = os.Remove(metafiles); err != nil {
   176  		t.Fatalf("removing metafiles file: %v", err)
   177  	}
   178  
   179  	// Look for the expected things in the coverage profile.
   180  	contents, err := os.ReadFile(textfile)
   181  	strc := string(contents)
   182  	if err != nil {
   183  		t.Fatalf("problems reading text file %s: %v", textfile, err)
   184  	}
   185  	if !strings.Contains(strc, token) {
   186  		t.Logf("content: %s\n", string(contents))
   187  		t.Fatalf("cov profile does not contain aux meta content %q", token)
   188  	}
   189  }
   190  

View as plain text