123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505 |
- // Copyright 2020 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- // +build ignore
- // Test cases for mkmerge.go.
- // Usage:
- // $ go test mkmerge.go mkmerge_test.go
- package main
- import (
- "bytes"
- "fmt"
- "go/parser"
- "go/token"
- "html/template"
- "strings"
- "testing"
- )
- func TestImports(t *testing.T) {
- t.Run("importName", func(t *testing.T) {
- cases := []struct {
- src string
- ident string
- }{
- {`"syscall"`, "syscall"},
- {`. "foobar"`, "."},
- {`"go/ast"`, "ast"},
- {`moo "go/format"`, "moo"},
- {`. "go/token"`, "."},
- {`"golang.org/x/sys/unix"`, "unix"},
- {`nix "golang.org/x/sys/unix"`, "nix"},
- {`_ "golang.org/x/sys/unix"`, "_"},
- }
- for _, c := range cases {
- pkgSrc := fmt.Sprintf("package main\nimport %s", c.src)
- f, err := parser.ParseFile(token.NewFileSet(), "", pkgSrc, parser.ImportsOnly)
- if err != nil {
- t.Error(err)
- continue
- }
- if len(f.Imports) != 1 {
- t.Errorf("Got %d imports, expected 1", len(f.Imports))
- continue
- }
- got, err := importName(f.Imports[0])
- if err != nil {
- t.Fatal(err)
- }
- if got != c.ident {
- t.Errorf("Got %q, expected %q", got, c.ident)
- }
- }
- })
- t.Run("filterImports", func(t *testing.T) {
- cases := []struct{ before, after string }{
- {`package test
- import (
- "foo"
- "bar"
- )`,
- "package test\n"},
- {`package test
- import (
- "foo"
- "bar"
- )
- func useFoo() { foo.Usage() }`,
- `package test
- import (
- "foo"
- )
- func useFoo() { foo.Usage() }
- `},
- }
- for _, c := range cases {
- got, err := filterImports([]byte(c.before))
- if err != nil {
- t.Error(err)
- }
- if string(got) != c.after {
- t.Errorf("Got:\n%s\nExpected:\n%s\n", got, c.after)
- }
- }
- })
- }
- func TestMerge(t *testing.T) {
- // Input architecture files
- inTmpl := template.Must(template.New("input").Parse(`
- // Package comments
- // build directives for arch{{.}}
- // +build goos,arch{{.}}
- package main
- /*
- #include <stdint.h>
- #include <stddef.h>
- int utimes(uintptr_t, uintptr_t);
- int utimensat(int, uintptr_t, uintptr_t, int);
- */
- import "C"
- // The imports
- import (
- "commonDep"
- "uniqueDep{{.}}"
- )
- // Vars
- var (
- commonVar = commonDep.Use("common")
- uniqueVar{{.}} = "unique{{.}}"
- )
- // Common free standing comment
- // Common comment
- const COMMON_INDEPENDENT = 1234
- const UNIQUE_INDEPENDENT_{{.}} = "UNIQUE_INDEPENDENT_{{.}}"
- // Group comment
- const (
- COMMON_GROUP = "COMMON_GROUP"
- UNIQUE_GROUP_{{.}} = "UNIQUE_GROUP_{{.}}"
- )
- // Group2 comment
- const (
- UNIQUE_GROUP21_{{.}} = "UNIQUE_GROUP21_{{.}}"
- UNIQUE_GROUP22_{{.}} = "UNIQUE_GROUP22_{{.}}"
- )
- // Group3 comment
- const (
- sub1Common1 = 11
- sub1Unique2{{.}} = 12
- sub1Common3_LONG = 13
- sub2Unique1{{.}} = 21
- sub2Common2 = 22
- sub2Common3 = 23
- sub2Unique4{{.}} = 24
- )
- type commonInt int
- type uniqueInt{{.}} int
- func commonF() string {
- return commonDep.Use("common")
- }
- func uniqueF() string {
- C.utimes(0, 0)
- return uniqueDep{{.}}.Use("{{.}}")
- }
- // Group4 comment
- const (
- sub3Common1 = 31
- sub3Unique2{{.}} = 32
- sub3Unique3{{.}} = 33
- sub3Common4 = 34
- sub4Common1, sub4Unique2{{.}} = 41, 42
- sub4Unique3{{.}}, sub4Common4 = 43, 44
- )
- `))
- // Filtered architecture files
- outTmpl := template.Must(template.New("output").Parse(`// Package comments
- // build directives for arch{{.}}
- // +build goos,arch{{.}}
- package main
- /*
- #include <stdint.h>
- #include <stddef.h>
- int utimes(uintptr_t, uintptr_t);
- int utimensat(int, uintptr_t, uintptr_t, int);
- */
- import "C"
- // The imports
- import (
- "commonDep"
- "uniqueDep{{.}}"
- )
- // Vars
- var (
- commonVar = commonDep.Use("common")
- uniqueVar{{.}} = "unique{{.}}"
- )
- const UNIQUE_INDEPENDENT_{{.}} = "UNIQUE_INDEPENDENT_{{.}}"
- // Group comment
- const (
- UNIQUE_GROUP_{{.}} = "UNIQUE_GROUP_{{.}}"
- )
- // Group2 comment
- const (
- UNIQUE_GROUP21_{{.}} = "UNIQUE_GROUP21_{{.}}"
- UNIQUE_GROUP22_{{.}} = "UNIQUE_GROUP22_{{.}}"
- )
- // Group3 comment
- const (
- sub1Unique2{{.}} = 12
- sub2Unique1{{.}} = 21
- sub2Unique4{{.}} = 24
- )
- type uniqueInt{{.}} int
- func uniqueF() string {
- C.utimes(0, 0)
- return uniqueDep{{.}}.Use("{{.}}")
- }
- // Group4 comment
- const (
- sub3Unique2{{.}} = 32
- sub3Unique3{{.}} = 33
- sub4Common1, sub4Unique2{{.}} = 41, 42
- sub4Unique3{{.}}, sub4Common4 = 43, 44
- )
- `))
- const mergedFile = `// Package comments
- package main
- // The imports
- import (
- "commonDep"
- )
- // Common free standing comment
- // Common comment
- const COMMON_INDEPENDENT = 1234
- // Group comment
- const (
- COMMON_GROUP = "COMMON_GROUP"
- )
- // Group3 comment
- const (
- sub1Common1 = 11
- sub1Common3_LONG = 13
- sub2Common2 = 22
- sub2Common3 = 23
- )
- type commonInt int
- func commonF() string {
- return commonDep.Use("common")
- }
- // Group4 comment
- const (
- sub3Common1 = 31
- sub3Common4 = 34
- )
- `
- // Generate source code for different "architectures"
- var inFiles, outFiles []srcFile
- for _, arch := range strings.Fields("A B C D") {
- buf := new(bytes.Buffer)
- err := inTmpl.Execute(buf, arch)
- if err != nil {
- t.Fatal(err)
- }
- inFiles = append(inFiles, srcFile{"file" + arch, buf.Bytes()})
- buf = new(bytes.Buffer)
- err = outTmpl.Execute(buf, arch)
- if err != nil {
- t.Fatal(err)
- }
- outFiles = append(outFiles, srcFile{"file" + arch, buf.Bytes()})
- }
- t.Run("getCodeSet", func(t *testing.T) {
- got, err := getCodeSet(inFiles[0].src)
- if err != nil {
- t.Fatal(err)
- }
- expectedElems := []codeElem{
- {token.COMMENT, "Package comments\n"},
- {token.COMMENT, "build directives for archA\n"},
- {token.COMMENT, "+build goos,archA\n"},
- {token.CONST, `COMMON_INDEPENDENT = 1234`},
- {token.CONST, `UNIQUE_INDEPENDENT_A = "UNIQUE_INDEPENDENT_A"`},
- {token.CONST, `COMMON_GROUP = "COMMON_GROUP"`},
- {token.CONST, `UNIQUE_GROUP_A = "UNIQUE_GROUP_A"`},
- {token.CONST, `UNIQUE_GROUP21_A = "UNIQUE_GROUP21_A"`},
- {token.CONST, `UNIQUE_GROUP22_A = "UNIQUE_GROUP22_A"`},
- {token.CONST, `sub1Common1 = 11`},
- {token.CONST, `sub1Unique2A = 12`},
- {token.CONST, `sub1Common3_LONG = 13`},
- {token.CONST, `sub2Unique1A = 21`},
- {token.CONST, `sub2Common2 = 22`},
- {token.CONST, `sub2Common3 = 23`},
- {token.CONST, `sub2Unique4A = 24`},
- {token.CONST, `sub3Common1 = 31`},
- {token.CONST, `sub3Unique2A = 32`},
- {token.CONST, `sub3Unique3A = 33`},
- {token.CONST, `sub3Common4 = 34`},
- {token.CONST, `sub4Common1, sub4Unique2A = 41, 42`},
- {token.CONST, `sub4Unique3A, sub4Common4 = 43, 44`},
- {token.TYPE, `commonInt int`},
- {token.TYPE, `uniqueIntA int`},
- {token.FUNC, `func commonF() string {
- return commonDep.Use("common")
- }`},
- {token.FUNC, `func uniqueF() string {
- C.utimes(0, 0)
- return uniqueDepA.Use("A")
- }`},
- }
- expected := newCodeSet()
- for _, d := range expectedElems {
- expected.add(d)
- }
- if len(got.set) != len(expected.set) {
- t.Errorf("Got %d codeElems, expected %d", len(got.set), len(expected.set))
- }
- for expElem := range expected.set {
- if !got.has(expElem) {
- t.Errorf("Didn't get expected codeElem %#v", expElem)
- }
- }
- for gotElem := range got.set {
- if !expected.has(gotElem) {
- t.Errorf("Got unexpected codeElem %#v", gotElem)
- }
- }
- })
- t.Run("getCommonSet", func(t *testing.T) {
- got, err := getCommonSet(inFiles)
- if err != nil {
- t.Fatal(err)
- }
- expected := newCodeSet()
- expected.add(codeElem{token.COMMENT, "Package comments\n"})
- expected.add(codeElem{token.CONST, `COMMON_INDEPENDENT = 1234`})
- expected.add(codeElem{token.CONST, `COMMON_GROUP = "COMMON_GROUP"`})
- expected.add(codeElem{token.CONST, `sub1Common1 = 11`})
- expected.add(codeElem{token.CONST, `sub1Common3_LONG = 13`})
- expected.add(codeElem{token.CONST, `sub2Common2 = 22`})
- expected.add(codeElem{token.CONST, `sub2Common3 = 23`})
- expected.add(codeElem{token.CONST, `sub3Common1 = 31`})
- expected.add(codeElem{token.CONST, `sub3Common4 = 34`})
- expected.add(codeElem{token.TYPE, `commonInt int`})
- expected.add(codeElem{token.FUNC, `func commonF() string {
- return commonDep.Use("common")
- }`})
- if len(got.set) != len(expected.set) {
- t.Errorf("Got %d codeElems, expected %d", len(got.set), len(expected.set))
- }
- for expElem := range expected.set {
- if !got.has(expElem) {
- t.Errorf("Didn't get expected codeElem %#v", expElem)
- }
- }
- for gotElem := range got.set {
- if !expected.has(gotElem) {
- t.Errorf("Got unexpected codeElem %#v", gotElem)
- }
- }
- })
- t.Run("filter(keepCommon)", func(t *testing.T) {
- commonSet, err := getCommonSet(inFiles)
- if err != nil {
- t.Fatal(err)
- }
- got, err := filter(inFiles[0].src, commonSet.keepCommon)
- expected := []byte(mergedFile)
- if !bytes.Equal(got, expected) {
- t.Errorf("Got:\n%s\nExpected:\n%s", addLineNr(got), addLineNr(expected))
- diffLines(t, got, expected)
- }
- })
- t.Run("filter(keepArchSpecific)", func(t *testing.T) {
- commonSet, err := getCommonSet(inFiles)
- if err != nil {
- t.Fatal(err)
- }
- for i := range inFiles {
- got, err := filter(inFiles[i].src, commonSet.keepArchSpecific)
- if err != nil {
- t.Fatal(err)
- }
- expected := outFiles[i].src
- if !bytes.Equal(got, expected) {
- t.Errorf("Got:\n%s\nExpected:\n%s", addLineNr(got), addLineNr(expected))
- diffLines(t, got, expected)
- }
- }
- })
- }
- func TestMergedName(t *testing.T) {
- t.Run("getValidGOOS", func(t *testing.T) {
- testcases := []struct {
- filename, goos string
- ok bool
- }{
- {"zerrors_aix.go", "aix", true},
- {"zerrors_darwin.go", "darwin", true},
- {"zerrors_dragonfly.go", "dragonfly", true},
- {"zerrors_freebsd.go", "freebsd", true},
- {"zerrors_linux.go", "linux", true},
- {"zerrors_netbsd.go", "netbsd", true},
- {"zerrors_openbsd.go", "openbsd", true},
- {"zerrors_solaris.go", "solaris", true},
- {"zerrors_multics.go", "", false},
- }
- for _, tc := range testcases {
- goos, ok := getValidGOOS(tc.filename)
- if goos != tc.goos {
- t.Errorf("got GOOS %q, expected %q", goos, tc.goos)
- }
- if ok != tc.ok {
- t.Errorf("got ok %v, expected %v", ok, tc.ok)
- }
- }
- })
- }
- // Helper functions to diff test sources
- func diffLines(t *testing.T, got, expected []byte) {
- t.Helper()
- gotLines := bytes.Split(got, []byte{'\n'})
- expLines := bytes.Split(expected, []byte{'\n'})
- i := 0
- for i < len(gotLines) && i < len(expLines) {
- if !bytes.Equal(gotLines[i], expLines[i]) {
- t.Errorf("Line %d: Got:\n%q\nExpected:\n%q", i+1, gotLines[i], expLines[i])
- return
- }
- i++
- }
- if i < len(gotLines) && i >= len(expLines) {
- t.Errorf("Line %d: got %q, expected EOF", i+1, gotLines[i])
- }
- if i >= len(gotLines) && i < len(expLines) {
- t.Errorf("Line %d: got EOF, expected %q", i+1, gotLines[i])
- }
- }
- func addLineNr(src []byte) []byte {
- lines := bytes.Split(src, []byte("\n"))
- for i, line := range lines {
- lines[i] = []byte(fmt.Sprintf("%d: %s", i+1, line))
- }
- return bytes.Join(lines, []byte("\n"))
- }
|