content: add a test for code snippets

Also: fix bad build tags, mark some snippets as no-build or no-run.

This is a step toward adding the tour to the build dashboard.

Change-Id: I58af8f2289fee4c2ceee3be5a44a3fb986b26296
Reviewed-on: https://go-review.googlesource.com/18555
Reviewed-by: Rob Pike <r@golang.org>
diff --git a/content/basics/exported-names.go b/content/basics/exported-names.go
index 3a12e08..1eec5cb 100644
--- a/content/basics/exported-names.go
+++ b/content/basics/exported-names.go
@@ -1,4 +1,4 @@
-// +build OMIT
+// +build no-build OMIT
 
 package main
 
diff --git a/content/basics/type-inference.go b/content/basics/type-inference.go
index 1db8ace..b311933 100644
--- a/content/basics/type-inference.go
+++ b/content/basics/type-inference.go
@@ -1,3 +1,5 @@
+// +build OMIT
+
 package main
 
 import "fmt"
diff --git a/content/basics/zero.go b/content/basics/zero.go
index 9a391c9..eb95a07 100644
--- a/content/basics/zero.go
+++ b/content/basics/zero.go
@@ -1,3 +1,5 @@
+// +build OMIT
+
 package main
 
 import "fmt"
diff --git a/content/concurrency/exercise-equivalent-binary-trees.go b/content/concurrency/exercise-equivalent-binary-trees.go
index 5edd476..56d98a7 100644
--- a/content/concurrency/exercise-equivalent-binary-trees.go
+++ b/content/concurrency/exercise-equivalent-binary-trees.go
@@ -1,4 +1,4 @@
-// +build OMIT
+// +build no-build OMIT
 
 package main
 
diff --git a/content/content_test.go b/content/content_test.go
new file mode 100644
index 0000000..1052b7e
--- /dev/null
+++ b/content/content_test.go
@@ -0,0 +1,79 @@
+// Copyright 2016 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.
+
+package content
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+	"testing"
+)
+
+// Test that all the .go files inside the content file build
+// and execute (without checking for output correctness).
+// Files that contain the string "// +build no-build" are not built.
+// Files that contain the string "// +build no-run" are not executed.
+func TestContent(t *testing.T) {
+	scratch, err := ioutil.TempDir("", "tour-content-test")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(scratch)
+
+	err = filepath.Walk(".", func(path string, fi os.FileInfo, err error) error {
+		if filepath.Ext(path) != ".go" {
+			return nil
+		}
+		if filepath.Base(path) == "content_test.go" {
+			return nil
+		}
+		if err := testSnippet(t, path, scratch); err != nil {
+			t.Errorf("%v: %v", path, err)
+		}
+		return nil
+	})
+	if err != nil {
+		t.Error(err)
+	}
+}
+
+func testSnippet(t *testing.T, path, scratch string) error {
+	b, err := ioutil.ReadFile(path)
+	if err != nil {
+		return err
+	}
+
+	build := string(bytes.SplitN(b, []byte{'\n'}, 2)[0])
+	if !strings.HasPrefix(build, "// +build ") {
+		return errors.New("first line is not a +build comment")
+	}
+	if !strings.Contains(build, "OMIT") {
+		return errors.New(`+build comment does not contain "OMIT"`)
+	}
+
+	if strings.Contains(build, "no-build") {
+		return nil
+	}
+	bin := filepath.Join(scratch, filepath.Base(path)+".exe")
+	out, err := exec.Command("go", "build", "-o", bin, path).CombinedOutput()
+	if err != nil {
+		return fmt.Errorf("build error: %v\noutput:\n%s", err, out)
+	}
+	defer os.Remove(bin)
+
+	if strings.Contains(build, "no-run") {
+		return nil
+	}
+	out, err = exec.Command(bin).CombinedOutput()
+	if err != nil {
+		return fmt.Errorf("%v\nOutput:\n%s", err, out)
+	}
+	return nil
+}
diff --git a/content/flowcontrol/defer-multi.go b/content/flowcontrol/defer-multi.go
index 30af534..82419d5 100644
--- a/content/flowcontrol/defer-multi.go
+++ b/content/flowcontrol/defer-multi.go
@@ -1,3 +1,5 @@
+// +build OMIT
+
 package main
 
 import "fmt"
diff --git a/content/flowcontrol/defer.go b/content/flowcontrol/defer.go
index 92cac76..3314c05 100644
--- a/content/flowcontrol/defer.go
+++ b/content/flowcontrol/defer.go
@@ -1,3 +1,5 @@
+// +build OMIT
+
 package main
 
 import "fmt"
diff --git a/content/flowcontrol/exercise-loops-and-functions.go b/content/flowcontrol/exercise-loops-and-functions.go
index e98eacc..68c334d 100644
--- a/content/flowcontrol/exercise-loops-and-functions.go
+++ b/content/flowcontrol/exercise-loops-and-functions.go
@@ -1,4 +1,4 @@
-// +build OMIT
+// +build no-build OMIT
 
 package main
 
