github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/coverage/pods/pods_test.go (about)

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