1package analysistest_test
2
3import (
4	"fmt"
5	"log"
6	"os"
7	"reflect"
8	"strings"
9	"testing"
10
11	"golang.org/x/tools/go/analysis/analysistest"
12	"golang.org/x/tools/go/analysis/passes/findcall"
13	"golang.org/x/tools/internal/testenv"
14)
15
16func init() {
17	// This test currently requires GOPATH mode.
18	// Explicitly disabling module mode should suffice, but
19	// we'll also turn off GOPROXY just for good measure.
20	if err := os.Setenv("GO111MODULE", "off"); err != nil {
21		log.Fatal(err)
22	}
23	if err := os.Setenv("GOPROXY", "off"); err != nil {
24		log.Fatal(err)
25	}
26}
27
28// TestTheTest tests the analysistest testing infrastructure.
29func TestTheTest(t *testing.T) {
30	testenv.NeedsTool(t, "go")
31
32	// We'll simulate a partly failing test of the findcall analysis,
33	// which (by default) reports calls to functions named 'println'.
34	findcall.Analyzer.Flags.Set("name", "println")
35
36	filemap := map[string]string{"a/b.go": `package main // want package:"found"
37
38func main() {
39	// The expectation is ill-formed:
40	print() // want: "diagnostic"
41	print() // want foo"fact"
42	print() // want foo:
43	print() // want "\xZZ scan error"
44
45	// A diagnostic is reported at this line, but the expectation doesn't match:
46	println("hello, world") // want "wrong expectation text"
47
48	// An unexpected diagnostic is reported at this line:
49	println() // trigger an unexpected diagnostic
50
51	// No diagnostic is reported at this line:
52	print()	// want "unsatisfied expectation"
53
54	// OK
55	println("hello, world") // want "call of println"
56
57	// OK (multiple expectations on same line)
58	println(); println() // want "call of println(...)" "call of println(...)"
59}
60
61// OK (facts and diagnostics on same line)
62func println(...interface{}) { println() } // want println:"found" "call of println(...)"
63
64`}
65	dir, cleanup, err := analysistest.WriteFiles(filemap)
66	if err != nil {
67		t.Fatal(err)
68	}
69	defer cleanup()
70
71	var got []string
72	t2 := errorfunc(func(s string) { got = append(got, s) }) // a fake *testing.T
73	analysistest.Run(t2, dir, findcall.Analyzer, "a")
74
75	want := []string{
76		`a/b.go:5: in 'want' comment: unexpected ":"`,
77		`a/b.go:6: in 'want' comment: got String after foo, want ':'`,
78		`a/b.go:7: in 'want' comment: got EOF, want regular expression`,
79		`a/b.go:8: in 'want' comment: invalid char escape`,
80		`a/b.go:11:9: diagnostic "call of println(...)" does not match pattern "wrong expectation text"`,
81		`a/b.go:14:9: unexpected diagnostic: call of println(...)`,
82		`a/b.go:11: no diagnostic was reported matching "wrong expectation text"`,
83		`a/b.go:17: no diagnostic was reported matching "unsatisfied expectation"`,
84	}
85	// Go 1.13's scanner error messages uses the word invalid where Go 1.12 used illegal. Convert them
86	// to keep tests compatible with both.
87	// TODO(matloob): Remove this once Go 1.13 is released.
88	for i := range got {
89		got[i] = strings.Replace(got[i], "illegal", "invalid", -1)
90	} //
91	if !reflect.DeepEqual(got, want) {
92		t.Errorf("got:\n%s\nwant:\n%s",
93			strings.Join(got, "\n"),
94			strings.Join(want, "\n"))
95	}
96}
97
98type errorfunc func(string)
99
100func (f errorfunc) Errorf(format string, args ...interface{}) {
101	f(fmt.Sprintf(format, args...))
102}
103