blob: f486def57122799f1e76f0a3afb1bd642ad9ea50 [file] [log] [blame]
Robert Griesemerd02228d2015-08-05 17:53:24 -07001// 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
Russ Cox23633912021-02-19 17:25:34 -05007//go:build !android && go1.11
8// +build !android,go1.11
Robert Griesemerd02228d2015-08-05 17:53:24 -07009
Alan Donovanb8a5fcf2014-11-12 17:36:22 -050010package main
11
12import (
13 "bytes"
14 "fmt"
Bryan C. Mills9fb5a2f2018-09-26 15:32:23 -040015 "log"
16 "os"
Alan Donovan1bd72982018-08-08 17:02:13 -040017 "path/filepath"
Alan Donovanb8a5fcf2014-11-12 17:36:22 -050018 "strings"
19 "testing"
Bryan C. Millsc17b0402019-08-29 16:22:26 -040020
21 "golang.org/x/tools/internal/testenv"
Alan Donovanb8a5fcf2014-11-12 17:36:22 -050022)
23
Bryan C. Mills9fb5a2f2018-09-26 15:32:23 -040024func init() {
25 // This test currently requires GOPATH mode.
26 // Explicitly disabling module mode should suffix, but
27 // we'll also turn off GOPROXY just for good measure.
28 if err := os.Setenv("GO111MODULE", "off"); err != nil {
29 log.Fatal(err)
30 }
31 if err := os.Setenv("GOPROXY", "off"); err != nil {
32 log.Fatal(err)
33 }
34}
35
Alan Donovanb8a5fcf2014-11-12 17:36:22 -050036func TestCallgraph(t *testing.T) {
Bryan C. Millsc17b0402019-08-29 16:22:26 -040037 testenv.NeedsTool(t, "go")
38
Alan Donovan1bd72982018-08-08 17:02:13 -040039 gopath, err := filepath.Abs("testdata")
40 if err != nil {
41 t.Fatal(err)
42 }
Alan Donovanb8a5fcf2014-11-12 17:36:22 -050043
44 for _, test := range []struct {
Alan Donovan1bd72982018-08-08 17:02:13 -040045 algo string
46 tests bool
47 want []string
Alan Donovanb8a5fcf2014-11-12 17:36:22 -050048 }{
Alan Donovan1bd72982018-08-08 17:02:13 -040049 {"rta", false, []string{
Alan Donovanb8a5fcf2014-11-12 17:36:22 -050050 // rta imprecisely shows cross product of {main,main2} x {C,D}
51 `pkg.main --> (pkg.C).f`,
52 `pkg.main --> (pkg.D).f`,
53 `pkg.main --> pkg.main2`,
54 `pkg.main2 --> (pkg.C).f`,
55 `pkg.main2 --> (pkg.D).f`,
56 }},
Alan Donovan1bd72982018-08-08 17:02:13 -040057 {"pta", false, []string{
Alan Donovanb8a5fcf2014-11-12 17:36:22 -050058 // pta distinguishes main->C, main2->D. Also has a root node.
59 `<root> --> pkg.init`,
60 `<root> --> pkg.main`,
61 `pkg.main --> (pkg.C).f`,
62 `pkg.main --> pkg.main2`,
63 `pkg.main2 --> (pkg.D).f`,
64 }},
Alan Donovan1bd72982018-08-08 17:02:13 -040065 // tests: both the package's main and the test's main are called.
66 // The callgraph includes all the guts of the "testing" package.
67 {"rta", true, []string{
68 `pkg.test.main --> testing.MainStart`,
69 `testing.runExample --> pkg.Example`,
Alan Donovanb8a5fcf2014-11-12 17:36:22 -050070 `pkg.Example --> (pkg.C).f`,
Alan Donovan1bd72982018-08-08 17:02:13 -040071 `pkg.main --> (pkg.C).f`,
Alan Donovanb8a5fcf2014-11-12 17:36:22 -050072 }},
Alan Donovan1bd72982018-08-08 17:02:13 -040073 {"pta", true, []string{
74 `<root> --> pkg.test.main`,
75 `<root> --> pkg.main`,
76 `pkg.test.main --> testing.MainStart`,
77 `testing.runExample --> pkg.Example`,
Alan Donovanb8a5fcf2014-11-12 17:36:22 -050078 `pkg.Example --> (pkg.C).f`,
Alan Donovan1bd72982018-08-08 17:02:13 -040079 `pkg.main --> (pkg.C).f`,
Alan Donovanb8a5fcf2014-11-12 17:36:22 -050080 }},
81 } {
Alan Donovan1bd72982018-08-08 17:02:13 -040082 const format = "{{.Caller}} --> {{.Callee}}"
Alan Donovanb8a5fcf2014-11-12 17:36:22 -050083 stdout = new(bytes.Buffer)
Alan Donovan1bd72982018-08-08 17:02:13 -040084 if err := doCallgraph("testdata/src", gopath, test.algo, format, test.tests, []string{"pkg"}); err != nil {
Alan Donovanb8a5fcf2014-11-12 17:36:22 -050085 t.Error(err)
86 continue
87 }
88
Alan Donovan1bd72982018-08-08 17:02:13 -040089 edges := make(map[string]bool)
90 for _, line := range strings.Split(fmt.Sprint(stdout), "\n") {
91 edges[line] = true
92 }
93 for _, edge := range test.want {
94 if !edges[edge] {
95 t.Errorf("callgraph(%q, %t): missing edge: %s",
96 test.algo, test.tests, edge)
97 }
98 }
99 if t.Failed() {
100 t.Log("got:\n", stdout)
Alan Donovanb8a5fcf2014-11-12 17:36:22 -0500101 }
102 }
103}