go/types: clean up test support code and remove global variables

This is a straightforward port of CL 244627.

Change-Id: Ide980957430b35e22a6e22818b0ce9de410988af
Reviewed-on: https://go-review.googlesource.com/c/go/+/247902
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go
index 51ee0b1..f5a3273 100644
--- a/src/go/types/stdlib_test.go
+++ b/src/go/types/stdlib_test.go
@@ -27,22 +27,21 @@
 	. "go/types"
 )
 
-var (
-	pkgCount int // number of packages processed
-	start    time.Time
-
-	// Use the same importer for all std lib tests to
-	// avoid repeated importing of the same packages.
-	stdLibImporter = importer.Default()
-)
+// Use the same importer for all std lib tests to
+// avoid repeated importing of the same packages.
+var stdLibImporter = importer.Default()
 
 func TestStdlib(t *testing.T) {
 	testenv.MustHaveGoBuild(t)
 
-	start = time.Now()
-	walkDirs(t, filepath.Join(runtime.GOROOT(), "src"))
+	pkgCount := 0
+	duration := walkPkgDirs(filepath.Join(runtime.GOROOT(), "src"), func(dir string, filenames []string) {
+		typecheck(t, dir, filenames)
+		pkgCount++
+	}, t.Error)
+
 	if testing.Verbose() {
-		fmt.Println(pkgCount, "packages typechecked in", time.Since(start))
+		fmt.Println(pkgCount, "packages typechecked in", duration)
 	}
 }
 
@@ -235,7 +234,6 @@
 	}
 	info := Info{Uses: make(map[*ast.Ident]Object)}
 	conf.Check(path, fset, files, &info)
-	pkgCount++
 
 	// Perform checks of API invariants.
 
@@ -278,39 +276,48 @@
 	return filenames, nil
 }
 
-// Note: Could use filepath.Walk instead of walkDirs but that wouldn't
-//       necessarily be shorter or clearer after adding the code to
-//       terminate early for -short tests.
+func walkPkgDirs(dir string, pkgh func(dir string, filenames []string), errh func(args ...interface{})) time.Duration {
+	w := walker{time.Now(), 10 * time.Millisecond, pkgh, errh}
+	w.walk(dir)
+	return time.Since(w.start)
+}
 
-func walkDirs(t *testing.T, dir string) {
+type walker struct {
+	start time.Time
+	dmax  time.Duration
+	pkgh  func(dir string, filenames []string)
+	errh  func(args ...interface{})
+}
+
+func (w *walker) walk(dir string) {
 	// limit run time for short tests
-	if testing.Short() && time.Since(start) >= 10*time.Millisecond {
+	if testing.Short() && time.Since(w.start) >= w.dmax {
 		return
 	}
 
 	fis, err := ioutil.ReadDir(dir)
 	if err != nil {
-		t.Error(err)
+		w.errh(err)
 		return
 	}
 
-	// typecheck package in directory
+	// apply pkgh to the files in directory dir
 	// but ignore files directly under $GOROOT/src (might be temporary test files).
 	if dir != filepath.Join(runtime.GOROOT(), "src") {
 		files, err := pkgFilenames(dir)
 		if err != nil {
-			t.Error(err)
+			w.errh(err)
 			return
 		}
 		if files != nil {
-			typecheck(t, dir, files)
+			w.pkgh(dir, files)
 		}
 	}
 
 	// traverse subdirectories, but don't walk into testdata
 	for _, fi := range fis {
 		if fi.IsDir() && fi.Name() != "testdata" {
-			walkDirs(t, filepath.Join(dir, fi.Name()))
+			w.walk(filepath.Join(dir, fi.Name()))
 		}
 	}
 }