Source file src/internal/coverage/pods/pods_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 pods_test
     6  
     7  import (
     8  	"fmt"
     9  	"hash/fnv"
    10  	"internal/coverage"
    11  	"internal/coverage/pods"
    12  	"os"
    13  	"path/filepath"
    14  	"runtime"
    15  	"testing"
    16  )
    17  
    18  func TestPodCollection(t *testing.T) {
    19  	//testenv.MustHaveGoBuild(t)
    20  
    21  	mkdir := func(d string, perm os.FileMode) string {
    22  		dp := filepath.Join(t.TempDir(), d)
    23  		if err := os.Mkdir(dp, perm); err != nil {
    24  			t.Fatal(err)
    25  		}
    26  		return dp
    27  	}
    28  
    29  	mkfile := func(d string, fn string) string {
    30  		fp := filepath.Join(d, fn)
    31  		if err := os.WriteFile(fp, []byte("foo"), 0666); err != nil {
    32  			t.Fatal(err)
    33  		}
    34  		return fp
    35  	}
    36  
    37  	mkmeta := func(dir string, tag string) string {
    38  		h := fnv.New128a()
    39  		h.Write([]byte(tag))
    40  		hash := h.Sum(nil)
    41  		fn := fmt.Sprintf("%s.%x", coverage.MetaFilePref, hash)
    42  		return mkfile(dir, fn)
    43  	}
    44  
    45  	mkcounter := func(dir string, tag string, nt int, pid int) string {
    46  		h := fnv.New128a()
    47  		h.Write([]byte(tag))
    48  		hash := h.Sum(nil)
    49  		fn := fmt.Sprintf(coverage.CounterFileTempl, coverage.CounterFilePref, hash, pid, nt)
    50  		return mkfile(dir, fn)
    51  	}
    52  
    53  	trim := func(path string) string {
    54  		b := filepath.Base(path)
    55  		d := filepath.Dir(path)
    56  		db := filepath.Base(d)
    57  		return db + "/" + b
    58  	}
    59  
    60  	podToString := func(p pods.Pod) string {
    61  		rv := trim(p.MetaFile) + " [\n"
    62  		for k, df := range p.CounterDataFiles {
    63  			rv += trim(df)
    64  			if p.Origins != nil {
    65  				rv += fmt.Sprintf(" o:%d", p.Origins[k])
    66  			}
    67  			rv += "\n"
    68  		}
    69  		return rv + "]"
    70  	}
    71  
    72  	// Create a couple of directories.
    73  	o1 := mkdir("o1", 0777)
    74  	o2 := mkdir("o2", 0777)
    75  
    76  	// Add some random files (not coverage related)
    77  	mkfile(o1, "blah.txt")
    78  	mkfile(o1, "something.exe")
    79  
    80  	// Add a meta-data file with two counter files to first dir.
    81  	mkmeta(o1, "m1")
    82  	mkcounter(o1, "m1", 1, 42)
    83  	mkcounter(o1, "m1", 2, 41)
    84  	mkcounter(o1, "m1", 2, 40)
    85  
    86  	// Add a counter file with no associated meta file.
    87  	mkcounter(o1, "orphan", 9, 39)
    88  
    89  	// Add a meta-data file with three counter files to second dir.
    90  	mkmeta(o2, "m2")
    91  	mkcounter(o2, "m2", 1, 38)
    92  	mkcounter(o2, "m2", 2, 37)
    93  	mkcounter(o2, "m2", 3, 36)
    94  
    95  	// Add a duplicate of the first meta-file and a corresponding
    96  	// counter file to the second dir. This is intended to capture
    97  	// the scenario where we have two different runs of the same
    98  	// coverage-instrumented binary, but with the output files
    99  	// sent to separate directories.
   100  	mkmeta(o2, "m1")
   101  	mkcounter(o2, "m1", 11, 35)
   102  
   103  	// Collect pods.
   104  	podlist, err := pods.CollectPods([]string{o1, o2}, true)
   105  	if err != nil {
   106  		t.Fatal(err)
   107  	}
   108  
   109  	// Verify pods
   110  	if len(podlist) != 2 {
   111  		t.Fatalf("expected 2 pods got %d pods", len(podlist))
   112  	}
   113  
   114  	for k, p := range podlist {
   115  		t.Logf("%d: mf=%s\n", k, p.MetaFile)
   116  	}
   117  
   118  	expected := []string{
   119  		`o1/covmeta.0880952782ab1be95aa0733055a4d06b [
   120  o1/covcounters.0880952782ab1be95aa0733055a4d06b.40.2 o:0
   121  o1/covcounters.0880952782ab1be95aa0733055a4d06b.41.2 o:0
   122  o1/covcounters.0880952782ab1be95aa0733055a4d06b.42.1 o:0
   123  o2/covcounters.0880952782ab1be95aa0733055a4d06b.35.11 o:1
   124  ]`,
   125  		`o2/covmeta.0880952783ab1be95aa0733055a4d1a6 [
   126  o2/covcounters.0880952783ab1be95aa0733055a4d1a6.36.3 o:1
   127  o2/covcounters.0880952783ab1be95aa0733055a4d1a6.37.2 o:1
   128  o2/covcounters.0880952783ab1be95aa0733055a4d1a6.38.1 o:1
   129  ]`,
   130  	}
   131  	for k, exp := range expected {
   132  		got := podToString(podlist[k])
   133  		if exp != got {
   134  			t.Errorf("pod %d: expected:\n%s\ngot:\n%s", k, exp, got)
   135  		}
   136  	}
   137  
   138  	// Check handling of bad/unreadable dir.
   139  	if runtime.GOOS == "linux" {
   140  		dbad := "/dev/null"
   141  		_, err = pods.CollectPods([]string{dbad}, true)
   142  		if err == nil {
   143  			t.Errorf("executed error due to unreadable dir")
   144  		}
   145  	}
   146  }
   147  

View as plain text