aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/doc/doc_test.go
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2015-06-19 12:39:02 +1000
committerRob Pike <r@golang.org>2015-06-19 21:56:59 +0000
commitd0652e7f82da12e84fb143c4ad6c19e39f238f05 (patch)
treea51e213ea5f835e1cfbbcc577905ab8aa8e9d337 /src/cmd/doc/doc_test.go
parent5ac5a9856288d20634ac21b457ec458f19ea0a37 (diff)
downloadgo-d0652e7f82da12e84fb143c4ad6c19e39f238f05.tar.xz
cmd/doc: add test
Refactor main a bit to make it possible to run tests without an exec every time. (Makes a huge difference in run time.) Add a silver test. Not quite golden, since it looks for pieces rather than the full output, and also includes tests for what should not appear. Fixes #10920. Change-Id: I6a4951cc14e61763379754a10b0cc3484d30c267 Reviewed-on: https://go-review.googlesource.com/11272 Reviewed-by: Russ Cox <rsc@golang.org> Run-TryBot: Rob Pike <r@golang.org>
Diffstat (limited to 'src/cmd/doc/doc_test.go')
-rw-r--r--src/cmd/doc/doc_test.go343
1 files changed, 343 insertions, 0 deletions
diff --git a/src/cmd/doc/doc_test.go b/src/cmd/doc/doc_test.go
new file mode 100644
index 0000000000..0936d4d2d4
--- /dev/null
+++ b/src/cmd/doc/doc_test.go
@@ -0,0 +1,343 @@
+// Copyright 2015 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 main
+
+import (
+ "bytes"
+ "flag"
+ "os"
+ "os/exec"
+ "regexp"
+ "testing"
+)
+
+const (
+ dataDir = "testdata"
+ binary = "testdoc"
+)
+
+type test struct {
+ name string
+ args []string // Arguments to "[go] doc".
+ yes []string // Regular expressions that should match.
+ no []string // Regular expressions that should not match.
+}
+
+const p = "cmd/doc/testdata"
+
+var tests = []test{
+ // Sanity check.
+ {
+ "fmt",
+ []string{`fmt`},
+ []string{`type Formatter interface`},
+ nil,
+ },
+
+ // Package dump includes import, package statement.
+ {
+ "package clause",
+ []string{p},
+ []string{`package pkg.*cmd/doc/testdata`},
+ nil,
+ },
+
+ // Constants.
+ // Package dump
+ {
+ "full package",
+ []string{p},
+ []string{
+ `Package comment`,
+ `const ExportedConstant = 1`, // Simple constant.
+ `ConstOne = 1`, // First entry in constant block.
+ `const ExportedVariable = 1`, // Simple variable.
+ `VarOne = 1`, // First entry in variable block.
+ `func ExportedFunc\(a int\) bool`, // Function.
+ `type ExportedType struct { ... }`, // Exported type.
+ `const ExportedTypedConstant ExportedType = iota`, // Typed constant.
+ `const ExportedTypedConstant_unexported unexportedType`, // Typed constant, exported for unexported type.
+ },
+ []string{
+ `const internalConstant = 2`, // No internal constants.
+ `const internalVariable = 2`, // No internal variables.
+ `func internalFunc(a int) bool`, // No internal functions.
+ `Comment about exported constant`, // No comment for single constant.
+ `Comment about exported variable`, // No comment for single variable.
+ `Comment about block of constants.`, // No comment for constant block.
+ `Comment about block of variables.`, // No comment for variable block.
+ `Comment before ConstOne`, // No comment for first entry in constant block.
+ `Comment before VarOne`, // No comment for first entry in variable block.
+ `ConstTwo = 2`, // No second entry in constant block.
+ `VarTwo = 2`, // No second entry in variable block.
+ `type unexportedType`, // No unexported type.
+ `unexportedTypedConstant`, // No unexported typed constant.
+ `Field`, // No fields.
+ `Method`, // No methods.
+ },
+ },
+ // Package dump -u
+ {
+ "full package with u",
+ []string{`-u`, p},
+ []string{
+ `const ExportedConstant = 1`, // Simple constant.
+ `const internalConstant = 2`, // Internal constants.
+ `func internalFunc\(a int\) bool`, // Internal functions.
+ },
+ []string{
+ `Comment about exported constant`, // No comment for simple constant.
+ `Comment about block of constants`, // No comment for constant block.
+ `Comment about internal function`, // No comment for internal function.
+ },
+ },
+
+ // Single constant.
+ {
+ "single constant",
+ []string{p, `ExportedConstant`},
+ []string{
+ `Comment about exported constant`, // Include comment.
+ `const ExportedConstant = 1`,
+ },
+ nil,
+ },
+ // Single constant -u.
+ {
+ "single constant with -u",
+ []string{`-u`, p, `internalConstant`},
+ []string{
+ `Comment about internal constant`, // Include comment.
+ `const internalConstant = 2`,
+ },
+ nil,
+ },
+ // Block of constants.
+ {
+ "block of constants",
+ []string{p, `ConstTwo`},
+ []string{
+ `Comment before ConstOne.\n.*ConstOne = 1`, // First...
+ `ConstTwo = 2.*Comment on line with ConstTwo`, // And second show up.
+ `Comment about block of constants`, // Comment does too.
+ },
+ []string{
+ `constThree`, // No unexported constant.
+ },
+ },
+ // Block of constants -u.
+ {
+ "block of constants with -u",
+ []string{"-u", p, `constThree`},
+ []string{
+ `constThree = 3.*Comment on line with constThree`,
+ },
+ nil,
+ },
+
+ // Single variable.
+ {
+ "single variable",
+ []string{p, `ExportedVariable`},
+ []string{
+ `ExportedVariable`, // Include comment.
+ `const ExportedVariable = 1`,
+ },
+ nil,
+ },
+ // Single variable -u.
+ {
+ "single variable with -u",
+ []string{`-u`, p, `internalVariable`},
+ []string{
+ `Comment about internal variable`, // Include comment.
+ `const internalVariable = 2`,
+ },
+ nil,
+ },
+ // Block of variables.
+ {
+ "block of variables",
+ []string{p, `VarTwo`},
+ []string{
+ `Comment before VarOne.\n.*VarOne = 1`, // First...
+ `VarTwo = 2.*Comment on line with VarTwo`, // And second show up.
+ `Comment about block of variables`, // Comment does too.
+ },
+ []string{
+ `varThree= 3`, // No unexported variable.
+ },
+ },
+ // Block of variables -u.
+ {
+ "block of variables with -u",
+ []string{"-u", p, `varThree`},
+ []string{
+ `varThree = 3.*Comment on line with varThree`,
+ },
+ nil,
+ },
+
+ // Function.
+ {
+ "function",
+ []string{p, `ExportedFunc`},
+ []string{
+ `Comment about exported function`, // Include comment.
+ `func ExportedFunc\(a int\) bool`,
+ },
+ nil,
+ },
+ // Function -u.
+ {
+ "function with -u",
+ []string{"-u", p, `internalFunc`},
+ []string{
+ `Comment about internal function`, // Include comment.
+ `func internalFunc\(a int\) bool`,
+ },
+ nil,
+ },
+
+ // Type.
+ {
+ "type",
+ []string{p, `ExportedType`},
+ []string{
+ `Comment about exported type`, // Include comment.
+ `type ExportedType struct`, // Type definition.
+ `Comment before exported field.*\n.*ExportedField +int`,
+ `Has unexported fields`,
+ `func \(ExportedType\) ExportedMethod\(a int\) bool`,
+ `const ExportedTypedConstant ExportedType = iota`, // Must include associated constant.
+ },
+ []string{
+ `unexportedField`, // No unexported field.
+ `Comment about exported method.`, // No comment about exported method.
+ `unexportedMethod`, // No unexported method.
+ `unexportedTypedConstant`, // No unexported constant.
+ },
+ },
+ // Type -u with unexported fields.
+ {
+ "type with unexported fields and -u",
+ []string{"-u", p, `ExportedType`},
+ []string{
+ `Comment about exported type`, // Include comment.
+ `type ExportedType struct`, // Type definition.
+ `Comment before exported field.*\n.*ExportedField +int`,
+ `unexportedField int.*Comment on line with unexported field.`,
+ `func \(ExportedType\) unexportedMethod\(a int\) bool`,
+ `unexportedTypedConstant`,
+ },
+ []string{
+ `Has unexported fields`,
+ },
+ },
+ // Unexported type with -u.
+ {
+ "unexported type with -u",
+ []string{"-u", p, `unexportedType`},
+ []string{
+ `Comment about unexported type`, // Include comment.
+ `type unexportedType int`, // Type definition.
+ `func \(unexportedType\) ExportedMethod\(\) bool`,
+ `func \(unexportedType\) unexportedMethod\(\) bool`,
+ `ExportedTypedConstant_unexported unexportedType = iota`,
+ `const unexportedTypedConstant unexportedType = 1`,
+ },
+ nil,
+ },
+
+ // Method.
+ {
+ "method",
+ []string{p, `ExportedType.ExportedMethod`},
+ []string{
+ `func \(ExportedType\) ExportedMethod\(a int\) bool`,
+ `Comment about exported method.`,
+ },
+ nil,
+ },
+ // Method with -u.
+ {
+ "method with -u",
+ []string{"-u", p, `ExportedType.unexportedMethod`},
+ []string{
+ `func \(ExportedType\) unexportedMethod\(a int\) bool`,
+ `Comment about unexported method.`,
+ },
+ nil,
+ },
+
+ // Case matching off.
+ {
+ "case matching off",
+ []string{p, `casematch`},
+ []string{
+ `CaseMatch`,
+ `Casematch`,
+ },
+ nil,
+ },
+
+ // Case matching on.
+ {
+ "case matching on",
+ []string{"-c", p, `Casematch`},
+ []string{
+ `Casematch`,
+ },
+ []string{
+ `CaseMatch`,
+ },
+ },
+}
+
+func TestDoc(t *testing.T) {
+ for _, test := range tests {
+ var b bytes.Buffer
+ var flagSet flag.FlagSet
+ err := do(&b, &flagSet, test.args)
+ if err != nil {
+ t.Fatalf("%s: %s\n", test.name, err)
+ }
+ output := b.Bytes()
+ failed := false
+ for j, yes := range test.yes {
+ re, err := regexp.Compile(yes)
+ if err != nil {
+ t.Fatalf("%s.%d: compiling %#q: %s", test.name, j, yes, err)
+ }
+ if !re.Match(output) {
+ t.Errorf("%s.%d: no match for %s %#q", test.name, j, test.args, yes)
+ failed = true
+ }
+ }
+ for j, no := range test.no {
+ re, err := regexp.Compile(no)
+ if err != nil {
+ t.Fatalf("%s.%d: compiling %#q: %s", test.name, j, no, err)
+ }
+ if re.Match(output) {
+ t.Errorf("%s.%d: incorrect match for %s %#q", test.name, j, test.args, no)
+ failed = true
+ }
+ }
+ if failed {
+ t.Logf("\n%s", output)
+ }
+ }
+}
+
+// run runs the command, but calls t.Fatal if there is an error.
+func run(c *exec.Cmd, t *testing.T) []byte {
+ output, err := c.CombinedOutput()
+ if err != nil {
+ os.Stdout.Write(output)
+ t.Fatal(err)
+ }
+ return output
+}