github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/cmd/callgraph/main_test.go (about) 1 // Copyright 2014 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 // No testdata on Android. 6 7 //go:build !android && go1.11 8 // +build !android,go1.11 9 10 package main 11 12 import ( 13 "bytes" 14 "fmt" 15 "log" 16 "os" 17 "path/filepath" 18 "runtime" 19 "strings" 20 "testing" 21 22 "golang.org/x/tools/internal/testenv" 23 ) 24 25 func init() { 26 // This test currently requires GOPATH mode. 27 // Explicitly disabling module mode should suffix, but 28 // we'll also turn off GOPROXY just for good measure. 29 if err := os.Setenv("GO111MODULE", "off"); err != nil { 30 log.Fatal(err) 31 } 32 if err := os.Setenv("GOPROXY", "off"); err != nil { 33 log.Fatal(err) 34 } 35 } 36 37 func TestCallgraph(t *testing.T) { 38 if runtime.GOOS == "windows" && runtime.GOARCH == "arm64" { 39 t.Skipf("skipping due to suspected file corruption bug on windows/arm64 (https://go.dev/issue/50706)") 40 } 41 42 testenv.NeedsTool(t, "go") 43 44 gopath, err := filepath.Abs("testdata") 45 if err != nil { 46 t.Fatal(err) 47 } 48 49 for _, test := range []struct { 50 algo string 51 tests bool 52 want []string 53 }{ 54 {"rta", false, []string{ 55 // rta imprecisely shows cross product of {main,main2} x {C,D} 56 `pkg.main --> (pkg.C).f`, 57 `pkg.main --> (pkg.D).f`, 58 `pkg.main --> pkg.main2`, 59 `pkg.main2 --> (pkg.C).f`, 60 `pkg.main2 --> (pkg.D).f`, 61 }}, 62 {"vta", false, []string{ 63 // vta distinguishes main->C, main2->D. 64 "pkg.main --> (pkg.C).f", 65 "pkg.main --> pkg.main2", 66 "pkg.main2 --> (pkg.D).f", 67 }}, 68 {"pta", false, []string{ 69 // pta distinguishes main->C, main2->D. Also has a root node. 70 `<root> --> pkg.init`, 71 `<root> --> pkg.main`, 72 `pkg.main --> (pkg.C).f`, 73 `pkg.main --> pkg.main2`, 74 `pkg.main2 --> (pkg.D).f`, 75 }}, 76 // tests: both the package's main and the test's main are called. 77 // The callgraph includes all the guts of the "testing" package. 78 {"rta", true, []string{ 79 `pkg.test.main --> testing.MainStart`, 80 `testing.runExample --> pkg.Example`, 81 `pkg.Example --> (pkg.C).f`, 82 `pkg.main --> (pkg.C).f`, 83 }}, 84 {"vta", true, []string{ 85 `pkg.test.main --> testing.MainStart`, 86 `testing.runExample --> pkg.Example`, 87 `pkg.Example --> (pkg.C).f`, 88 `pkg.main --> (pkg.C).f`, 89 }}, 90 {"pta", true, []string{ 91 `<root> --> pkg.test.main`, 92 `<root> --> pkg.main`, 93 `pkg.test.main --> testing.MainStart`, 94 `testing.runExample --> pkg.Example`, 95 `pkg.Example --> (pkg.C).f`, 96 `pkg.main --> (pkg.C).f`, 97 }}, 98 } { 99 const format = "{{.Caller}} --> {{.Callee}}" 100 stdout = new(bytes.Buffer) 101 if err := doCallgraph("testdata/src", gopath, test.algo, format, test.tests, []string{"pkg"}); err != nil { 102 t.Error(err) 103 continue 104 } 105 106 edges := make(map[string]bool) 107 for _, line := range strings.Split(fmt.Sprint(stdout), "\n") { 108 edges[line] = true 109 } 110 ok := true 111 for _, edge := range test.want { 112 if !edges[edge] { 113 ok = false 114 t.Errorf("callgraph(%q, %t): missing edge: %s", 115 test.algo, test.tests, edge) 116 } 117 } 118 if !ok { 119 t.Log("got:\n", stdout) 120 } 121 } 122 }