1package predeclared
2
3import (
4	"bytes"
5	"fmt"
6	"go/parser"
7	"go/token"
8	"io/ioutil"
9	"strings"
10	"testing"
11
12	"golang.org/x/tools/go/analysis"
13)
14
15func outPath(p string) string { return strings.TrimSuffix(p, ".go") + ".out" }
16
17func equalBytes(t *testing.T, a, b []byte, normalize func([]byte) []byte) {
18	if normalize != nil {
19		a = normalize(a)
20		b = normalize(b)
21	}
22	if !bytes.Equal(a, b) {
23		t.Errorf(`bytes not equal
24want: %s
25got:  %s
26`, a, b)
27	}
28}
29
30func setupConfig(p string) *config {
31	ignore := ""
32	qualified := false
33
34	// Get the first line.
35	b, err := ioutil.ReadFile(p)
36	if err != nil {
37		panic(fmt.Sprintf("failed to read file: %s", p))
38	}
39	idx := bytes.IndexByte(b, '\n')
40	if idx == -1 {
41		panic(fmt.Sprintf("no lines in file: %s", p))
42	}
43	// Does it have the prefix?
44	const prefix = "//predeclared"
45	line := string(b[:idx])
46	if !strings.HasPrefix(line, prefix) {
47		return newConfig(ignore, qualified)
48	} else {
49		line = strings.TrimPrefix(line, prefix)
50	}
51	// Parse.
52	args := strings.Fields(line)
53	for i := 0; i < len(args); {
54		arg := args[i]
55		switch arg {
56		case "-ignore":
57			i++
58			ignore = args[i]
59		case "-q":
60			qualified = true
61		default:
62			panic("unhandled flag")
63		}
64		i++
65	}
66
67	return newConfig(ignore, qualified)
68}
69
70func TestAll(t *testing.T) {
71	filenames := []string{
72		"testdata/example1.go",
73		"testdata/example2.go",
74		"testdata/example3.go",
75		"testdata/ignore.go",
76		"testdata/all.go",
77		"testdata/all-q.go",
78		"testdata/no-issues.go",
79		"testdata/no-issues2.go",
80	}
81
82	for i, path := range filenames {
83		if testing.Verbose() {
84			t.Logf("test [%d]: %s", i, path)
85		}
86		runOneFile(t, setupConfig(path), path)
87	}
88}
89
90func runOneFile(t *testing.T, cfg *config, path string) {
91	src, err := ioutil.ReadFile(path)
92	if err != nil {
93		t.Errorf("failed to read file: %s", err)
94		return
95	}
96
97	outContent, err := ioutil.ReadFile(outPath(path))
98	if err != nil {
99		t.Errorf("failed to read out file: %s", err)
100		return
101	}
102
103	fset := token.NewFileSet()
104	file, err := parser.ParseFile(fset, path, src, parser.AllErrors)
105	if err != nil {
106		t.Errorf("failed to parse file")
107		return
108	}
109
110	dummyReportFunc := func(analysis.Diagnostic) {}
111
112	issues := processFile(dummyReportFunc, cfg, fset, file)
113	var buf bytes.Buffer
114	for _, issue := range issues {
115		fmt.Fprintf(&buf, "%s\n", issue)
116	}
117
118	equalBytes(t, outContent, buf.Bytes(), bytes.TrimSpace)
119}
120