github.com/dara-project/godist@v0.0.0-20200823115410-e0c80c8f0c78/src/cmd/api/goapi_test.go (about) 1 // Copyright 2011 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 main 6 7 import ( 8 "bytes" 9 "flag" 10 "fmt" 11 "go/build" 12 "internal/testenv" 13 "io/ioutil" 14 "os" 15 "os/exec" 16 "path/filepath" 17 "sort" 18 "strings" 19 "testing" 20 ) 21 22 var ( 23 updateGolden = flag.Bool("updategolden", false, "update golden files") 24 ) 25 26 func TestGolden(t *testing.T) { 27 td, err := os.Open("testdata/src/pkg") 28 if err != nil { 29 t.Fatal(err) 30 } 31 fis, err := td.Readdir(0) 32 if err != nil { 33 t.Fatal(err) 34 } 35 for _, fi := range fis { 36 if !fi.IsDir() { 37 continue 38 } 39 40 // TODO(gri) remove extra pkg directory eventually 41 goldenFile := filepath.Join("testdata", "src", "pkg", fi.Name(), "golden.txt") 42 w := NewWalker(nil, "testdata/src/pkg") 43 pkg, _ := w.Import(fi.Name()) 44 w.export(pkg) 45 46 if *updateGolden { 47 os.Remove(goldenFile) 48 f, err := os.Create(goldenFile) 49 if err != nil { 50 t.Fatal(err) 51 } 52 for _, feat := range w.Features() { 53 fmt.Fprintf(f, "%s\n", feat) 54 } 55 f.Close() 56 } 57 58 bs, err := ioutil.ReadFile(goldenFile) 59 if err != nil { 60 t.Fatalf("opening golden.txt for package %q: %v", fi.Name(), err) 61 } 62 wanted := strings.Split(string(bs), "\n") 63 sort.Strings(wanted) 64 for _, feature := range wanted { 65 if feature == "" { 66 continue 67 } 68 _, ok := w.features[feature] 69 if !ok { 70 t.Errorf("package %s: missing feature %q", fi.Name(), feature) 71 } 72 delete(w.features, feature) 73 } 74 75 for _, feature := range w.Features() { 76 t.Errorf("package %s: extra feature not in golden file: %q", fi.Name(), feature) 77 } 78 } 79 } 80 81 func TestCompareAPI(t *testing.T) { 82 tests := []struct { 83 name string 84 features, required, optional, exception []string 85 ok bool // want 86 out string // want 87 }{ 88 { 89 name: "feature added", 90 features: []string{"A", "B", "C", "D", "E", "F"}, 91 required: []string{"B", "D"}, 92 ok: true, 93 out: "+A\n+C\n+E\n+F\n", 94 }, 95 { 96 name: "feature removed", 97 features: []string{"C", "A"}, 98 required: []string{"A", "B", "C"}, 99 ok: false, 100 out: "-B\n", 101 }, 102 { 103 name: "feature added then removed", 104 features: []string{"A", "C"}, 105 optional: []string{"B"}, 106 required: []string{"A", "C"}, 107 ok: true, 108 out: "±B\n", 109 }, 110 { 111 name: "exception removal", 112 required: []string{"A", "B", "C"}, 113 features: []string{"A", "C"}, 114 exception: []string{"B"}, 115 ok: true, 116 out: "", 117 }, 118 { 119 // https://golang.org/issue/4303 120 name: "contexts reconverging", 121 required: []string{ 122 "A", 123 "pkg syscall (darwin-386), type RawSockaddrInet6 struct", 124 "pkg syscall (darwin-amd64), type RawSockaddrInet6 struct", 125 }, 126 features: []string{ 127 "A", 128 "pkg syscall, type RawSockaddrInet6 struct", 129 }, 130 ok: true, 131 out: "+pkg syscall, type RawSockaddrInet6 struct\n", 132 }, 133 } 134 for _, tt := range tests { 135 buf := new(bytes.Buffer) 136 gotok := compareAPI(buf, tt.features, tt.required, tt.optional, tt.exception, true) 137 if gotok != tt.ok { 138 t.Errorf("%s: ok = %v; want %v", tt.name, gotok, tt.ok) 139 } 140 if got := buf.String(); got != tt.out { 141 t.Errorf("%s: output differs\nGOT:\n%s\nWANT:\n%s", tt.name, got, tt.out) 142 } 143 } 144 } 145 146 func TestSkipInternal(t *testing.T) { 147 tests := []struct { 148 pkg string 149 want bool 150 }{ 151 {"net/http", true}, 152 {"net/http/internal-foo", true}, 153 {"net/http/internal", false}, 154 {"net/http/internal/bar", false}, 155 {"internal/foo", false}, 156 {"internal", false}, 157 } 158 for _, tt := range tests { 159 got := !internalPkg.MatchString(tt.pkg) 160 if got != tt.want { 161 t.Errorf("%s is internal = %v; want %v", tt.pkg, got, tt.want) 162 } 163 } 164 } 165 166 func BenchmarkAll(b *testing.B) { 167 stds, err := exec.Command(testenv.GoToolPath(b), "list", "std").Output() 168 if err != nil { 169 b.Fatal(err) 170 } 171 b.ResetTimer() 172 pkgNames := strings.Fields(string(stds)) 173 174 for _, c := range contexts { 175 c.Compiler = build.Default.Compiler 176 } 177 178 for i := 0; i < b.N; i++ { 179 for _, context := range contexts { 180 w := NewWalker(context, filepath.Join(build.Default.GOROOT, "src")) 181 for _, name := range pkgNames { 182 if name != "unsafe" && !strings.HasPrefix(name, "cmd/") && !internalPkg.MatchString(name) { 183 pkg, _ := w.Import(name) 184 w.export(pkg) 185 } 186 } 187 w.Features() 188 } 189 } 190 }