From b92ac73ae3bda96ce077e32036a544b9b09d950d Mon Sep 17 00:00:00 2001 From: Ross Light Date: Thu, 29 Mar 2018 15:17:58 -0700 Subject: [PATCH] goose: read tests from testdata Since tests are all written in terms of Go source, it makes tests easier to write. They still need to be arranged in a GOPATH for go build, but tests that just call Generate can operate in-place because I've faked the filesystem. Reviewed-by: Tuo Shan Reviewed-by: Herbie Ong --- internal/goose/goose_test.go | 698 +++++++++--------- internal/goose/testdata/Chain/foo/foo.go | 20 + .../goose/testdata/Chain/foo/foo_goose.go | 7 + internal/goose/testdata/Chain/out.txt | 1 + internal/goose/testdata/Chain/pkg | 1 + .../goose/testdata/InjectInput/foo/foo.go | 21 + .../testdata/InjectInput/foo/foo_goose.go | 7 + internal/goose/testdata/InjectInput/out.txt | 1 + internal/goose/testdata/InjectInput/pkg | 1 + .../testdata/InjectInputConflict/foo/foo.go | 23 + .../InjectInputConflict/foo/foo_goose.go | 7 + .../testdata/InjectInputConflict/out.txt | 1 + .../goose/testdata/InjectInputConflict/pkg | 1 + internal/goose/testdata/MissingUse/foo/foo.go | 14 + .../testdata/MissingUse/foo/foo_goose.go | 5 + internal/goose/testdata/MissingUse/out.txt | 1 + internal/goose/testdata/MissingUse/pkg | 1 + .../goose/testdata/NiladicIdentity/foo/foo.go | 14 + .../testdata/NiladicIdentity/foo/foo_goose.go | 7 + .../goose/testdata/NiladicIdentity/out.txt | 1 + internal/goose/testdata/NiladicIdentity/pkg | 1 + internal/goose/testdata/NoopBuild/foo/foo.go | 7 + internal/goose/testdata/NoopBuild/out.txt | 1 + internal/goose/testdata/NoopBuild/pkg | 1 + .../goose/testdata/ReturnError/foo/foo.go | 22 + .../testdata/ReturnError/foo/foo_goose.go | 7 + internal/goose/testdata/ReturnError/out.txt | 2 + internal/goose/testdata/ReturnError/pkg | 1 + internal/goose/testdata/TwoDeps/foo/foo.go | 26 + .../goose/testdata/TwoDeps/foo/foo_goose.go | 7 + internal/goose/testdata/TwoDeps/out.txt | 1 + internal/goose/testdata/TwoDeps/pkg | 1 + 32 files changed, 578 insertions(+), 331 deletions(-) create mode 100644 internal/goose/testdata/Chain/foo/foo.go create mode 100644 internal/goose/testdata/Chain/foo/foo_goose.go create mode 100644 internal/goose/testdata/Chain/out.txt create mode 100644 internal/goose/testdata/Chain/pkg create mode 100644 internal/goose/testdata/InjectInput/foo/foo.go create mode 100644 internal/goose/testdata/InjectInput/foo/foo_goose.go create mode 100644 internal/goose/testdata/InjectInput/out.txt create mode 100644 internal/goose/testdata/InjectInput/pkg create mode 100644 internal/goose/testdata/InjectInputConflict/foo/foo.go create mode 100644 internal/goose/testdata/InjectInputConflict/foo/foo_goose.go create mode 100644 internal/goose/testdata/InjectInputConflict/out.txt create mode 100644 internal/goose/testdata/InjectInputConflict/pkg create mode 100644 internal/goose/testdata/MissingUse/foo/foo.go create mode 100644 internal/goose/testdata/MissingUse/foo/foo_goose.go create mode 100644 internal/goose/testdata/MissingUse/out.txt create mode 100644 internal/goose/testdata/MissingUse/pkg create mode 100644 internal/goose/testdata/NiladicIdentity/foo/foo.go create mode 100644 internal/goose/testdata/NiladicIdentity/foo/foo_goose.go create mode 100644 internal/goose/testdata/NiladicIdentity/out.txt create mode 100644 internal/goose/testdata/NiladicIdentity/pkg create mode 100644 internal/goose/testdata/NoopBuild/foo/foo.go create mode 100644 internal/goose/testdata/NoopBuild/out.txt create mode 100644 internal/goose/testdata/NoopBuild/pkg create mode 100644 internal/goose/testdata/ReturnError/foo/foo.go create mode 100644 internal/goose/testdata/ReturnError/foo/foo_goose.go create mode 100644 internal/goose/testdata/ReturnError/out.txt create mode 100644 internal/goose/testdata/ReturnError/pkg create mode 100644 internal/goose/testdata/TwoDeps/foo/foo.go create mode 100644 internal/goose/testdata/TwoDeps/foo/foo_goose.go create mode 100644 internal/goose/testdata/TwoDeps/out.txt create mode 100644 internal/goose/testdata/TwoDeps/pkg diff --git a/internal/goose/goose_test.go b/internal/goose/goose_test.go index 0a1f331..23e3468 100644 --- a/internal/goose/goose_test.go +++ b/internal/goose/goose_test.go @@ -2,351 +2,387 @@ package goose import ( "bytes" + "errors" "fmt" "go/build" + "io" "io/ioutil" "os" "os/exec" "path/filepath" + "runtime" + "sort" + "strings" "testing" + "time" ) -// TODO(light): pull this out into a testdata directory - -var tests = []struct { - name string - files map[string]string - pkg string - wantOutput string - wantError bool -}{ - { - name: "No-op build", - files: map[string]string{ - "foo/foo.go": `package main; import "fmt"; func main() { fmt.Println("Hello, World!"); }`, - }, - pkg: "foo", - wantOutput: "Hello, World!\n", - }, - { - name: "Niladic identity provider", - files: map[string]string{ - "foo/foo.go": `package main -import "fmt" -func main() { fmt.Println(injectedMessage()); } - -//goose:provide - -// provideMessage provides a friendly user greeting. -func provideMessage() string { return "Hello, World!"; } -`, - "foo/foo_goose.go": `//+build gooseinject - -package main - -//goose:use provideMessage - -func injectedMessage() string -`, - }, - pkg: "foo", - wantOutput: "Hello, World!\n", - }, - { - name: "Missing use", - files: map[string]string{ - "foo/foo.go": `package main -import "fmt" -func main() { fmt.Println(injectedMessage()); } - -//goose:provide Set - -// provideMessage provides a friendly user greeting. -func provideMessage() string { return "Hello, World!"; } -`, - "foo/foo_goose.go": `//+build gooseinject - -package main - -func injectedMessage() string -`, - }, - pkg: "foo", - wantError: true, - }, - { - name: "Chain", - files: map[string]string{ - "foo/foo.go": `package main -import "fmt" -func main() { - fmt.Println(injectFooBar()) -} - -type Foo int -type FooBar int - -//goose:provide Set -func provideFoo() Foo { return 41 } - -//goose:provide Set -func provideFooBar(foo Foo) FooBar { return FooBar(foo) + 1 } -`, - "foo/foo_goose.go": `//+build gooseinject - -package main - -//goose:use Set - -func injectFooBar() FooBar -`, - }, - pkg: "foo", - wantOutput: "42\n", - }, - { - name: "Two deps", - files: map[string]string{ - "foo/foo.go": `package main -import "fmt" -func main() { - fmt.Println(injectFooBar()) -} - -type Foo int -type Bar int -type FooBar int - -//goose:provide Set -func provideFoo() Foo { return 40 } - -//goose:provide Set -func provideBar() Bar { return 2 } - -//goose:provide Set -func provideFooBar(foo Foo, bar Bar) FooBar { return FooBar(foo) + FooBar(bar) } -`, - "foo/foo_goose.go": `//+build gooseinject - -package main - -//goose:use Set - -func injectFooBar() FooBar -`, - }, - pkg: "foo", - wantOutput: "42\n", - }, - { - name: "Inject input", - files: map[string]string{ - "foo/foo.go": `package main -import "fmt" -func main() { - fmt.Println(injectFooBar(40)) -} - -type Foo int -type Bar int -type FooBar int - -//goose:provide Set -func provideBar() Bar { return 2 } - -//goose:provide Set -func provideFooBar(foo Foo, bar Bar) FooBar { return FooBar(foo) + FooBar(bar) } -`, - "foo/foo_goose.go": `//+build gooseinject - -package main - -//goose:use Set - -func injectFooBar(foo Foo) FooBar -`, - }, - pkg: "foo", - wantOutput: "42\n", - }, - { - name: "Inject input conflict", - files: map[string]string{ - "foo/foo.go": `package main -import "fmt" -func main() { - fmt.Println(injectBar(40)) -} - -type Foo int -type Bar int - -//goose:provide Set -func provideFoo() Foo { return -888 } - -//goose:provide Set -func provideBar(foo Foo) Bar { return 2 } -`, - "foo/foo_goose.go": `//+build gooseinject - -package main - -//goose:use Set - -func injectBar(foo Foo) Bar -`, - }, - pkg: "foo", - wantError: true, - }, - { - name: "Return error", - files: map[string]string{ - "foo/foo.go": `package main -import "errors" -import "fmt" -import "strings" -func main() { - foo, err := injectFoo() - fmt.Println(foo) - if err == nil { - fmt.Println("") - } else { - fmt.Println(strings.Contains(err.Error(), "there is no Foo")) +func TestGoose(t *testing.T) { + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) } -} - -type Foo int - -//goose:provide Set -func provideFoo() (Foo, error) { return 42, errors.New("there is no Foo") } -`, - "foo/foo_goose.go": `//+build gooseinject - -package main - -//goose:use Set - -func injectFoo() (Foo, error) -`, - }, - pkg: "foo", - wantOutput: "0\ntrue\n", - }, -} - -func TestGeneratedCode(t *testing.T) { - if _, err := os.Stat(filepath.Join(build.Default.GOROOT, "bin", "go")); err != nil { - t.Fatalf("go toolchain not available: %v", err) + const testRoot = "testdata" + testdataEnts, err := ioutil.ReadDir(testRoot) // ReadDir sorts by name + if err != nil { + t.Fatal(err) } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - gopath, err := ioutil.TempDir("", "goose_test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(gopath) - bctx := &build.Context{ - GOARCH: build.Default.GOARCH, - GOOS: build.Default.GOOS, - GOROOT: build.Default.GOROOT, - GOPATH: gopath, - CgoEnabled: build.Default.CgoEnabled, - Compiler: build.Default.Compiler, - ReleaseTags: build.Default.ReleaseTags, - } - for name, content := range test.files { - p := filepath.Join(gopath, "src", filepath.FromSlash(name)) - if err := os.MkdirAll(filepath.Dir(p), 0777); err != nil { - t.Fatal(err) - } - if err := ioutil.WriteFile(p, []byte(content), 0666); err != nil { - t.Fatal(err) - } - } - gen, err := Generate(bctx, gopath, test.pkg) - if len(gen) > 0 { - defer t.Logf("goose_gen.go:\n%s", gen) - } - if err != nil { - if !test.wantError { - t.Fatalf("goose: %v", err) - } - return - } - if err == nil && test.wantError { - t.Fatal("goose succeeded; want error") - } - if len(gen) > 0 { - genPath := filepath.Join(gopath, "src", filepath.FromSlash(test.pkg), "goose_gen.go") - if err := ioutil.WriteFile(genPath, gen, 0666); err != nil { - t.Fatal(err) - } - } - testExePath := filepath.Join(gopath, "bin", "testprog") - if err := runGo(bctx, "build", "-o", testExePath, test.pkg); err != nil { - t.Fatal("build:", err) - } - out, err := exec.Command(testExePath).Output() - if err != nil { - t.Fatal("run compiled program:", err) - } - if string(out) != test.wantOutput { - t.Errorf("compiled program output = %q; want %q", out, test.wantOutput) - } - }) - } -} - -func TestDeterminism(t *testing.T) { - runs := 10 - if testing.Short() { - runs = 3 - } - for _, test := range tests { - if test.wantError { + tests := make([]*testCase, 0, len(testdataEnts)) + for _, ent := range testdataEnts { + name := ent.Name() + if !ent.IsDir() || strings.HasPrefix(name, ".") || strings.HasPrefix(name, "_") { continue } - t.Run(test.name, func(t *testing.T) { - gopath, err := ioutil.TempDir("", "goose_test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(gopath) - bctx := &build.Context{ - GOARCH: build.Default.GOARCH, - GOOS: build.Default.GOOS, - GOROOT: build.Default.GOROOT, - GOPATH: gopath, - CgoEnabled: build.Default.CgoEnabled, - Compiler: build.Default.Compiler, - ReleaseTags: build.Default.ReleaseTags, - } - for name, content := range test.files { - p := filepath.Join(gopath, "src", filepath.FromSlash(name)) - if err := os.MkdirAll(filepath.Dir(p), 0777); err != nil { - t.Fatal(err) - } - if err := ioutil.WriteFile(p, []byte(content), 0666); err != nil { - t.Fatal(err) - } - } - gold, err := Generate(bctx, gopath, test.pkg) - if err != nil { - t.Fatal("goose:", err) - } - goldstr := string(gold) - for i := 0; i < runs-1; i++ { - out, err := Generate(bctx, gopath, test.pkg) - if err != nil { - t.Fatal("goose (on subsequent run):", err) - } - if !bytes.Equal(gold, out) { - t.Fatalf("goose output differs when run repeatedly on same input:\n%s", diff(goldstr, string(out))) - } - } - }) + test, err := loadTestCase(filepath.Join(testRoot, name)) + if err != nil { + t.Error(err) + } + tests = append(tests, test) } + + t.Run("Generate", func(t *testing.T) { + if _, err := os.Stat(filepath.Join(build.Default.GOROOT, "bin", "go")); err != nil { + t.Skip("go toolchain not available:", err) + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + bctx := test.buildContext() + gen, err := Generate(bctx, wd, test.pkg) + if len(gen) > 0 { + defer t.Logf("goose_gen.go:\n%s", gen) + } + if err != nil { + if !test.wantError { + t.Fatalf("goose: %v", err) + } + return + } + if err == nil && test.wantError { + t.Fatal("goose succeeded; want error") + } + + gopath, err := ioutil.TempDir("", "goose_test") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(gopath) + if err := test.materialize(gopath); err != nil { + t.Fatal(err) + } + if len(gen) > 0 { + genPath := filepath.Join(gopath, "src", filepath.FromSlash(test.pkg), "goose_gen.go") + if err := ioutil.WriteFile(genPath, gen, 0666); err != nil { + t.Fatal(err) + } + } + testExePath := filepath.Join(gopath, "bin", "testprog") + realBuildCtx := &build.Context{ + GOARCH: bctx.GOARCH, + GOOS: bctx.GOOS, + GOROOT: bctx.GOROOT, + GOPATH: gopath, + CgoEnabled: bctx.CgoEnabled, + Compiler: bctx.Compiler, + BuildTags: bctx.BuildTags, + ReleaseTags: bctx.ReleaseTags, + } + if err := runGo(realBuildCtx, "build", "-o", testExePath, test.pkg); err != nil { + t.Fatal("build:", err) + } + out, err := exec.Command(testExePath).Output() + if err != nil { + t.Fatal("run compiled program:", err) + } + if !bytes.Equal(out, test.wantOutput) { + t.Errorf("compiled program output = %q; want %q", out, test.wantOutput) + } + }) + } + }) + + t.Run("Determinism", func(t *testing.T) { + runs := 10 + if testing.Short() { + runs = 3 + } + for _, test := range tests { + if test.wantError { + continue + } + t.Run(test.name, func(t *testing.T) { + bctx := test.buildContext() + gold, err := Generate(bctx, wd, test.pkg) + if err != nil { + t.Fatal("goose:", err) + } + goldstr := string(gold) + for i := 0; i < runs-1; i++ { + out, err := Generate(bctx, wd, test.pkg) + if err != nil { + t.Fatal("goose (on subsequent run):", err) + } + if !bytes.Equal(gold, out) { + t.Fatalf("goose output differs when run repeatedly on same input:\n%s", diff(goldstr, string(out))) + } + } + }) + } + }) +} + +type testCase struct { + name string + pkg string + goFiles map[string][]byte + wantOutput []byte + wantError bool +} + +// loadTestCase reads a test case from a directory. +// +// The directory structure is: +// +// root/ +// pkg file containing the package name containing the inject function +// (must also be package main) +// out.txt file containing the expected output, or the magic string "ERROR" +// if this test should cause generation to fail +// ... any Go files found recursively placed under GOPATH/src/... +func loadTestCase(root string) (*testCase, error) { + name := filepath.Base(root) + pkg, err := ioutil.ReadFile(filepath.Join(root, "pkg")) + if err != nil { + return nil, fmt.Errorf("load test case %s: %v", name, err) + } + out, err := ioutil.ReadFile(filepath.Join(root, "out.txt")) + if err != nil { + return nil, fmt.Errorf("load test case %s: %v", name, err) + } + wantError := false + if bytes.Equal(bytes.TrimSpace(out), []byte("ERROR")) { + wantError = true + out = nil + } + goFiles := make(map[string][]byte) + err = filepath.Walk(root, func(src string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.Mode().IsRegular() || filepath.Ext(src) != ".go" { + return nil + } + rel, err := filepath.Rel(root, src) + if err != nil { + return err // unlikely + } + data, err := ioutil.ReadFile(src) + if err != nil { + return err + } + goFiles[rel] = data + return nil + }) + if err != nil { + return nil, fmt.Errorf("load test case %s: %v", name, err) + } + return &testCase{ + name: name, + pkg: string(bytes.TrimSpace(pkg)), + goFiles: goFiles, + wantOutput: out, + wantError: wantError, + }, nil +} + +func (test *testCase) buildContext() *build.Context { + return &build.Context{ + GOARCH: build.Default.GOARCH, + GOOS: build.Default.GOOS, + GOROOT: build.Default.GOROOT, + GOPATH: magicGOPATH(), + CgoEnabled: build.Default.CgoEnabled, + Compiler: build.Default.Compiler, + ReleaseTags: build.Default.ReleaseTags, + HasSubdir: test.hasSubdir, + ReadDir: test.readDir, + OpenFile: test.openFile, + IsDir: test.isDir, + } +} + +const ( + magicGOPATHUnix = "/goose_gopath" + magicGOPATHWindows = `C:\goose_gopath` +) + +func magicGOPATH() string { + if runtime.GOOS == "windows" { + return magicGOPATHWindows + } else { + return magicGOPATHUnix + } +} + +func (test *testCase) hasSubdir(root, dir string) (rel string, ok bool) { + // Don't consult filesystem, just lexical. + + if dir == root { + return "", true + } + prefix := root + if !strings.HasSuffix(prefix, string(filepath.Separator)) { + prefix += string(filepath.Separator) + } + if !strings.HasPrefix(dir, prefix) { + return "", false + } + return filepath.ToSlash(dir[len(prefix):]), true +} + +func (test *testCase) resolve(path string) (resolved string, pathType int) { + subpath, isMagic := test.hasSubdir(magicGOPATH(), path) + if !isMagic { + return path, systemPath + } + if subpath == "src" { + return "", gopathRoot + } + const srcPrefix = "src/" + if !strings.HasPrefix(subpath, srcPrefix) { + return subpath, gopathRoot + } + return subpath[len(srcPrefix):], gopathSrc +} + +// Path types +const ( + systemPath = iota + gopathRoot + gopathSrc +) + +func (test *testCase) readDir(dir string) ([]os.FileInfo, error) { + rpath, pathType := test.resolve(dir) + switch { + case pathType == systemPath: + return ioutil.ReadDir(rpath) + case pathType == gopathRoot && rpath == "": + return []os.FileInfo{dirInfo{name: "src"}}, nil + case pathType == gopathSrc: + names := make([]string, 0, len(test.goFiles)) + prefix := rpath + string(filepath.Separator) + for name := range test.goFiles { + if strings.HasPrefix(name, prefix) { + names = append(names, name[len(prefix):]) + } + } + sort.Strings(names) + ents := make([]os.FileInfo, 0, len(names)) + for _, name := range names { + if i := strings.IndexRune(name, filepath.Separator); i != -1 { + // Directory + dirName := name[:i] + if len(ents) == 0 || ents[len(ents)-1].Name() != dirName { + ents = append(ents, dirInfo{name: dirName}) + } + continue + } + ents = append(ents, fileInfo{ + name: name, + size: int64(len(test.goFiles[name])), + }) + } + return ents, nil + default: + return nil, &os.PathError{ + Op: "open", + Path: dir, + Err: os.ErrNotExist, + } + } +} + +func (test *testCase) isDir(path string) bool { + rpath, pathType := test.resolve(path) + switch { + case pathType == systemPath: + info, err := os.Stat(rpath) + return err == nil && info.IsDir() + case pathType == gopathRoot && rpath == "": + return true + case pathType == gopathSrc: + prefix := rpath + string(filepath.Separator) + for name := range test.goFiles { + if strings.HasPrefix(name, prefix) { + return true + } + } + return false + default: + return false + } +} + +type dirInfo struct { + name string +} + +func (d dirInfo) Name() string { return d.name } +func (d dirInfo) Size() int64 { return 0 } +func (d dirInfo) Mode() os.FileMode { return os.ModeDir | 0777 } +func (d dirInfo) ModTime() time.Time { return time.Unix(0, 0) } +func (d dirInfo) IsDir() bool { return true } +func (d dirInfo) Sys() interface{} { return nil } + +type fileInfo struct { + name string + size int64 +} + +func (f fileInfo) Name() string { return f.name } +func (f fileInfo) Size() int64 { return f.size } +func (f fileInfo) Mode() os.FileMode { return os.ModeDir | 0666 } +func (f fileInfo) ModTime() time.Time { return time.Unix(0, 0) } +func (f fileInfo) IsDir() bool { return false } +func (f fileInfo) Sys() interface{} { return nil } + +func (test *testCase) openFile(path string) (io.ReadCloser, error) { + rpath, pathType := test.resolve(path) + switch { + case pathType == systemPath: + return os.Open(path) + case pathType == gopathSrc: + content, ok := test.goFiles[rpath] + if !ok { + return nil, &os.PathError{ + Op: "open", + Path: path, + Err: errors.New("does not exist or is not a file"), + } + } + return ioutil.NopCloser(bytes.NewReader(content)), nil + default: + return nil, &os.PathError{ + Op: "open", + Path: path, + Err: errors.New("does not exist or is not a file"), + } + } +} + +// materialize creates a new GOPATH at the given directory, which may or +// may not exist. +func (test *testCase) materialize(gopath string) error { + for name, content := range test.goFiles { + dst := filepath.Join(gopath, "src", name) + if err := os.MkdirAll(filepath.Dir(dst), 0777); err != nil { + return fmt.Errorf("materialize GOPATH: %v", err) + } + if err := ioutil.WriteFile(dst, content, 0666); err != nil { + return fmt.Errorf("materialize GOPATH: %v", err) + } + } + return nil } func runGo(bctx *build.Context, args ...string) error { diff --git a/internal/goose/testdata/Chain/foo/foo.go b/internal/goose/testdata/Chain/foo/foo.go new file mode 100644 index 0000000..502e200 --- /dev/null +++ b/internal/goose/testdata/Chain/foo/foo.go @@ -0,0 +1,20 @@ +package main + +import "fmt" + +func main() { + fmt.Println(injectFooBar()) +} + +type Foo int +type FooBar int + +//goose:provide Set +func provideFoo() Foo { + return 41 +} + +//goose:provide Set +func provideFooBar(foo Foo) FooBar { + return FooBar(foo) + 1 +} diff --git a/internal/goose/testdata/Chain/foo/foo_goose.go b/internal/goose/testdata/Chain/foo/foo_goose.go new file mode 100644 index 0000000..73f5093 --- /dev/null +++ b/internal/goose/testdata/Chain/foo/foo_goose.go @@ -0,0 +1,7 @@ +//+build gooseinject + +package main + +//goose:use Set + +func injectFooBar() FooBar diff --git a/internal/goose/testdata/Chain/out.txt b/internal/goose/testdata/Chain/out.txt new file mode 100644 index 0000000..d81cc07 --- /dev/null +++ b/internal/goose/testdata/Chain/out.txt @@ -0,0 +1 @@ +42 diff --git a/internal/goose/testdata/Chain/pkg b/internal/goose/testdata/Chain/pkg new file mode 100644 index 0000000..257cc56 --- /dev/null +++ b/internal/goose/testdata/Chain/pkg @@ -0,0 +1 @@ +foo diff --git a/internal/goose/testdata/InjectInput/foo/foo.go b/internal/goose/testdata/InjectInput/foo/foo.go new file mode 100644 index 0000000..bd2a6d4 --- /dev/null +++ b/internal/goose/testdata/InjectInput/foo/foo.go @@ -0,0 +1,21 @@ +package main + +import "fmt" + +func main() { + fmt.Println(injectFooBar(40)) +} + +type Foo int +type Bar int +type FooBar int + +//goose:provide Set +func provideBar() Bar { + return 2 +} + +//goose:provide Set +func provideFooBar(foo Foo, bar Bar) FooBar { + return FooBar(foo) + FooBar(bar) +} diff --git a/internal/goose/testdata/InjectInput/foo/foo_goose.go b/internal/goose/testdata/InjectInput/foo/foo_goose.go new file mode 100644 index 0000000..cabd74b --- /dev/null +++ b/internal/goose/testdata/InjectInput/foo/foo_goose.go @@ -0,0 +1,7 @@ +//+build gooseinject + +package main + +//goose:use Set + +func injectFooBar(foo Foo) FooBar diff --git a/internal/goose/testdata/InjectInput/out.txt b/internal/goose/testdata/InjectInput/out.txt new file mode 100644 index 0000000..d81cc07 --- /dev/null +++ b/internal/goose/testdata/InjectInput/out.txt @@ -0,0 +1 @@ +42 diff --git a/internal/goose/testdata/InjectInput/pkg b/internal/goose/testdata/InjectInput/pkg new file mode 100644 index 0000000..257cc56 --- /dev/null +++ b/internal/goose/testdata/InjectInput/pkg @@ -0,0 +1 @@ +foo diff --git a/internal/goose/testdata/InjectInputConflict/foo/foo.go b/internal/goose/testdata/InjectInputConflict/foo/foo.go new file mode 100644 index 0000000..6afb76d --- /dev/null +++ b/internal/goose/testdata/InjectInputConflict/foo/foo.go @@ -0,0 +1,23 @@ +package main + +import "fmt" + +func main() { + // I'm on the fence as to whether this should be an error (versus an + // override). For now, I will make it an error that can be relaxed + // later. + fmt.Println(injectBar(40)) +} + +type Foo int +type Bar int + +//goose:provide Set +func provideFoo() Foo { + return -888 +} + +//goose:provide Set +func provideBar(foo Foo) Bar { + return 2 +} diff --git a/internal/goose/testdata/InjectInputConflict/foo/foo_goose.go b/internal/goose/testdata/InjectInputConflict/foo/foo_goose.go new file mode 100644 index 0000000..282ae3f --- /dev/null +++ b/internal/goose/testdata/InjectInputConflict/foo/foo_goose.go @@ -0,0 +1,7 @@ +//+build gooseinject + +package main + +//goose:use Set + +func injectBar(foo Foo) Bar diff --git a/internal/goose/testdata/InjectInputConflict/out.txt b/internal/goose/testdata/InjectInputConflict/out.txt new file mode 100644 index 0000000..5df7507 --- /dev/null +++ b/internal/goose/testdata/InjectInputConflict/out.txt @@ -0,0 +1 @@ +ERROR diff --git a/internal/goose/testdata/InjectInputConflict/pkg b/internal/goose/testdata/InjectInputConflict/pkg new file mode 100644 index 0000000..257cc56 --- /dev/null +++ b/internal/goose/testdata/InjectInputConflict/pkg @@ -0,0 +1 @@ +foo diff --git a/internal/goose/testdata/MissingUse/foo/foo.go b/internal/goose/testdata/MissingUse/foo/foo.go new file mode 100644 index 0000000..65ab36b --- /dev/null +++ b/internal/goose/testdata/MissingUse/foo/foo.go @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + fmt.Println(injectedMessage()) +} + +//goose:provide Set + +// provideMessage provides a friendly user greeting. +func provideMessage() string { + return "Hello, World!" +} diff --git a/internal/goose/testdata/MissingUse/foo/foo_goose.go b/internal/goose/testdata/MissingUse/foo/foo_goose.go new file mode 100644 index 0000000..fea1a42 --- /dev/null +++ b/internal/goose/testdata/MissingUse/foo/foo_goose.go @@ -0,0 +1,5 @@ +//+build gooseinject + +package main + +func injectedMessage() string diff --git a/internal/goose/testdata/MissingUse/out.txt b/internal/goose/testdata/MissingUse/out.txt new file mode 100644 index 0000000..5df7507 --- /dev/null +++ b/internal/goose/testdata/MissingUse/out.txt @@ -0,0 +1 @@ +ERROR diff --git a/internal/goose/testdata/MissingUse/pkg b/internal/goose/testdata/MissingUse/pkg new file mode 100644 index 0000000..257cc56 --- /dev/null +++ b/internal/goose/testdata/MissingUse/pkg @@ -0,0 +1 @@ +foo diff --git a/internal/goose/testdata/NiladicIdentity/foo/foo.go b/internal/goose/testdata/NiladicIdentity/foo/foo.go new file mode 100644 index 0000000..ac80c0a --- /dev/null +++ b/internal/goose/testdata/NiladicIdentity/foo/foo.go @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + fmt.Println(injectedMessage()) +} + +//goose:provide + +// provideMessage provides a friendly user greeting. +func provideMessage() string { + return "Hello, World!" +} diff --git a/internal/goose/testdata/NiladicIdentity/foo/foo_goose.go b/internal/goose/testdata/NiladicIdentity/foo/foo_goose.go new file mode 100644 index 0000000..d63fbe3 --- /dev/null +++ b/internal/goose/testdata/NiladicIdentity/foo/foo_goose.go @@ -0,0 +1,7 @@ +//+build gooseinject + +package main + +//goose:use provideMessage + +func injectedMessage() string diff --git a/internal/goose/testdata/NiladicIdentity/out.txt b/internal/goose/testdata/NiladicIdentity/out.txt new file mode 100644 index 0000000..8ab686e --- /dev/null +++ b/internal/goose/testdata/NiladicIdentity/out.txt @@ -0,0 +1 @@ +Hello, World! diff --git a/internal/goose/testdata/NiladicIdentity/pkg b/internal/goose/testdata/NiladicIdentity/pkg new file mode 100644 index 0000000..257cc56 --- /dev/null +++ b/internal/goose/testdata/NiladicIdentity/pkg @@ -0,0 +1 @@ +foo diff --git a/internal/goose/testdata/NoopBuild/foo/foo.go b/internal/goose/testdata/NoopBuild/foo/foo.go new file mode 100644 index 0000000..a3dd973 --- /dev/null +++ b/internal/goose/testdata/NoopBuild/foo/foo.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + +func main() { + fmt.Println("Hello, World!") +} diff --git a/internal/goose/testdata/NoopBuild/out.txt b/internal/goose/testdata/NoopBuild/out.txt new file mode 100644 index 0000000..8ab686e --- /dev/null +++ b/internal/goose/testdata/NoopBuild/out.txt @@ -0,0 +1 @@ +Hello, World! diff --git a/internal/goose/testdata/NoopBuild/pkg b/internal/goose/testdata/NoopBuild/pkg new file mode 100644 index 0000000..257cc56 --- /dev/null +++ b/internal/goose/testdata/NoopBuild/pkg @@ -0,0 +1 @@ +foo diff --git a/internal/goose/testdata/ReturnError/foo/foo.go b/internal/goose/testdata/ReturnError/foo/foo.go new file mode 100644 index 0000000..cf415b1 --- /dev/null +++ b/internal/goose/testdata/ReturnError/foo/foo.go @@ -0,0 +1,22 @@ +package main + +import "errors" +import "fmt" +import "strings" + +func main() { + foo, err := injectFoo() + fmt.Println(foo) // should be zero, the injector should ignore provideFoo's return value. + if err == nil { + fmt.Println("") + } else { + fmt.Println(strings.Contains(err.Error(), "there is no Foo")) + } +} + +type Foo int + +//goose:provide Set +func provideFoo() (Foo, error) { + return 42, errors.New("there is no Foo") +} diff --git a/internal/goose/testdata/ReturnError/foo/foo_goose.go b/internal/goose/testdata/ReturnError/foo/foo_goose.go new file mode 100644 index 0000000..5aa8775 --- /dev/null +++ b/internal/goose/testdata/ReturnError/foo/foo_goose.go @@ -0,0 +1,7 @@ +//+build gooseinject + +package main + +//goose:use Set + +func injectFoo() (Foo, error) diff --git a/internal/goose/testdata/ReturnError/out.txt b/internal/goose/testdata/ReturnError/out.txt new file mode 100644 index 0000000..f9d60c0 --- /dev/null +++ b/internal/goose/testdata/ReturnError/out.txt @@ -0,0 +1,2 @@ +0 +true diff --git a/internal/goose/testdata/ReturnError/pkg b/internal/goose/testdata/ReturnError/pkg new file mode 100644 index 0000000..257cc56 --- /dev/null +++ b/internal/goose/testdata/ReturnError/pkg @@ -0,0 +1 @@ +foo diff --git a/internal/goose/testdata/TwoDeps/foo/foo.go b/internal/goose/testdata/TwoDeps/foo/foo.go new file mode 100644 index 0000000..3284c2c --- /dev/null +++ b/internal/goose/testdata/TwoDeps/foo/foo.go @@ -0,0 +1,26 @@ +package main + +import "fmt" + +func main() { + fmt.Println(injectFooBar()) +} + +type Foo int +type Bar int +type FooBar int + +//goose:provide Set +func provideFoo() Foo { + return 40 +} + +//goose:provide Set +func provideBar() Bar { + return 2 +} + +//goose:provide Set +func provideFooBar(foo Foo, bar Bar) FooBar { + return FooBar(foo) + FooBar(bar) +} diff --git a/internal/goose/testdata/TwoDeps/foo/foo_goose.go b/internal/goose/testdata/TwoDeps/foo/foo_goose.go new file mode 100644 index 0000000..73f5093 --- /dev/null +++ b/internal/goose/testdata/TwoDeps/foo/foo_goose.go @@ -0,0 +1,7 @@ +//+build gooseinject + +package main + +//goose:use Set + +func injectFooBar() FooBar diff --git a/internal/goose/testdata/TwoDeps/out.txt b/internal/goose/testdata/TwoDeps/out.txt new file mode 100644 index 0000000..d81cc07 --- /dev/null +++ b/internal/goose/testdata/TwoDeps/out.txt @@ -0,0 +1 @@ +42 diff --git a/internal/goose/testdata/TwoDeps/pkg b/internal/goose/testdata/TwoDeps/pkg new file mode 100644 index 0000000..257cc56 --- /dev/null +++ b/internal/goose/testdata/TwoDeps/pkg @@ -0,0 +1 @@ +foo