diff --git a/content/flowcontrol/forever.go b/content/flowcontrol/forever.go
index 7b40099..d3a9c9d 100644
--- a/content/flowcontrol/forever.go
+++ b/content/flowcontrol/forever.go
@@ -1,4 +1,4 @@
-// +build OMIT
+// +build no-run OMIT
 
 package main
 
diff --git a/content/methods/exercise-images.go b/content/methods/exercise-images.go
index 408ed9b..5b93246 100644
--- a/content/methods/exercise-images.go
+++ b/content/methods/exercise-images.go
@@ -1,4 +1,4 @@
-// +build OMIT
+// +build no-build OMIT
 
 package main
 
diff --git a/content/methods/exercise-reader.go b/content/methods/exercise-reader.go
index 9a3221e..e1394b2 100644
--- a/content/methods/exercise-reader.go
+++ b/content/methods/exercise-reader.go
@@ -1,3 +1,5 @@
+// +build no-build OMIT
+
 package main
 
 import "golang.org/x/tour/reader"
diff --git a/content/methods/exercise-rot-reader.go b/content/methods/exercise-rot-reader.go
index ff22119..21aead5 100644
--- a/content/methods/exercise-rot-reader.go
+++ b/content/methods/exercise-rot-reader.go
@@ -1,4 +1,4 @@
-// +build OMIT
+// +build no-build OMIT
 
 package main
 
diff --git a/content/methods/exercise-stringer.go b/content/methods/exercise-stringer.go
index ef656b4..11fc7b5 100644
--- a/content/methods/exercise-stringer.go
+++ b/content/methods/exercise-stringer.go
@@ -1,3 +1,5 @@
+// +build OMIT
+
 package main
 
 import "fmt"
diff --git a/content/methods/interface-values-with-nil.go b/content/methods/interface-values-with-nil.go
index 60d69d5..9c4773a 100644
--- a/content/methods/interface-values-with-nil.go
+++ b/content/methods/interface-values-with-nil.go
@@ -1,4 +1,4 @@
-// build +OMIT
+// +build OMIT
 
 package main
 
diff --git a/content/methods/interface-values.go b/content/methods/interface-values.go
index 52d2b3d..82d096f 100644
--- a/content/methods/interface-values.go
+++ b/content/methods/interface-values.go
@@ -1,4 +1,4 @@
-// build +OMIT
+// +build OMIT
 
 package main
 
diff --git a/content/methods/interfaces.go b/content/methods/interfaces.go
index 78ba3ba..a6eda32 100644
--- a/content/methods/interfaces.go
+++ b/content/methods/interfaces.go
@@ -1,4 +1,4 @@
-// +build OMIT
+// +build no-build OMIT
 
 package main
 
diff --git a/content/methods/nil-interface-values.go b/content/methods/nil-interface-values.go
index e15bdc9..55dbf86 100644
--- a/content/methods/nil-interface-values.go
+++ b/content/methods/nil-interface-values.go
@@ -1,4 +1,4 @@
-// build +OMIT
+// +build no-run OMIT
 
 package main
 
diff --git a/content/methods/reader.go b/content/methods/reader.go
index f22a1f2..4c97eb4 100644
--- a/content/methods/reader.go
+++ b/content/methods/reader.go
@@ -1,3 +1,5 @@
+// +build OMIT
+
 package main
 
 import (
diff --git a/content/methods/stringer.go b/content/methods/stringer.go
index 9fb98b5..10944b9 100644
--- a/content/methods/stringer.go
+++ b/content/methods/stringer.go
@@ -1,3 +1,5 @@
+// +build OMIT
+
 package main
 
 import "fmt"
diff --git a/content/methods/type-assertions.go b/content/methods/type-assertions.go
index fcd5685..7e81499 100644
--- a/content/methods/type-assertions.go
+++ b/content/methods/type-assertions.go
@@ -1,4 +1,4 @@
-// build +OMIT
+// +build no-run OMIT
 
 package main
 
diff --git a/content/moretypes/append.go b/content/moretypes/append.go
index f68e4f8..675cf52 100644
--- a/content/moretypes/append.go
+++ b/content/moretypes/append.go
@@ -1,3 +1,5 @@
+// +build OMIT
+
 package main
 
 import "fmt"
diff --git a/content/moretypes/exercise-fibonacci-closure.go b/content/moretypes/exercise-fibonacci-closure.go
index baa6fdb..d5a4e00 100644
--- a/content/moretypes/exercise-fibonacci-closure.go
+++ b/content/moretypes/exercise-fibonacci-closure.go
@@ -1,4 +1,4 @@
-// +build OMIT
+// +build no-build OMIT
 
 package main
 
diff --git a/content/moretypes/exercise-slices.go b/content/moretypes/exercise-slices.go
index 74b3abb..094ec09 100644
--- a/content/moretypes/exercise-slices.go
+++ b/content/moretypes/exercise-slices.go
@@ -1,4 +1,4 @@
-// +build OMIT
+// +build no-build OMIT
 
 package main