github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gotools/go/loader/stdlib_test.go (about)

     1  // Copyright 2013 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 loader_test
     6  
     7  // This file enumerates all packages beneath $GOROOT, loads them, plus
     8  // their external tests if any, runs the type checker on them, and
     9  // prints some summary information.
    10  //
    11  // Run test with GOMAXPROCS=8.
    12  
    13  import (
    14  	"bytes"
    15  	"fmt"
    16  	"go/ast"
    17  	"go/build"
    18  	"go/token"
    19  	"io/ioutil"
    20  	"path/filepath"
    21  	"runtime"
    22  	"strings"
    23  	"testing"
    24  	"time"
    25  
    26  	"llvm.org/llgo/third_party/gotools/go/buildutil"
    27  	"llvm.org/llgo/third_party/gotools/go/loader"
    28  	"llvm.org/llgo/third_party/gotools/go/types"
    29  )
    30  
    31  func TestStdlib(t *testing.T) {
    32  	runtime.GC()
    33  	t0 := time.Now()
    34  	var memstats runtime.MemStats
    35  	runtime.ReadMemStats(&memstats)
    36  	alloc := memstats.Alloc
    37  
    38  	// Load, parse and type-check the program.
    39  	ctxt := build.Default // copy
    40  	ctxt.GOPATH = ""      // disable GOPATH
    41  	conf := loader.Config{Build: &ctxt}
    42  	for _, path := range buildutil.AllPackages(conf.Build) {
    43  		conf.ImportWithTests(path)
    44  	}
    45  
    46  	prog, err := conf.Load()
    47  	if err != nil {
    48  		t.Fatalf("Load failed: %v", err)
    49  	}
    50  
    51  	t1 := time.Now()
    52  	runtime.GC()
    53  	runtime.ReadMemStats(&memstats)
    54  
    55  	numPkgs := len(prog.AllPackages)
    56  	if want := 205; numPkgs < want {
    57  		t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want)
    58  	}
    59  
    60  	// Dump package members.
    61  	if false {
    62  		for pkg := range prog.AllPackages {
    63  			fmt.Printf("Package %s:\n", pkg.Path())
    64  			scope := pkg.Scope()
    65  			for _, name := range scope.Names() {
    66  				if ast.IsExported(name) {
    67  					fmt.Printf("\t%s\n", types.ObjectString(pkg, scope.Lookup(name)))
    68  				}
    69  			}
    70  			fmt.Println()
    71  		}
    72  	}
    73  
    74  	// Check that Test functions for io/ioutil, regexp and
    75  	// compress/bzip2 are all simultaneously present.
    76  	// (The apparent cycle formed when augmenting all three of
    77  	// these packages by their tests was the original motivation
    78  	// for reporting b/7114.)
    79  	//
    80  	// compress/bzip2.TestBitReader in bzip2_test.go    imports io/ioutil
    81  	// io/ioutil.TestTempFile       in tempfile_test.go imports regexp
    82  	// regexp.TestRE2Search         in exec_test.go     imports compress/bzip2
    83  	for _, test := range []struct{ pkg, fn string }{
    84  		{"io/ioutil", "TestTempFile"},
    85  		{"regexp", "TestRE2Search"},
    86  		{"compress/bzip2", "TestBitReader"},
    87  	} {
    88  		info := prog.Imported[test.pkg]
    89  		if info == nil {
    90  			t.Errorf("failed to load package %q", test.pkg)
    91  			continue
    92  		}
    93  		obj, _ := info.Pkg.Scope().Lookup(test.fn).(*types.Func)
    94  		if obj == nil {
    95  			t.Errorf("package %q has no func %q", test.pkg, test.fn)
    96  			continue
    97  		}
    98  	}
    99  
   100  	// Dump some statistics.
   101  
   102  	// determine line count
   103  	var lineCount int
   104  	prog.Fset.Iterate(func(f *token.File) bool {
   105  		lineCount += f.LineCount()
   106  		return true
   107  	})
   108  
   109  	t.Log("GOMAXPROCS:           ", runtime.GOMAXPROCS(0))
   110  	t.Log("#Source lines:        ", lineCount)
   111  	t.Log("Load/parse/typecheck: ", t1.Sub(t0))
   112  	t.Log("#MB:                  ", int64(memstats.Alloc-alloc)/1000000)
   113  }
   114  
   115  func TestCgoOption(t *testing.T) {
   116  	switch runtime.GOOS {
   117  	// On these systems, the net and os/user packages don't use cgo.
   118  	case "plan9", "solaris", "windows":
   119  		return
   120  	}
   121  	// In nocgo builds (e.g. linux-amd64-nocgo),
   122  	// there is no "runtime/cgo" package,
   123  	// so cgo-generated Go files will have a failing import.
   124  	if !build.Default.CgoEnabled {
   125  		return
   126  	}
   127  	// Test that we can load cgo-using packages with
   128  	// CGO_ENABLED=[01], which causes go/build to select pure
   129  	// Go/native implementations, respectively, based on build
   130  	// tags.
   131  	//
   132  	// Each entry specifies a package-level object and the generic
   133  	// file expected to define it when cgo is disabled.
   134  	// When cgo is enabled, the exact file is not specified (since
   135  	// it varies by platform), but must differ from the generic one.
   136  	//
   137  	// The test also loads the actual file to verify that the
   138  	// object is indeed defined at that location.
   139  	for _, test := range []struct {
   140  		pkg, name, genericFile string
   141  	}{
   142  		{"net", "cgoLookupHost", "cgo_stub.go"},
   143  		{"os/user", "lookupId", "lookup_stubs.go"},
   144  	} {
   145  		ctxt := build.Default
   146  		for _, ctxt.CgoEnabled = range []bool{false, true} {
   147  			conf := loader.Config{Build: &ctxt}
   148  			conf.Import(test.pkg)
   149  			prog, err := conf.Load()
   150  			if err != nil {
   151  				t.Errorf("Load failed: %v", err)
   152  				continue
   153  			}
   154  			info := prog.Imported[test.pkg]
   155  			if info == nil {
   156  				t.Errorf("package %s not found", test.pkg)
   157  				continue
   158  			}
   159  			obj := info.Pkg.Scope().Lookup(test.name)
   160  			if obj == nil {
   161  				t.Errorf("no object %s.%s", test.pkg, test.name)
   162  				continue
   163  			}
   164  			posn := prog.Fset.Position(obj.Pos())
   165  			t.Logf("%s: %s (CgoEnabled=%t)", posn, obj, ctxt.CgoEnabled)
   166  
   167  			gotFile := filepath.Base(posn.Filename)
   168  			filesMatch := gotFile == test.genericFile
   169  
   170  			if ctxt.CgoEnabled && filesMatch {
   171  				t.Errorf("CGO_ENABLED=1: %s found in %s, want native file",
   172  					obj, gotFile)
   173  			} else if !ctxt.CgoEnabled && !filesMatch {
   174  				t.Errorf("CGO_ENABLED=0: %s found in %s, want %s",
   175  					obj, gotFile, test.genericFile)
   176  			}
   177  
   178  			// Load the file and check the object is declared at the right place.
   179  			b, err := ioutil.ReadFile(posn.Filename)
   180  			if err != nil {
   181  				t.Errorf("can't read %s: %s", posn.Filename, err)
   182  				continue
   183  			}
   184  			line := string(bytes.Split(b, []byte("\n"))[posn.Line-1])
   185  			ident := line[posn.Column-1:]
   186  			if !strings.HasPrefix(ident, test.name) {
   187  				t.Errorf("%s: %s not declared here (looking at %q)", posn, obj, ident)
   188  			}
   189  		}
   190  	}
   191  }