| package bind |
| |
| import ( |
| "bytes" |
| "flag" |
| "go/ast" |
| "go/parser" |
| "go/token" |
| "io/ioutil" |
| "log" |
| "os" |
| "os/exec" |
| "path/filepath" |
| "runtime" |
| "strings" |
| "testing" |
| |
| _ "golang.org/x/tools/go/gcimporter" |
| "golang.org/x/tools/go/types" |
| ) |
| |
| func init() { |
| log.SetFlags(log.Lshortfile) |
| } |
| |
| var updateFlag = flag.Bool("update", false, "Update the golden files.") |
| |
| var tests = []string{ |
| "testdata/basictypes.go", |
| "testdata/structs.go", |
| "testdata/interfaces.go", |
| "testdata/issue10788.go", |
| } |
| |
| var fset = token.NewFileSet() |
| |
| func typeCheck(t *testing.T, filename string) *types.Package { |
| f, err := parser.ParseFile(fset, filename, nil, parser.AllErrors) |
| if err != nil { |
| t.Fatalf("%s: %v", filename, err) |
| } |
| |
| pkgName := filepath.Base(filename) |
| pkgName = strings.TrimSuffix(pkgName, ".go") |
| |
| // typecheck and collect typechecker errors |
| var conf types.Config |
| conf.Error = func(err error) { |
| t.Error(err) |
| } |
| pkg, err := conf.Check(pkgName, fset, []*ast.File{f}, nil) |
| if err != nil { |
| t.Fatal(err) |
| } |
| return pkg |
| } |
| |
| // diff runs the command "diff a b" and returns its output |
| func diff(a, b string) string { |
| var buf bytes.Buffer |
| var cmd *exec.Cmd |
| switch runtime.GOOS { |
| case "plan9": |
| cmd = exec.Command("/bin/diff", "-c", a, b) |
| default: |
| cmd = exec.Command("/usr/bin/diff", "-u", a, b) |
| } |
| cmd.Stdout = &buf |
| cmd.Stderr = &buf |
| cmd.Run() |
| return buf.String() |
| } |
| |
| func writeTempFile(t *testing.T, name string, contents []byte) string { |
| f, err := ioutil.TempFile("", name) |
| if err != nil { |
| t.Fatal(err) |
| } |
| if _, err := f.Write(contents); err != nil { |
| t.Fatal(err) |
| } |
| if err := f.Close(); err != nil { |
| t.Fatal(err) |
| } |
| return f.Name() |
| } |
| |
| func TestGenObjc(t *testing.T) { |
| var suffixes = map[bool]string{ |
| true: ".objc.h.golden", |
| false: ".objc.m.golden", |
| } |
| |
| for _, filename := range tests { |
| pkg := typeCheck(t, filename) |
| |
| for isHeader, suffix := range suffixes { |
| var buf bytes.Buffer |
| if err := GenObjc(&buf, fset, pkg, isHeader); err != nil { |
| t.Errorf("%s: %v", filename, err) |
| continue |
| } |
| out := writeTempFile(t, "generated"+suffix, buf.Bytes()) |
| defer os.Remove(out) |
| golden := filename[:len(filename)-len(".go")] + suffix |
| if diffstr := diff(golden, out); diffstr != "" { |
| t.Errorf("%s: does not match Objective-C golden:\n%s", filename, diffstr) |
| if *updateFlag { |
| t.Logf("Updating %s...", golden) |
| err := exec.Command("/bin/cp", out, golden).Run() |
| if err != nil { |
| t.Errorf("Update failed: %s", err) |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| func TestGenJava(t *testing.T) { |
| for _, filename := range tests { |
| var buf bytes.Buffer |
| pkg := typeCheck(t, filename) |
| if err := GenJava(&buf, fset, pkg); err != nil { |
| t.Errorf("%s: %v", filename, err) |
| continue |
| } |
| out := writeTempFile(t, "java", buf.Bytes()) |
| defer os.Remove(out) |
| golden := filename[:len(filename)-len(".go")] + ".java.golden" |
| if diffstr := diff(golden, out); diffstr != "" { |
| t.Errorf("%s: does not match Java golden:\n%s", filename, diffstr) |
| |
| if *updateFlag { |
| t.Logf("Updating %s...", golden) |
| if err := exec.Command("/bin/cp", out, golden).Run(); err != nil { |
| t.Errorf("Update failed: %s", err) |
| } |
| } |
| |
| } |
| } |
| } |
| |
| func TestGenGo(t *testing.T) { |
| for _, filename := range tests { |
| var buf bytes.Buffer |
| pkg := typeCheck(t, filename) |
| if err := GenGo(&buf, fset, pkg); err != nil { |
| t.Errorf("%s: %v", filename, err) |
| continue |
| } |
| out := writeTempFile(t, "go", buf.Bytes()) |
| defer os.Remove(out) |
| golden := filename + ".golden" |
| if diffstr := diff(golden, out); diffstr != "" { |
| t.Errorf("%s: does not match Java golden:\n%s", filename, diffstr) |
| |
| if *updateFlag { |
| t.Logf("Updating %s...", golden) |
| if err := exec.Command("/bin/cp", out, golden).Run(); err != nil { |
| t.Errorf("Update failed: %s", err) |
| } |
| } |
| } |
| } |
| } |