From 349af1589b539703469de100beeac1b45a2a0d54 Mon Sep 17 00:00:00 2001 From: Carolyn Van Slyck Date: Sat, 9 Mar 2019 21:08:45 -0600 Subject: [PATCH 01/12] scaffolding --- main.go | 4 ++++ src/cmd/tinygo/test/test.go | 41 +++++++++++++++++++++++++++++++++++++ src/testing/testing.go | 13 ++++++++++++ src/testing/testmain.go | 9 ++++++++ 4 files changed, 67 insertions(+) create mode 100644 src/cmd/tinygo/test/test.go create mode 100644 src/testing/testing.go create mode 100644 src/testing/testmain.go diff --git a/main.go b/main.go index 4eaa359cbd..b8d210844d 100644 --- a/main.go +++ b/main.go @@ -19,6 +19,7 @@ import ( "github.com/tinygo-org/tinygo/compiler" "github.com/tinygo-org/tinygo/interp" "github.com/tinygo-org/tinygo/loader" + "github.com/tinygo-org/tinygo/src/cmd/tinygo/test" ) // commandError is an error type to wrap os/exec.Command errors. This provides @@ -656,6 +657,9 @@ func main() { } err := Run(flag.Arg(0), *target, config) handleCompilerError(err) + case "test": + test.RunTests() + os.Exit(0) case "clean": // remove cache directory dir := cacheDir() diff --git a/src/cmd/tinygo/test/test.go b/src/cmd/tinygo/test/test.go new file mode 100644 index 0000000000..287ee619a1 --- /dev/null +++ b/src/cmd/tinygo/test/test.go @@ -0,0 +1,41 @@ +package test + +import ( + "fmt" + "os" + "path/filepath" + "strings" +) + +func RunTests() error { + _, err := findTestFiles() + if err != nil { + return err + } + + return nil +} + +func findTestFiles() ([]string, error) { + var testFiles []string + err := filepath.Walk(".", func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if info.IsDir() { + return nil + } + + if strings.HasSuffix(info.Name(), "_test.go") { + fmt.Println(path) + testFiles = append(testFiles, path) + } + + return nil + }) + if err != nil { + return nil, err + } + return testFiles, nil +} \ No newline at end of file diff --git a/src/testing/testing.go b/src/testing/testing.go new file mode 100644 index 0000000000..a2acf3f600 --- /dev/null +++ b/src/testing/testing.go @@ -0,0 +1,13 @@ +package testing + +import ( + "fmt" +) + +type T struct { + +} + +func (t *T) Fatal(args ...string) { + fmt.Println(args) +} \ No newline at end of file diff --git a/src/testing/testmain.go b/src/testing/testmain.go new file mode 100644 index 0000000000..8ab2f2dc22 --- /dev/null +++ b/src/testing/testmain.go @@ -0,0 +1,9 @@ +package testing + +import ( + "fmt" +) + +func TestMain() { + fmt.Println("running tests") +} From 38122d8ffaa513e82cd524e8cdfabfa7ecccb640 Mon Sep 17 00:00:00 2001 From: Carolyn Van Slyck Date: Sat, 9 Mar 2019 22:04:22 -0600 Subject: [PATCH 02/12] getpackageroot --- main.go | 3 +-- target.go | 24 +++++++++++++++++++ target_test.go | 32 ++++++++++++++++++++++++++ src/cmd/tinygo/test/test.go => test.go | 10 ++++++-- 4 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 target_test.go rename src/cmd/tinygo/test/test.go => test.go (84%) diff --git a/main.go b/main.go index b8d210844d..2dcb461870 100644 --- a/main.go +++ b/main.go @@ -19,7 +19,6 @@ import ( "github.com/tinygo-org/tinygo/compiler" "github.com/tinygo-org/tinygo/interp" "github.com/tinygo-org/tinygo/loader" - "github.com/tinygo-org/tinygo/src/cmd/tinygo/test" ) // commandError is an error type to wrap os/exec.Command errors. This provides @@ -658,7 +657,7 @@ func main() { err := Run(flag.Arg(0), *target, config) handleCompilerError(err) case "test": - test.RunTests() + RunTests() os.Exit(0) case "clean": // remove cache directory diff --git a/target.go b/target.go index d732e716bd..f689f95939 100644 --- a/target.go +++ b/target.go @@ -303,6 +303,30 @@ func getGopath() string { return filepath.Join(home, "go") } +func getPackageRoot() (string, error) { + wd, err := os.Getwd() + if err != nil { + return "", err + } + if rwd, err := filepath.EvalSymlinks(wd); err == nil { + wd = rwd + } + + // TODO: This assumes a single gopath + // A more robust solution can be found in golang/dep, and probably golang/go. + // See https://github.com/golang/dep/blob/9227ca64191910befb850cfc4dc85fd93e12ba68/context.go#L256 + gopath := getGopath() + if rgopath, err := filepath.EvalSymlinks(gopath); err == nil { + gopath = rgopath + } + + src := filepath.Join(gopath, "src") + string(os.PathSeparator) + if strings.HasPrefix(wd, src) { + return strings.TrimPrefix(wd, src), nil + } + return "", fmt.Errorf("could not determine the package root from the current directory %q and gopath %q", wd, gopath) +} + func getHomeDir() string { u, err := user.Current() if err != nil { diff --git a/target_test.go b/target_test.go new file mode 100644 index 0000000000..1244af2cf8 --- /dev/null +++ b/target_test.go @@ -0,0 +1,32 @@ +package main + +import ( + "os" + "path/filepath" + "testing" +) + +func TestGetPackageRoot(t *testing.T) { + wantRoot := "github.com/my/root" + + gopath := os.TempDir() + defer os.Unsetenv("GOPATH") + os.Setenv("GOPATH", gopath) + wd := filepath.Join(gopath, "src", wantRoot) + err := os.MkdirAll(wd, 0755) + if err != nil { + t.Fatal(err) + } + err = os.Chdir(wd) + if err != nil { + t.Fatal(err) + } + + gotRoot, err := getPackageRoot() + if err != nil { + t.Fatal(err) + } + if gotRoot != wantRoot { + t.Fatalf("want %q got %q", wantRoot, gotRoot) + } +} diff --git a/src/cmd/tinygo/test/test.go b/test.go similarity index 84% rename from src/cmd/tinygo/test/test.go rename to test.go index 287ee619a1..ac0e4f92df 100644 --- a/src/cmd/tinygo/test/test.go +++ b/test.go @@ -1,4 +1,4 @@ -package test +package main import ( "fmt" @@ -8,7 +8,13 @@ import ( ) func RunTests() error { - _, err := findTestFiles() + + _, err := getPackageRoot() + if err != nil { + return err + } + + _, err = findTestFiles() if err != nil { return err } From 216b30368d19425e4ff2b39479d0d7b01ef53755 Mon Sep 17 00:00:00 2001 From: Carolyn Van Slyck Date: Sun, 17 Mar 2019 21:45:27 -0500 Subject: [PATCH 03/12] Add test command to tinygo * Test command passes flag to compile indicating that a test binary should be built * Adds the test build tag * Imports packages from test files Stuck on how to find the TestMain that I have defined in my test file. It is coming back nil. Not sure how I would reflect on the functions defined in the test files and then build up the test suite (M) in a basic block. First step I figured was calling a simple predefined test suite though. --- Makefile | 5 ++++ compiler/compiler.go | 40 +++++++++++++++++++++----------- loader/loader.go | 37 ++++++++++++++++++++++-------- main.go | 51 +++++++++++++++++++++++++++++++++-------- src/reflect/value.go | 2 +- src/testing/doc.go | 6 +++++ src/testing/testing.go | 45 ++++++++++++++++++++++++++++++++++-- src/testing/testmain.go | 9 -------- 8 files changed, 150 insertions(+), 45 deletions(-) create mode 100644 src/testing/doc.go delete mode 100644 src/testing/testmain.go diff --git a/Makefile b/Makefile index c65fa7d27f..c487422acd 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,7 @@ fmt: fmt-check: @unformatted=$$(gofmt -l $(FMT_PATHS)); [ -z "$$unformatted" ] && exit 0; echo "Unformatted:"; for fn in $$unformatted; do echo " $$fn"; done; exit 1 + gen-device: gen-device-avr gen-device-nrf gen-device-sam gen-device-stm32 gen-device-avr: @@ -84,6 +85,10 @@ build/tinygo: test: CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" go test -v -tags byollvm . + $(MAKE) tinygo-test + +tinygo-test: build/tinygo + cd tests/example1 && ../../build/tinygo test .PHONY: smoketest smoketest-no-avr smoketest: smoketest-no-avr diff --git a/compiler/compiler.go b/compiler/compiler.go index 27ee530bc9..cb22b0cde3 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -32,22 +32,28 @@ const tinygoPath = "github.com/tinygo-org/tinygo" // Configure the compiler. type Config struct { - Triple string // LLVM target triple, e.g. x86_64-unknown-linux-gnu (empty string means default) - CPU string // LLVM CPU name, e.g. atmega328p (empty string means default) + Triple string // LLVM target triple, e.g. x86_64-unknown-linux-gnu (empty string means default) + CPU string // LLVM CPU name, e.g. atmega328p (empty string means default) Features []string // LLVM CPU features - GOOS string // - GOARCH string // - GC string // garbage collection strategy + GOOS string // + GOARCH string // + GC string // garbage collection strategy PanicStrategy string // panic strategy ("abort" or "trap") - CFlags []string // cflags to pass to cgo - LDFlags []string // ldflags to pass to cgo + CFlags []string // cflags to pass to cgo + LDFlags []string // ldflags to pass to cgo ClangHeaders string // Clang built-in header include path - DumpSSA bool // dump Go SSA, for compiler debugging - Debug bool // add debug symbols for gdb + DumpSSA bool // dump Go SSA, for compiler debugging + Debug bool // add debug symbols for gdb GOROOT string // GOROOT TINYGOROOT string // GOROOT for TinyGo - GOPATH string // GOPATH, like `go env GOPATH` - BuildTags []string // build tags for TinyGo (empty means {Config.GOOS/Config.GOARCH}) + GOPATH string // GOPATH, like `go env GOPATH` + BuildTags []string // build tags for TinyGo (empty means {Config.GOOS/Config.GOARCH}) + TestConfig TestConfig +} + +type TestConfig struct { + CompileTestBinary bool + // TODO: Filter the test functions to run, include verbose flag, etc } type Compiler struct { @@ -252,12 +258,13 @@ func (c *Compiler) Compile(mainPath string) []error { return []error{err} } } + _, err = lprogram.Import("runtime", "") if err != nil { return []error{err} } - err = lprogram.Parse() + err = lprogram.Parse(c.TestConfig.CompileTestBinary) if err != nil { return []error{err} } @@ -324,9 +331,16 @@ func (c *Compiler) Compile(mainPath string) []error { } c.builder.CreateRetVoid() + realMain := c.mod.NamedFunction(c.ir.MainPkg().Pkg.Path() + ".main") + + // Swap the main impl with the TestMain block + // TODO: generate a TestMain + //l := c.mod.NamedFunction(c.ir.MainPkg().Pkg.Path() + ".TestMain") + // TODO: why is this nil? + //fmt.Println("DEBUG TestMain: ", l) + // Conserve for goroutine lowering. Without marking these as external, they // would be optimized away. - realMain := c.mod.NamedFunction(c.ir.MainPkg().Pkg.Path() + ".main") realMain.SetLinkage(llvm.ExternalLinkage) // keep alive until goroutine lowering c.mod.NamedFunction("runtime.alloc").SetLinkage(llvm.ExternalLinkage) c.mod.NamedFunction("runtime.free").SetLinkage(llvm.ExternalLinkage) diff --git a/loader/loader.go b/loader/loader.go index cfa81e99f8..9c1aec97e3 100644 --- a/loader/loader.go +++ b/loader/loader.go @@ -64,6 +64,7 @@ func (p *Program) Import(path, srcDir string) (*Package, error) { p.sorted = nil // invalidate the sorted order of packages pkg := p.newPackage(buildPkg) p.Packages[buildPkg.ImportPath] = pkg + return pkg, nil } @@ -171,10 +172,10 @@ func (p *Program) sort() { // The returned error may be an Errors error, which contains a list of errors. // // Idempotent. -func (p *Program) Parse() error { +func (p *Program) Parse(includeTests bool) error { // Load all imports for _, pkg := range p.Sorted() { - err := pkg.importRecursively() + err := pkg.importRecursively(includeTests) if err != nil { if err, ok := err.(*ImportCycleError); ok { if pkg.ImportPath != err.Packages[0] { @@ -187,7 +188,7 @@ func (p *Program) Parse() error { // Parse all packages. for _, pkg := range p.Sorted() { - err := pkg.Parse() + err := pkg.Parse(includeTests) if err != nil { return err } @@ -228,7 +229,7 @@ func (p *Program) parseFile(path string, mode parser.Mode) (*ast.File, error) { // Parse parses and typechecks this package. // // Idempotent. -func (p *Package) Parse() error { +func (p *Package) Parse(includeTests bool) error { if len(p.Files) != 0 { return nil } @@ -242,7 +243,7 @@ func (p *Package) Parse() error { return nil } - files, err := p.parseFiles() + files, err := p.parseFiles(includeTests) if err != nil { return err } @@ -281,11 +282,21 @@ func (p *Package) Check() error { } // parseFiles parses the loaded list of files and returns this list. -func (p *Package) parseFiles() ([]*ast.File, error) { +func (p *Package) parseFiles(includeTests bool) ([]*ast.File, error) { // TODO: do this concurrently. var files []*ast.File var fileErrs []error - for _, file := range p.GoFiles { + + var gofiles []string + if includeTests { + gofiles = make([]string, 0, len(p.GoFiles)+len(p.TestGoFiles)) + gofiles = append(gofiles, p.GoFiles...) + gofiles = append(gofiles, p.TestGoFiles...) + } else { + gofiles = p.GoFiles + } + + for _, file := range gofiles { f, err := p.parseFile(filepath.Join(p.Package.Dir, file), parser.ParseComments) if err != nil { fileErrs = append(fileErrs, err) @@ -340,9 +351,15 @@ func (p *Package) Import(to string) (*types.Package, error) { // importRecursively() on the imported packages as well. // // Idempotent. -func (p *Package) importRecursively() error { +func (p *Package) importRecursively(includeTests bool) error { p.Importing = true - for _, to := range p.Package.Imports { + + imports := p.Package.Imports + if includeTests { + imports = append(imports, p.Package.TestImports...) + } + + for _, to := range imports { if to == "C" { // Do CGo processing in a later stage. continue @@ -360,7 +377,7 @@ func (p *Package) importRecursively() error { if importedPkg.Importing { return &ImportCycleError{[]string{p.ImportPath, importedPkg.ImportPath}, p.ImportPos[to]} } - err = importedPkg.importRecursively() + err = importedPkg.importRecursively(includeTests) if err != nil { if err, ok := err.(*ImportCycleError); ok { err.Packages = append([]string{p.ImportPath}, err.Packages...) diff --git a/main.go b/main.go index 2dcb461870..de2f1c327b 100644 --- a/main.go +++ b/main.go @@ -54,6 +54,7 @@ type BuildConfig struct { cFlags []string ldFlags []string wasmAbi string + testConfig compiler.TestConfig } // Helper function for Compiler object. @@ -92,22 +93,23 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act tags = append(tags, fmt.Sprintf("go1.%d", i)) } compilerConfig := compiler.Config{ - Triple: spec.Triple, - CPU: spec.CPU, + Triple: spec.Triple, + CPU: spec.CPU, Features: spec.Features, - GOOS: spec.GOOS, - GOARCH: spec.GOARCH, - GC: config.gc, + GOOS: spec.GOOS, + GOARCH: spec.GOARCH, + GC: config.gc, PanicStrategy: config.panicStrategy, CFlags: cflags, LDFlags: ldflags, ClangHeaders: getClangHeaderPath(root), - Debug: config.debug, - DumpSSA: config.dumpSSA, + Debug: config.debug, + DumpSSA: config.dumpSSA, TINYGOROOT: root, GOROOT: goroot, - GOPATH: getGopath(), + GOPATH: getGopath(), BuildTags: tags, + TestConfig: config.testConfig, } c, err := compiler.NewCompiler(pkgName, compilerConfig) if err != nil { @@ -349,6 +351,30 @@ func Build(pkgName, outpath, target string, config *BuildConfig) error { }) } +func Test(pkgName, target string, config *BuildConfig) error { + spec, err := LoadTarget(target) + if err != nil { + return err + } + + spec.BuildTags = append(spec.BuildTags, "test") + config.testConfig.CompileTestBinary = true + return Compile(pkgName, ".elf", spec, config, func(tmppath string) error { + cmd := exec.Command(tmppath) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err := cmd.Run() + if err != nil { + if err, ok := err.(*exec.ExitError); ok && err.Exited() { + // Workaround for QEMU which always exits with an error. + return nil + } + return &commandError{"failed to run compiled binary", tmppath, err} + } + return nil + }) +} + func Flash(pkgName, target, port string, config *BuildConfig) error { spec, err := LoadTarget(target) if err != nil { @@ -657,8 +683,13 @@ func main() { err := Run(flag.Arg(0), *target, config) handleCompilerError(err) case "test": - RunTests() - os.Exit(0) + pkgRoot, err := getPackageRoot() + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + err = Test(pkgRoot, *target, config) + handleCompilerError(err) case "clean": // remove cache directory dir := cacheDir() diff --git a/src/reflect/value.go b/src/reflect/value.go index 51128b81e9..577a944ba4 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -92,7 +92,7 @@ func (v Value) Pointer() uintptr { } func (v Value) IsValid() bool { - panic("unimplemented: (reflect.Value).IsValid()") + return v.typecode != 0 } func (v Value) CanInterface() bool { diff --git a/src/testing/doc.go b/src/testing/doc.go new file mode 100644 index 0000000000..b5026d8062 --- /dev/null +++ b/src/testing/doc.go @@ -0,0 +1,6 @@ +package testing + +/* + This is a sad stub of the upstream testing package because it doesn't compile + with tinygo right now. +*/ diff --git a/src/testing/testing.go b/src/testing/testing.go index a2acf3f600..1d8891e17f 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -4,10 +4,51 @@ import ( "fmt" ) +// T is a test helper. type T struct { +} + +// TestToCall is a reference to a test that should be called during a test suite run. +type TestToCall struct { + // Name of the test to call. + Name string + // Function reference to the test. + Func func(*T) +} + +// M is a test suite. +type M struct { + // tests is a list of the test names to execute + Tests []TestToCall +} +// Run the test suite. +func (m *M) Run() int { + for _, test := range m.Tests { + t := &T{} + test.Func(t) + } + // TODO: detect failures and return a failing exit code + // Right now we can't handle one anyway so it doesn't matter much + return 0 } +// Fatal is equivalent to Log followed by FailNow func (t *T) Fatal(args ...string) { - fmt.Println(args) -} \ No newline at end of file + // This doesn't print the same as in upstream go, but works good enough + fmt.Print(args) + //t.FailNow() +} + +/* +func (t *T) FailNow() { + // This fails with +Undefined symbols for architecture x86_64: +"_syscall.Exit", referenced from: + _main in main.o +ld: symbol(s) not found for architecture x86_64 +clang: error: linker command failed with exit code 1 (use -v to see invocation) +error: failed to link /var/folders/_t/fbw4wf_s42dfqdfjq7shdfm40000gn/T/tinygo382510652/main: exit status 1 + os.Exit(12) +} +*/ diff --git a/src/testing/testmain.go b/src/testing/testmain.go deleted file mode 100644 index 8ab2f2dc22..0000000000 --- a/src/testing/testmain.go +++ /dev/null @@ -1,9 +0,0 @@ -package testing - -import ( - "fmt" -) - -func TestMain() { - fmt.Println("running tests") -} From 104c1d794309c04acfd3367cf0ad521f68db8f45 Mon Sep 17 00:00:00 2001 From: Carolyn Van Slyck Date: Sun, 24 Mar 2019 13:05:18 -0500 Subject: [PATCH 04/12] Call TestMain instead of main --- compiler/compiler.go | 12 ++------ loader/loader.go | 61 ++++++++++++++++++++++++++++++++++++- src/testing/testing.go | 30 ++++++++---------- tests/example1/main.go | 14 +++++++++ tests/example1/main_test.go | 22 +++++++++++++ 5 files changed, 112 insertions(+), 27 deletions(-) create mode 100644 tests/example1/main.go create mode 100644 tests/example1/main_test.go diff --git a/compiler/compiler.go b/compiler/compiler.go index cb22b0cde3..30706cdbfe 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -220,7 +220,7 @@ func (c *Compiler) Compile(mainPath string) []error { path = path[len(tinygoPath+"/src/"):] } switch path { - case "machine", "os", "reflect", "runtime", "runtime/volatile", "sync": + case "machine", "os", "reflect", "runtime", "runtime/volatile", "sync", "testing": return path default: if strings.HasPrefix(path, "device/") || strings.HasPrefix(path, "examples/") { @@ -247,6 +247,7 @@ func (c *Compiler) Compile(mainPath string) []error { CFlags: c.CFlags, ClangHeaders: c.ClangHeaders, } + if strings.HasSuffix(mainPath, ".go") { _, err = lprogram.ImportFile(mainPath) if err != nil { @@ -331,16 +332,9 @@ func (c *Compiler) Compile(mainPath string) []error { } c.builder.CreateRetVoid() - realMain := c.mod.NamedFunction(c.ir.MainPkg().Pkg.Path() + ".main") - - // Swap the main impl with the TestMain block - // TODO: generate a TestMain - //l := c.mod.NamedFunction(c.ir.MainPkg().Pkg.Path() + ".TestMain") - // TODO: why is this nil? - //fmt.Println("DEBUG TestMain: ", l) - // Conserve for goroutine lowering. Without marking these as external, they // would be optimized away. + realMain := c.mod.NamedFunction(c.ir.MainPkg().Pkg.Path() + ".main") realMain.SetLinkage(llvm.ExternalLinkage) // keep alive until goroutine lowering c.mod.NamedFunction("runtime.alloc").SetLinkage(llvm.ExternalLinkage) c.mod.NamedFunction("runtime.free").SetLinkage(llvm.ExternalLinkage) diff --git a/loader/loader.go b/loader/loader.go index 9c1aec97e3..f4f26096da 100644 --- a/loader/loader.go +++ b/loader/loader.go @@ -1,6 +1,7 @@ package loader import ( + "bytes" "errors" "go/ast" "go/build" @@ -16,6 +17,7 @@ import ( // Program holds all packages and some metadata about the program as a whole. type Program struct { + mainPkg string Build *build.Context OverlayBuild *build.Context OverlayPath func(path string) string @@ -65,6 +67,10 @@ func (p *Program) Import(path, srcDir string) (*Package, error) { pkg := p.newPackage(buildPkg) p.Packages[buildPkg.ImportPath] = pkg + if p.mainPkg == "" { + p.mainPkg = buildPkg.ImportPath + } + return pkg, nil } @@ -94,6 +100,11 @@ func (p *Program) ImportFile(path string) (*Package, error) { p.sorted = nil // invalidate the sorted order of packages pkg := p.newPackage(buildPkg) p.Packages[buildPkg.ImportPath] = pkg + + if p.mainPkg == "" { + p.mainPkg = buildPkg.ImportPath + } + return pkg, nil } @@ -172,7 +183,9 @@ func (p *Program) sort() { // The returned error may be an Errors error, which contains a list of errors. // // Idempotent. -func (p *Program) Parse(includeTests bool) error { +func (p *Program) Parse(compileTestBinary bool) error { + includeTests := compileTestBinary + // Load all imports for _, pkg := range p.Sorted() { err := pkg.importRecursively(includeTests) @@ -194,6 +207,10 @@ func (p *Program) Parse(includeTests bool) error { } } + if compileTestBinary { + p.SwapTestMain() + } + // Typecheck all packages. for _, pkg := range p.Sorted() { err := pkg.Check() @@ -205,6 +222,47 @@ func (p *Program) Parse(includeTests bool) error { return nil } +func (p *Program) SwapTestMain() error { + mainPkg := p.Packages[p.mainPkg] + for _, f := range mainPkg.Files { + for i, d := range f.Decls { + switch v := d.(type) { + case *ast.FuncDecl: + if v.Name.Name == "main" { + // Remove main + if len(f.Decls) == 1 { + f.Decls = make([]ast.Decl, 0) + } else { + f.Decls[i] = f.Decls[len(f.Decls)-1] + f.Decls = f.Decls[:len(f.Decls)-1] + } + } + } + } + } + + // TODO: generate a new main all fancy like, but for now assume that they wrote one + const mainBody = `package main +func main () { + TestMain() +} +` + b := bytes.NewBufferString(mainBody) + path := filepath.Join(p.mainPkg, "$testmain.go") + + if p.fset == nil { + p.fset = token.NewFileSet() + } + + newMain, err := parser.ParseFile(p.fset, path, b, parser.ParseComments) + if err != nil { + return err + } + mainPkg.Files = append(mainPkg.Files, newMain) + + return nil +} + // parseFile is a wrapper around parser.ParseFile. func (p *Program) parseFile(path string, mode parser.Mode) (*ast.File, error) { if p.fset == nil { @@ -331,6 +389,7 @@ func (p *Package) parseFiles(includeTests bool) ([]*ast.File, error) { if len(fileErrs) != 0 { return nil, Errors{p, fileErrs} } + return files, nil } diff --git a/src/testing/testing.go b/src/testing/testing.go index 1d8891e17f..45f451fc70 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -6,6 +6,9 @@ import ( // T is a test helper. type T struct { + + // flags the test as having failed when non-zero + failed int } // TestToCall is a reference to a test that should be called during a test suite run. @@ -24,31 +27,24 @@ type M struct { // Run the test suite. func (m *M) Run() int { + failures := 0 for _, test := range m.Tests { t := &T{} test.Func(t) + + failures += t.failed } - // TODO: detect failures and return a failing exit code - // Right now we can't handle one anyway so it doesn't matter much - return 0 + + return failures } -// Fatal is equivalent to Log followed by FailNow -func (t *T) Fatal(args ...string) { +// Fatal is equivalent to Log followed by Fail +func (t *T) Error(args ...string) { // This doesn't print the same as in upstream go, but works good enough fmt.Print(args) - //t.FailNow() + t.Fail() } -/* -func (t *T) FailNow() { - // This fails with -Undefined symbols for architecture x86_64: -"_syscall.Exit", referenced from: - _main in main.o -ld: symbol(s) not found for architecture x86_64 -clang: error: linker command failed with exit code 1 (use -v to see invocation) -error: failed to link /var/folders/_t/fbw4wf_s42dfqdfjq7shdfm40000gn/T/tinygo382510652/main: exit status 1 - os.Exit(12) +func (t *T) Fail() { + t.failed = 1 } -*/ diff --git a/tests/example1/main.go b/tests/example1/main.go new file mode 100644 index 0000000000..84ed970002 --- /dev/null +++ b/tests/example1/main.go @@ -0,0 +1,14 @@ +package main + +import ( + "fmt" +) + +func main() { + Thing() + fmt.Println("normal main") +} + +func Thing() { + fmt.Println("THING") +} diff --git a/tests/example1/main_test.go b/tests/example1/main_test.go new file mode 100644 index 0000000000..48f9a0256b --- /dev/null +++ b/tests/example1/main_test.go @@ -0,0 +1,22 @@ +package main + +import ( + "fmt" + "os" + "testing" // This is the tinygo testing package +) + +func TestFoo(t *testing.T) { + t.Error("test failed\n") +} + +// TODO: change signature to accept a prepopulated test suite +func TestMain() { + fmt.Println("running tests...") + m := testing.M{ + Tests: []testing.TestToCall{ + {Name: "TestFoo", Func: TestFoo}, + }, + } + os.Exit(m.Run()) +} From 076c4fb880ddf1f4e57f52b90b0f4af07766a29d Mon Sep 17 00:00:00 2001 From: Carolyn Van Slyck Date: Mon, 22 Apr 2019 22:02:11 -0500 Subject: [PATCH 05/12] Call TestMain with the proper signature This is currently failing with panic: interface conversion: ssa.Member is nil, not *ssa.Function --- loader/loader.go | 43 +++++++++++++++++++++++++++++++++++-- tests/example1/main_test.go | 7 +----- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/loader/loader.go b/loader/loader.go index f4f26096da..8cfc62b45b 100644 --- a/loader/loader.go +++ b/loader/loader.go @@ -3,6 +3,7 @@ package loader import ( "bytes" "errors" + "fmt" "go/ast" "go/build" "go/parser" @@ -11,6 +12,8 @@ import ( "os" "path/filepath" "sort" + "strings" + "text/template" "github.com/tinygo-org/tinygo/cgo" ) @@ -223,11 +226,23 @@ func (p *Program) Parse(compileTestBinary bool) error { } func (p *Program) SwapTestMain() error { + var tests []string + + isTestFunc := func(f *ast.FuncDecl) bool { + // TODO: improve signature check + if strings.HasPrefix(f.Name.Name, "Test") && f.Name.Name != "TestMain" { + return true + } + return false + } mainPkg := p.Packages[p.mainPkg] for _, f := range mainPkg.Files { for i, d := range f.Decls { switch v := d.(type) { case *ast.FuncDecl: + if isTestFunc(v) { + tests = append(tests, v.Name.Name) + } if v.Name.Name == "main" { // Remove main if len(f.Decls) == 1 { @@ -243,11 +258,35 @@ func (p *Program) SwapTestMain() error { // TODO: generate a new main all fancy like, but for now assume that they wrote one const mainBody = `package main + func main () { - TestMain() + m := &testing.M{ + Tests: []testing.TestToCall{ +{{range .TestFunctions}} + {Name: "{{.}}", Func: {{.}}}, +{{end}} + }, + } + TestMain(m) } ` - b := bytes.NewBufferString(mainBody) + tmpl := template.Must(template.New("testmain").Parse(mainBody)) + b := bytes.Buffer{} + tmplData := struct { + // NOTE: this isn't necessary when we are only testing the main package + // but will be needed later when we are testing multiple packages + TestPkg string + TestFunctions []string + }{ + TestFunctions: tests, + } + + err := tmpl.Execute(&b, tmplData) + if err != nil { + return err + } + fmt.Println("DEBUG: TEST MAIN CONTENTS") + fmt.Println(string(b.Bytes())) path := filepath.Join(p.mainPkg, "$testmain.go") if p.fset == nil { diff --git a/tests/example1/main_test.go b/tests/example1/main_test.go index 48f9a0256b..14ddda32c3 100644 --- a/tests/example1/main_test.go +++ b/tests/example1/main_test.go @@ -11,12 +11,7 @@ func TestFoo(t *testing.T) { } // TODO: change signature to accept a prepopulated test suite -func TestMain() { +func TestMain(m *testing.M) { fmt.Println("running tests...") - m := testing.M{ - Tests: []testing.TestToCall{ - {Name: "TestFoo", Func: TestFoo}, - }, - } os.Exit(m.Run()) } From 1ef3b603c0ea3980b5d759e1ddaa7290609bee9d Mon Sep 17 00:00:00 2001 From: Carolyn Van Slyck Date: Sun, 26 May 2019 09:16:51 -0500 Subject: [PATCH 06/12] Fix running tests --- loader/loader.go | 24 +++++++++++++----------- src/testing/testing.go | 5 +++++ tests/example1/main_test.go | 10 +--------- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/loader/loader.go b/loader/loader.go index 8cfc62b45b..39942b7137 100644 --- a/loader/loader.go +++ b/loader/loader.go @@ -3,7 +3,6 @@ package loader import ( "bytes" "errors" - "fmt" "go/ast" "go/build" "go/parser" @@ -20,7 +19,7 @@ import ( // Program holds all packages and some metadata about the program as a whole. type Program struct { - mainPkg string + mainPkg string Build *build.Context OverlayBuild *build.Context OverlayPath func(path string) string @@ -211,7 +210,10 @@ func (p *Program) Parse(compileTestBinary bool) error { } if compileTestBinary { - p.SwapTestMain() + err := p.SwapTestMain() + if err != nil { + return err + } } // Typecheck all packages. @@ -256,9 +258,13 @@ func (p *Program) SwapTestMain() error { } } - // TODO: generate a new main all fancy like, but for now assume that they wrote one + // TODO: Check if they defined a TestMain and call it instead of testing.TestMain const mainBody = `package main +import ( + "testing" +) + func main () { m := &testing.M{ Tests: []testing.TestToCall{ @@ -267,15 +273,13 @@ func main () { {{end}} }, } - TestMain(m) + + testing.TestMain(m) } ` tmpl := template.Must(template.New("testmain").Parse(mainBody)) b := bytes.Buffer{} tmplData := struct { - // NOTE: this isn't necessary when we are only testing the main package - // but will be needed later when we are testing multiple packages - TestPkg string TestFunctions []string }{ TestFunctions: tests, @@ -285,15 +289,13 @@ func main () { if err != nil { return err } - fmt.Println("DEBUG: TEST MAIN CONTENTS") - fmt.Println(string(b.Bytes())) path := filepath.Join(p.mainPkg, "$testmain.go") if p.fset == nil { p.fset = token.NewFileSet() } - newMain, err := parser.ParseFile(p.fset, path, b, parser.ParseComments) + newMain, err := parser.ParseFile(p.fset, path, b.Bytes(), parser.AllErrors) if err != nil { return err } diff --git a/src/testing/testing.go b/src/testing/testing.go index 45f451fc70..47fc994a2e 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -2,6 +2,7 @@ package testing import ( "fmt" + "os" ) // T is a test helper. @@ -38,6 +39,10 @@ func (m *M) Run() int { return failures } +func TestMain(m *M) { + os.Exit(m.Run()) +} + // Fatal is equivalent to Log followed by Fail func (t *T) Error(args ...string) { // This doesn't print the same as in upstream go, but works good enough diff --git a/tests/example1/main_test.go b/tests/example1/main_test.go index 14ddda32c3..5f227ccc9e 100644 --- a/tests/example1/main_test.go +++ b/tests/example1/main_test.go @@ -1,17 +1,9 @@ package main import ( - "fmt" - "os" "testing" // This is the tinygo testing package ) func TestFoo(t *testing.T) { - t.Error("test failed\n") -} - -// TODO: change signature to accept a prepopulated test suite -func TestMain(m *testing.M) { - fmt.Println("running tests...") - os.Exit(m.Run()) + t.Error("TestFoo failed because of stuff and things") } From 7edfa9636497f9bb8c0cf523db2fcb17b8f5828a Mon Sep 17 00:00:00 2001 From: Carolyn Van Slyck Date: Sun, 26 May 2019 09:35:26 -0500 Subject: [PATCH 07/12] Improve failed test formatting --- src/testing/testing.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/testing/testing.go b/src/testing/testing.go index 47fc994a2e..c01d982b16 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -7,6 +7,7 @@ import ( // T is a test helper. type T struct { + name string // flags the test as having failed when non-zero failed int @@ -30,12 +31,18 @@ type M struct { func (m *M) Run() int { failures := 0 for _, test := range m.Tests { - t := &T{} + t := &T{ + name: test.Name, + } test.Func(t) failures += t.failed } + if failures > 0 { + fmt.Printf("exit status %d\n", failures) + fmt.Println("FAIL") + } return failures } @@ -44,9 +51,12 @@ func TestMain(m *M) { } // Fatal is equivalent to Log followed by Fail -func (t *T) Error(args ...string) { +func (t *T) Error(args ...interface{}) { // This doesn't print the same as in upstream go, but works good enough - fmt.Print(args) + // TODO: buffer test output like go does + fmt.Printf("--- FAIL: %s\n", t.name) + fmt.Printf("\t") + fmt.Println(args...) t.Fail() } From a85f02feab6860a6e43f88a7ee6eefb8b5d868be Mon Sep 17 00:00:00 2001 From: Carolyn Van Slyck Date: Sun, 26 May 2019 11:54:38 -0500 Subject: [PATCH 08/12] Fix make tinygo-test Don't use build/tinygo since it assumes that you are building llvm from source Example: $ go install && make tinygo-test cd tests/tinygotest && tinygo test === RUN TestFail1 --- FAIL: TestFail1 TestFail1 failed because of stuff and things === RUN TestFail2 --- FAIL: TestFail2 TestFail2 failed for reasons === RUN TestPass --- PASS: TestPass exit status 2 FAIL --- Makefile | 5 ++--- src/testing/testing.go | 22 +++++++++++++++++----- tests/example1/main_test.go | 9 --------- tests/{example1 => tinygotest}/main.go | 0 tests/tinygotest/main_test.go | 16 ++++++++++++++++ 5 files changed, 35 insertions(+), 17 deletions(-) delete mode 100644 tests/example1/main_test.go rename tests/{example1 => tinygotest}/main.go (100%) create mode 100644 tests/tinygotest/main_test.go diff --git a/Makefile b/Makefile index c487422acd..04342dd1e9 100644 --- a/Makefile +++ b/Makefile @@ -85,10 +85,9 @@ build/tinygo: test: CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" go test -v -tags byollvm . - $(MAKE) tinygo-test -tinygo-test: build/tinygo - cd tests/example1 && ../../build/tinygo test +tinygo-test: + cd tests/tinygotest && tinygo test .PHONY: smoketest smoketest-no-avr smoketest: smoketest-no-avr diff --git a/src/testing/testing.go b/src/testing/testing.go index c01d982b16..bceb716784 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1,13 +1,16 @@ package testing import ( + "bytes" "fmt" + "io" "os" ) // T is a test helper. type T struct { - name string + name string + output io.Writer // flags the test as having failed when non-zero failed int @@ -32,10 +35,20 @@ func (m *M) Run() int { failures := 0 for _, test := range m.Tests { t := &T{ - name: test.Name, + name: test.Name, + output: &bytes.Buffer{}, } + + fmt.Printf("=== RUN %s\n", test.Name) test.Func(t) + if t.failed == 0 { + fmt.Printf("--- PASS: %s\n", test.Name) + } else { + fmt.Printf("--- FAIL: %s\n", test.Name) + } + fmt.Println(t.output) + failures += t.failed } @@ -54,9 +67,8 @@ func TestMain(m *M) { func (t *T) Error(args ...interface{}) { // This doesn't print the same as in upstream go, but works good enough // TODO: buffer test output like go does - fmt.Printf("--- FAIL: %s\n", t.name) - fmt.Printf("\t") - fmt.Println(args...) + fmt.Fprintf(t.output, "\t") + fmt.Fprintln(t.output, args...) t.Fail() } diff --git a/tests/example1/main_test.go b/tests/example1/main_test.go deleted file mode 100644 index 5f227ccc9e..0000000000 --- a/tests/example1/main_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import ( - "testing" // This is the tinygo testing package -) - -func TestFoo(t *testing.T) { - t.Error("TestFoo failed because of stuff and things") -} diff --git a/tests/example1/main.go b/tests/tinygotest/main.go similarity index 100% rename from tests/example1/main.go rename to tests/tinygotest/main.go diff --git a/tests/tinygotest/main_test.go b/tests/tinygotest/main_test.go new file mode 100644 index 0000000000..61ce28285f --- /dev/null +++ b/tests/tinygotest/main_test.go @@ -0,0 +1,16 @@ +package main + +import ( + "testing" // This is the tinygo testing package +) + +func TestFail1(t *testing.T) { + t.Error("TestFail1 failed because of stuff and things") +} + +func TestFail2(t *testing.T) { + t.Error("TestFail2 failed for reasons") +} + +func TestPass(t *testing.T) { +} From 667f9ab02025fdd759f9b417320389e791c2beef Mon Sep 17 00:00:00 2001 From: Carolyn Van Slyck Date: Sun, 26 May 2019 12:47:56 -0500 Subject: [PATCH 09/12] Propagate the test binary exit code --- main.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index de2f1c327b..7c192af843 100644 --- a/main.go +++ b/main.go @@ -365,9 +365,9 @@ func Test(pkgName, target string, config *BuildConfig) error { cmd.Stderr = os.Stderr err := cmd.Run() if err != nil { - if err, ok := err.(*exec.ExitError); ok && err.Exited() { - // Workaround for QEMU which always exits with an error. - return nil + // Propagate the exit code + if err, ok := err.(*exec.ExitError); ok { + os.Exit(err.ExitCode()) } return &commandError{"failed to run compiled binary", tmppath, err} } From dd765dc60de14a6dd2e93d0a8ecffa63f31044c8 Mon Sep 17 00:00:00 2001 From: Carolyn Van Slyck Date: Sun, 26 May 2019 13:42:50 -0500 Subject: [PATCH 10/12] Format code --- compiler/compiler.go | 24 ++++++++++++------------ main.go | 20 ++++++++++---------- test.go | 2 +- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/compiler/compiler.go b/compiler/compiler.go index 30706cdbfe..93c3f496ae 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -32,23 +32,23 @@ const tinygoPath = "github.com/tinygo-org/tinygo" // Configure the compiler. type Config struct { - Triple string // LLVM target triple, e.g. x86_64-unknown-linux-gnu (empty string means default) - CPU string // LLVM CPU name, e.g. atmega328p (empty string means default) + Triple string // LLVM target triple, e.g. x86_64-unknown-linux-gnu (empty string means default) + CPU string // LLVM CPU name, e.g. atmega328p (empty string means default) Features []string // LLVM CPU features - GOOS string // - GOARCH string // - GC string // garbage collection strategy + GOOS string // + GOARCH string // + GC string // garbage collection strategy PanicStrategy string // panic strategy ("abort" or "trap") - CFlags []string // cflags to pass to cgo - LDFlags []string // ldflags to pass to cgo + CFlags []string // cflags to pass to cgo + LDFlags []string // ldflags to pass to cgo ClangHeaders string // Clang built-in header include path - DumpSSA bool // dump Go SSA, for compiler debugging - Debug bool // add debug symbols for gdb + DumpSSA bool // dump Go SSA, for compiler debugging + Debug bool // add debug symbols for gdb GOROOT string // GOROOT TINYGOROOT string // GOROOT for TinyGo - GOPATH string // GOPATH, like `go env GOPATH` - BuildTags []string // build tags for TinyGo (empty means {Config.GOOS/Config.GOARCH}) - TestConfig TestConfig + GOPATH string // GOPATH, like `go env GOPATH` + BuildTags []string // build tags for TinyGo (empty means {Config.GOOS/Config.GOARCH}) + TestConfig TestConfig } type TestConfig struct { diff --git a/main.go b/main.go index 7c192af843..0ac3a63956 100644 --- a/main.go +++ b/main.go @@ -54,7 +54,7 @@ type BuildConfig struct { cFlags []string ldFlags []string wasmAbi string - testConfig compiler.TestConfig + testConfig compiler.TestConfig } // Helper function for Compiler object. @@ -93,23 +93,23 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act tags = append(tags, fmt.Sprintf("go1.%d", i)) } compilerConfig := compiler.Config{ - Triple: spec.Triple, - CPU: spec.CPU, + Triple: spec.Triple, + CPU: spec.CPU, Features: spec.Features, - GOOS: spec.GOOS, - GOARCH: spec.GOARCH, - GC: config.gc, + GOOS: spec.GOOS, + GOARCH: spec.GOARCH, + GC: config.gc, PanicStrategy: config.panicStrategy, CFlags: cflags, LDFlags: ldflags, ClangHeaders: getClangHeaderPath(root), - Debug: config.debug, - DumpSSA: config.dumpSSA, + Debug: config.debug, + DumpSSA: config.dumpSSA, TINYGOROOT: root, GOROOT: goroot, - GOPATH: getGopath(), + GOPATH: getGopath(), BuildTags: tags, - TestConfig: config.testConfig, + TestConfig: config.testConfig, } c, err := compiler.NewCompiler(pkgName, compilerConfig) if err != nil { diff --git a/test.go b/test.go index ac0e4f92df..379bffeded 100644 --- a/test.go +++ b/test.go @@ -44,4 +44,4 @@ func findTestFiles() ([]string, error) { return nil, err } return testFiles, nil -} \ No newline at end of file +} From 04e49fa35c718b0ed5ae6463f2f1993b4a602a4f Mon Sep 17 00:00:00 2001 From: Carolyn Van Slyck Date: Sun, 26 May 2019 13:43:02 -0500 Subject: [PATCH 11/12] Fix docstring --- src/testing/testing.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/testing/testing.go b/src/testing/testing.go index bceb716784..1d7ea051dd 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -63,7 +63,7 @@ func TestMain(m *M) { os.Exit(m.Run()) } -// Fatal is equivalent to Log followed by Fail +// Error is equivalent to Log followed by Fail func (t *T) Error(args ...interface{}) { // This doesn't print the same as in upstream go, but works good enough // TODO: buffer test output like go does From b94fe7f168f1fc34197a222d3bfbb6f7e8124f97 Mon Sep 17 00:00:00 2001 From: Carolyn Van Slyck Date: Fri, 14 Jun 2019 13:29:59 -0500 Subject: [PATCH 12/12] Incororate review feedback * Remove getPackageRoot and use . instead * Do not recursively import test files * Remove unused test --- loader/loader.go | 2 +- main.go | 9 ++++----- target.go | 24 ------------------------ target_test.go | 32 -------------------------------- test.go | 47 ----------------------------------------------- 5 files changed, 5 insertions(+), 109 deletions(-) delete mode 100644 target_test.go delete mode 100644 test.go diff --git a/loader/loader.go b/loader/loader.go index 39942b7137..1cf3715655 100644 --- a/loader/loader.go +++ b/loader/loader.go @@ -477,7 +477,7 @@ func (p *Package) importRecursively(includeTests bool) error { if importedPkg.Importing { return &ImportCycleError{[]string{p.ImportPath, importedPkg.ImportPath}, p.ImportPos[to]} } - err = importedPkg.importRecursively(includeTests) + err = importedPkg.importRecursively(false) if err != nil { if err, ok := err.(*ImportCycleError); ok { err.Packages = append([]string{p.ImportPath}, err.Packages...) diff --git a/main.go b/main.go index 0ac3a63956..97ea47d360 100644 --- a/main.go +++ b/main.go @@ -683,12 +683,11 @@ func main() { err := Run(flag.Arg(0), *target, config) handleCompilerError(err) case "test": - pkgRoot, err := getPackageRoot() - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) + pkgRoot := "." + if flag.NArg() == 1 { + pkgRoot = flag.Arg(0) } - err = Test(pkgRoot, *target, config) + err := Test(pkgRoot, *target, config) handleCompilerError(err) case "clean": // remove cache directory diff --git a/target.go b/target.go index f689f95939..d732e716bd 100644 --- a/target.go +++ b/target.go @@ -303,30 +303,6 @@ func getGopath() string { return filepath.Join(home, "go") } -func getPackageRoot() (string, error) { - wd, err := os.Getwd() - if err != nil { - return "", err - } - if rwd, err := filepath.EvalSymlinks(wd); err == nil { - wd = rwd - } - - // TODO: This assumes a single gopath - // A more robust solution can be found in golang/dep, and probably golang/go. - // See https://github.com/golang/dep/blob/9227ca64191910befb850cfc4dc85fd93e12ba68/context.go#L256 - gopath := getGopath() - if rgopath, err := filepath.EvalSymlinks(gopath); err == nil { - gopath = rgopath - } - - src := filepath.Join(gopath, "src") + string(os.PathSeparator) - if strings.HasPrefix(wd, src) { - return strings.TrimPrefix(wd, src), nil - } - return "", fmt.Errorf("could not determine the package root from the current directory %q and gopath %q", wd, gopath) -} - func getHomeDir() string { u, err := user.Current() if err != nil { diff --git a/target_test.go b/target_test.go deleted file mode 100644 index 1244af2cf8..0000000000 --- a/target_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package main - -import ( - "os" - "path/filepath" - "testing" -) - -func TestGetPackageRoot(t *testing.T) { - wantRoot := "github.com/my/root" - - gopath := os.TempDir() - defer os.Unsetenv("GOPATH") - os.Setenv("GOPATH", gopath) - wd := filepath.Join(gopath, "src", wantRoot) - err := os.MkdirAll(wd, 0755) - if err != nil { - t.Fatal(err) - } - err = os.Chdir(wd) - if err != nil { - t.Fatal(err) - } - - gotRoot, err := getPackageRoot() - if err != nil { - t.Fatal(err) - } - if gotRoot != wantRoot { - t.Fatalf("want %q got %q", wantRoot, gotRoot) - } -} diff --git a/test.go b/test.go deleted file mode 100644 index 379bffeded..0000000000 --- a/test.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import ( - "fmt" - "os" - "path/filepath" - "strings" -) - -func RunTests() error { - - _, err := getPackageRoot() - if err != nil { - return err - } - - _, err = findTestFiles() - if err != nil { - return err - } - - return nil -} - -func findTestFiles() ([]string, error) { - var testFiles []string - err := filepath.Walk(".", func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - - if info.IsDir() { - return nil - } - - if strings.HasSuffix(info.Name(), "_test.go") { - fmt.Println(path) - testFiles = append(testFiles, path) - } - - return nil - }) - if err != nil { - return nil, err - } - return testFiles, nil -}