.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.1.1-0.20210319172145-bda8f5cee399 / internal / apidiff / apidiff_test.go
1 // Copyright 2019 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package apidiff
6
7 import (
8         "bufio"
9         "fmt"
10         "go/types"
11         "io/ioutil"
12         "os"
13         "path/filepath"
14         "reflect"
15         "sort"
16         "strings"
17         "testing"
18
19         "golang.org/x/tools/go/packages"
20         "golang.org/x/tools/internal/testenv"
21 )
22
23 func TestChanges(t *testing.T) {
24         dir, err := ioutil.TempDir("", "apidiff_test")
25         if err != nil {
26                 t.Fatal(err)
27         }
28         dir = filepath.Join(dir, "go")
29         wanti, wantc := splitIntoPackages(t, dir)
30         defer os.RemoveAll(dir)
31         sort.Strings(wanti)
32         sort.Strings(wantc)
33
34         oldpkg, err := load(t, "apidiff/old", dir)
35         if err != nil {
36                 t.Fatal(err)
37         }
38         newpkg, err := load(t, "apidiff/new", dir)
39         if err != nil {
40                 t.Fatal(err)
41         }
42
43         report := Changes(oldpkg.Types, newpkg.Types)
44
45         got := report.messages(false)
46         if !reflect.DeepEqual(got, wanti) {
47                 t.Errorf("incompatibles: got %v\nwant %v\n", got, wanti)
48         }
49         got = report.messages(true)
50         if !reflect.DeepEqual(got, wantc) {
51                 t.Errorf("compatibles: got %v\nwant %v\n", got, wantc)
52         }
53 }
54
55 func splitIntoPackages(t *testing.T, dir string) (incompatibles, compatibles []string) {
56         // Read the input file line by line.
57         // Write a line into the old or new package,
58         // dependent on comments.
59         // Also collect expected messages.
60         f, err := os.Open("testdata/tests.go")
61         if err != nil {
62                 t.Fatal(err)
63         }
64         defer f.Close()
65
66         if err := os.MkdirAll(filepath.Join(dir, "src", "apidiff"), 0700); err != nil {
67                 t.Fatal(err)
68         }
69         if err := ioutil.WriteFile(filepath.Join(dir, "src", "apidiff", "go.mod"), []byte("module apidiff\n"), 0666); err != nil {
70                 t.Fatal(err)
71         }
72
73         oldd := filepath.Join(dir, "src/apidiff/old")
74         newd := filepath.Join(dir, "src/apidiff/new")
75         if err := os.MkdirAll(oldd, 0700); err != nil {
76                 t.Fatal(err)
77         }
78         if err := os.Mkdir(newd, 0700); err != nil && !os.IsExist(err) {
79                 t.Fatal(err)
80         }
81
82         oldf, err := os.Create(filepath.Join(oldd, "old.go"))
83         if err != nil {
84                 t.Fatal(err)
85         }
86         newf, err := os.Create(filepath.Join(newd, "new.go"))
87         if err != nil {
88                 t.Fatal(err)
89         }
90
91         wl := func(f *os.File, line string) {
92                 if _, err := fmt.Fprintln(f, line); err != nil {
93                         t.Fatal(err)
94                 }
95         }
96         writeBoth := func(line string) { wl(oldf, line); wl(newf, line) }
97         writeln := writeBoth
98         s := bufio.NewScanner(f)
99         for s.Scan() {
100                 line := s.Text()
101                 tl := strings.TrimSpace(line)
102                 switch {
103                 case tl == "// old":
104                         writeln = func(line string) { wl(oldf, line) }
105                 case tl == "// new":
106                         writeln = func(line string) { wl(newf, line) }
107                 case tl == "// both":
108                         writeln = writeBoth
109                 case strings.HasPrefix(tl, "// i "):
110                         incompatibles = append(incompatibles, strings.TrimSpace(tl[4:]))
111                 case strings.HasPrefix(tl, "// c "):
112                         compatibles = append(compatibles, strings.TrimSpace(tl[4:]))
113                 default:
114                         writeln(line)
115                 }
116         }
117         if s.Err() != nil {
118                 t.Fatal(s.Err())
119         }
120         return
121 }
122
123 func load(t *testing.T, importPath, goPath string) (*packages.Package, error) {
124         testenv.NeedsGoPackages(t)
125
126         cfg := &packages.Config{
127                 Mode: packages.LoadTypes,
128         }
129         if goPath != "" {
130                 cfg.Env = append(os.Environ(), "GOPATH="+goPath)
131                 cfg.Dir = filepath.Join(goPath, "src", filepath.FromSlash(importPath))
132         }
133         pkgs, err := packages.Load(cfg, importPath)
134         if err != nil {
135                 return nil, err
136         }
137         if len(pkgs[0].Errors) > 0 {
138                 return nil, pkgs[0].Errors[0]
139         }
140         return pkgs[0], nil
141 }
142
143 func TestExportedFields(t *testing.T) {
144         pkg, err := load(t, "golang.org/x/tools/internal/apidiff/testdata/exported_fields", "")
145         if err != nil {
146                 t.Fatal(err)
147         }
148         typeof := func(name string) types.Type {
149                 return pkg.Types.Scope().Lookup(name).Type()
150         }
151
152         s := typeof("S")
153         su := s.(*types.Named).Underlying().(*types.Struct)
154
155         ef := exportedSelectableFields(su)
156         wants := []struct {
157                 name string
158                 typ  types.Type
159         }{
160                 {"A1", typeof("A1")},
161                 {"D", types.Typ[types.Bool]},
162                 {"E", types.Typ[types.Int]},
163                 {"F", typeof("F")},
164                 {"S", types.NewPointer(s)},
165         }
166
167         if got, want := len(ef), len(wants); got != want {
168                 t.Errorf("got %d fields, want %d\n%+v", got, want, ef)
169         }
170         for _, w := range wants {
171                 if got := ef[w.name]; got != nil && !types.Identical(got.Type(), w.typ) {
172                         t.Errorf("%s: got %v, want %v", w.name, got.Type(), w.typ)
173                 }
174         }
175 }