github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/go/generate/generate_test.go (about)

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