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  }