| 
									
										
										
										
											2012-03-22 02:14:44 +08:00
										 |  |  | // skip | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Copyright 2012 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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Run runs tests in the test directory. | 
					
						
							| 
									
										
										
										
											2012-12-22 19:16:31 +01:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | // TODO(bradfitz): docs of some sort, once we figure out how we're changing | 
					
						
							|  |  |  | // headers of files | 
					
						
							|  |  |  | package main | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 	"errors" | 
					
						
							|  |  |  | 	"flag" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"go/build" | 
					
						
							|  |  |  | 	"io/ioutil" | 
					
						
							|  |  |  | 	"log" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"os/exec" | 
					
						
							| 
									
										
										
										
											2012-09-23 13:16:14 -04:00
										 |  |  | 	"path" | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 	"path/filepath" | 
					
						
							|  |  |  | 	"regexp" | 
					
						
							|  |  |  | 	"runtime" | 
					
						
							|  |  |  | 	"sort" | 
					
						
							|  |  |  | 	"strconv" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							| 
									
										
										
										
											2013-01-12 17:52:52 +11:00
										 |  |  | 	verbose        = flag.Bool("v", false, "verbose. if set, parallelism is set to 1.") | 
					
						
							|  |  |  | 	numParallel    = flag.Int("n", runtime.NumCPU(), "number of parallel tests to run") | 
					
						
							|  |  |  | 	summary        = flag.Bool("summary", false, "show summary of results") | 
					
						
							|  |  |  | 	showSkips      = flag.Bool("show_skips", false, "show skipped tests") | 
					
						
							|  |  |  | 	runoutputLimit = flag.Int("l", defaultRunOutputLimit(), "number of parallel runoutput tests to run") | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	// gc and ld are [568][gl]. | 
					
						
							|  |  |  | 	gc, ld string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// letter is the build.ArchChar | 
					
						
							|  |  |  | 	letter string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// dirs are the directories to look for *.go files in. | 
					
						
							|  |  |  | 	// TODO(bradfitz): just use all directories? | 
					
						
							|  |  |  | 	dirs = []string{".", "ken", "chan", "interface", "syntax", "dwarf", "fixedbugs", "bugs"} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// ratec controls the max number of tests running at a time. | 
					
						
							|  |  |  | 	ratec chan bool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// toRun is the channel of tests to run. | 
					
						
							|  |  |  | 	// It is nil until the first test is started. | 
					
						
							|  |  |  | 	toRun chan *test | 
					
						
							| 
									
										
										
										
											2013-01-12 17:52:52 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// rungatec controls the max number of runoutput tests | 
					
						
							|  |  |  | 	// executed in parallel as they can each consume a lot of memory. | 
					
						
							|  |  |  | 	rungatec chan bool | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // maxTests is an upper bound on the total number of tests. | 
					
						
							|  |  |  | // It is used as a channel buffer size to make sure sends don't block. | 
					
						
							|  |  |  | const maxTests = 5000 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func main() { | 
					
						
							|  |  |  | 	flag.Parse() | 
					
						
							| 
									
										
										
										
											2012-03-07 12:43:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Disable parallelism if printing | 
					
						
							|  |  |  | 	if *verbose { | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 		*numParallel = 1 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ratec = make(chan bool, *numParallel) | 
					
						
							| 
									
										
										
										
											2013-01-12 17:52:52 +11:00
										 |  |  | 	rungatec = make(chan bool, *runoutputLimit) | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 	var err error | 
					
						
							| 
									
										
										
										
											2012-03-06 03:34:53 +08:00
										 |  |  | 	letter, err = build.ArchChar(build.Default.GOARCH) | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 	check(err) | 
					
						
							|  |  |  | 	gc = letter + "g" | 
					
						
							|  |  |  | 	ld = letter + "l" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var tests []*test | 
					
						
							|  |  |  | 	if flag.NArg() > 0 { | 
					
						
							|  |  |  | 		for _, arg := range flag.Args() { | 
					
						
							|  |  |  | 			if arg == "-" || arg == "--" { | 
					
						
							| 
									
										
										
										
											2012-08-07 09:38:35 +08:00
										 |  |  | 				// Permit running: | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 				// $ go run run.go - env.go | 
					
						
							|  |  |  | 				// $ go run run.go -- env.go | 
					
						
							| 
									
										
										
										
											2012-08-07 09:38:35 +08:00
										 |  |  | 				// $ go run run.go - ./fixedbugs | 
					
						
							|  |  |  | 				// $ go run run.go -- ./fixedbugs | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-08-07 09:38:35 +08:00
										 |  |  | 			if fi, err := os.Stat(arg); err == nil && fi.IsDir() { | 
					
						
							|  |  |  | 				for _, baseGoFile := range goFiles(arg) { | 
					
						
							|  |  |  | 					tests = append(tests, startTest(arg, baseGoFile)) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} else if strings.HasSuffix(arg, ".go") { | 
					
						
							|  |  |  | 				dir, file := filepath.Split(arg) | 
					
						
							|  |  |  | 				tests = append(tests, startTest(dir, file)) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				log.Fatalf("can't yet deal with non-directory and non-go file %q", arg) | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		for _, dir := range dirs { | 
					
						
							|  |  |  | 			for _, baseGoFile := range goFiles(dir) { | 
					
						
							|  |  |  | 				tests = append(tests, startTest(dir, baseGoFile)) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	failed := false | 
					
						
							|  |  |  | 	resCount := map[string]int{} | 
					
						
							|  |  |  | 	for _, test := range tests { | 
					
						
							|  |  |  | 		<-test.donec | 
					
						
							|  |  |  | 		_, isSkip := test.err.(skipError) | 
					
						
							| 
									
										
										
										
											2012-02-24 12:52:15 +11:00
										 |  |  | 		errStr := "pass" | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 		if test.err != nil { | 
					
						
							|  |  |  | 			errStr = test.err.Error() | 
					
						
							|  |  |  | 			if !isSkip { | 
					
						
							|  |  |  | 				failed = true | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-09-23 13:16:14 -04:00
										 |  |  | 		if isSkip && !skipOkay[path.Join(test.dir, test.gofile)] { | 
					
						
							|  |  |  | 			errStr = "unexpected skip for " + path.Join(test.dir, test.gofile) + ": " + errStr | 
					
						
							|  |  |  | 			isSkip = false | 
					
						
							|  |  |  | 			failed = true | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 		resCount[errStr]++ | 
					
						
							| 
									
										
										
										
											2012-02-24 12:52:15 +11:00
										 |  |  | 		if isSkip && !*verbose && !*showSkips { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 		if !*verbose && test.err == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2012-02-24 12:52:15 +11:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-11-07 12:33:54 -08:00
										 |  |  | 		fmt.Printf("%-20s %-20s: %s\n", test.action, test.goFileName(), errStr) | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if *summary { | 
					
						
							|  |  |  | 		for k, v := range resCount { | 
					
						
							|  |  |  | 			fmt.Printf("%5d %s\n", v, k) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if failed { | 
					
						
							|  |  |  | 		os.Exit(1) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func toolPath(name string) string { | 
					
						
							|  |  |  | 	p := filepath.Join(os.Getenv("GOROOT"), "bin", "tool", name) | 
					
						
							|  |  |  | 	if _, err := os.Stat(p); err != nil { | 
					
						
							|  |  |  | 		log.Fatalf("didn't find binary at %s", p) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return p | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func goFiles(dir string) []string { | 
					
						
							|  |  |  | 	f, err := os.Open(dir) | 
					
						
							|  |  |  | 	check(err) | 
					
						
							|  |  |  | 	dirnames, err := f.Readdirnames(-1) | 
					
						
							|  |  |  | 	check(err) | 
					
						
							|  |  |  | 	names := []string{} | 
					
						
							|  |  |  | 	for _, name := range dirnames { | 
					
						
							| 
									
										
										
										
											2012-03-08 14:03:40 -05:00
										 |  |  | 		if !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") { | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 			names = append(names, name) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	sort.Strings(names) | 
					
						
							|  |  |  | 	return names | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | type runCmd func(...string) ([]byte, error) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func compileFile(runcmd runCmd, longname string) (out []byte, err error) { | 
					
						
							|  |  |  | 	return runcmd("go", "tool", gc, "-e", longname) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-02 15:31:49 -05:00
										 |  |  | func compileInDir(runcmd runCmd, dir string, names ...string) (out []byte, err error) { | 
					
						
							|  |  |  | 	cmd := []string{"go", "tool", gc, "-e", "-D", ".", "-I", "."} | 
					
						
							|  |  |  | 	for _, name := range names { | 
					
						
							|  |  |  | 		cmd = append(cmd, filepath.Join(dir, name)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return runcmd(cmd...) | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func linkFile(runcmd runCmd, goname string) (err error) { | 
					
						
							|  |  |  | 	pfile := strings.Replace(goname, ".go", "."+letter, -1) | 
					
						
							| 
									
										
										
										
											2012-10-08 01:54:56 +08:00
										 |  |  | 	_, err = runcmd("go", "tool", ld, "-o", "a.exe", "-L", ".", pfile) | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | // skipError describes why a test was skipped. | 
					
						
							|  |  |  | type skipError string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s skipError) Error() string { return string(s) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func check(err error) { | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		log.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // test holds the state of a test. | 
					
						
							|  |  |  | type test struct { | 
					
						
							|  |  |  | 	dir, gofile string | 
					
						
							|  |  |  | 	donec       chan bool // closed when done | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	src    string | 
					
						
							| 
									
										
										
										
											2012-11-07 12:33:54 -08:00
										 |  |  | 	action string // "compile", "build", etc. | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	tempDir string | 
					
						
							|  |  |  | 	err     error | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-22 19:16:31 +01:00
										 |  |  | // startTest | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | func startTest(dir, gofile string) *test { | 
					
						
							|  |  |  | 	t := &test{ | 
					
						
							|  |  |  | 		dir:    dir, | 
					
						
							|  |  |  | 		gofile: gofile, | 
					
						
							|  |  |  | 		donec:  make(chan bool, 1), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if toRun == nil { | 
					
						
							|  |  |  | 		toRun = make(chan *test, maxTests) | 
					
						
							|  |  |  | 		go runTests() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	select { | 
					
						
							|  |  |  | 	case toRun <- t: | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		panic("toRun buffer size (maxTests) is too small") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return t | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // runTests runs tests in parallel, but respecting the order they | 
					
						
							|  |  |  | // were enqueued on the toRun channel. | 
					
						
							|  |  |  | func runTests() { | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		ratec <- true | 
					
						
							|  |  |  | 		t := <-toRun | 
					
						
							|  |  |  | 		go func() { | 
					
						
							|  |  |  | 			t.run() | 
					
						
							|  |  |  | 			<-ratec | 
					
						
							|  |  |  | 		}() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 01:54:39 -05:00
										 |  |  | var cwd, _ = os.Getwd() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | func (t *test) goFileName() string { | 
					
						
							|  |  |  | 	return filepath.Join(t.dir, t.gofile) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-30 21:12:05 +02:00
										 |  |  | func (t *test) goDirName() string { | 
					
						
							|  |  |  | 	return filepath.Join(t.dir, strings.Replace(t.gofile, ".go", ".dir", -1)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | func goDirFiles(longdir string) (filter []os.FileInfo, err error) { | 
					
						
							|  |  |  | 	files, dirErr := ioutil.ReadDir(longdir) | 
					
						
							|  |  |  | 	if dirErr != nil { | 
					
						
							|  |  |  | 		return nil, dirErr | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, gofile := range files { | 
					
						
							|  |  |  | 		if filepath.Ext(gofile.Name()) == ".go" { | 
					
						
							|  |  |  | 			filter = append(filter, gofile) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-02 15:31:49 -05:00
										 |  |  | var packageRE = regexp.MustCompile(`(?m)^package (\w+)`) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func goDirPackages(longdir string) ([][]string, error) { | 
					
						
							|  |  |  | 	files, err := goDirFiles(longdir) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var pkgs [][]string | 
					
						
							|  |  |  | 	m := make(map[string]int) | 
					
						
							|  |  |  | 	for _, file := range files { | 
					
						
							|  |  |  | 		name := file.Name() | 
					
						
							|  |  |  | 		data, err := ioutil.ReadFile(filepath.Join(longdir, name)) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		pkgname := packageRE.FindStringSubmatch(string(data)) | 
					
						
							|  |  |  | 		if pkgname == nil { | 
					
						
							|  |  |  | 			return nil, fmt.Errorf("cannot find package name in %s", name) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		i, ok := m[pkgname[1]] | 
					
						
							|  |  |  | 		if !ok { | 
					
						
							|  |  |  | 			i = len(pkgs) | 
					
						
							|  |  |  | 			pkgs = append(pkgs, nil) | 
					
						
							|  |  |  | 			m[pkgname[1]] = i | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		pkgs[i] = append(pkgs[i], name) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return pkgs, nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-01-11 22:00:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | // run runs a test. | 
					
						
							|  |  |  | func (t *test) run() { | 
					
						
							|  |  |  | 	defer close(t.donec) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	srcBytes, err := ioutil.ReadFile(t.goFileName()) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.err = err | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	t.src = string(srcBytes) | 
					
						
							|  |  |  | 	if t.src[0] == '\n' { | 
					
						
							|  |  |  | 		t.err = skipError("starts with newline") | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	pos := strings.Index(t.src, "\n\n") | 
					
						
							|  |  |  | 	if pos == -1 { | 
					
						
							|  |  |  | 		t.err = errors.New("double newline not found") | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	action := t.src[:pos] | 
					
						
							|  |  |  | 	if strings.HasPrefix(action, "//") { | 
					
						
							|  |  |  | 		action = action[2:] | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-08 14:03:40 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-23 13:16:14 -04:00
										 |  |  | 	var args, flags []string | 
					
						
							|  |  |  | 	wantError := false | 
					
						
							| 
									
										
										
										
											2012-03-07 01:54:39 -05:00
										 |  |  | 	f := strings.Fields(action) | 
					
						
							|  |  |  | 	if len(f) > 0 { | 
					
						
							|  |  |  | 		action = f[0] | 
					
						
							|  |  |  | 		args = f[1:] | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	switch action { | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 	case "rundircmpout": | 
					
						
							|  |  |  | 		action = "rundir" | 
					
						
							|  |  |  | 		t.action = "rundir" | 
					
						
							| 
									
										
										
										
											2012-02-24 13:17:26 +11:00
										 |  |  | 	case "cmpout": | 
					
						
							|  |  |  | 		action = "run" // the run case already looks for <dir>/<test>.out files | 
					
						
							|  |  |  | 		fallthrough | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 	case "compile", "compiledir", "build", "run", "runoutput", "rundir": | 
					
						
							| 
									
										
										
										
											2012-09-23 13:16:14 -04:00
										 |  |  | 		t.action = action | 
					
						
							| 
									
										
										
										
											2012-11-07 12:33:54 -08:00
										 |  |  | 	case "errorcheck", "errorcheckdir", "errorcheckoutput": | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 		t.action = action | 
					
						
							| 
									
										
										
										
											2012-09-23 13:16:14 -04:00
										 |  |  | 		wantError = true | 
					
						
							|  |  |  | 		for len(args) > 0 && strings.HasPrefix(args[0], "-") { | 
					
						
							|  |  |  | 			if args[0] == "-0" { | 
					
						
							|  |  |  | 				wantError = false | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				flags = append(flags, args[0]) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			args = args[1:] | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-22 02:14:44 +08:00
										 |  |  | 	case "skip": | 
					
						
							|  |  |  | 		t.action = "skip" | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 		t.err = skipError("skipped; unknown pattern: " + action) | 
					
						
							|  |  |  | 		t.action = "??" | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.makeTempDir() | 
					
						
							|  |  |  | 	defer os.RemoveAll(t.tempDir) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = ioutil.WriteFile(filepath.Join(t.tempDir, t.gofile), srcBytes, 0644) | 
					
						
							|  |  |  | 	check(err) | 
					
						
							| 
									
										
										
										
											2012-03-08 14:03:40 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 02:22:08 -05:00
										 |  |  | 	// A few tests (of things like the environment) require these to be set. | 
					
						
							|  |  |  | 	os.Setenv("GOOS", runtime.GOOS) | 
					
						
							|  |  |  | 	os.Setenv("GOARCH", runtime.GOARCH) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 01:54:39 -05:00
										 |  |  | 	useTmp := true | 
					
						
							|  |  |  | 	runcmd := func(args ...string) ([]byte, error) { | 
					
						
							|  |  |  | 		cmd := exec.Command(args[0], args[1:]...) | 
					
						
							|  |  |  | 		var buf bytes.Buffer | 
					
						
							|  |  |  | 		cmd.Stdout = &buf | 
					
						
							|  |  |  | 		cmd.Stderr = &buf | 
					
						
							|  |  |  | 		if useTmp { | 
					
						
							|  |  |  | 			cmd.Dir = t.tempDir | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		err := cmd.Run() | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			err = fmt.Errorf("%s\n%s", err, buf.Bytes()) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-07 01:54:39 -05:00
										 |  |  | 		return buf.Bytes(), err | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 01:54:39 -05:00
										 |  |  | 	long := filepath.Join(cwd, t.goFileName()) | 
					
						
							| 
									
										
										
										
											2012-03-08 14:03:40 -05:00
										 |  |  | 	switch action { | 
					
						
							| 
									
										
										
										
											2012-03-07 01:54:39 -05:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 		t.err = fmt.Errorf("unimplemented action %q", action) | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 01:54:39 -05:00
										 |  |  | 	case "errorcheck": | 
					
						
							| 
									
										
										
										
											2012-09-23 13:16:14 -04:00
										 |  |  | 		cmdline := []string{"go", "tool", gc, "-e", "-o", "a." + letter} | 
					
						
							|  |  |  | 		cmdline = append(cmdline, flags...) | 
					
						
							|  |  |  | 		cmdline = append(cmdline, long) | 
					
						
							|  |  |  | 		out, err := runcmd(cmdline...) | 
					
						
							|  |  |  | 		if wantError { | 
					
						
							|  |  |  | 			if err == nil { | 
					
						
							|  |  |  | 				t.err = fmt.Errorf("compilation succeeded unexpectedly\n%s", out) | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 				t.err = err | 
					
						
							| 
									
										
										
										
											2012-09-23 13:16:14 -04:00
										 |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-07 01:54:39 -05:00
										 |  |  | 		t.err = t.errorCheck(string(out), long, t.gofile) | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2012-03-08 14:03:40 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 01:54:39 -05:00
										 |  |  | 	case "compile": | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 		_, t.err = compileFile(runcmd, long) | 
					
						
							| 
									
										
										
										
											2012-03-08 14:03:40 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-30 21:12:05 +02:00
										 |  |  | 	case "compiledir": | 
					
						
							|  |  |  | 		// Compile all files in the directory in lexicographic order. | 
					
						
							|  |  |  | 		longdir := filepath.Join(cwd, t.goDirName()) | 
					
						
							| 
									
										
										
										
											2013-01-02 15:31:49 -05:00
										 |  |  | 		pkgs, err := goDirPackages(longdir) | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.err = err | 
					
						
							| 
									
										
										
										
											2012-07-30 21:12:05 +02:00
										 |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2013-01-02 15:31:49 -05:00
										 |  |  | 		for _, gofiles := range pkgs { | 
					
						
							|  |  |  | 			_, t.err = compileInDir(runcmd, longdir, gofiles...) | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 			if t.err != nil { | 
					
						
							|  |  |  | 				return | 
					
						
							| 
									
										
										
										
											2012-08-06 14:56:39 +10:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case "errorcheckdir": | 
					
						
							|  |  |  | 		// errorcheck all files in lexicographic order | 
					
						
							|  |  |  | 		// useful for finding importing errors | 
					
						
							|  |  |  | 		longdir := filepath.Join(cwd, t.goDirName()) | 
					
						
							| 
									
										
										
										
											2013-01-02 15:31:49 -05:00
										 |  |  | 		pkgs, err := goDirPackages(longdir) | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.err = err | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2013-01-02 15:31:49 -05:00
										 |  |  | 		for i, gofiles := range pkgs { | 
					
						
							|  |  |  | 			out, err := compileInDir(runcmd, longdir, gofiles...) | 
					
						
							|  |  |  | 			if i == len(pkgs)-1 { | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 				if wantError && err == nil { | 
					
						
							|  |  |  | 					t.err = fmt.Errorf("compilation succeeded unexpectedly\n%s", out) | 
					
						
							|  |  |  | 					return | 
					
						
							|  |  |  | 				} else if !wantError && err != nil { | 
					
						
							|  |  |  | 					t.err = err | 
					
						
							|  |  |  | 					return | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} else if err != nil { | 
					
						
							|  |  |  | 				t.err = err | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2013-01-02 15:31:49 -05:00
										 |  |  | 			var fullshort []string | 
					
						
							|  |  |  | 			for _, name := range gofiles { | 
					
						
							|  |  |  | 				fullshort = append(fullshort, filepath.Join(longdir, name), name) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			t.err = t.errorCheck(string(out), fullshort...) | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 			if t.err != nil { | 
					
						
							| 
									
										
										
										
											2012-07-30 21:12:05 +02:00
										 |  |  | 				break | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 	case "rundir": | 
					
						
							|  |  |  | 		// Compile all files in the directory in lexicographic order. | 
					
						
							|  |  |  | 		// then link as if the last file is the main package and run it | 
					
						
							|  |  |  | 		longdir := filepath.Join(cwd, t.goDirName()) | 
					
						
							| 
									
										
										
										
											2013-01-11 22:00:48 +01:00
										 |  |  | 		pkgs, err := goDirPackages(longdir) | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.err = err | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2013-01-11 22:00:48 +01:00
										 |  |  | 		for i, gofiles := range pkgs { | 
					
						
							|  |  |  | 			_, err := compileInDir(runcmd, longdir, gofiles...) | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.err = err | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2013-01-11 22:00:48 +01:00
										 |  |  | 			if i == len(pkgs)-1 { | 
					
						
							|  |  |  | 				err = linkFile(runcmd, gofiles[0]) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					t.err = err | 
					
						
							|  |  |  | 					return | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				out, err := runcmd(append([]string{filepath.Join(t.tempDir, "a.exe")}, args...)...) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					t.err = err | 
					
						
							|  |  |  | 					return | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() { | 
					
						
							|  |  |  | 					t.err = fmt.Errorf("incorrect output\n%s", out) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 01:54:39 -05:00
										 |  |  | 	case "build": | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 		_, err := runcmd("go", "build", "-o", "a.exe", long) | 
					
						
							| 
									
										
										
										
											2012-03-07 01:54:39 -05:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 			t.err = err | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-08 14:03:40 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 01:54:39 -05:00
										 |  |  | 	case "run": | 
					
						
							|  |  |  | 		useTmp = false | 
					
						
							|  |  |  | 		out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...) | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 			t.err = err | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-09-20 00:27:23 +08:00
										 |  |  | 		if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() { | 
					
						
							| 
									
										
										
										
											2012-03-07 01:54:39 -05:00
										 |  |  | 			t.err = fmt.Errorf("incorrect output\n%s", out) | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-04-20 23:45:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	case "runoutput": | 
					
						
							| 
									
										
										
										
											2013-01-12 17:52:52 +11:00
										 |  |  | 		rungatec <- true | 
					
						
							|  |  |  | 		defer func() { | 
					
						
							|  |  |  | 			<-rungatec | 
					
						
							|  |  |  | 		}() | 
					
						
							| 
									
										
										
										
											2012-04-20 23:45:43 +08:00
										 |  |  | 		useTmp = false | 
					
						
							| 
									
										
										
										
											2012-11-07 12:33:54 -08:00
										 |  |  | 		out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...) | 
					
						
							| 
									
										
										
										
											2012-04-20 23:45:43 +08:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 			t.err = err | 
					
						
							| 
									
										
										
										
											2012-04-20 23:45:43 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		tfile := filepath.Join(t.tempDir, "tmp__.go") | 
					
						
							| 
									
										
										
										
											2013-01-12 17:52:52 +11:00
										 |  |  | 		if err := ioutil.WriteFile(tfile, out, 0666); err != nil { | 
					
						
							| 
									
										
										
										
											2012-04-20 23:45:43 +08:00
										 |  |  | 			t.err = fmt.Errorf("write tempfile:%s", err) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		out, err = runcmd("go", "run", tfile) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 			t.err = err | 
					
						
							| 
									
										
										
										
											2012-04-20 23:45:43 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if string(out) != t.expectedOutput() { | 
					
						
							|  |  |  | 			t.err = fmt.Errorf("incorrect output\n%s", out) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-11-07 12:33:54 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	case "errorcheckoutput": | 
					
						
							|  |  |  | 		useTmp = false | 
					
						
							|  |  |  | 		out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.err = err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		tfile := filepath.Join(t.tempDir, "tmp__.go") | 
					
						
							|  |  |  | 		err = ioutil.WriteFile(tfile, out, 0666) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.err = fmt.Errorf("write tempfile:%s", err) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		cmdline := []string{"go", "tool", gc, "-e", "-o", "a." + letter} | 
					
						
							|  |  |  | 		cmdline = append(cmdline, flags...) | 
					
						
							|  |  |  | 		cmdline = append(cmdline, tfile) | 
					
						
							|  |  |  | 		out, err = runcmd(cmdline...) | 
					
						
							|  |  |  | 		if wantError { | 
					
						
							|  |  |  | 			if err == nil { | 
					
						
							|  |  |  | 				t.err = fmt.Errorf("compilation succeeded unexpectedly\n%s", out) | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.err = err | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		t.err = t.errorCheck(string(out), tfile, "tmp__.go") | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (t *test) String() string { | 
					
						
							|  |  |  | 	return filepath.Join(t.dir, t.gofile) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (t *test) makeTempDir() { | 
					
						
							|  |  |  | 	var err error | 
					
						
							|  |  |  | 	t.tempDir, err = ioutil.TempDir("", "") | 
					
						
							|  |  |  | 	check(err) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (t *test) expectedOutput() string { | 
					
						
							|  |  |  | 	filename := filepath.Join(t.dir, t.gofile) | 
					
						
							|  |  |  | 	filename = filename[:len(filename)-len(".go")] | 
					
						
							|  |  |  | 	filename += ".out" | 
					
						
							|  |  |  | 	b, _ := ioutil.ReadFile(filename) | 
					
						
							|  |  |  | 	return string(b) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-02 15:31:49 -05:00
										 |  |  | func (t *test) errorCheck(outStr string, fullshort ...string) (err error) { | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 	defer func() { | 
					
						
							|  |  |  | 		if *verbose && err != nil { | 
					
						
							|  |  |  | 			log.Printf("%s gc output:\n%s", t, outStr) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 	var errs []error | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var out []string | 
					
						
							|  |  |  | 	// 6g error messages continue onto additional lines with leading tabs. | 
					
						
							|  |  |  | 	// Split the output at the beginning of each line that doesn't begin with a tab. | 
					
						
							|  |  |  | 	for _, line := range strings.Split(outStr, "\n") { | 
					
						
							| 
									
										
										
										
											2012-09-23 13:16:14 -04:00
										 |  |  | 		if strings.HasSuffix(line, "\r") { // remove '\r', output by compiler on windows | 
					
						
							| 
									
										
										
										
											2012-08-16 16:46:59 +10:00
										 |  |  | 			line = line[:len(line)-1] | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 		if strings.HasPrefix(line, "\t") { | 
					
						
							|  |  |  | 			out[len(out)-1] += "\n" + line | 
					
						
							| 
									
										
										
										
											2012-10-08 16:36:45 +02:00
										 |  |  | 		} else if strings.HasPrefix(line, "go tool") { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} else if strings.TrimSpace(line) != "" { | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 			out = append(out, line) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 01:54:39 -05:00
										 |  |  | 	// Cut directory name. | 
					
						
							|  |  |  | 	for i := range out { | 
					
						
							| 
									
										
										
										
											2013-01-02 15:31:49 -05:00
										 |  |  | 		for j := 0; j < len(fullshort); j += 2 { | 
					
						
							|  |  |  | 			full, short := fullshort[j], fullshort[j+1] | 
					
						
							|  |  |  | 			out[i] = strings.Replace(out[i], full, short, -1) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-01-11 22:00:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-02 15:31:49 -05:00
										 |  |  | 	var want []wantedError | 
					
						
							|  |  |  | 	for j := 0; j < len(fullshort); j += 2 { | 
					
						
							|  |  |  | 		full, short := fullshort[j], fullshort[j+1] | 
					
						
							|  |  |  | 		want = append(want, t.wantedErrors(full, short)...) | 
					
						
							| 
									
										
										
										
											2012-03-07 01:54:39 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-02 15:31:49 -05:00
										 |  |  | 	for _, we := range want { | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 		var errmsgs []string | 
					
						
							|  |  |  | 		errmsgs, out = partitionStrings(we.filterRe, out) | 
					
						
							|  |  |  | 		if len(errmsgs) == 0 { | 
					
						
							| 
									
										
										
										
											2012-03-07 01:54:39 -05:00
										 |  |  | 			errs = append(errs, fmt.Errorf("%s:%d: missing error %q", we.file, we.lineNum, we.reStr)) | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		matched := false | 
					
						
							|  |  |  | 		for _, errmsg := range errmsgs { | 
					
						
							|  |  |  | 			if we.re.MatchString(errmsg) { | 
					
						
							|  |  |  | 				matched = true | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				out = append(out, errmsg) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if !matched { | 
					
						
							| 
									
										
										
										
											2012-03-07 01:54:39 -05:00
										 |  |  | 			errs = append(errs, fmt.Errorf("%s:%d: no match for %q in%s", we.file, we.lineNum, we.reStr, strings.Join(out, "\n"))) | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-08 16:36:45 +02:00
										 |  |  | 	if len(out) > 0 { | 
					
						
							|  |  |  | 		errs = append(errs, fmt.Errorf("Unmatched Errors:")) | 
					
						
							|  |  |  | 		for _, errLine := range out { | 
					
						
							|  |  |  | 			errs = append(errs, fmt.Errorf("%s", errLine)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 	if len(errs) == 0 { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if len(errs) == 1 { | 
					
						
							|  |  |  | 		return errs[0] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var buf bytes.Buffer | 
					
						
							| 
									
										
										
										
											2012-03-07 01:54:39 -05:00
										 |  |  | 	fmt.Fprintf(&buf, "\n") | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 	for _, err := range errs { | 
					
						
							|  |  |  | 		fmt.Fprintf(&buf, "%s\n", err.Error()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return errors.New(buf.String()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func partitionStrings(rx *regexp.Regexp, strs []string) (matched, unmatched []string) { | 
					
						
							|  |  |  | 	for _, s := range strs { | 
					
						
							|  |  |  | 		if rx.MatchString(s) { | 
					
						
							|  |  |  | 			matched = append(matched, s) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			unmatched = append(unmatched, s) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type wantedError struct { | 
					
						
							|  |  |  | 	reStr    string | 
					
						
							|  |  |  | 	re       *regexp.Regexp | 
					
						
							|  |  |  | 	lineNum  int | 
					
						
							|  |  |  | 	file     string | 
					
						
							|  |  |  | 	filterRe *regexp.Regexp // /^file:linenum\b/m | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	errRx       = regexp.MustCompile(`// (?:GC_)?ERROR (.*)`) | 
					
						
							|  |  |  | 	errQuotesRx = regexp.MustCompile(`"([^"]*)"`) | 
					
						
							|  |  |  | 	lineRx      = regexp.MustCompile(`LINE(([+-])([0-9]+))?`) | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | func (t *test) wantedErrors(file, short string) (errs []wantedError) { | 
					
						
							|  |  |  | 	src, _ := ioutil.ReadFile(file) | 
					
						
							|  |  |  | 	for i, line := range strings.Split(string(src), "\n") { | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 		lineNum := i + 1 | 
					
						
							|  |  |  | 		if strings.Contains(line, "////") { | 
					
						
							|  |  |  | 			// double comment disables ERROR | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		m := errRx.FindStringSubmatch(line) | 
					
						
							|  |  |  | 		if m == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		all := m[1] | 
					
						
							|  |  |  | 		mm := errQuotesRx.FindAllStringSubmatch(all, -1) | 
					
						
							|  |  |  | 		if mm == nil { | 
					
						
							|  |  |  | 			log.Fatalf("invalid errchk line in %s: %s", t.goFileName(), line) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for _, m := range mm { | 
					
						
							|  |  |  | 			rx := lineRx.ReplaceAllStringFunc(m[1], func(m string) string { | 
					
						
							|  |  |  | 				n := lineNum | 
					
						
							|  |  |  | 				if strings.HasPrefix(m, "LINE+") { | 
					
						
							|  |  |  | 					delta, _ := strconv.Atoi(m[5:]) | 
					
						
							|  |  |  | 					n += delta | 
					
						
							|  |  |  | 				} else if strings.HasPrefix(m, "LINE-") { | 
					
						
							|  |  |  | 					delta, _ := strconv.Atoi(m[5:]) | 
					
						
							|  |  |  | 					n -= delta | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 				return fmt.Sprintf("%s:%d", short, n) | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 			filterPattern := fmt.Sprintf(`^(\w+/)?%s:%d[:[]`, short, lineNum) | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 			errs = append(errs, wantedError{ | 
					
						
							|  |  |  | 				reStr:    rx, | 
					
						
							|  |  |  | 				re:       regexp.MustCompile(rx), | 
					
						
							|  |  |  | 				filterRe: regexp.MustCompile(filterPattern), | 
					
						
							|  |  |  | 				lineNum:  lineNum, | 
					
						
							| 
									
										
										
										
											2012-10-06 09:23:31 +02:00
										 |  |  | 				file:     short, | 
					
						
							| 
									
										
										
										
											2012-02-21 14:28:49 +11:00
										 |  |  | 			}) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-09-23 13:16:14 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | var skipOkay = map[string]bool{ | 
					
						
							| 
									
										
										
										
											2012-12-22 19:16:31 +01:00
										 |  |  | 	"linkx.go":               true, | 
					
						
							|  |  |  | 	"sigchld.go":             true, | 
					
						
							|  |  |  | 	"sinit.go":               true, | 
					
						
							|  |  |  | 	"fixedbugs/bug248.go":    true, // combines errorcheckdir and rundir in the same dir. | 
					
						
							|  |  |  | 	"fixedbugs/bug302.go":    true, // tests both .$O and .a imports. | 
					
						
							|  |  |  | 	"fixedbugs/bug345.go":    true, // needs the appropriate flags in gc invocation. | 
					
						
							|  |  |  | 	"fixedbugs/bug369.go":    true, // needs compiler flags. | 
					
						
							|  |  |  | 	"fixedbugs/bug385_32.go": true, // arch-specific errors. | 
					
						
							|  |  |  | 	"fixedbugs/bug385_64.go": true, // arch-specific errors. | 
					
						
							|  |  |  | 	"fixedbugs/bug429.go":    true, | 
					
						
							|  |  |  | 	"bugs/bug395.go":         true, | 
					
						
							| 
									
										
										
										
											2012-09-23 13:16:14 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-01-12 17:52:52 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | // defaultRunOutputLimit returns the number of runoutput tests that | 
					
						
							|  |  |  | // can be executed in parallel. | 
					
						
							|  |  |  | func defaultRunOutputLimit() int { | 
					
						
							|  |  |  | 	const maxArmCPU = 2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cpu := runtime.NumCPU() | 
					
						
							|  |  |  | 	if runtime.GOARCH == "arm" && cpu > maxArmCPU { | 
					
						
							|  |  |  | 		cpu = maxArmCPU | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return cpu | 
					
						
							|  |  |  | } |