-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
upgrade golang.org/x/tools, add integration tests #2
- Loading branch information
Showing
74 changed files
with
2,429 additions
and
7,399 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"io" | ||
"os" | ||
"path" | ||
"path/filepath" | ||
"strings" | ||
"sync" | ||
"testing" | ||
|
||
"github.com/flier/go-bitflags/internal/testenv" | ||
) | ||
|
||
// This file contains a test that compiles and runs each program in testdata | ||
// after generating the string method for its type. The rule is that for testdata/x.go | ||
// we run `bitflags -type X` and then compile and run the program. The resulting | ||
// binary panics if the String method for X is not correct, including for error cases. | ||
|
||
func TestMain(m *testing.M) { | ||
if os.Getenv("BITFLAGS_TEST_IS_BITFLAGS") != "" { | ||
main() | ||
os.Exit(0) | ||
} | ||
|
||
// Inform subprocesses that they should run the `cmd/bitflags` main instead of | ||
// running tests. It's a close approximation to building and running the real | ||
// command, and much less complicated and expensive to build and clean up. | ||
os.Setenv("BITFLAGS_TEST_IS_BITFLAGS", "1") | ||
|
||
flag.Parse() | ||
if testing.Verbose() { | ||
os.Setenv("GOPACKAGESDEBUG", "true") | ||
} | ||
|
||
os.Exit(m.Run()) | ||
} | ||
|
||
func TestEndToEnd(t *testing.T) { | ||
testenv.NeedsTool(t, "go") | ||
|
||
executable := executablePath(t) | ||
// Read the testdata directory. | ||
fd, err := os.Open("testdata") | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
defer fd.Close() | ||
names, err := fd.Readdirnames(-1) | ||
if err != nil { | ||
t.Fatalf("Readdirnames: %s", err) | ||
} | ||
// Generate, compile, and run the test programs. | ||
for _, name := range names { | ||
if name == "typeparams" { | ||
// ignore the directory containing the tests with type params | ||
continue | ||
} | ||
if !strings.HasSuffix(name, ".go") { | ||
t.Errorf("%s is not a Go file", name) | ||
continue | ||
} | ||
if strings.HasPrefix(name, "tag_") || strings.HasPrefix(name, "vary_") { | ||
// This file is used for tag processing in TestTags or TestConstValueChange, below. | ||
continue | ||
} | ||
t.Run(name, func(t *testing.T) { | ||
if name == "cgo.go" { | ||
testenv.NeedsTool(t, "cgo") | ||
} | ||
bitflagsCompileAndRun(t, t.TempDir(), executable, typeName(name), name) | ||
}) | ||
} | ||
} | ||
|
||
var exe struct { | ||
path string | ||
err error | ||
once sync.Once | ||
} | ||
|
||
func executablePath(t *testing.T) string { | ||
testenv.NeedsExec(t) | ||
|
||
exe.once.Do(func() { | ||
exe.path, exe.err = os.Executable() | ||
}) | ||
if exe.err != nil { | ||
t.Fatal(exe.err) | ||
} | ||
return exe.path | ||
} | ||
|
||
// a type name for stringer. use the last component of the file name with the .go | ||
func typeName(fname string) string { | ||
// file names are known to be ascii and end .go | ||
base := path.Base(fname) | ||
return fmt.Sprintf("%c%s", base[0]+'A'-'a', base[1:len(base)-len(".go")]) | ||
} | ||
|
||
// stringerCompileAndRun runs stringer for the named file and compiles and | ||
// runs the target binary in directory dir. That binary will panic if the String method is incorrect. | ||
func bitflagsCompileAndRun(t *testing.T, dir, executable, typeName, fileName string) { | ||
t.Logf("run: %s %s\n", fileName, typeName) | ||
source := filepath.Join(dir, path.Base(fileName)) | ||
err := copyFile(source, filepath.Join("testdata", fileName)) | ||
if err != nil { | ||
t.Fatalf("copying file to temporary directory: %s", err) | ||
} | ||
stringSource := filepath.Join(dir, typeName+"_string.go") | ||
// Run stringer in temporary directory. | ||
err = run(t, executable, "-type", typeName, "-output", stringSource, source) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
// Run the binary in the temporary directory. | ||
err = run(t, "go", "run", stringSource, source) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
} | ||
|
||
// copyFile copies the from file to the to file. | ||
func copyFile(to, from string) error { | ||
toFd, err := os.Create(to) | ||
if err != nil { | ||
return err | ||
} | ||
defer toFd.Close() | ||
fromFd, err := os.Open(from) | ||
if err != nil { | ||
return err | ||
} | ||
defer fromFd.Close() | ||
_, err = io.Copy(toFd, fromFd) | ||
return err | ||
} | ||
|
||
// run runs a single command and returns an error if it does not succeed. | ||
// os/exec should have this function, to be honest. | ||
func run(t testing.TB, name string, arg ...string) error { | ||
t.Helper() | ||
return runInDir(t, ".", name, arg...) | ||
} | ||
|
||
// runInDir runs a single command in directory dir and returns an error if | ||
// it does not succeed. | ||
func runInDir(t testing.TB, dir, name string, arg ...string) error { | ||
t.Helper() | ||
cmd := testenv.Command(t, name, arg...) | ||
cmd.Dir = dir | ||
cmd.Env = append(os.Environ(), "GO111MODULE=auto") | ||
out, err := cmd.CombinedOutput() | ||
if len(out) > 0 { | ||
t.Logf("%s", out) | ||
} | ||
if err != nil { | ||
return fmt.Errorf("%v: %v", cmd, err) | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
// Bitflags is a tool to automate the creation of methods that satisfy the fmt.Stringer | ||
// interface. Given the name of a (signed or unsigned) integer type T that has constants | ||
// defined, bitflags will create a new self-contained Go source file implementing | ||
// | ||
// func (t T) String() string | ||
// | ||
// The file is created in the same package and directory as the package that defines T. | ||
// It has helpful defaults designed for use with go generate. | ||
// | ||
|
@@ -95,25 +97,14 @@ type config struct { | |
} | ||
|
||
const ( | ||
prog = "bitflags" | ||
author = "Flier Lu <[email protected]>" | ||
repo = "https://github.com/flier/go-bitflags" | ||
summary = ` | ||
{{ .Name }} [flags] -type T [directory] | ||
{{ .Name }} [flags] -type T files... # Must be a single package | ||
For more information, see: | ||
https://github.com/flier/go-bitflags/cmd/bitflags` | ||
prog = "bitflags" | ||
author = "Flier Lu <[email protected]>" | ||
repo = "https://github.com/flier/go-bitflags" | ||
) | ||
|
||
func main() { | ||
var b strings.Builder | ||
template.Must(template.New("summary").Parse(summary)).Execute(&b, map[string]interface{}{"Name": prog}) | ||
summary := strings.TrimRight(b.String(), "\n") | ||
|
||
c := config{} | ||
opts.New(&c).Author(author).Summary(summary).Repo(repo).Parse() | ||
opts.New(&c).Summary(summary()).Repo(repo).Author(author).Parse() | ||
|
||
g := gen.New(c.TrimPrefix, c.LineComment) | ||
|
||
|
@@ -165,6 +156,15 @@ func main() { | |
} | ||
} | ||
|
||
func summary() string { | ||
var b strings.Builder | ||
template.Must(template.New("summary").Parse(` | ||
{{ .Name }} [flags] -type T [directory] | ||
{{ .Name }} [flags] -type T files... # Must be a single package | ||
`)).Execute(&b, map[string]interface{}{"Name": prog}) | ||
return strings.Trim(b.String(), "\n") | ||
} | ||
|
||
func isDirectory(name string) bool { | ||
info, err := os.Stat(name) | ||
if err != nil { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,15 @@ | ||
module github.com/flier/go-bitflags | ||
|
||
go 1.16 | ||
go 1.18 | ||
|
||
require ( | ||
github.com/jpillora/opts v1.2.0 | ||
golang.org/x/mod v0.15.0 | ||
golang.org/x/tools v0.18.0 | ||
) | ||
|
||
require ( | ||
github.com/hashicorp/errwrap v1.1.0 // indirect | ||
github.com/hashicorp/go-multierror v1.1.1 // indirect | ||
github.com/jpillora/opts v1.2.0 | ||
github.com/posener/complete v1.2.3 // indirect | ||
golang.org/x/sys v0.1.0 // indirect | ||
golang.org/x/tools v0.1.8 | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
// Copyright 2022 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 goroot is a copy of package internal/goroot | ||
// in the main GO repot. It provides a utility to produce | ||
// an importcfg and import path to package file map mapping | ||
// standard library packages to the locations of their export | ||
// data files. | ||
package goroot | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"os/exec" | ||
"strings" | ||
"sync" | ||
) | ||
|
||
// Importcfg returns an importcfg file to be passed to the | ||
// Go compiler that contains the cached paths for the .a files for the | ||
// standard library. | ||
func Importcfg() (string, error) { | ||
var icfg bytes.Buffer | ||
|
||
m, err := PkgfileMap() | ||
if err != nil { | ||
return "", err | ||
} | ||
fmt.Fprintf(&icfg, "# import config") | ||
for importPath, export := range m { | ||
fmt.Fprintf(&icfg, "\npackagefile %s=%s", importPath, export) | ||
} | ||
s := icfg.String() | ||
return s, nil | ||
} | ||
|
||
var ( | ||
stdlibPkgfileMap map[string]string | ||
stdlibPkgfileErr error | ||
once sync.Once | ||
) | ||
|
||
// PkgfileMap returns a map of package paths to the location on disk | ||
// of the .a file for the package. | ||
// The caller must not modify the map. | ||
func PkgfileMap() (map[string]string, error) { | ||
once.Do(func() { | ||
m := make(map[string]string) | ||
output, err := exec.Command("go", "list", "-export", "-e", "-f", "{{.ImportPath}} {{.Export}}", "std", "cmd").Output() | ||
if err != nil { | ||
stdlibPkgfileErr = err | ||
} | ||
for _, line := range strings.Split(string(output), "\n") { | ||
if line == "" { | ||
continue | ||
} | ||
sp := strings.SplitN(line, " ", 2) | ||
if len(sp) != 2 { | ||
err = fmt.Errorf("determining pkgfile map: invalid line in go list output: %q", line) | ||
return | ||
} | ||
importPath, export := sp[0], sp[1] | ||
if export != "" { | ||
m[importPath] = export | ||
} | ||
} | ||
stdlibPkgfileMap = m | ||
}) | ||
return stdlibPkgfileMap, stdlibPkgfileErr | ||
} |
Oops, something went wrong.