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 }