github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/lang/expressions/parse_switch_test.go (about) 1 package expressions_test 2 3 import ( 4 "testing" 5 6 _ "github.com/lmorg/murex/builtins" 7 "github.com/lmorg/murex/config/defaults" 8 "github.com/lmorg/murex/lang" 9 "github.com/lmorg/murex/lang/expressions" 10 "github.com/lmorg/murex/test/count" 11 "github.com/lmorg/murex/utils/home" 12 "github.com/lmorg/murex/utils/json" 13 ) 14 15 type testParseSwitchT struct { 16 Expression string 17 Expected []testParseSwitchNodeT 18 Error bool 19 } 20 21 type testParseSwitchNodeT struct { 22 Condition string 23 Parameters []string 24 } 25 26 func (t *testParseSwitchT) Json() string { return json.LazyLoggingPretty(t.Expected) } 27 28 func runTestParseSwitch(t *testing.T, tests []testParseSwitchT) { 29 t.Helper() 30 31 count.Tests(t, len(tests)) 32 33 lang.InitEnv() 34 defaults.Config(lang.ShellProcess.Config, false) 35 36 for i, test := range tests { 37 p := lang.NewTestProcess() 38 p.Name.Set(t.Name()) 39 defaults.Config(p.Config, false) 40 41 if err := p.Config.Set("proc", "strict-vars", false, nil); err != nil { 42 panic(err) 43 } 44 if err := p.Config.Set("proc", "strict-arrays", false, nil); err != nil { 45 panic(err) 46 } 47 expSwitch, err := expressions.ParseSwitch(p, []rune(test.Expression)) 48 49 if (err != nil) != test.Error { 50 t.Errorf("Unexpected mismatch in errors in test %d", i) 51 t.Logf(" Expression: '%s'", test.Expression) 52 t.Logf(" Expected: %s", test.Json()) 53 t.Logf(" err exp: %v", test.Error) 54 t.Logf(" err act: %v", err) 55 continue 56 } 57 58 var actual testParseSwitchT 59 for j := range expSwitch { 60 node := testParseSwitchNodeT{ 61 Condition: expSwitch[j].Condition, 62 Parameters: expSwitch[j].ParametersAll(), 63 } 64 actual.Expected = append(actual.Expected, node) 65 } 66 67 if test.Json() != actual.Json() { 68 t.Errorf("Expected does not match actual in test %d", i) 69 t.Logf(" Expression: '%s'", test.Expression) 70 t.Logf(" Expected: %s", test.Json()) 71 t.Logf(" Actual: %s", actual.Json()) 72 t.Logf(" err exp: %v", test.Error) 73 t.Logf(" err act: %v", err) 74 } 75 } 76 } 77 78 func TestParseSwitchBasic(t *testing.T) { 79 tests := []testParseSwitchT{ 80 { 81 Expression: `case "foo" { bar }`, 82 Expected: []testParseSwitchNodeT{ 83 { 84 Condition: "case", 85 Parameters: []string{"foo", "{ bar }"}, 86 }, 87 }, 88 }, 89 { 90 Expression: `if "foo" { bar }`, 91 Expected: []testParseSwitchNodeT{ 92 { 93 Condition: "if", 94 Parameters: []string{"foo", "{ bar }"}, 95 }, 96 }, 97 }, 98 { 99 Expression: `case "foo" then { bar }`, 100 Expected: []testParseSwitchNodeT{ 101 { 102 Condition: "case", 103 Parameters: []string{"foo", "then", "{ bar }"}, 104 }, 105 }, 106 }, 107 { 108 Expression: `if "foo" then { bar }`, 109 Expected: []testParseSwitchNodeT{ 110 { 111 Condition: "if", 112 Parameters: []string{"foo", "then", "{ bar }"}, 113 }, 114 }, 115 }, 116 { 117 Expression: `default { bar }`, 118 Expected: []testParseSwitchNodeT{ 119 { 120 Condition: "default", 121 Parameters: []string{"{ bar }"}, 122 }, 123 }, 124 }, 125 { 126 Expression: `if:"foo" {bar}`, 127 Expected: []testParseSwitchNodeT{ 128 { 129 Condition: "if", 130 Parameters: []string{"foo", "{bar}"}, 131 }, 132 }, 133 }, 134 } 135 136 runTestParseSwitch(t, tests) 137 } 138 139 func TestParseSwitchQuotes(t *testing.T) { 140 tests := []testParseSwitchT{ 141 { 142 Expression: `case 'foo'`, 143 Expected: []testParseSwitchNodeT{ 144 { 145 Condition: "case", 146 Parameters: []string{"foo"}, 147 }, 148 }, 149 }, 150 { 151 Expression: `case "foo"`, 152 Expected: []testParseSwitchNodeT{ 153 { 154 Condition: "case", 155 Parameters: []string{"foo"}, 156 }, 157 }, 158 }, 159 { 160 Expression: `case (foo)`, 161 Expected: []testParseSwitchNodeT{ 162 { 163 Condition: "case", 164 Parameters: []string{"foo"}, 165 }, 166 }, 167 }, 168 { 169 Expression: `case (f(o)o)`, 170 Expected: []testParseSwitchNodeT{ 171 { 172 Condition: "case", 173 Parameters: []string{"f(o)o"}, 174 }, 175 }, 176 }, 177 } 178 179 runTestParseSwitch(t, tests) 180 } 181 182 func TestParseSwitchMultiStatement(t *testing.T) { 183 tests := []testParseSwitchT{ 184 { 185 Expression: `if "a" { b }; case "c" { d }; default { e }`, 186 Expected: []testParseSwitchNodeT{ 187 { 188 Condition: "if", 189 Parameters: []string{"a", "{ b }"}, 190 }, 191 { 192 Condition: "case", 193 Parameters: []string{"c", "{ d }"}, 194 }, 195 { 196 Condition: "default", 197 Parameters: []string{"{ e }"}, 198 }, 199 }, 200 }, 201 { 202 Expression: ` 203 if "a" { b } 204 case "c" { d } 205 default { e } 206 `, 207 Expected: []testParseSwitchNodeT{ 208 { 209 Condition: "if", 210 Parameters: []string{"a", "{ b }"}, 211 }, 212 { 213 Condition: "case", 214 Parameters: []string{"c", "{ d }"}, 215 }, 216 { 217 Condition: "default", 218 Parameters: []string{"{ e }"}, 219 }, 220 }, 221 }, 222 } 223 224 runTestParseSwitch(t, tests) 225 } 226 227 func TestParseSwitchEscape(t *testing.T) { 228 tests := []testParseSwitchT{ 229 { 230 Expression: `case \s { bar }`, 231 Expected: []testParseSwitchNodeT{ 232 { 233 Condition: "case", 234 Parameters: []string{" ", "{ bar }"}, 235 }, 236 }, 237 }, 238 { 239 Expression: `case \t { bar }`, 240 Expected: []testParseSwitchNodeT{ 241 { 242 Condition: "case", 243 Parameters: []string{"\t", "{ bar }"}, 244 }, 245 }, 246 }, 247 { 248 Expression: `case \r { bar }`, 249 Expected: []testParseSwitchNodeT{ 250 { 251 Condition: "case", 252 Parameters: []string{"\r", "{ bar }"}, 253 }, 254 }, 255 }, 256 { 257 Expression: `case \n { bar }`, 258 Expected: []testParseSwitchNodeT{ 259 { 260 Condition: "case", 261 Parameters: []string{"\n", "{ bar }"}, 262 }, 263 }, 264 }, 265 { 266 Expression: `case \q { bar }`, 267 Expected: []testParseSwitchNodeT{ 268 { 269 Condition: "case", 270 Parameters: []string{"q", "{ bar }"}, 271 }, 272 }, 273 }, 274 { 275 Expression: `case \\ { bar }`, 276 Expected: []testParseSwitchNodeT{ 277 { 278 Condition: "case", 279 Parameters: []string{"\\", "{ bar }"}, 280 }, 281 }, 282 }, 283 } 284 285 runTestParseSwitch(t, tests) 286 } 287 288 func TestParseSwitchComments(t *testing.T) { 289 tests := []testParseSwitchT{ 290 { 291 Expression: ` 292 case 1 { a } 293 # case 2 { b } 294 case 3 { c }`, 295 Expected: []testParseSwitchNodeT{ 296 { 297 Condition: "case", 298 Parameters: []string{"1", "{ a }"}, 299 }, 300 { 301 Condition: "case", 302 Parameters: []string{"3", "{ c }"}, 303 }, 304 }, 305 }, 306 { 307 Expression: ` 308 case 1 { a } 309 /# case 2 { b } #/ 310 case 3 { c }`, 311 Expected: []testParseSwitchNodeT{ 312 { 313 Condition: "case", 314 Parameters: []string{"1", "{ a }"}, 315 }, 316 { 317 Condition: "case", 318 Parameters: []string{"3", "{ c }"}, 319 }, 320 }, 321 }, 322 { 323 Expression: `case 1 /#2#/ 3 { a }`, 324 Expected: []testParseSwitchNodeT{ 325 { 326 Condition: "case", 327 Parameters: []string{"1", "3", "{ a }"}, 328 }, 329 }, 330 }, 331 } 332 333 runTestParseSwitch(t, tests) 334 } 335 336 func TestParseSwitchVariables(t *testing.T) { 337 tests := []testParseSwitchT{ 338 { 339 Expression: `case $foo { $bar }`, 340 Expected: []testParseSwitchNodeT{ 341 { 342 Condition: "case", 343 Parameters: []string{"", "{ $bar }"}, 344 }, 345 }, 346 }, 347 { 348 Expression: `case @foo { $bar }`, 349 Expected: []testParseSwitchNodeT{ 350 { 351 Condition: "case", 352 Parameters: []string{"{ $bar }"}, 353 }, 354 }, 355 }, 356 { 357 Expression: `case ~ { ~ }`, 358 Expected: []testParseSwitchNodeT{ 359 { 360 Condition: "case", 361 Parameters: []string{home.MyDir, "{ ~ }"}, 362 }, 363 }, 364 }, 365 } 366 367 runTestParseSwitch(t, tests) 368 } 369 370 func TestParseSwitchSubshells(t *testing.T) { 371 tests := []testParseSwitchT{ 372 { 373 Expression: `case ${out foo} { $bar }`, 374 Expected: []testParseSwitchNodeT{ 375 { 376 Condition: "case", 377 Parameters: []string{"foo", "{ $bar }"}, 378 }, 379 }, 380 }, 381 { 382 Expression: `case @{ja: [1..3]} { ~ }`, 383 Expected: []testParseSwitchNodeT{ 384 { 385 Condition: "case", 386 Parameters: []string{"1", "2", "3", "{ ~ }"}, 387 }, 388 }, 389 }, 390 } 391 392 runTestParseSwitch(t, tests) 393 } 394 395 func TestParseSwitchCreators(t *testing.T) { 396 tests := []testParseSwitchT{ 397 { 398 Expression: `case %(foo) { bar }`, 399 Expected: []testParseSwitchNodeT{ 400 { 401 Condition: "case", 402 Parameters: []string{"foo", "{ bar }"}, 403 }, 404 }, 405 }, 406 { 407 Expression: `case %[1 2 3] { bar }`, 408 Expected: []testParseSwitchNodeT{ 409 { 410 Condition: "case", 411 Parameters: []string{"[1,2,3]", "{ bar }"}, 412 }, 413 }, 414 }, 415 { 416 Expression: `case %{a:1, b:2, c:3} { bar }`, 417 Expected: []testParseSwitchNodeT{ 418 { 419 Condition: "case", 420 Parameters: []string{`{"a":1,"b":2,"c":3}`, "{ bar }"}, 421 }, 422 }, 423 }, 424 } 425 426 runTestParseSwitch(t, tests) 427 }