mirror of
https://github.com/rwinkhart/sys.git
synced 2026-09-03 07:37:34 -04:00
Factor mkmerge.go and mkmerge_test.go into package internal/mkmerge. Due to ignore constraints, mkmerge_test.go wasn't run by the Go builders and failing tests were unnoticed. Factoring mkmerge into its own package and removing ignore constraints makes the tests run automatically by the Go builders. Fixes golang/go#49484 Change-Id: I56a0b7220e40d1d7e5193490cb547cad4202f9ac Reviewed-on: https://go-review.googlesource.com/c/sys/+/363334 Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com> Reviewed-by: Bryan C. Mills <bcmills@google.com> Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com> Trust: Bryan C. Mills <bcmills@google.com> TryBot-Result: Go Bot <gobot@golang.org>
503 lines
11 KiB
Go
503 lines
11 KiB
Go
// 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.
|
|
|
|
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{{.}}
|
|
|
|
//go:build goos && 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{{.}}
|
|
|
|
//go:build goos && 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"))
|
|
}
|