.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / sys@v0.0.0-20210124154548-22da62e12c0c / unix / mkmerge_test.go
1 // Copyright 2020 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 // +build ignore
6
7 // Test cases for mkmerge.go.
8 // Usage:
9 //     $ go test mkmerge.go mkmerge_test.go
10 package main
11
12 import (
13         "bytes"
14         "fmt"
15         "go/parser"
16         "go/token"
17         "html/template"
18         "strings"
19         "testing"
20 )
21
22 func TestImports(t *testing.T) {
23         t.Run("importName", func(t *testing.T) {
24                 cases := []struct {
25                         src   string
26                         ident string
27                 }{
28                         {`"syscall"`, "syscall"},
29                         {`. "foobar"`, "."},
30                         {`"go/ast"`, "ast"},
31                         {`moo "go/format"`, "moo"},
32                         {`. "go/token"`, "."},
33                         {`"golang.org/x/sys/unix"`, "unix"},
34                         {`nix "golang.org/x/sys/unix"`, "nix"},
35                         {`_ "golang.org/x/sys/unix"`, "_"},
36                 }
37
38                 for _, c := range cases {
39                         pkgSrc := fmt.Sprintf("package main\nimport %s", c.src)
40
41                         f, err := parser.ParseFile(token.NewFileSet(), "", pkgSrc, parser.ImportsOnly)
42                         if err != nil {
43                                 t.Error(err)
44                                 continue
45                         }
46                         if len(f.Imports) != 1 {
47                                 t.Errorf("Got %d imports, expected 1", len(f.Imports))
48                                 continue
49                         }
50
51                         got, err := importName(f.Imports[0])
52                         if err != nil {
53                                 t.Fatal(err)
54                         }
55                         if got != c.ident {
56                                 t.Errorf("Got %q, expected %q", got, c.ident)
57                         }
58                 }
59         })
60
61         t.Run("filterImports", func(t *testing.T) {
62                 cases := []struct{ before, after string }{
63                         {`package test
64
65                         import (
66                                 "foo"
67                                 "bar"
68                         )`,
69                                 "package test\n"},
70                         {`package test
71
72                         import (
73                                 "foo"
74                                 "bar"
75                         )
76
77                         func useFoo() { foo.Usage() }`,
78                                 `package test
79
80 import (
81         "foo"
82 )
83
84 func useFoo() { foo.Usage() }
85 `},
86                 }
87                 for _, c := range cases {
88                         got, err := filterImports([]byte(c.before))
89                         if err != nil {
90                                 t.Error(err)
91                         }
92
93                         if string(got) != c.after {
94                                 t.Errorf("Got:\n%s\nExpected:\n%s\n", got, c.after)
95                         }
96                 }
97         })
98 }
99
100 func TestMerge(t *testing.T) {
101         // Input architecture files
102         inTmpl := template.Must(template.New("input").Parse(`
103 // Package comments
104
105 // build directives for arch{{.}}
106
107 // +build goos,arch{{.}}
108
109 package main
110
111 /*
112 #include <stdint.h>
113 #include <stddef.h>
114 int utimes(uintptr_t, uintptr_t);
115 int utimensat(int, uintptr_t, uintptr_t, int);
116 */
117 import "C"
118
119 // The imports
120 import (
121         "commonDep"
122         "uniqueDep{{.}}"
123 )
124
125 // Vars
126 var (
127         commonVar = commonDep.Use("common")
128
129         uniqueVar{{.}} = "unique{{.}}"
130 )
131
132 // Common free standing comment
133
134 // Common comment
135 const COMMON_INDEPENDENT = 1234
136 const UNIQUE_INDEPENDENT_{{.}} = "UNIQUE_INDEPENDENT_{{.}}"
137
138 // Group comment
139 const (
140         COMMON_GROUP = "COMMON_GROUP"
141         UNIQUE_GROUP_{{.}} = "UNIQUE_GROUP_{{.}}"
142 )
143
144 // Group2 comment
145 const (
146         UNIQUE_GROUP21_{{.}} = "UNIQUE_GROUP21_{{.}}"
147         UNIQUE_GROUP22_{{.}} = "UNIQUE_GROUP22_{{.}}"
148 )
149
150 // Group3 comment
151 const (
152         sub1Common1 = 11
153         sub1Unique2{{.}} = 12
154         sub1Common3_LONG = 13
155
156         sub2Unique1{{.}} = 21
157         sub2Common2 = 22
158         sub2Common3 = 23
159         sub2Unique4{{.}} = 24
160 )
161
162 type commonInt int
163
164 type uniqueInt{{.}} int
165
166 func commonF() string {
167         return commonDep.Use("common")
168         }
169
170 func uniqueF() string {
171         C.utimes(0, 0)
172         return uniqueDep{{.}}.Use("{{.}}")
173         }
174
175 // Group4 comment
176 const (
177         sub3Common1 = 31
178         sub3Unique2{{.}} = 32
179         sub3Unique3{{.}} = 33
180         sub3Common4 = 34
181
182         sub4Common1, sub4Unique2{{.}} = 41, 42
183         sub4Unique3{{.}}, sub4Common4 = 43, 44
184 )
185 `))
186
187         // Filtered architecture files
188         outTmpl := template.Must(template.New("output").Parse(`// Package comments
189
190 // build directives for arch{{.}}
191
192 // +build goos,arch{{.}}
193
194 package main
195
196 /*
197 #include <stdint.h>
198 #include <stddef.h>
199 int utimes(uintptr_t, uintptr_t);
200 int utimensat(int, uintptr_t, uintptr_t, int);
201 */
202 import "C"
203
204 // The imports
205 import (
206         "commonDep"
207         "uniqueDep{{.}}"
208 )
209
210 // Vars
211 var (
212         commonVar = commonDep.Use("common")
213
214         uniqueVar{{.}} = "unique{{.}}"
215 )
216
217 const UNIQUE_INDEPENDENT_{{.}} = "UNIQUE_INDEPENDENT_{{.}}"
218
219 // Group comment
220 const (
221         UNIQUE_GROUP_{{.}} = "UNIQUE_GROUP_{{.}}"
222 )
223
224 // Group2 comment
225 const (
226         UNIQUE_GROUP21_{{.}} = "UNIQUE_GROUP21_{{.}}"
227         UNIQUE_GROUP22_{{.}} = "UNIQUE_GROUP22_{{.}}"
228 )
229
230 // Group3 comment
231 const (
232         sub1Unique2{{.}} = 12
233
234         sub2Unique1{{.}} = 21
235         sub2Unique4{{.}} = 24
236 )
237
238 type uniqueInt{{.}} int
239
240 func uniqueF() string {
241         C.utimes(0, 0)
242         return uniqueDep{{.}}.Use("{{.}}")
243 }
244
245 // Group4 comment
246 const (
247         sub3Unique2{{.}} = 32
248         sub3Unique3{{.}} = 33
249
250         sub4Common1, sub4Unique2{{.}} = 41, 42
251         sub4Unique3{{.}}, sub4Common4 = 43, 44
252 )
253 `))
254
255         const mergedFile = `// Package comments
256
257 package main
258
259 // The imports
260 import (
261         "commonDep"
262 )
263
264 // Common free standing comment
265
266 // Common comment
267 const COMMON_INDEPENDENT = 1234
268
269 // Group comment
270 const (
271         COMMON_GROUP = "COMMON_GROUP"
272 )
273
274 // Group3 comment
275 const (
276         sub1Common1      = 11
277         sub1Common3_LONG = 13
278
279         sub2Common2 = 22
280         sub2Common3 = 23
281 )
282
283 type commonInt int
284
285 func commonF() string {
286         return commonDep.Use("common")
287 }
288
289 // Group4 comment
290 const (
291         sub3Common1 = 31
292         sub3Common4 = 34
293 )
294 `
295
296         // Generate source code for different "architectures"
297         var inFiles, outFiles []srcFile
298         for _, arch := range strings.Fields("A B C D") {
299                 buf := new(bytes.Buffer)
300                 err := inTmpl.Execute(buf, arch)
301                 if err != nil {
302                         t.Fatal(err)
303                 }
304                 inFiles = append(inFiles, srcFile{"file" + arch, buf.Bytes()})
305
306                 buf = new(bytes.Buffer)
307                 err = outTmpl.Execute(buf, arch)
308                 if err != nil {
309                         t.Fatal(err)
310                 }
311                 outFiles = append(outFiles, srcFile{"file" + arch, buf.Bytes()})
312         }
313
314         t.Run("getCodeSet", func(t *testing.T) {
315                 got, err := getCodeSet(inFiles[0].src)
316                 if err != nil {
317                         t.Fatal(err)
318                 }
319
320                 expectedElems := []codeElem{
321                         {token.COMMENT, "Package comments\n"},
322                         {token.COMMENT, "build directives for archA\n"},
323                         {token.COMMENT, "+build goos,archA\n"},
324                         {token.CONST, `COMMON_INDEPENDENT = 1234`},
325                         {token.CONST, `UNIQUE_INDEPENDENT_A = "UNIQUE_INDEPENDENT_A"`},
326                         {token.CONST, `COMMON_GROUP = "COMMON_GROUP"`},
327                         {token.CONST, `UNIQUE_GROUP_A = "UNIQUE_GROUP_A"`},
328                         {token.CONST, `UNIQUE_GROUP21_A = "UNIQUE_GROUP21_A"`},
329                         {token.CONST, `UNIQUE_GROUP22_A = "UNIQUE_GROUP22_A"`},
330                         {token.CONST, `sub1Common1 = 11`},
331                         {token.CONST, `sub1Unique2A = 12`},
332                         {token.CONST, `sub1Common3_LONG = 13`},
333                         {token.CONST, `sub2Unique1A = 21`},
334                         {token.CONST, `sub2Common2 = 22`},
335                         {token.CONST, `sub2Common3 = 23`},
336                         {token.CONST, `sub2Unique4A = 24`},
337                         {token.CONST, `sub3Common1 = 31`},
338                         {token.CONST, `sub3Unique2A = 32`},
339                         {token.CONST, `sub3Unique3A = 33`},
340                         {token.CONST, `sub3Common4 = 34`},
341                         {token.CONST, `sub4Common1, sub4Unique2A = 41, 42`},
342                         {token.CONST, `sub4Unique3A, sub4Common4 = 43, 44`},
343                         {token.TYPE, `commonInt int`},
344                         {token.TYPE, `uniqueIntA int`},
345                         {token.FUNC, `func commonF() string {
346         return commonDep.Use("common")
347 }`},
348                         {token.FUNC, `func uniqueF() string {
349         C.utimes(0, 0)
350         return uniqueDepA.Use("A")
351 }`},
352                 }
353                 expected := newCodeSet()
354                 for _, d := range expectedElems {
355                         expected.add(d)
356                 }
357
358                 if len(got.set) != len(expected.set) {
359                         t.Errorf("Got %d codeElems, expected %d", len(got.set), len(expected.set))
360                 }
361                 for expElem := range expected.set {
362                         if !got.has(expElem) {
363                                 t.Errorf("Didn't get expected codeElem %#v", expElem)
364                         }
365                 }
366                 for gotElem := range got.set {
367                         if !expected.has(gotElem) {
368                                 t.Errorf("Got unexpected codeElem %#v", gotElem)
369                         }
370                 }
371         })
372
373         t.Run("getCommonSet", func(t *testing.T) {
374                 got, err := getCommonSet(inFiles)
375                 if err != nil {
376                         t.Fatal(err)
377                 }
378
379                 expected := newCodeSet()
380                 expected.add(codeElem{token.COMMENT, "Package comments\n"})
381                 expected.add(codeElem{token.CONST, `COMMON_INDEPENDENT = 1234`})
382                 expected.add(codeElem{token.CONST, `COMMON_GROUP = "COMMON_GROUP"`})
383                 expected.add(codeElem{token.CONST, `sub1Common1 = 11`})
384                 expected.add(codeElem{token.CONST, `sub1Common3_LONG = 13`})
385                 expected.add(codeElem{token.CONST, `sub2Common2 = 22`})
386                 expected.add(codeElem{token.CONST, `sub2Common3 = 23`})
387                 expected.add(codeElem{token.CONST, `sub3Common1 = 31`})
388                 expected.add(codeElem{token.CONST, `sub3Common4 = 34`})
389                 expected.add(codeElem{token.TYPE, `commonInt int`})
390                 expected.add(codeElem{token.FUNC, `func commonF() string {
391         return commonDep.Use("common")
392 }`})
393
394                 if len(got.set) != len(expected.set) {
395                         t.Errorf("Got %d codeElems, expected %d", len(got.set), len(expected.set))
396                 }
397                 for expElem := range expected.set {
398                         if !got.has(expElem) {
399                                 t.Errorf("Didn't get expected codeElem %#v", expElem)
400                         }
401                 }
402                 for gotElem := range got.set {
403                         if !expected.has(gotElem) {
404                                 t.Errorf("Got unexpected codeElem %#v", gotElem)
405                         }
406                 }
407         })
408
409         t.Run("filter(keepCommon)", func(t *testing.T) {
410                 commonSet, err := getCommonSet(inFiles)
411                 if err != nil {
412                         t.Fatal(err)
413                 }
414
415                 got, err := filter(inFiles[0].src, commonSet.keepCommon)
416                 expected := []byte(mergedFile)
417
418                 if !bytes.Equal(got, expected) {
419                         t.Errorf("Got:\n%s\nExpected:\n%s", addLineNr(got), addLineNr(expected))
420                         diffLines(t, got, expected)
421                 }
422         })
423
424         t.Run("filter(keepArchSpecific)", func(t *testing.T) {
425                 commonSet, err := getCommonSet(inFiles)
426                 if err != nil {
427                         t.Fatal(err)
428                 }
429
430                 for i := range inFiles {
431                         got, err := filter(inFiles[i].src, commonSet.keepArchSpecific)
432                         if err != nil {
433                                 t.Fatal(err)
434                         }
435
436                         expected := outFiles[i].src
437
438                         if !bytes.Equal(got, expected) {
439                                 t.Errorf("Got:\n%s\nExpected:\n%s", addLineNr(got), addLineNr(expected))
440                                 diffLines(t, got, expected)
441                         }
442                 }
443         })
444 }
445
446 func TestMergedName(t *testing.T) {
447         t.Run("getValidGOOS", func(t *testing.T) {
448                 testcases := []struct {
449                         filename, goos string
450                         ok             bool
451                 }{
452                         {"zerrors_aix.go", "aix", true},
453                         {"zerrors_darwin.go", "darwin", true},
454                         {"zerrors_dragonfly.go", "dragonfly", true},
455                         {"zerrors_freebsd.go", "freebsd", true},
456                         {"zerrors_linux.go", "linux", true},
457                         {"zerrors_netbsd.go", "netbsd", true},
458                         {"zerrors_openbsd.go", "openbsd", true},
459                         {"zerrors_solaris.go", "solaris", true},
460                         {"zerrors_multics.go", "", false},
461                 }
462                 for _, tc := range testcases {
463                         goos, ok := getValidGOOS(tc.filename)
464                         if goos != tc.goos {
465                                 t.Errorf("got GOOS %q, expected %q", goos, tc.goos)
466                         }
467                         if ok != tc.ok {
468                                 t.Errorf("got ok %v, expected %v", ok, tc.ok)
469                         }
470                 }
471         })
472 }
473
474 // Helper functions to diff test sources
475
476 func diffLines(t *testing.T, got, expected []byte) {
477         t.Helper()
478
479         gotLines := bytes.Split(got, []byte{'\n'})
480         expLines := bytes.Split(expected, []byte{'\n'})
481
482         i := 0
483         for i < len(gotLines) && i < len(expLines) {
484                 if !bytes.Equal(gotLines[i], expLines[i]) {
485                         t.Errorf("Line %d: Got:\n%q\nExpected:\n%q", i+1, gotLines[i], expLines[i])
486                         return
487                 }
488                 i++
489         }
490
491         if i < len(gotLines) && i >= len(expLines) {
492                 t.Errorf("Line %d: got %q, expected EOF", i+1, gotLines[i])
493         }
494         if i >= len(gotLines) && i < len(expLines) {
495                 t.Errorf("Line %d: got EOF, expected %q", i+1, gotLines[i])
496         }
497 }
498
499 func addLineNr(src []byte) []byte {
500         lines := bytes.Split(src, []byte("\n"))
501         for i, line := range lines {
502                 lines[i] = []byte(fmt.Sprintf("%d: %s", i+1, line))
503         }
504         return bytes.Join(lines, []byte("\n"))
505 }