...
Run Format

Source file src/go/internal/srcimporter/srcimporter_test.go

Documentation: go/internal/srcimporter

  // Copyright 2017 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  package srcimporter
  
  import (
  	"go/build"
  	"go/token"
  	"go/types"
  	"internal/testenv"
  	"io/ioutil"
  	"path/filepath"
  	"runtime"
  	"strings"
  	"testing"
  	"time"
  )
  
  const maxTime = 2 * time.Second
  
  var importer = New(&build.Default, token.NewFileSet(), make(map[string]*types.Package))
  
  func doImport(t *testing.T, path, srcDir string) {
  	t0 := time.Now()
  	if _, err := importer.ImportFrom(path, srcDir, 0); err != nil {
  		// don't report an error if there's no buildable Go files
  		if _, nogo := err.(*build.NoGoError); !nogo {
  			t.Errorf("import %q failed (%v)", path, err)
  		}
  		return
  	}
  	t.Logf("import %q: %v", path, time.Since(t0))
  }
  
  // walkDir imports the all the packages with the given path
  // prefix recursively. It returns the number of packages
  // imported and whether importing was aborted because time
  // has passed endTime.
  func walkDir(t *testing.T, path string, endTime time.Time) (int, bool) {
  	if time.Now().After(endTime) {
  		t.Log("testing time used up")
  		return 0, true
  	}
  
  	// ignore fake packages and testdata directories
  	if path == "builtin" || path == "unsafe" || strings.HasSuffix(path, "testdata") {
  		return 0, false
  	}
  
  	list, err := ioutil.ReadDir(filepath.Join(runtime.GOROOT(), "src", path))
  	if err != nil {
  		t.Fatalf("walkDir %s failed (%v)", path, err)
  	}
  
  	nimports := 0
  	hasGoFiles := false
  	for _, f := range list {
  		if f.IsDir() {
  			n, abort := walkDir(t, filepath.Join(path, f.Name()), endTime)
  			nimports += n
  			if abort {
  				return nimports, true
  			}
  		} else if strings.HasSuffix(f.Name(), ".go") {
  			hasGoFiles = true
  		}
  	}
  
  	if hasGoFiles {
  		doImport(t, path, "")
  		nimports++
  	}
  
  	return nimports, false
  }
  
  func TestImportStdLib(t *testing.T) {
  	if !testenv.HasSrc() {
  		t.Skip("no source code available")
  	}
  
  	dt := maxTime
  	if testing.Short() && testenv.Builder() == "" {
  		dt = 500 * time.Millisecond
  	}
  	nimports, _ := walkDir(t, "", time.Now().Add(dt)) // installed packages
  	t.Logf("tested %d imports", nimports)
  }
  
  var importedObjectTests = []struct {
  	name string
  	want string
  }{
  	{"flag.Bool", "func Bool(name string, value bool, usage string) *bool"},
  	{"io.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"},
  	{"io.ReadWriter", "type ReadWriter interface{Reader; Writer}"}, // go/types.gcCompatibilityMode is off => interface not flattened
  	{"math.Pi", "const Pi untyped float"},
  	{"math.Sin", "func Sin(x float64) float64"},
  	{"math/big.Int", "type Int struct{neg bool; abs nat}"},
  	{"golang_org/x/text/unicode/norm.MaxSegmentSize", "const MaxSegmentSize untyped int"},
  }
  
  func TestImportedTypes(t *testing.T) {
  	if !testenv.HasSrc() {
  		t.Skip("no source code available")
  	}
  
  	for _, test := range importedObjectTests {
  		s := strings.Split(test.name, ".")
  		if len(s) != 2 {
  			t.Fatal("invalid test data format")
  		}
  		importPath := s[0]
  		objName := s[1]
  
  		pkg, err := importer.ImportFrom(importPath, ".", 0)
  		if err != nil {
  			t.Error(err)
  			continue
  		}
  
  		obj := pkg.Scope().Lookup(objName)
  		if obj == nil {
  			t.Errorf("%s: object not found", test.name)
  			continue
  		}
  
  		got := types.ObjectString(obj, types.RelativeTo(pkg))
  		if got != test.want {
  			t.Errorf("%s: got %q; want %q", test.name, got, test.want)
  		}
  	}
  }
  
  func TestReimport(t *testing.T) {
  	if !testenv.HasSrc() {
  		t.Skip("no source code available")
  	}
  
  	// Reimporting a partially imported (incomplete) package is not supported (see issue #19337).
  	// Make sure we recognize the situation and report an error.
  
  	mathPkg := types.NewPackage("math", "math") // incomplete package
  	importer := New(&build.Default, token.NewFileSet(), map[string]*types.Package{mathPkg.Path(): mathPkg})
  	_, err := importer.ImportFrom("math", ".", 0)
  	if err == nil || !strings.HasPrefix(err.Error(), "reimport") {
  		t.Errorf("got %v; want reimport error", err)
  	}
  }
  

View as plain text