Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / cmd / digraph / digraph_test.go
1 // Copyright 2019 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 package main
5
6 import (
7         "bytes"
8         "fmt"
9         "reflect"
10         "sort"
11         "strings"
12         "testing"
13 )
14
15 func TestDigraph(t *testing.T) {
16         const g1 = `
17 socks shoes
18 shorts pants
19 pants belt shoes
20 shirt tie sweater
21 sweater jacket
22 hat
23 `
24
25         const g2 = `
26 a b c
27 b d
28 c d
29 d c
30 `
31
32         for _, test := range []struct {
33                 name  string
34                 input string
35                 cmd   string
36                 args  []string
37                 want  string
38         }{
39                 {"nodes", g1, "nodes", nil, "belt\nhat\njacket\npants\nshirt\nshoes\nshorts\nsocks\nsweater\ntie\n"},
40                 {"reverse", g1, "reverse", []string{"jacket"}, "jacket\nshirt\nsweater\n"},
41                 {"transpose", g1, "transpose", nil, "belt pants\njacket sweater\npants shorts\nshoes pants\nshoes socks\nsweater shirt\ntie shirt\n"},
42                 {"forward", g1, "forward", []string{"socks"}, "shoes\nsocks\n"},
43                 {"forward multiple args", g1, "forward", []string{"socks", "sweater"}, "jacket\nshoes\nsocks\nsweater\n"},
44                 {"scss", g2, "sccs", nil, "a\nb\nc d\n"},
45                 {"scc", g2, "scc", []string{"d"}, "c\nd\n"},
46                 {"succs", g2, "succs", []string{"a"}, "b\nc\n"},
47                 {"preds", g2, "preds", []string{"c"}, "a\nd\n"},
48                 {"preds multiple args", g2, "preds", []string{"c", "d"}, "a\nb\nc\nd\n"},
49         } {
50                 t.Run(test.name, func(t *testing.T) {
51                         stdin = strings.NewReader(test.input)
52                         stdout = new(bytes.Buffer)
53                         if err := digraph(test.cmd, test.args); err != nil {
54                                 t.Fatal(err)
55                         }
56
57                         got := stdout.(fmt.Stringer).String()
58                         if got != test.want {
59                                 t.Errorf("digraph(%s, %s) = got %q, want %q", test.cmd, test.args, got, test.want)
60                         }
61                 })
62         }
63
64         // TODO(adonovan):
65         // - test somepath (it's nondeterministic).
66         // - test errors
67 }
68
69 func TestAllpaths(t *testing.T) {
70         for _, test := range []struct {
71                 name string
72                 in   string
73                 to   string // from is always "A"
74                 want string
75         }{
76                 {
77                         name: "Basic",
78                         in:   "A B\nB C",
79                         to:   "B",
80                         want: "A B\n",
81                 },
82                 {
83                         name: "Long",
84                         in:   "A B\nB C\n",
85                         to:   "C",
86                         want: "A B\nB C\n",
87                 },
88                 {
89                         name: "Cycle Basic",
90                         in:   "A B\nB A",
91                         to:   "B",
92                         want: "A B\nB A\n",
93                 },
94                 {
95                         name: "Cycle Path Out",
96                         // A <-> B -> C -> D
97                         in:   "A B\nB A\nB C\nC D",
98                         to:   "C",
99                         want: "A B\nB A\nB C\n",
100                 },
101                 {
102                         name: "Cycle Path Out Further Out",
103                         // A -> B <-> C -> D -> E
104                         in:   "A B\nB C\nC D\nC B\nD E",
105                         to:   "D",
106                         want: "A B\nB C\nC B\nC D\n",
107                 },
108                 {
109                         name: "Two Paths Basic",
110                         //           /-> C --\
111                         // A -> B --          -> E -> F
112                         //           \-> D --/
113                         in:   "A B\nB C\nC E\nB D\nD E\nE F",
114                         to:   "E",
115                         want: "A B\nB C\nB D\nC E\nD E\n",
116                 },
117                 {
118                         name: "Two Paths With One Immediately From Start",
119                         //      /-> B -+ -> D
120                         // A --        |
121                         //      \-> C <+
122                         in:   "A B\nA C\nB C\nB D",
123                         to:   "C",
124                         want: "A B\nA C\nB C\n",
125                 },
126                 {
127                         name: "Two Paths Further Up",
128                         //      /-> B --\
129                         // A --          -> D -> E -> F
130                         //      \-> C --/
131                         in:   "A B\nA C\nB D\nC D\nD E\nE F",
132                         to:   "E",
133                         want: "A B\nA C\nB D\nC D\nD E\n",
134                 },
135                 {
136                         // We should include A - C  - D even though it's further up the
137                         // second path than D (which would already be in the graph by
138                         // the time we get around to integrating the second path).
139                         name: "Two Splits",
140                         //      /-> B --\         /-> E --\
141                         // A --           -> D --          -> G -> H
142                         //      \-> C --/         \-> F --/
143                         in:   "A B\nA C\nB D\nC D\nD E\nD F\nE G\nF G\nG H",
144                         to:   "G",
145                         want: "A B\nA C\nB D\nC D\nD E\nD F\nE G\nF G\n",
146                 },
147                 {
148                         // D - E should not be duplicated.
149                         name: "Two Paths - Two Splits With Gap",
150                         //      /-> B --\              /-> F --\
151                         // A --           -> D -> E --          -> H -> I
152                         //      \-> C --/              \-> G --/
153                         in:   "A B\nA C\nB D\nC D\nD E\nE F\nE G\nF H\nG H\nH I",
154                         to:   "H",
155                         want: "A B\nA C\nB D\nC D\nD E\nE F\nE G\nF H\nG H\n",
156                 },
157         } {
158                 t.Run(test.name, func(t *testing.T) {
159                         stdin = strings.NewReader(test.in)
160                         stdout = new(bytes.Buffer)
161                         if err := digraph("allpaths", []string{"A", test.to}); err != nil {
162                                 t.Fatal(err)
163                         }
164
165                         got := stdout.(fmt.Stringer).String()
166                         if got != test.want {
167                                 t.Errorf("digraph(allpaths, A, %s) = got %q, want %q", test.to, got, test.want)
168                         }
169                 })
170         }
171 }
172
173 func TestSomepath(t *testing.T) {
174         for _, test := range []struct {
175                 name string
176                 in   string
177                 to   string
178                 // somepath is non-deterministic, so we have to provide all the
179                 // possible options. Each option is separated with |.
180                 wantAnyOf string
181         }{
182                 {
183                         name:      "Basic",
184                         in:        "A B\n",
185                         to:        "B",
186                         wantAnyOf: "A B",
187                 },
188                 {
189                         name:      "Basic With Cycle",
190                         in:        "A B\nB A",
191                         to:        "B",
192                         wantAnyOf: "A B",
193                 },
194                 {
195                         name: "Two Paths",
196                         //      /-> B --\
197                         // A --          -> D
198                         //      \-> C --/
199                         in:        "A B\nA C\nB D\nC D",
200                         to:        "D",
201                         wantAnyOf: "A B\nB D|A C\nC D",
202                 },
203         } {
204                 t.Run(test.name, func(t *testing.T) {
205                         stdin = strings.NewReader(test.in)
206                         stdout = new(bytes.Buffer)
207                         if err := digraph("somepath", []string{"A", test.to}); err != nil {
208                                 t.Fatal(err)
209                         }
210
211                         got := stdout.(fmt.Stringer).String()
212                         lines := strings.Split(got, "\n")
213                         sort.Strings(lines)
214                         got = strings.Join(lines[1:], "\n")
215
216                         var oneMatch bool
217                         for _, want := range strings.Split(test.wantAnyOf, "|") {
218                                 if got == want {
219                                         oneMatch = true
220                                 }
221                         }
222                         if !oneMatch {
223                                 t.Errorf("digraph(somepath, A, %s) = got %q, want any of\n%s", test.to, got, test.wantAnyOf)
224                         }
225                 })
226         }
227 }
228
229 func TestSplit(t *testing.T) {
230         for _, test := range []struct {
231                 line string
232                 want []string
233         }{
234                 {`one "2a 2b" three`, []string{"one", "2a 2b", "three"}},
235                 {`one tw"\n\x0a\u000a\012"o three`, []string{"one", "tw\n\n\n\no", "three"}},
236         } {
237                 got, err := split(test.line)
238                 if err != nil {
239                         t.Errorf("split(%s) failed: %v", test.line, err)
240                 }
241                 if !reflect.DeepEqual(got, test.want) {
242                         t.Errorf("split(%s) = %v, want %v", test.line, got, test.want)
243                 }
244         }
245 }
246
247 func TestQuotedLength(t *testing.T) {
248         for _, test := range []struct {
249                 input string
250                 want  int
251         }{
252                 {`"abc"`, 5},
253                 {`"abc"def`, 5},
254                 {`"abc\"d"ef`, 8}, // "abc\"d" is consumed, ef is residue
255                 {`"\012\n\x0a\u000a\U0000000a"`, 28},
256                 {"\"\xff\"", 3}, // bad UTF-8 is ok
257                 {`"\xff"`, 6},   // hex escape for bad UTF-8 is ok
258         } {
259                 got, ok := quotedLength(test.input)
260                 if !ok {
261                         got = 0
262                 }
263                 if got != test.want {
264                         t.Errorf("quotedLength(%s) = %d, want %d", test.input, got, test.want)
265                 }
266         }
267
268         // errors
269         for _, input := range []string{
270                 ``,            // not a quotation
271                 `a`,           // not a quotation
272                 `'a'`,         // not a quotation
273                 `"a`,          // not terminated
274                 `"\0"`,        // short octal escape
275                 `"\x1"`,       // short hex escape
276                 `"\u000"`,     // short \u escape
277                 `"\U0000000"`, // short \U escape
278                 `"\k"`,        // invalid escape
279                 "\"ab\nc\"",   // newline
280         } {
281                 if n, ok := quotedLength(input); ok {
282                         t.Errorf("quotedLength(%s) = %d, want !ok", input, n)
283                 }
284         }
285 }
286
287 func TestFocus(t *testing.T) {
288         for _, test := range []struct {
289                 name  string
290                 in    string
291                 focus string
292                 want  string
293         }{
294                 {
295                         name:  "Basic",
296                         in:    "A B",
297                         focus: "B",
298                         want:  "A B\n",
299                 },
300                 {
301                         name: "Some Nodes Not Included",
302                         // C does not have a path involving B, and should not be included
303                         // in the output.
304                         in:    "A B\nA C",
305                         focus: "B",
306                         want:  "A B\n",
307                 },
308                 {
309                         name: "Cycle In Path",
310                         // A <-> B -> C
311                         in:    "A B\nB A\nB C",
312                         focus: "C",
313                         want:  "A B\nB A\nB C\n",
314                 },
315                 {
316                         name: "Cycle Out Of Path",
317                         // C <- A <->B
318                         in:    "A B\nB A\nB C",
319                         focus: "C",
320                         want:  "A B\nB A\nB C\n",
321                 },
322                 {
323                         name: "Complex",
324                         // Paths in and out from focus.
325                         //                   /-> F
326                         //      /-> B -> D --
327                         // A --              \-> E
328                         //      \-> C
329                         in:    "A B\nA C\nB D\nD F\nD E",
330                         focus: "D",
331                         want:  "A B\nB D\nD E\nD F\n",
332                 },
333         } {
334                 t.Run(test.name, func(t *testing.T) {
335                         stdin = strings.NewReader(test.in)
336                         stdout = new(bytes.Buffer)
337                         if err := digraph("focus", []string{test.focus}); err != nil {
338                                 t.Fatal(err)
339                         }
340                         got := stdout.(fmt.Stringer).String()
341                         if got != test.want {
342                                 t.Errorf("digraph(focus, %s) = got %q, want %q", test.focus, got, test.want)
343                         }
344                 })
345         }
346 }