1
2
3
4
5 package main
6
7 import (
8 "bytes"
9 "encoding/json"
10 "flag"
11 "fmt"
12 "go/build/constraint"
13 "math/rand"
14 "os"
15 "path/filepath"
16 "strings"
17 "testing"
18
19 "golang.org/x/tools/internal/bisect"
20 "golang.org/x/tools/internal/diffp"
21 "golang.org/x/tools/txtar"
22 )
23
24 var update = flag.Bool("update", false, "update testdata with new stdout/stderr")
25
26 func Test(t *testing.T) {
27 files, err := filepath.Glob("testdata/*.txt")
28 if err != nil {
29 t.Fatal(err)
30 }
31 for _, file := range files {
32 t.Run(strings.TrimSuffix(filepath.Base(file), ".txt"), func(t *testing.T) {
33 data, err := os.ReadFile(file)
34 if err != nil {
35 t.Fatal(err)
36 }
37 a := txtar.Parse(data)
38 var wantStdout, wantStderr []byte
39 files := a.Files
40 if len(files) > 0 && files[0].Name == "stdout" {
41 wantStdout = files[0].Data
42 files = files[1:]
43 }
44 if len(files) > 0 && files[0].Name == "stderr" {
45 wantStderr = files[0].Data
46 files = files[1:]
47 }
48 if len(files) > 0 {
49 t.Fatalf("unexpected txtar entry: %s", files[0].Name)
50 }
51
52 var tt struct {
53 Fail string
54 Bisect Bisect
55 }
56 if err := json.Unmarshal(a.Comment, &tt); err != nil {
57 t.Fatal(err)
58 }
59
60 expr, err := constraint.Parse("//go:build " + tt.Fail)
61 if err != nil {
62 t.Fatalf("invalid Cmd: %v", err)
63 }
64
65 rnd := rand.New(rand.NewSource(1))
66 b := &tt.Bisect
67 b.Cmd = "test"
68 b.Args = []string{"PATTERN"}
69 var stdout, stderr bytes.Buffer
70 b.Stdout = &stdout
71 b.Stderr = &stderr
72 b.TestRun = func(env []string, cmd string, args []string) (out []byte, err error) {
73 pattern := args[0]
74 m, err := bisect.New(pattern)
75 if err != nil {
76 t.Fatal(err)
77 }
78 have := make(map[string]bool)
79 for i, color := range colors {
80 if m.ShouldEnable(uint64(i)) {
81 have[color] = true
82 }
83 if m.ShouldReport(uint64(i)) {
84 out = fmt.Appendf(out, "%s %s\n", color, bisect.Marker(uint64(i)))
85 }
86 }
87 err = nil
88 if eval(rnd, expr, have) {
89 err = fmt.Errorf("failed")
90 }
91 return out, err
92 }
93
94 if !b.Search() {
95 stderr.WriteString("<bisect failed>\n")
96 }
97 rewrite := false
98 if !bytes.Equal(stdout.Bytes(), wantStdout) {
99 if *update {
100 rewrite = true
101 } else {
102 t.Errorf("incorrect stdout: %s", diffp.Diff("have", stdout.Bytes(), "want", wantStdout))
103 }
104 }
105 if !bytes.Equal(stderr.Bytes(), wantStderr) {
106 if *update {
107 rewrite = true
108 } else {
109 t.Errorf("incorrect stderr: %s", diffp.Diff("have", stderr.Bytes(), "want", wantStderr))
110 }
111 }
112 if rewrite {
113 a.Files = []txtar.File{{Name: "stdout", Data: stdout.Bytes()}, {Name: "stderr", Data: stderr.Bytes()}}
114 err := os.WriteFile(file, txtar.Format(a), 0666)
115 if err != nil {
116 t.Fatal(err)
117 }
118 t.Logf("updated %s", file)
119 }
120 })
121 }
122 }
123
124 func eval(rnd *rand.Rand, z constraint.Expr, have map[string]bool) bool {
125 switch z := z.(type) {
126 default:
127 panic(fmt.Sprintf("unexpected type %T", z))
128 case *constraint.NotExpr:
129 return !eval(rnd, z.X, have)
130 case *constraint.AndExpr:
131 return eval(rnd, z.X, have) && eval(rnd, z.Y, have)
132 case *constraint.OrExpr:
133 return eval(rnd, z.X, have) || eval(rnd, z.Y, have)
134 case *constraint.TagExpr:
135 if z.Tag == "random" {
136 return rnd.Intn(2) == 1
137 }
138 return have[z.Tag]
139 }
140 }
141
142 var colors = strings.Fields(`
143 aliceblue
144 amaranth
145 amber
146 amethyst
147 applegreen
148 applered
149 apricot
150 aquamarine
151 azure
152 babyblue
153 beige
154 brickred
155 black
156 blue
157 bluegreen
158 blueviolet
159 blush
160 bronze
161 brown
162 burgundy
163 byzantium
164 carmine
165 cerise
166 cerulean
167 champagne
168 chartreusegreen
169 chocolate
170 cobaltblue
171 coffee
172 copper
173 coral
174 crimson
175 cyan
176 desertsand
177 electricblue
178 emerald
179 erin
180 gold
181 gray
182 green
183 harlequin
184 indigo
185 ivory
186 jade
187 junglegreen
188 lavender
189 lemon
190 lilac
191 lime
192 magenta
193 magentarose
194 maroon
195 mauve
196 navyblue
197 ochre
198 olive
199 orange
200 orangered
201 orchid
202 peach
203 pear
204 periwinkle
205 persianblue
206 pink
207 plum
208 prussianblue
209 puce
210 purple
211 raspberry
212 red
213 redviolet
214 rose
215 ruby
216 salmon
217 sangria
218 sapphire
219 scarlet
220 silver
221 slategray
222 springbud
223 springgreen
224 tan
225 taupe
226 teal
227 turquoise
228 ultramarine
229 violet
230 viridian
231 white
232 yellow
233 `)
234
View as plain text