github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gotools/go/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 "go/build" 9 "io/ioutil" 10 "os" 11 "os/exec" 12 "path/filepath" 13 "runtime" 14 "strings" 15 "testing" 16 "time" 17 18 "llvm.org/llgo/third_party/gotools/go/types" 19 ) 20 21 var gcPath string // Go compiler path 22 23 func init() { 24 // determine compiler 25 var gc string 26 switch runtime.GOARCH { 27 case "386": 28 gc = "8g" 29 case "amd64": 30 gc = "6g" 31 case "arm": 32 gc = "5g" 33 default: 34 gcPath = "unknown-GOARCH-compiler" 35 return 36 } 37 gcPath = filepath.Join(build.ToolDir, gc) 38 } 39 40 func compile(t *testing.T, dirname, filename string) string { 41 cmd := exec.Command(gcPath, filename) 42 cmd.Dir = dirname 43 out, err := cmd.CombinedOutput() 44 if err != nil { 45 t.Logf("%s", out) 46 t.Fatalf("%s %s failed: %s", gcPath, filename, err) 47 } 48 archCh, _ := build.ArchChar(runtime.GOARCH) 49 // filename should end with ".go" 50 return filepath.Join(dirname, filename[:len(filename)-2]+archCh) 51 } 52 53 // Use the same global imports map for all tests. The effect is 54 // as if all tested packages were imported into a single package. 55 var imports = make(map[string]*types.Package) 56 57 func testPath(t *testing.T, path string) bool { 58 t0 := time.Now() 59 _, err := Import(imports, path) 60 if err != nil { 61 t.Errorf("testPath(%s): %s", path, err) 62 return false 63 } 64 t.Logf("testPath(%s): %v", path, time.Since(t0)) 65 return true 66 } 67 68 const maxTime = 30 * time.Second 69 70 func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) { 71 dirname := filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH, dir) 72 list, err := ioutil.ReadDir(dirname) 73 if err != nil { 74 t.Fatalf("testDir(%s): %s", dirname, err) 75 } 76 for _, f := range list { 77 if time.Now().After(endTime) { 78 t.Log("testing time used up") 79 return 80 } 81 switch { 82 case !f.IsDir(): 83 // try extensions 84 for _, ext := range pkgExts { 85 if strings.HasSuffix(f.Name(), ext) { 86 name := f.Name()[0 : len(f.Name())-len(ext)] // remove extension 87 if testPath(t, filepath.Join(dir, name)) { 88 nimports++ 89 } 90 } 91 } 92 case f.IsDir(): 93 nimports += testDir(t, filepath.Join(dir, f.Name()), endTime) 94 } 95 } 96 return 97 } 98 99 func TestImport(t *testing.T) { 100 // This package does not handle gccgo export data. 101 if runtime.Compiler == "gccgo" { 102 return 103 } 104 105 // On cross-compile builds, the path will not exist. 106 // Need to use GOHOSTOS, which is not available. 107 if _, err := os.Stat(gcPath); err != nil { 108 t.Skipf("skipping test: %v", err) 109 } 110 111 if outFn := compile(t, "testdata", "exports.go"); outFn != "" { 112 defer os.Remove(outFn) 113 } 114 115 nimports := 0 116 if testPath(t, "./testdata/exports") { 117 nimports++ 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 {"unsafe.Pointer", "type Pointer unsafe.Pointer"}, 128 {"math.Pi", "const Pi untyped float"}, 129 {"io.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"}, 130 {"io.ReadWriter", "type ReadWriter interface{Read(p []byte) (n int, err error); Write(p []byte) (n int, err error)}"}, 131 {"math.Sin", "func Sin(x float64) float64"}, 132 // TODO(gri) add more tests 133 } 134 135 func TestImportedTypes(t *testing.T) { 136 // This package does not handle gccgo export data. 137 if runtime.Compiler == "gccgo" { 138 return 139 } 140 for _, test := range importedObjectTests { 141 s := strings.Split(test.name, ".") 142 if len(s) != 2 { 143 t.Fatal("inconsistent test data") 144 } 145 importPath := s[0] 146 objName := s[1] 147 148 pkg, err := Import(imports, importPath) 149 if err != nil { 150 t.Error(err) 151 continue 152 } 153 154 obj := pkg.Scope().Lookup(objName) 155 if obj == nil { 156 t.Errorf("%s: object not found", test.name) 157 continue 158 } 159 160 got := types.ObjectString(pkg, obj) 161 if got != test.want { 162 t.Errorf("%s: got %q; want %q", test.name, got, test.want) 163 } 164 } 165 } 166 167 func TestIssue5815(t *testing.T) { 168 // This package does not handle gccgo export data. 169 if runtime.Compiler == "gccgo" { 170 return 171 } 172 173 pkg, err := Import(make(map[string]*types.Package), "strings") 174 if err != nil { 175 t.Fatal(err) 176 } 177 178 scope := pkg.Scope() 179 for _, name := range scope.Names() { 180 obj := scope.Lookup(name) 181 if obj.Pkg() == nil { 182 t.Errorf("no pkg for %s", obj) 183 } 184 if tname, _ := obj.(*types.TypeName); tname != nil { 185 named := tname.Type().(*types.Named) 186 for i := 0; i < named.NumMethods(); i++ { 187 m := named.Method(i) 188 if m.Pkg() == nil { 189 t.Errorf("no pkg for %s", m) 190 } 191 } 192 } 193 } 194 } 195 196 // Smoke test to ensure that imported methods get the correct package. 197 func TestCorrectMethodPackage(t *testing.T) { 198 // This package does not handle gccgo export data. 199 if runtime.Compiler == "gccgo" { 200 return 201 } 202 203 imports := make(map[string]*types.Package) 204 _, err := Import(imports, "net/http") 205 if err != nil { 206 t.Fatal(err) 207 } 208 209 mutex := imports["sync"].Scope().Lookup("Mutex").(*types.TypeName).Type() 210 mset := types.NewMethodSet(types.NewPointer(mutex)) // methods of *sync.Mutex 211 sel := mset.Lookup(nil, "Lock") 212 lock := sel.Obj().(*types.Func) 213 if got, want := lock.Pkg().Path(), "sync"; got != want { 214 t.Errorf("got package path %q; want %q", got, want) 215 } 216 }