release-request-bd6aa7dd-7b02-4794-942c-14599bf61208-for-git_oc-mr1-release-4193791 snap-temp-L98700000083613807

Change-Id: I96265329a0b73b0379aa076ee3c55b16082e3f35
diff --git a/.travis.yml b/.travis.yml
index 2824056..aab67c8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,8 @@
 language: go
 
 go:
-    - 1.5.1
+    - 1.8.3
+    - 1.7.6
 
 cache:
     directories:
diff --git a/Blueprints b/Blueprints
index 582a0aa..c33b981 100644
--- a/Blueprints
+++ b/Blueprints
@@ -123,6 +123,7 @@
     deps = [
         "blueprint",
         "blueprint-bootstrap",
+        "gotestmain-tests",
     ],
     srcs = ["bootstrap/minibp/main.go"],
 )
@@ -150,6 +151,19 @@
     srcs = ["gotestmain/gotestmain.go"],
 )
 
+// gotestmain tests can't be on the gotestmain module because it is an implicit dependency of tests.
+// Put the tests in their own package and make it a dependency of minibp to make sure they run.
+bootstrap_go_package(
+    name = "gotestmain-tests",
+    pkgPath = "github.com/google/blueprint/gotestmain",
+    srcs = [
+        "gotestmain/dummy.go",
+    ],
+    testSrcs = [
+        "gotestmain/testmain_test.go",
+    ],
+)
+
 bootstrap_core_go_binary(
     name = "gotestrunner",
     srcs = ["gotestrunner/gotestrunner.go"],
diff --git a/build.ninja.in b/build.ninja.in
index 1de3dbb..51476ca 100644
--- a/build.ninja.in
+++ b/build.ninja.in
@@ -199,7 +199,7 @@
 # Variant:
 # Type:    bootstrap_core_go_binary
 # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
-# Defined: Blueprints:130:1
+# Defined: Blueprints:131:1
 
 build ${g.bootstrap.buildDir}/.bootstrap/bpglob/obj/bpglob.a: $
         g.bootstrap.compile ${g.bootstrap.srcDir}/bootstrap/bpglob/bpglob.go | $
@@ -225,7 +225,7 @@
 # Variant:
 # Type:    bootstrap_core_go_binary
 # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
-# Defined: Blueprints:148:1
+# Defined: Blueprints:149:1
 
 build ${g.bootstrap.buildDir}/.bootstrap/gotestmain/obj/gotestmain.a: $
         g.bootstrap.compile ${g.bootstrap.srcDir}/gotestmain/gotestmain.go | $
@@ -244,11 +244,26 @@
 default ${g.bootstrap.BinDir}/gotestmain
 
 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# Module:  gotestmain-tests
+# Variant:
+# Type:    bootstrap_go_package
+# Factory: github.com/google/blueprint/bootstrap.newGoPackageModuleFactory.func1
+# Defined: Blueprints:156:1
+
+build $
+        ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg/github.com/google/blueprint/gotestmain.a $
+        : g.bootstrap.compile ${g.bootstrap.srcDir}/gotestmain/dummy.go | $
+        ${g.bootstrap.compileCmd}
+    pkgPath = github.com/google/blueprint/gotestmain
+default $
+        ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg/github.com/google/blueprint/gotestmain.a
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 # Module:  gotestrunner
 # Variant:
 # Type:    bootstrap_core_go_binary
 # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
-# Defined: Blueprints:153:1
+# Defined: Blueprints:167:1
 
 build ${g.bootstrap.buildDir}/.bootstrap/gotestrunner/obj/gotestrunner.a: $
         g.bootstrap.compile ${g.bootstrap.srcDir}/gotestrunner/gotestrunner.go $
@@ -282,15 +297,16 @@
         ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg/github.com/google/blueprint/proptools.a $
         ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg/github.com/google/blueprint.a $
         ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg/github.com/google/blueprint/bootstrap/bpdoc.a $
-        ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a
-    incFlags = -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg
+        ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $
+        ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg/github.com/google/blueprint/gotestmain.a
+    incFlags = -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg -I ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg
     pkgPath = minibp
 default ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/minibp.a
 
 build ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/a.out: g.bootstrap.link $
         ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/minibp.a | $
         ${g.bootstrap.linkCmd}
-    libDirFlags = -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg
+    libDirFlags = -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg -L ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg
 default ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/a.out
 
 build ${g.bootstrap.BinDir}/minibp: g.bootstrap.cp $
diff --git a/gotestmain/dummy.go b/gotestmain/dummy.go
new file mode 100644
index 0000000..06ab7d0
--- /dev/null
+++ b/gotestmain/dummy.go
@@ -0,0 +1 @@
+package main
diff --git a/gotestmain/gotestmain.go b/gotestmain/gotestmain.go
index 8d1287c..9bf78b5 100644
--- a/gotestmain/gotestmain.go
+++ b/gotestmain/gotestmain.go
@@ -23,8 +23,10 @@
 	"go/token"
 	"io/ioutil"
 	"os"
+	"reflect"
 	"sort"
 	"strings"
+	"testing"
 	"text/template"
 )
 
