github.com/peggyl/go@v0.0.0-20151008231540-ae315999c2d5/src/go/internal/gcimporter/gcimporter_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 gcimporter 6 7 import ( 8 "fmt" 9 "internal/testenv" 10 "io/ioutil" 11 "os" 12 "os/exec" 13 "path/filepath" 14 "runtime" 15 "strings" 16 "testing" 17 "time" 18 19 "go/types" 20 ) 21 22 // skipSpecialPlatforms causes the test to be skipped for platforms where 23 // builders (build.golang.org) don't have access to compiled packages for 24 // import. 25 func skipSpecialPlatforms(t *testing.T) { 26 switch platform := runtime.GOOS + "-" + runtime.GOARCH; platform { 27 case "nacl-amd64p32", 28 "nacl-386", 29 "nacl-arm", 30 "darwin-arm", 31 "darwin-arm64": 32 t.Skipf("no compiled packages available for import on %s", platform) 33 } 34 } 35 36 func compile(t *testing.T, dirname, filename string) string { 37 testenv.MustHaveGoBuild(t) 38 cmd := exec.Command("go", "tool", "compile", filename) 39 cmd.Dir = dirname 40 out, err := cmd.CombinedOutput() 41 if err != nil { 42 t.Logf("%s", out) 43 t.Fatalf("go tool compile %s failed: %s", filename, err) 44 } 45 // filename should end with ".go" 46 return filepath.Join(dirname, filename[:len(filename)-2]+"o") 47 } 48 49 // Use the same global imports map for all tests. The effect is 50 // as if all tested packages were imported into a single package. 51 var imports = make(map[string]*types.Package) 52 53 func testPath(t *testing.T, path string) *types.Package { 54 t0 := time.Now() 55 pkg, err := Import(imports, path) 56 if err != nil { 57 t.Errorf("testPath(%s): %s", path, err) 58 return nil 59 } 60 t.Logf("testPath(%s): %v", path, time.Since(t0)) 61 return pkg 62 } 63 64 const maxTime = 30 * time.Second 65 66 func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) { 67 dirname := filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH, dir) 68 list, err := ioutil.ReadDir(dirname) 69 if err != nil { 70 t.Fatalf("testDir(%s): %s", dirname, err) 71 } 72 for _, f := range list { 73 if time.Now().After(endTime) { 74 t.Log("testing time used up") 75 return 76 } 77 switch { 78 case !f.IsDir(): 79 // try extensions 80 for _, ext := range pkgExts { 81 if strings.HasSuffix(f.Name(), ext) { 82 name := f.Name()[0 : len(f.Name())-len(ext)] // remove extension 83 if testPath(t, filepath.Join(dir, name)) != nil { 84 nimports++ 85 } 86 } 87 } 88 case f.IsDir(): 89 nimports += testDir(t, filepath.Join(dir, f.Name()), endTime) 90 } 91 } 92 return 93 } 94 95 func TestImport(t *testing.T) { 96 // This package only handles gc export data. 97 if runtime.Compiler != "gc" { 98 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 99 return 100 } 101 102 if outFn := compile(t, "testdata", "exports.go"); outFn != "" { 103 defer os.Remove(outFn) 104 } 105 106 nimports := 0 107 if pkg := testPath(t, "./testdata/exports"); pkg != nil { 108 nimports++ 109 // The package's Imports should include all the types 110 // referenced by the exportdata, which may be more than 111 // the import statements in the package's source, but 112 // fewer than the transitive closure of dependencies. 113 want := `[package ast ("go/ast") package token ("go/token") package runtime ("runtime")]` 114 got := fmt.Sprint(pkg.Imports()) 115 if got != want { 116 t.Errorf(`Package("exports").Imports() = %s, want %s`, got, want) 117 } 118 } 119 nimports += testDir(t, "", time.Now().Add(maxTime)) // installed packages 120 t.Logf("tested %d imports", nimports) 121 } 122 123 var importedObjectTests = []struct { 124 name string 125 want string 126 }{ 127 {"math.Pi", "const Pi untyped float"}, 128 {"io.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"}, 129 {"io.ReadWriter", "type ReadWriter interface{Read(p []byte) (n int, err error); Write(p []byte) (n int, err error)}"}, 130 {"math.Sin", "func Sin(x float64) float64"}, 131 // TODO(gri) add more tests 132 } 133 134 func TestImportedTypes(t *testing.T) { 135 skipSpecialPlatforms(t) 136 137 // This package only handles gc export data. 138 if runtime.Compiler != "gc" { 139 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 140 return 141 } 142 143 for _, test := range importedObjectTests { 144 s := strings.Split(test.name, ".") 145 if len(s) != 2 { 146 t.Fatal("inconsistent test data") 147 } 148 importPath := s[0] 149 objName := s[1] 150 151 pkg, err := Import(imports, importPath) 152 if err != nil { 153 t.Error(err) 154 continue 155 } 156 157 obj := pkg.Scope().Lookup(objName) 158 if obj == nil { 159 t.Errorf("%s: object not found", test.name) 160 continue 161 } 162 163 got := types.ObjectString(obj, types.RelativeTo(pkg)) 164 if got != test.want { 165 t.Errorf("%s: got %q; want %q", test.name, got, test.want) 166 } 167 } 168 } 169 170 func TestIssue5815(t *testing.T) { 171 skipSpecialPlatforms(t) 172 173 // This package only handles gc export data. 174 if runtime.Compiler != "gc" { 175 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 176 return 177 } 178 179 pkg, err := Import(make(map[string]*types.Package), "strings") 180 if err != nil { 181 t.Fatal(err) 182 } 183 184 scope := pkg.Scope() 185 for _, name := range scope.Names() { 186 obj := scope.Lookup(name) 187 if obj.Pkg() == nil { 188 t.Errorf("no pkg for %s", obj) 189 } 190 if tname, _ := obj.(*types.TypeName); tname != nil { 191 named := tname.Type().(*types.Named) 192 for i := 0; i < named.NumMethods(); i++ { 193 m := named.Method(i) 194 if m.Pkg() == nil { 195 t.Errorf("no pkg for %s", m) 196 } 197 } 198 } 199 } 200 } 201 202 // Smoke test to ensure that imported methods get the correct package. 203 func TestCorrectMethodPackage(t *testing.T) { 204 skipSpecialPlatforms(t) 205 206 // This package only handles gc export data. 207 if runtime.Compiler != "gc" { 208 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 209 return 210 } 211 212 imports := make(map[string]*types.Package) 213 _, err := Import(imports, "net/http") 214 if err != nil { 215 t.Fatal(err) 216 } 217 218 mutex := imports["sync"].Scope().Lookup("Mutex").(*types.TypeName).Type() 219 mset := types.NewMethodSet(types.NewPointer(mutex)) // methods of *sync.Mutex 220 sel := mset.Lookup(nil, "Lock") 221 lock := sel.Obj().(*types.Func) 222 if got, want := lock.Pkg().Path(), "sync"; got != want { 223 t.Errorf("got package path %q; want %q", got, want) 224 } 225 }