github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/tools/go/ssa/interp/interp14_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  // +build !go1.5
     6  
     7  // +build !android,!windows,!plan9
     8  
     9  package interp_test
    10  
    11  import (
    12  	"bytes"
    13  	"fmt"
    14  	"go/build"
    15  	"os"
    16  	"path/filepath"
    17  	"strings"
    18  	"testing"
    19  	"time"
    20  
    21  	"golang.org/x/tools/go/loader"
    22  	"golang.org/x/tools/go/ssa"
    23  	"golang.org/x/tools/go/ssa/interp"
    24  	"golang.org/x/tools/go/ssa/ssautil"
    25  	"golang.org/x/tools/go/types"
    26  )
    27  
    28  // Each line contains a space-separated list of $GOROOT/test/
    29  // filenames comprising the main package of a program.
    30  // They are ordered quickest-first, roughly.
    31  //
    32  // TODO(adonovan): integrate into the $GOROOT/test driver scripts,
    33  // golden file checking, etc.
    34  var gorootTestTests = []string{
    35  	"235.go",
    36  	"alias1.go",
    37  	"chancap.go",
    38  	"func5.go",
    39  	"func6.go",
    40  	"func7.go",
    41  	"func8.go",
    42  	"helloworld.go",
    43  	"varinit.go",
    44  	"escape3.go",
    45  	"initcomma.go",
    46  	"cmp.go",
    47  	"compos.go",
    48  	"turing.go",
    49  	"indirect.go",
    50  	// "complit.go", // tests go1.5 features
    51  	"for.go",
    52  	"struct0.go",
    53  	"intcvt.go",
    54  	"printbig.go",
    55  	"deferprint.go",
    56  	"escape.go",
    57  	"range.go",
    58  	"const4.go",
    59  	"float_lit.go",
    60  	"bigalg.go",
    61  	"decl.go",
    62  	"if.go",
    63  	"named.go",
    64  	"bigmap.go",
    65  	"func.go",
    66  	"reorder2.go",
    67  	"closure.go",
    68  	"gc.go",
    69  	"simassign.go",
    70  	"iota.go",
    71  	"nilptr2.go",
    72  	"goprint.go", // doesn't actually assert anything (cmpout)
    73  	"utf.go",
    74  	"method.go",
    75  	"char_lit.go",
    76  	"env.go",
    77  	"int_lit.go",
    78  	"string_lit.go",
    79  	"defer.go",
    80  	"typeswitch.go",
    81  	"stringrange.go",
    82  	"reorder.go",
    83  	"method3.go",
    84  	"literal.go",
    85  	"nul1.go", // doesn't actually assert anything (errorcheckoutput)
    86  	"zerodivide.go",
    87  	"convert.go",
    88  	"convT2X.go",
    89  	"switch.go",
    90  	"initialize.go",
    91  	"ddd.go",
    92  	"blank.go", // partly disabled
    93  	"map.go",
    94  	"closedchan.go",
    95  	"divide.go",
    96  	"rename.go",
    97  	"const3.go",
    98  	"nil.go",
    99  	"recover.go", // reflection parts disabled
   100  	"recover1.go",
   101  	"recover2.go",
   102  	"recover3.go",
   103  	"typeswitch1.go",
   104  	"floatcmp.go",
   105  	"crlf.go", // doesn't actually assert anything (runoutput)
   106  	// Slow tests follow.
   107  	"bom.go", // ~1.7s
   108  	"gc1.go", // ~1.7s
   109  	"cmplxdivide.go cmplxdivide1.go", // ~2.4s
   110  
   111  	// Working, but not worth enabling:
   112  	// "append.go",    // works, but slow (15s).
   113  	// "gc2.go",       // works, but slow, and cheats on the memory check.
   114  	// "sigchld.go",   // works, but only on POSIX.
   115  	// "peano.go",     // works only up to n=9, and slow even then.
   116  	// "stack.go",     // works, but too slow (~30s) by default.
   117  	// "solitaire.go", // works, but too slow (~30s).
   118  	// "const.go",     // works but for but one bug: constant folder doesn't consider representations.
   119  	// "init1.go",     // too slow (80s) and not that interesting. Cheats on ReadMemStats check too.
   120  	// "rotate.go rotate0.go", // emits source for a test
   121  	// "rotate.go rotate1.go", // emits source for a test
   122  	// "rotate.go rotate2.go", // emits source for a test
   123  	// "rotate.go rotate3.go", // emits source for a test
   124  	// "64bit.go",             // emits source for a test
   125  	// "run.go",               // test driver, not a test.
   126  
   127  	// Broken.  TODO(adonovan): fix.
   128  	// copy.go         // very slow; but with N=4 quickly crashes, slice index out of range.
   129  	// nilptr.go       // interp: V > uintptr not implemented. Slow test, lots of mem
   130  	// args.go         // works, but requires specific os.Args from the driver.
   131  	// index.go        // a template, not a real test.
   132  	// mallocfin.go    // SetFinalizer not implemented.
   133  
   134  	// TODO(adonovan): add tests from $GOROOT/test/* subtrees:
   135  	// bench chan bugs fixedbugs interface ken.
   136  }
   137  
   138  // These are files in go.tools/go/ssa/interp/testdata/.
   139  var testdataTests = []string{
   140  	"boundmeth.go",
   141  	// "complit.go", // requires go1.5
   142  	"coverage.go",
   143  	"defer.go",
   144  	"fieldprom.go",
   145  	"ifaceconv.go",
   146  	"ifaceprom.go",
   147  	"initorder.go",
   148  	"methprom.go",
   149  	"mrvchain.go",
   150  	"range.go",
   151  	"recover.go",
   152  	"reflect.go",
   153  	"static.go",
   154  	"callstack.go",
   155  }
   156  
   157  // These are files and packages in $GOROOT/src/.
   158  var gorootSrcTests = []string{
   159  	"encoding/ascii85",
   160  	"encoding/hex",
   161  	// "encoding/pem", // TODO(adonovan): implement (reflect.Value).SetString
   162  	// "testing",      // TODO(adonovan): implement runtime.Goexit correctly
   163  	// "hash/crc32",   // TODO(adonovan): implement hash/crc32.haveCLMUL
   164  	// "log",          // TODO(adonovan): implement runtime.Callers correctly
   165  
   166  	// Too slow:
   167  	// "container/ring",
   168  	// "hash/adler32",
   169  
   170  	"unicode/utf8",
   171  	"path",
   172  	"flag",
   173  	"encoding/csv",
   174  	"text/scanner",
   175  	"unicode",
   176  }
   177  
   178  type successPredicate func(exitcode int, output string) error
   179  
   180  func run(t *testing.T, dir, input string, success successPredicate) bool {
   181  	fmt.Printf("Input: %s\n", input)
   182  
   183  	start := time.Now()
   184  
   185  	var inputs []string
   186  	for _, i := range strings.Split(input, " ") {
   187  		if strings.HasSuffix(i, ".go") {
   188  			i = dir + i
   189  		}
   190  		inputs = append(inputs, i)
   191  	}
   192  
   193  	var conf loader.Config
   194  	if _, err := conf.FromArgs(inputs, true); err != nil {
   195  		t.Errorf("FromArgs(%s) failed: %s", inputs, err)
   196  		return false
   197  	}
   198  
   199  	conf.Import("runtime")
   200  
   201  	// Print a helpful hint if we don't make it to the end.
   202  	var hint string
   203  	defer func() {
   204  		if hint != "" {
   205  			fmt.Println("FAIL")
   206  			fmt.Println(hint)
   207  		} else {
   208  			fmt.Println("PASS")
   209  		}
   210  
   211  		interp.CapturedOutput = nil
   212  	}()
   213  
   214  	hint = fmt.Sprintf("To dump SSA representation, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -test -build=CFP %s\n", input)
   215  
   216  	iprog, err := conf.Load()
   217  	if err != nil {
   218  		t.Errorf("conf.Load(%s) failed: %s", inputs, err)
   219  		return false
   220  	}
   221  
   222  	prog := ssautil.CreateProgram(iprog, ssa.SanityCheckFunctions)
   223  	prog.Build()
   224  
   225  	var mainPkg *ssa.Package
   226  	var initialPkgs []*ssa.Package
   227  	for _, info := range iprog.InitialPackages() {
   228  		if info.Pkg.Path() == "runtime" {
   229  			continue // not an initial package
   230  		}
   231  		p := prog.Package(info.Pkg)
   232  		initialPkgs = append(initialPkgs, p)
   233  		if mainPkg == nil && p.Func("main") != nil {
   234  			mainPkg = p
   235  		}
   236  	}
   237  	if mainPkg == nil {
   238  		testmainPkg := prog.CreateTestMainPackage(initialPkgs...)
   239  		if testmainPkg == nil {
   240  			t.Errorf("CreateTestMainPackage(%s) returned nil", mainPkg)
   241  			return false
   242  		}
   243  		if testmainPkg.Func("main") == nil {
   244  			t.Errorf("synthetic testmain package has no main")
   245  			return false
   246  		}
   247  		mainPkg = testmainPkg
   248  	}
   249  
   250  	var out bytes.Buffer
   251  	interp.CapturedOutput = &out
   252  
   253  	hint = fmt.Sprintf("To trace execution, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -build=C -run --interp=T %s\n", input)
   254  	exitCode := interp.Interpret(mainPkg, 0, &types.StdSizes{8, 8}, inputs[0], []string{})
   255  
   256  	// The definition of success varies with each file.
   257  	if err := success(exitCode, out.String()); err != nil {
   258  		t.Errorf("interp.Interpret(%s) failed: %s", inputs, err)
   259  		return false
   260  	}
   261  
   262  	hint = "" // call off the hounds
   263  
   264  	if false {
   265  		fmt.Println(input, time.Since(start)) // test profiling
   266  	}
   267  
   268  	return true
   269  }
   270  
   271  const slash = string(os.PathSeparator)
   272  
   273  func printFailures(failures []string) {
   274  	if failures != nil {
   275  		fmt.Println("The following tests failed:")
   276  		for _, f := range failures {
   277  			fmt.Printf("\t%s\n", f)
   278  		}
   279  	}
   280  }
   281  
   282  func success(exitcode int, output string) error {
   283  	if exitcode != 0 {
   284  		return fmt.Errorf("exit code was %d", exitcode)
   285  	}
   286  	if strings.Contains(output, "BUG") {
   287  		return fmt.Errorf("exited zero but output contained 'BUG'")
   288  	}
   289  	return nil
   290  }
   291  
   292  // TestTestdataFiles runs the interpreter on testdata/*.go.
   293  func TestTestdataFiles(t *testing.T) {
   294  	var failures []string
   295  	start := time.Now()
   296  	for _, input := range testdataTests {
   297  		if testing.Short() && time.Since(start) > 30*time.Second {
   298  			printFailures(failures)
   299  			t.Skipf("timeout - aborting test")
   300  		}
   301  		if !run(t, "testdata"+slash, input, success) {
   302  			failures = append(failures, input)
   303  		}
   304  	}
   305  	printFailures(failures)
   306  }
   307  
   308  // TestGorootTest runs the interpreter on $GOROOT/test/*.go.
   309  func TestGorootTest(t *testing.T) {
   310  	if testing.Short() {
   311  		t.Skip() // too slow (~30s)
   312  	}
   313  
   314  	var failures []string
   315  
   316  	for _, input := range gorootTestTests {
   317  		if !run(t, filepath.Join(build.Default.GOROOT, "test")+slash, input, success) {
   318  			failures = append(failures, input)
   319  		}
   320  	}
   321  	for _, input := range gorootSrcTests {
   322  		if !run(t, filepath.Join(build.Default.GOROOT, "src")+slash, input, success) {
   323  			failures = append(failures, input)
   324  		}
   325  	}
   326  	printFailures(failures)
   327  }
   328  
   329  // TestTestmainPackage runs the interpreter on a synthetic "testmain" package.
   330  func TestTestmainPackage(t *testing.T) {
   331  	if testing.Short() {
   332  		t.Skip() // too slow on some platforms
   333  	}
   334  
   335  	success := func(exitcode int, output string) error {
   336  		if exitcode == 0 {
   337  			return fmt.Errorf("unexpected success")
   338  		}
   339  		if !strings.Contains(output, "FAIL: TestFoo") {
   340  			return fmt.Errorf("missing failure log for TestFoo")
   341  		}
   342  		if !strings.Contains(output, "FAIL: TestBar") {
   343  			return fmt.Errorf("missing failure log for TestBar")
   344  		}
   345  		// TODO(adonovan): test benchmarks too
   346  		return nil
   347  	}
   348  	run(t, "testdata"+slash, "a_test.go", success)
   349  }
   350  
   351  // CreateTestMainPackage should return nil if there were no tests.
   352  func TestNullTestmainPackage(t *testing.T) {
   353  	var conf loader.Config
   354  	conf.CreateFromFilenames("", "testdata/b_test.go")
   355  	iprog, err := conf.Load()
   356  	if err != nil {
   357  		t.Fatalf("CreatePackages failed: %s", err)
   358  	}
   359  	prog := ssautil.CreateProgram(iprog, ssa.SanityCheckFunctions)
   360  	mainPkg := prog.Package(iprog.Created[0].Pkg)
   361  	if mainPkg.Func("main") != nil {
   362  		t.Fatalf("unexpected main function")
   363  	}
   364  	if prog.CreateTestMainPackage(mainPkg) != nil {
   365  		t.Fatalf("CreateTestMainPackage returned non-nil")
   366  	}
   367  }