@@ -35,11 +37,13 @@
 )
 
 type data struct {
-	Package string
-	Tests   []string
+	Package                 string
+	Tests                   []string
+	HasMain                 bool
+	MainStartTakesInterface bool
 }
 
-func findTests(srcs []string) (tests []string) {
+func findTests(srcs []string) (tests []string, hasMain bool) {
 	for _, src := range srcs {
 		f, err := parser.ParseFile(token.NewFileSet(), src, nil, 0)
 		if err != nil {
@@ -49,13 +53,23 @@
 			if obj.Kind != ast.Fun || !strings.HasPrefix(obj.Name, "Test") {
 				continue
 			}
-			tests = append(tests, obj.Name)
+			if obj.Name == "TestMain" {
+				hasMain = true
+			} else {
+				tests = append(tests, obj.Name)
+			}
 		}
 	}
 	sort.Strings(tests)
 	return
 }
 
+// Returns true for go1.8+, where testing.MainStart takes an interface instead of a function
+// as its first argument.
+func mainStartTakesInterface() bool {
+	return reflect.TypeOf(testing.MainStart).In(0).Kind() == reflect.Interface
+}
+
 func main() {
 	flag.Parse()
 
@@ -67,9 +81,13 @@
 
 	buf := &bytes.Buffer{}
 
+	tests, hasMain := findTests(flag.Args())
+
 	d := data{
-		Package: *pkg,
-		Tests:   findTests(flag.Args()),
+		Package:                 *pkg,
+		Tests:                   tests,
+		HasMain:                 hasMain,
+		MainStartTakesInterface: mainStartTakesInterface(),
 	}
 
 	err := testMainTmpl.Execute(buf, d)
@@ -87,6 +105,10 @@
 package main
 
 import (
+	"io"
+{{if not .HasMain}}
+	"os"
+{{end}}
 	"regexp"
 	"testing"
 
@@ -102,7 +124,9 @@
 var matchPat string
 var matchRe *regexp.Regexp
 
-func matchString(pat, str string) (result bool, err error) {
+type matchString struct{}
+
+func MatchString(pat, str string) (result bool, err error) {
 	if matchRe == nil || matchPat != pat {
 		matchPat = pat
 		matchRe, err = regexp.Compile(matchPat)
@@ -113,7 +137,35 @@
 	return matchRe.MatchString(str), nil
 }
 
+func (matchString) MatchString(pat, str string) (bool, error) {
+	return MatchString(pat, str)
+}
+
+func (matchString) StartCPUProfile(w io.Writer) error {
+	panic("shouldn't get here")
+}
+
+func (matchString) StopCPUProfile() {
+}
+
+func (matchString) WriteHeapProfile(w io.Writer) error {
+    panic("shouldn't get here")
+}
+
+func (matchString) WriteProfileTo(string, io.Writer, int) error {
+    panic("shouldn't get here")
+}
+
 func main() {
-	testing.Main(matchString, t, nil, nil)
+{{if .MainStartTakesInterface}}
+	m := testing.MainStart(matchString{}, t, nil, nil)
+{{else}}
+	m := testing.MainStart(MatchString, t, nil, nil)
+{{end}}
+{{if .HasMain}}
+	pkg.TestMain(m)
+{{else}}
+	os.Exit(m.Run())
+{{end}}
 }
 `))
diff --git a/gotestmain/testmain_test.go b/gotestmain/testmain_test.go
new file mode 100644
index 0000000..e011eeb
--- /dev/null
+++ b/gotestmain/testmain_test.go
@@ -0,0 +1,33 @@
+// Copyright 2017 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+	"os"
+	"testing"
+)
+
+var a int
+
+func TestMain(m *testing.M) {
+	a = 1
+	os.Exit(m.Run())
+}
+
+func TestTestMain(t *testing.T) {
+	if a != 1 {
+		t.Errorf("TestMain didn't run")
+	}
+}
diff --git a/pathtools/fs.go b/pathtools/fs.go
index 4ed91ff..4f98c6e 100644
--- a/pathtools/fs.go
+++ b/pathtools/fs.go
@@ -41,6 +41,7 @@
 			fs.dirs[dir] = true
 			dir = filepath.Dir(dir)
 		}
+		fs.dirs[dir] = true
 	}
 
 	for f := range fs.files {
diff --git a/regen_build_ninja_in.sh b/regen_build_ninja_in.sh
new file mode 100755
index 0000000..152fd95
--- /dev/null
+++ b/regen_build_ninja_in.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+SRC=$(cd $(dirname $0) && pwd)
+OUT=/tmp/blueprint.$$
+
+rm -rf ${OUT}
+mkdir ${OUT}
+
+(
+  cd ${OUT}
+  ${SRC}/bootstrap.bash
+  ./blueprint.bash
+  ${SRC}/bootstrap.bash -r
+)
+
+rm -rf ${OUT}
+mkdir ${OUT}
+
+(
+  cd ${OUT}
+  cp -r ${SRC}/tests/test_tree test_tree
+  ln -s ${SRC} test_tree/blueprint
+  mkdir out
+  cd out
+
+  export SRCDIR=../test_tree
+  ${SRCDIR}/blueprint/bootstrap.bash
+  ./blueprint.bash
+  cp .minibootstrap/build.ninja.in ${SRC}/tests/test_tree/build.ninja.in
+)
+
+rm -rf ${OUT}
diff --git a/tests/test_tree/build.ninja.in b/tests/test_tree/build.ninja.in
index 7728ca3..b3ef0a3 100644
--- a/tests/test_tree/build.ninja.in
+++ b/tests/test_tree/build.ninja.in
@@ -209,7 +209,7 @@
 # Variant:
 # Type:    bootstrap_core_go_binary
 # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
-# Defined: blueprint/Blueprints:130:1
+# Defined: blueprint/Blueprints:131:1
 
 build ${g.bootstrap.buildDir}/.bootstrap/bpglob/obj/bpglob.a: $
         g.bootstrap.compile $
@@ -236,7 +236,7 @@
 # Variant:
 # Type:    bootstrap_core_go_binary
 # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
-# Defined: blueprint/Blueprints:148:1
+# Defined: blueprint/Blueprints:149:1
 
 build ${g.bootstrap.buildDir}/.bootstrap/gotestmain/obj/gotestmain.a: $
         g.bootstrap.compile $
@@ -256,11 +256,27 @@
 default ${g.bootstrap.BinDir}/gotestmain
 
 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# Module:  gotestmain-tests
+# Variant:
+# Type:    bootstrap_go_package
+# Factory: github.com/google/blueprint/bootstrap.newGoPackageModuleFactory.func1
+# Defined: blueprint/Blueprints:156:1
+
+build $
+        ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg/github.com/google/blueprint/gotestmain.a $
+        : g.bootstrap.compile $
+        ${g.bootstrap.srcDir}/blueprint/gotestmain/dummy.go | $
+        ${g.bootstrap.compileCmd}
+    pkgPath = github.com/google/blueprint/gotestmain
+default $
+        ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg/github.com/google/blueprint/gotestmain.a
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 # Module:  gotestrunner
 # Variant:
 # Type:    bootstrap_core_go_binary
 # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
-# Defined: blueprint/Blueprints:153:1
+# Defined: blueprint/Blueprints:167:1
 
 build ${g.bootstrap.buildDir}/.bootstrap/gotestrunner/obj/gotestrunner.a: $
         g.bootstrap.compile $
@@ -296,15 +312,16 @@
         ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg/github.com/google/blueprint/proptools.a $
         ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg/github.com/google/blueprint.a $
         ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg/github.com/google/blueprint/bootstrap/bpdoc.a $
-        ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a
-    incFlags = -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg
+        ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $
+        ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg/github.com/google/blueprint/gotestmain.a
+    incFlags = -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg -I ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg
     pkgPath = minibp
 default ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/minibp.a
 
 build ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/a.out: g.bootstrap.link $
         ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/minibp.a | $
         ${g.bootstrap.linkCmd}
-    libDirFlags = -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg
+    libDirFlags = -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg -L ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg
 default ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/a.out
 
 build ${g.bootstrap.BinDir}/minibp: g.bootstrap.cp $
diff --git a/tests/test_tree_tests.sh b/tests/test_tree_tests.sh
index 43f12fc..515e2b6 100755
--- a/tests/test_tree_tests.sh
+++ b/tests/test_tree_tests.sh
@@ -23,6 +23,7 @@
 
 if ! cmp -s ${SRCDIR}/build.ninja.in .minibootstrap/build.ninja.in; then
     echo "tests/test_tree/build.ninja.in and .minibootstrap/build.ninja.in should be the same" >&2
+    echo "run regen_build_ninja_in.sh" >&2
     exit 1
 fi