github.com/zxy12/golang151_with_comment@v0.0.0-20190507085033-721809559d3c/cmd/doc/doc_test.go (about)

     1  // Copyright 2015 The Go Authors.  All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"bytes"
     9  	"flag"
    10  	"os"
    11  	"os/exec"
    12  	"regexp"
    13  	"runtime"
    14  	"testing"
    15  )
    16  
    17  const (
    18  	dataDir = "testdata"
    19  	binary  = "testdoc"
    20  )
    21  
    22  type test struct {
    23  	name string
    24  	args []string // Arguments to "[go] doc".
    25  	yes  []string // Regular expressions that should match.
    26  	no   []string // Regular expressions that should not match.
    27  }
    28  
    29  const p = "cmd/doc/testdata"
    30  
    31  var tests = []test{
    32  	// Sanity check.
    33  	{
    34  		"sanity check",
    35  		[]string{p},
    36  		[]string{`type ExportedType struct`},
    37  		nil,
    38  	},
    39  
    40  	// Package dump includes import, package statement.
    41  	{
    42  		"package clause",
    43  		[]string{p},
    44  		[]string{`package pkg.*cmd/doc/testdata`},
    45  		nil,
    46  	},
    47  
    48  	// Constants.
    49  	// Package dump
    50  	{
    51  		"full package",
    52  		[]string{p},
    53  		[]string{
    54  			`Package comment`,
    55  			`const ExportedConstant = 1`,                            // Simple constant.
    56  			`const ConstOne = 1`,                                    // First entry in constant block.
    57  			`var ExportedVariable = 1`,                              // Simple variable.
    58  			`var VarOne = 1`,                                        // First entry in variable block.
    59  			`func ExportedFunc\(a int\) bool`,                       // Function.
    60  			`type ExportedType struct { ... }`,                      // Exported type.
    61  			`const ExportedTypedConstant ExportedType = iota`,       // Typed constant.
    62  			`const ExportedTypedConstant_unexported unexportedType`, // Typed constant, exported for unexported type.
    63  		},
    64  		[]string{
    65  			`const internalConstant = 2`,        // No internal constants.
    66  			`var internalVariable = 2`,          // No internal variables.
    67  			`func internalFunc(a int) bool`,     // No internal functions.
    68  			`Comment about exported constant`,   // No comment for single constant.
    69  			`Comment about exported variable`,   // No comment for single variable.
    70  			`Comment about block of constants.`, // No comment for constant block.
    71  			`Comment about block of variables.`, // No comment for variable block.
    72  			`Comment before ConstOne`,           // No comment for first entry in constant block.
    73  			`Comment before VarOne`,             // No comment for first entry in variable block.
    74  			`ConstTwo = 2`,                      // No second entry in constant block.
    75  			`VarTwo = 2`,                        // No second entry in variable block.
    76  			`type unexportedType`,               // No unexported type.
    77  			`unexportedTypedConstant`,           // No unexported typed constant.
    78  			`Field`,                             // No fields.
    79  			`Method`,                            // No methods.
    80  		},
    81  	},
    82  	// Package dump -u
    83  	{
    84  		"full package with u",
    85  		[]string{`-u`, p},
    86  		[]string{
    87  			`const ExportedConstant = 1`,      // Simple constant.
    88  			`const internalConstant = 2`,      // Internal constants.
    89  			`func internalFunc\(a int\) bool`, // Internal functions.
    90  		},
    91  		[]string{
    92  			`Comment about exported constant`,  // No comment for simple constant.
    93  			`Comment about block of constants`, // No comment for constant block.
    94  			`Comment about internal function`,  // No comment for internal function.
    95  		},
    96  	},
    97  
    98  	// Single constant.
    99  	{
   100  		"single constant",
   101  		[]string{p, `ExportedConstant`},
   102  		[]string{
   103  			`Comment about exported constant`, // Include comment.
   104  			`const ExportedConstant = 1`,
   105  		},
   106  		nil,
   107  	},
   108  	// Single constant -u.
   109  	{
   110  		"single constant with -u",
   111  		[]string{`-u`, p, `internalConstant`},
   112  		[]string{
   113  			`Comment about internal constant`, // Include comment.
   114  			`const internalConstant = 2`,
   115  		},
   116  		nil,
   117  	},
   118  	// Block of constants.
   119  	{
   120  		"block of constants",
   121  		[]string{p, `ConstTwo`},
   122  		[]string{
   123  			`Comment before ConstOne.\n.*ConstOne = 1`,    // First...
   124  			`ConstTwo = 2.*Comment on line with ConstTwo`, // And second show up.
   125  			`Comment about block of constants`,            // Comment does too.
   126  		},
   127  		[]string{
   128  			`constThree`, // No unexported constant.
   129  		},
   130  	},
   131  	// Block of constants -u.
   132  	{
   133  		"block of constants with -u",
   134  		[]string{"-u", p, `constThree`},
   135  		[]string{
   136  			`constThree = 3.*Comment on line with constThree`,
   137  		},
   138  		nil,
   139  	},
   140  
   141  	// Single variable.
   142  	{
   143  		"single variable",
   144  		[]string{p, `ExportedVariable`},
   145  		[]string{
   146  			`ExportedVariable`, // Include comment.
   147  			`var ExportedVariable = 1`,
   148  		},
   149  		nil,
   150  	},
   151  	// Single variable -u.
   152  	{
   153  		"single variable with -u",
   154  		[]string{`-u`, p, `internalVariable`},
   155  		[]string{
   156  			`Comment about internal variable`, // Include comment.
   157  			`var internalVariable = 2`,
   158  		},
   159  		nil,
   160  	},
   161  	// Block of variables.
   162  	{
   163  		"block of variables",
   164  		[]string{p, `VarTwo`},
   165  		[]string{
   166  			`Comment before VarOne.\n.*VarOne = 1`,    // First...
   167  			`VarTwo = 2.*Comment on line with VarTwo`, // And second show up.
   168  			`Comment about block of variables`,        // Comment does too.
   169  		},
   170  		[]string{
   171  			`varThree= 3`, // No unexported variable.
   172  		},
   173  	},
   174  	// Block of variables -u.
   175  	{
   176  		"block of variables with -u",
   177  		[]string{"-u", p, `varThree`},
   178  		[]string{
   179  			`varThree = 3.*Comment on line with varThree`,
   180  		},
   181  		nil,
   182  	},
   183  
   184  	// Function.
   185  	{
   186  		"function",
   187  		[]string{p, `ExportedFunc`},
   188  		[]string{
   189  			`Comment about exported function`, // Include comment.
   190  			`func ExportedFunc\(a int\) bool`,
   191  		},
   192  		nil,
   193  	},
   194  	// Function -u.
   195  	{
   196  		"function with -u",
   197  		[]string{"-u", p, `internalFunc`},
   198  		[]string{
   199  			`Comment about internal function`, // Include comment.
   200  			`func internalFunc\(a int\) bool`,
   201  		},
   202  		nil,
   203  	},
   204  
   205  	// Type.
   206  	{
   207  		"type",
   208  		[]string{p, `ExportedType`},
   209  		[]string{
   210  			`Comment about exported type`, // Include comment.
   211  			`type ExportedType struct`,    // Type definition.
   212  			`Comment before exported field.*\n.*ExportedField +int`,
   213  			`Has unexported fields`,
   214  			`func \(ExportedType\) ExportedMethod\(a int\) bool`,
   215  			`const ExportedTypedConstant ExportedType = iota`, // Must include associated constant.
   216  			`func ExportedTypeConstructor\(\) \*ExportedType`, // Must include constructor.
   217  		},
   218  		[]string{
   219  			`unexportedField`,                // No unexported field.
   220  			`Comment about exported method.`, // No comment about exported method.
   221  			`unexportedMethod`,               // No unexported method.
   222  			`unexportedTypedConstant`,        // No unexported constant.
   223  		},
   224  	},
   225  	// Type -u with unexported fields.
   226  	{
   227  		"type with unexported fields and -u",
   228  		[]string{"-u", p, `ExportedType`},
   229  		[]string{
   230  			`Comment about exported type`, // Include comment.
   231  			`type ExportedType struct`,    // Type definition.
   232  			`Comment before exported field.*\n.*ExportedField +int`,
   233  			`unexportedField int.*Comment on line with unexported field.`,
   234  			`func \(ExportedType\) unexportedMethod\(a int\) bool`,
   235  			`unexportedTypedConstant`,
   236  		},
   237  		[]string{
   238  			`Has unexported fields`,
   239  		},
   240  	},
   241  	// Unexported type with -u.
   242  	{
   243  		"unexported type with -u",
   244  		[]string{"-u", p, `unexportedType`},
   245  		[]string{
   246  			`Comment about unexported type`, // Include comment.
   247  			`type unexportedType int`,       // Type definition.
   248  			`func \(unexportedType\) ExportedMethod\(\) bool`,
   249  			`func \(unexportedType\) unexportedMethod\(\) bool`,
   250  			`ExportedTypedConstant_unexported unexportedType = iota`,
   251  			`const unexportedTypedConstant unexportedType = 1`,
   252  		},
   253  		nil,
   254  	},
   255  
   256  	// Method.
   257  	{
   258  		"method",
   259  		[]string{p, `ExportedType.ExportedMethod`},
   260  		[]string{
   261  			`func \(ExportedType\) ExportedMethod\(a int\) bool`,
   262  			`Comment about exported method.`,
   263  		},
   264  		nil,
   265  	},
   266  	// Method  with -u.
   267  	{
   268  		"method with -u",
   269  		[]string{"-u", p, `ExportedType.unexportedMethod`},
   270  		[]string{
   271  			`func \(ExportedType\) unexportedMethod\(a int\) bool`,
   272  			`Comment about unexported method.`,
   273  		},
   274  		nil,
   275  	},
   276  
   277  	// Case matching off.
   278  	{
   279  		"case matching off",
   280  		[]string{p, `casematch`},
   281  		[]string{
   282  			`CaseMatch`,
   283  			`Casematch`,
   284  		},
   285  		nil,
   286  	},
   287  
   288  	// Case matching on.
   289  	{
   290  		"case matching on",
   291  		[]string{"-c", p, `Casematch`},
   292  		[]string{
   293  			`Casematch`,
   294  		},
   295  		[]string{
   296  			`CaseMatch`,
   297  		},
   298  	},
   299  }
   300  
   301  func TestDoc(t *testing.T) {
   302  	if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
   303  		t.Skip("TODO: on darwin/arm, test fails: no such package cmd/doc/testdata")
   304  	}
   305  	for _, test := range tests {
   306  		var b bytes.Buffer
   307  		var flagSet flag.FlagSet
   308  		err := do(&b, &flagSet, test.args)
   309  		if err != nil {
   310  			t.Fatalf("%s: %s\n", test.name, err)
   311  		}
   312  		output := b.Bytes()
   313  		failed := false
   314  		for j, yes := range test.yes {
   315  			re, err := regexp.Compile(yes)
   316  			if err != nil {
   317  				t.Fatalf("%s.%d: compiling %#q: %s", test.name, j, yes, err)
   318  			}
   319  			if !re.Match(output) {
   320  				t.Errorf("%s.%d: no match for %s %#q", test.name, j, test.args, yes)
   321  				failed = true
   322  			}
   323  		}
   324  		for j, no := range test.no {
   325  			re, err := regexp.Compile(no)
   326  			if err != nil {
   327  				t.Fatalf("%s.%d: compiling %#q: %s", test.name, j, no, err)
   328  			}
   329  			if re.Match(output) {
   330  				t.Errorf("%s.%d: incorrect match for %s %#q", test.name, j, test.args, no)
   331  				failed = true
   332  			}
   333  		}
   334  		if failed {
   335  			t.Logf("\n%s", output)
   336  		}
   337  	}
   338  }
   339  
   340  // run runs the command, but calls t.Fatal if there is an error.
   341  func run(c *exec.Cmd, t *testing.T) []byte {
   342  	output, err := c.CombinedOutput()
   343  	if err != nil {
   344  		os.Stdout.Write(output)
   345  		t.Fatal(err)
   346  	}
   347  	return output
   348  }