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

View as plain text