+++ /dev/null
-package apidiff
-
-import (
- "bufio"
- "fmt"
- "go/types"
- "io/ioutil"
- "os"
- "path/filepath"
- "reflect"
- "sort"
- "strings"
- "testing"
-
- "golang.org/x/tools/go/packages"
- "golang.org/x/tools/internal/testenv"
-)
-
-func TestChanges(t *testing.T) {
- dir, err := ioutil.TempDir("", "apidiff_test")
- if err != nil {
- t.Fatal(err)
- }
- dir = filepath.Join(dir, "go")
- wanti, wantc := splitIntoPackages(t, dir)
- defer os.RemoveAll(dir)
- sort.Strings(wanti)
- sort.Strings(wantc)
-
- oldpkg, err := load(t, "apidiff/old", dir)
- if err != nil {
- t.Fatal(err)
- }
- newpkg, err := load(t, "apidiff/new", dir)
- if err != nil {
- t.Fatal(err)
- }
-
- report := Changes(oldpkg.Types, newpkg.Types)
-
- got := report.messages(false)
- if !reflect.DeepEqual(got, wanti) {
- t.Errorf("incompatibles: got %v\nwant %v\n", got, wanti)
- }
- got = report.messages(true)
- if !reflect.DeepEqual(got, wantc) {
- t.Errorf("compatibles: got %v\nwant %v\n", got, wantc)
- }
-}
-
-func splitIntoPackages(t *testing.T, dir string) (incompatibles, compatibles []string) {
- // Read the input file line by line.
- // Write a line into the old or new package,
- // dependent on comments.
- // Also collect expected messages.
- f, err := os.Open("testdata/tests.go")
- if err != nil {
- t.Fatal(err)
- }
- defer f.Close()
-
- if err := os.MkdirAll(filepath.Join(dir, "src", "apidiff"), 0700); err != nil {
- t.Fatal(err)
- }
- if err := ioutil.WriteFile(filepath.Join(dir, "src", "apidiff", "go.mod"), []byte("module apidiff\n"), 0666); err != nil {
- t.Fatal(err)
- }
-
- oldd := filepath.Join(dir, "src/apidiff/old")
- newd := filepath.Join(dir, "src/apidiff/new")
- if err := os.MkdirAll(oldd, 0700); err != nil {
- t.Fatal(err)
- }
- if err := os.Mkdir(newd, 0700); err != nil && !os.IsExist(err) {
- t.Fatal(err)
- }
-
- oldf, err := os.Create(filepath.Join(oldd, "old.go"))
- if err != nil {
- t.Fatal(err)
- }
- newf, err := os.Create(filepath.Join(newd, "new.go"))
- if err != nil {
- t.Fatal(err)
- }
-
- wl := func(f *os.File, line string) {
- if _, err := fmt.Fprintln(f, line); err != nil {
- t.Fatal(err)
- }
- }
- writeBoth := func(line string) { wl(oldf, line); wl(newf, line) }
- writeln := writeBoth
- s := bufio.NewScanner(f)
- for s.Scan() {
- line := s.Text()
- tl := strings.TrimSpace(line)
- switch {
- case tl == "// old":
- writeln = func(line string) { wl(oldf, line) }
- case tl == "// new":
- writeln = func(line string) { wl(newf, line) }
- case tl == "// both":
- writeln = writeBoth
- case strings.HasPrefix(tl, "// i "):
- incompatibles = append(incompatibles, strings.TrimSpace(tl[4:]))
- case strings.HasPrefix(tl, "// c "):
- compatibles = append(compatibles, strings.TrimSpace(tl[4:]))
- default:
- writeln(line)
- }
- }
- if s.Err() != nil {
- t.Fatal(s.Err())
- }
- return
-}
-
-func load(t *testing.T, importPath, goPath string) (*packages.Package, error) {
- testenv.NeedsGoPackages(t)
-
- cfg := &packages.Config{
- Mode: packages.LoadTypes,
- }
- if goPath != "" {
- cfg.Env = append(os.Environ(), "GOPATH="+goPath)
- cfg.Dir = filepath.Join(goPath, "src", filepath.FromSlash(importPath))
- }
- pkgs, err := packages.Load(cfg, importPath)
- if err != nil {
- return nil, err
- }
- if len(pkgs[0].Errors) > 0 {
- return nil, pkgs[0].Errors[0]
- }
- return pkgs[0], nil
-}
-
-func TestExportedFields(t *testing.T) {
- pkg, err := load(t, "golang.org/x/tools/internal/apidiff/testdata/exported_fields", "")
- if err != nil {
- t.Fatal(err)
- }
- typeof := func(name string) types.Type {
- return pkg.Types.Scope().Lookup(name).Type()
- }
-
- s := typeof("S")
- su := s.(*types.Named).Underlying().(*types.Struct)
-
- ef := exportedSelectableFields(su)
- wants := []struct {
- name string
- typ types.Type
- }{
- {"A1", typeof("A1")},
- {"D", types.Typ[types.Bool]},
- {"E", types.Typ[types.Int]},
- {"F", typeof("F")},
- {"S", types.NewPointer(s)},
- }
-
- if got, want := len(ef), len(wants); got != want {
- t.Errorf("got %d fields, want %d\n%+v", got, want, ef)
- }
- for _, w := range wants {
- if got := ef[w.name]; got != nil && !types.Identical(got.Type(), w.typ) {
- t.Errorf("%s: got %v, want %v", w.name, got.Type(), w.typ)
- }
- }
-}