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 }