github.com/zebozhuang/go@v0.0.0-20200207033046-f8a98f6f5c5d/src/go/internal/srcimporter/srcimporter_test.go (about) 1 // Copyright 2017 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 srcimporter 6 7 import ( 8 "go/build" 9 "go/token" 10 "go/types" 11 "internal/testenv" 12 "io/ioutil" 13 "path/filepath" 14 "runtime" 15 "strings" 16 "testing" 17 "time" 18 ) 19 20 const maxTime = 2 * time.Second 21 22 var importer = New(&build.Default, token.NewFileSet(), make(map[string]*types.Package)) 23 24 func doImport(t *testing.T, path, srcDir string) { 25 t0 := time.Now() 26 if _, err := importer.ImportFrom(path, srcDir, 0); err != nil { 27 // don't report an error if there's no buildable Go files 28 if _, nogo := err.(*build.NoGoError); !nogo { 29 t.Errorf("import %q failed (%v)", path, err) 30 } 31 return 32 } 33 t.Logf("import %q: %v", path, time.Since(t0)) 34 } 35 36 // walkDir imports the all the packages with the given path 37 // prefix recursively. It returns the number of packages 38 // imported and whether importing was aborted because time 39 // has passed endTime. 40 func walkDir(t *testing.T, path string, endTime time.Time) (int, bool) { 41 if time.Now().After(endTime) { 42 t.Log("testing time used up") 43 return 0, true 44 } 45 46 // ignore fake packages and testdata directories 47 if path == "builtin" || path == "unsafe" || strings.HasSuffix(path, "testdata") { 48 return 0, false 49 } 50 51 list, err := ioutil.ReadDir(filepath.Join(runtime.GOROOT(), "src", path)) 52 if err != nil { 53 t.Fatalf("walkDir %s failed (%v)", path, err) 54 } 55 56 nimports := 0 57 hasGoFiles := false 58 for _, f := range list { 59 if f.IsDir() { 60 n, abort := walkDir(t, filepath.Join(path, f.Name()), endTime) 61 nimports += n 62 if abort { 63 return nimports, true 64 } 65 } else if strings.HasSuffix(f.Name(), ".go") { 66 hasGoFiles = true 67 } 68 } 69 70 if hasGoFiles { 71 doImport(t, path, "") 72 nimports++ 73 } 74 75 return nimports, false 76 } 77 78 func TestImportStdLib(t *testing.T) { 79 if !testenv.HasSrc() { 80 t.Skip("no source code available") 81 } 82 83 dt := maxTime 84 if testing.Short() && testenv.Builder() == "" { 85 dt = 500 * time.Millisecond 86 } 87 nimports, _ := walkDir(t, "", time.Now().Add(dt)) // installed packages 88 t.Logf("tested %d imports", nimports) 89 } 90 91 var importedObjectTests = []struct { 92 name string 93 want string 94 }{ 95 {"flag.Bool", "func Bool(name string, value bool, usage string) *bool"}, 96 {"io.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"}, 97 {"io.ReadWriter", "type ReadWriter interface{Reader; Writer}"}, // go/types.gcCompatibilityMode is off => interface not flattened 98 {"math.Pi", "const Pi untyped float"}, 99 {"math.Sin", "func Sin(x float64) float64"}, 100 {"math/big.Int", "type Int struct{neg bool; abs nat}"}, 101 {"golang_org/x/text/unicode/norm.MaxSegmentSize", "const MaxSegmentSize untyped int"}, 102 } 103 104 func TestImportedTypes(t *testing.T) { 105 if !testenv.HasSrc() { 106 t.Skip("no source code available") 107 } 108 109 for _, test := range importedObjectTests { 110 s := strings.Split(test.name, ".") 111 if len(s) != 2 { 112 t.Fatal("invalid test data format") 113 } 114 importPath := s[0] 115 objName := s[1] 116 117 pkg, err := importer.ImportFrom(importPath, ".", 0) 118 if err != nil { 119 t.Error(err) 120 continue 121 } 122 123 obj := pkg.Scope().Lookup(objName) 124 if obj == nil { 125 t.Errorf("%s: object not found", test.name) 126 continue 127 } 128 129 got := types.ObjectString(obj, types.RelativeTo(pkg)) 130 if got != test.want { 131 t.Errorf("%s: got %q; want %q", test.name, got, test.want) 132 } 133 } 134 } 135 136 func TestReimport(t *testing.T) { 137 if !testenv.HasSrc() { 138 t.Skip("no source code available") 139 } 140 141 // Reimporting a partially imported (incomplete) package is not supported (see issue #19337). 142 // Make sure we recognize the situation and report an error. 143 144 mathPkg := types.NewPackage("math", "math") // incomplete package 145 importer := New(&build.Default, token.NewFileSet(), map[string]*types.Package{mathPkg.Path(): mathPkg}) 146 _, err := importer.ImportFrom("math", ".", 0) 147 if err == nil || !strings.HasPrefix(err.Error(), "reimport") { 148 t.Errorf("got %v; want reimport error", err) 149 } 150 }