Source file src/cmd/go/internal/generate/generate_test.go

Documentation: cmd/go/internal/generate

     1  // Copyright 2011 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 generate
     6  
     7  import (
     8  	"os"
     9  	"reflect"
    10  	"runtime"
    11  	"testing"
    12  )
    13  
    14  type splitTest struct {
    15  	in  string
    16  	out []string
    17  }
    18  
    19  // Same as above, except including source line number to set
    20  type splitTestWithLine struct {
    21  	in         string
    22  	out        []string
    23  	lineNumber int
    24  }
    25  
    26  const anyLineNo = 0
    27  
    28  var splitTests = []splitTest{
    29  	{"", nil},
    30  	{"x", []string{"x"}},
    31  	{" a b\tc ", []string{"a", "b", "c"}},
    32  	{` " a " `, []string{" a "}},
    33  	{"$GOARCH", []string{runtime.GOARCH}},
    34  	{"$GOOS", []string{runtime.GOOS}},
    35  	{"$GOFILE", []string{"proc.go"}},
    36  	{"$GOPACKAGE", []string{"sys"}},
    37  	{"a $XXNOTDEFINEDXX b", []string{"a", "", "b"}},
    38  	{"/$XXNOTDEFINED/", []string{"//"}},
    39  	{"/$DOLLAR/", []string{"/$/"}},
    40  	{"yacc -o $GOARCH/yacc_$GOFILE", []string{"go", "tool", "yacc", "-o", runtime.GOARCH + "/yacc_proc.go"}},
    41  }
    42  
    43  func TestGenerateCommandParse(t *testing.T) {
    44  	g := &Generator{
    45  		r:        nil, // Unused here.
    46  		path:     "/usr/ken/sys/proc.go",
    47  		dir:      "/usr/ken/sys",
    48  		file:     "proc.go",
    49  		pkg:      "sys",
    50  		commands: make(map[string][]string),
    51  	}
    52  	g.setEnv()
    53  	g.setShorthand([]string{"-command", "yacc", "go", "tool", "yacc"})
    54  	for _, test := range splitTests {
    55  		// First with newlines.
    56  		got := g.split("//go:generate " + test.in + "\n")
    57  		if !reflect.DeepEqual(got, test.out) {
    58  			t.Errorf("split(%q): got %q expected %q", test.in, got, test.out)
    59  		}
    60  		// Then with CRLFs, thank you Windows.
    61  		got = g.split("//go:generate " + test.in + "\r\n")
    62  		if !reflect.DeepEqual(got, test.out) {
    63  			t.Errorf("split(%q): got %q expected %q", test.in, got, test.out)
    64  		}
    65  	}
    66  }
    67  
    68  // These environment variables will be undefined before the splitTestWithLine tests
    69  var undefEnvList = []string{
    70  	"_XYZZY_",
    71  }
    72  
    73  // These environment variables will be defined before the splitTestWithLine tests
    74  var defEnvMap = map[string]string{
    75  	"_PLUGH_": "SomeVal",
    76  	"_X":      "Y",
    77  }
    78  
    79  // TestGenerateCommandShortHand - similar to TestGenerateCommandParse,
    80  // except:
    81  //    1. if the result starts with -command, record that shorthand
    82  //       before moving on to the next test.
    83  //    2. If a source line number is specified, set that in the parser
    84  //       before executing the test.  i.e., execute the split as if it
    85  //       processing that source line.
    86  func TestGenerateCommandShorthand(t *testing.T) {
    87  	g := &Generator{
    88  		r:        nil, // Unused here.
    89  		path:     "/usr/ken/sys/proc.go",
    90  		dir:      "/usr/ken/sys",
    91  		file:     "proc.go",
    92  		pkg:      "sys",
    93  		commands: make(map[string][]string),
    94  	}
    95  
    96  	var inLine string
    97  	var expected, got []string
    98  
    99  	g.setEnv()
   100  
   101  	// Set up the system environment variables
   102  	for i := range undefEnvList {
   103  		os.Unsetenv(undefEnvList[i])
   104  	}
   105  	for k := range defEnvMap {
   106  		os.Setenv(k, defEnvMap[k])
   107  	}
   108  
   109  	// simple command from environment variable
   110  	inLine = "//go:generate -command CMD0 \"ab${_X}cd\""
   111  	expected = []string{"-command", "CMD0", "abYcd"}
   112  	got = g.split(inLine + "\n")
   113  
   114  	if !reflect.DeepEqual(got, expected) {
   115  		t.Errorf("split(%q): got %q expected %q", inLine, got, expected)
   116  	}
   117  
   118  	// try again, with an extra level of indirection (should leave variable in command)
   119  	inLine = "//go:generate -command CMD0 \"ab${DOLLAR}{_X}cd\""
   120  	expected = []string{"-command", "CMD0", "ab${_X}cd"}
   121  	got = g.split(inLine + "\n")
   122  
   123  	if !reflect.DeepEqual(got, expected) {
   124  		t.Errorf("split(%q): got %q expected %q", inLine, got, expected)
   125  	}
   126  
   127  	// Now the interesting part, record that output as a command
   128  	g.setShorthand(got)
   129  
   130  	// see that the command still substitutes correctly from env. variable
   131  	inLine = "//go:generate CMD0"
   132  	expected = []string{"abYcd"}
   133  	got = g.split(inLine + "\n")
   134  
   135  	if !reflect.DeepEqual(got, expected) {
   136  		t.Errorf("split(%q): got %q expected %q", inLine, got, expected)
   137  	}
   138  
   139  	// Now change the value of $X and see if the recorded definition is
   140  	// still intact (vs. having the $_X already substituted out)
   141  
   142  	os.Setenv("_X", "Z")
   143  	inLine = "//go:generate CMD0"
   144  	expected = []string{"abZcd"}
   145  	got = g.split(inLine + "\n")
   146  
   147  	if !reflect.DeepEqual(got, expected) {
   148  		t.Errorf("split(%q): got %q expected %q", inLine, got, expected)
   149  	}
   150  
   151  	// What if the variable is now undefined?  Should be empty substitution.
   152  
   153  	os.Unsetenv("_X")
   154  	inLine = "//go:generate CMD0"
   155  	expected = []string{"abcd"}
   156  	got = g.split(inLine + "\n")
   157  
   158  	if !reflect.DeepEqual(got, expected) {
   159  		t.Errorf("split(%q): got %q expected %q", inLine, got, expected)
   160  	}
   161  
   162  	// Try another undefined variable as an extra check
   163  	os.Unsetenv("_Z")
   164  	inLine = "//go:generate -command CMD1 \"ab${_Z}cd\""
   165  	expected = []string{"-command", "CMD1", "abcd"}
   166  	got = g.split(inLine + "\n")
   167  
   168  	if !reflect.DeepEqual(got, expected) {
   169  		t.Errorf("split(%q): got %q expected %q", inLine, got, expected)
   170  	}
   171  
   172  	g.setShorthand(got)
   173  
   174  	inLine = "//go:generate CMD1"
   175  	expected = []string{"abcd"}
   176  	got = g.split(inLine + "\n")
   177  
   178  	if !reflect.DeepEqual(got, expected) {
   179  		t.Errorf("split(%q): got %q expected %q", inLine, got, expected)
   180  	}
   181  
   182  	const val = "someNewValue"
   183  	os.Setenv("_Z", val)
   184  
   185  	// try again with the properly-escaped variable.
   186  
   187  	inLine = "//go:generate -command CMD2 \"ab${DOLLAR}{_Z}cd\""
   188  	expected = []string{"-command", "CMD2", "ab${_Z}cd"}
   189  	got = g.split(inLine + "\n")
   190  
   191  	if !reflect.DeepEqual(got, expected) {
   192  		t.Errorf("split(%q): got %q expected %q", inLine, got, expected)
   193  	}
   194  
   195  	g.setShorthand(got)
   196  
   197  	inLine = "//go:generate CMD2"
   198  	expected = []string{"ab" + val + "cd"}
   199  	got = g.split(inLine + "\n")
   200  
   201  	if !reflect.DeepEqual(got, expected) {
   202  		t.Errorf("split(%q): got %q expected %q", inLine, got, expected)
   203  	}
   204  }
   205  
   206  // Command-related tests for TestGenerateCommandShortHand2
   207  // -- Note line numbers included to check substitutions from "build-in" variable - $GOLINE
   208  var splitTestsLines = []splitTestWithLine{
   209  	{"-command TEST1 $GOLINE", []string{"-command", "TEST1", "22"}, 22},
   210  	{"-command TEST2 ${DOLLAR}GOLINE", []string{"-command", "TEST2", "$GOLINE"}, 26},
   211  	{"TEST1", []string{"22"}, 33},
   212  	{"TEST2", []string{"66"}, 66},
   213  	{"TEST1 ''", []string{"22", "''"}, 99},
   214  	{"TEST2 ''", []string{"44", "''"}, 44},
   215  }
   216  
   217  // TestGenerateCommandShortHand - similar to TestGenerateCommandParse,
   218  // except:
   219  //    1. if the result starts with -command, record that shorthand
   220  //       before moving on to the next test.
   221  //    2. If a source line number is specified, set that in the parser
   222  //       before executing the test.  i.e., execute the split as if it
   223  //       processing that source line.
   224  func TestGenerateCommandShortHand2(t *testing.T) {
   225  	g := &Generator{
   226  		r:        nil, // Unused here.
   227  		path:     "/usr/ken/sys/proc.go",
   228  		dir:      "/usr/ken/sys",
   229  		file:     "proc.go",
   230  		pkg:      "sys",
   231  		commands: make(map[string][]string),
   232  	}
   233  	g.setEnv()
   234  	for _, test := range splitTestsLines {
   235  		// if the test specified a line number, reflect that
   236  		if test.lineNumber != anyLineNo {
   237  			g.lineNum = test.lineNumber
   238  			g.setEnv()
   239  		}
   240  		// First with newlines.
   241  		got := g.split("//go:generate " + test.in + "\n")
   242  		if !reflect.DeepEqual(got, test.out) {
   243  			t.Errorf("split(%q): got %q expected %q", test.in, got, test.out)
   244  		}
   245  		// Then with CRLFs, thank you Windows.
   246  		got = g.split("//go:generate " + test.in + "\r\n")
   247  		if !reflect.DeepEqual(got, test.out) {
   248  			t.Errorf("split(%q): got %q expected %q", test.in, got, test.out)
   249  		}
   250  		if got[0] == "-command" { // record commands
   251  			g.setShorthand(got)
   252  		}
   253  	}
   254  }
   255  

View as plain text