github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/lang/expressions/parse_block_test.go (about) 1 package expressions_test 2 3 import ( 4 "embed" 5 "fmt" 6 "testing" 7 "time" 8 9 _ "github.com/lmorg/murex/builtins" 10 "github.com/lmorg/murex/lang/expressions" 11 "github.com/lmorg/murex/test" 12 "github.com/lmorg/murex/test/count" 13 "github.com/lmorg/murex/utils/json" 14 ) 15 16 func TestParseBlock(t *testing.T) { 17 tests := []test.MurexTest{ 18 { 19 Block: `out 1;out 2;out 3;out 4;out 5`, 20 Stdout: "1\n2\n3\n4\n5\n", 21 }, 22 { 23 Block: `out 1;out 2;out 3;out 4;out 5;`, 24 Stdout: "1\n2\n3\n4\n5\n", 25 }, 26 { 27 Block: "out 1\nout 2\nout 3\nout 4\nout 5", 28 Stdout: "1\n2\n3\n4\n5\n", 29 }, 30 { 31 Block: "out 1\nout 2\nout 3\nout 4\nout 5\n\n", 32 Stdout: "1\n2\n3\n4\n5\n", 33 }, 34 { 35 Block: `${err 1|err 2|err 3|err 4|err 5} ? msort`, 36 Stdout: "1\n2\n3\n4\n5\n", 37 }, 38 { 39 Block: "out:1\nout:2\nout:3\nout:4\nout:5", 40 Stdout: "1\n2\n3\n4\n5\n", 41 }, 42 } 43 44 test.RunMurexTests(tests, t) 45 } 46 47 //go:embed testcode/*.mx 48 var testcode embed.FS 49 50 func TestParseBlockExampleRealCode(t *testing.T) { 51 dir, err := testcode.ReadDir("testcode") 52 if err != nil { 53 // not a bug in murex 54 panic(err) 55 } 56 57 count.Tests(t, len(dir)) 58 59 for i := range dir { 60 name := dir[i].Name() 61 62 b, err := testcode.ReadFile("testcode/" + name) 63 if err != nil { 64 // not a bug in murex 65 panic(err) 66 } 67 68 block := []rune(string(b)) 69 blk := expressions.NewBlock(block) 70 err = blk.ParseBlock() 71 if err != nil { 72 // this _is_ a bug in murex! 73 t.Errorf("testcode failed to parse: `%s`", name) 74 t.Logf(" Error returned: %v", err) 75 } 76 } 77 } 78 79 func TestParseBlockSubBlocks(t *testing.T) { 80 tests := []test.MurexTest{ 81 { 82 Block: `function a {$ARGS};a (${out foo bar},)`, 83 Stdout: `["a","foo bar,"]`, 84 }, 85 { 86 Block: `function a {$PARAMS};a { bob }`, 87 Stdout: `["{ bob }"]`, 88 }, 89 { 90 Block: `function a {$PARAMS};a { { bob } }`, 91 Stdout: `["{ { bob } }"]`, 92 }, 93 { 94 Block: `function a {$PARAMS};a ${ out { { bob } } }`, 95 Stdout: `["{ { bob } }"]`, 96 }, 97 { 98 Block: `function a {$PARAMS};a {({({4})})}{({({4})})}`, 99 Stdout: `["{({({4})})}{({({4})})}"]`, 100 }, 101 { 102 Block: `function a {$PARAMS};a ${ out {({({5})})}{({({5})})} }`, 103 Stdout: `["{({({5})})}{({({5})})}"]`, 104 }, 105 /*{ 106 Block: "function a {$PARAMS};a ${\n\nout ({\n(\n{\n(\n{\n5\n}\n)\n}\n)\n}\n{\n(\n{\n(\n{\n5\n}\n)\n}\n)\n}\n\n})", 107 Stdout: "[\"{\n(\n{\n(\n{\n5\n}\n)\n}\n)\n}\n{\n(\n{\n(\n{\n5\n}\n)\n}\n)\n}\"]", 108 },*/ 109 { 110 Block: `function a {$PARAMS};a ${ out ${ out ${ out bob } } }`, 111 Stdout: `["bob"]`, 112 }, 113 { 114 Block: `function a {$PARAMS};a ${ ${ ${ out bob } } }`, 115 Stdout: `["bob"]`, 116 }, 117 } 118 119 test.RunMurexTests(tests, t) 120 } 121 122 func TestParseBlockExistingCodeBugFixes1(t *testing.T) { 123 tests := []test.MurexTest{ 124 { 125 Block: `config: eval shell safe-commands { 126 -> alter --merge / ([ 127 "builtins", "jobs" 128 ]) 129 }`, 130 Stdout: ``, 131 }, 132 } 133 134 test.RunMurexTests(tests, t) 135 } 136 137 func TestParseBlockEscapedCrLf(t *testing.T) { 138 tests := []test.MurexTest{ 139 { 140 Block: ` 141 out \ 142 bob`, 143 Stdout: "bob\n", 144 }, 145 ///// 146 { 147 Block: ` 148 out \ # comment 149 bob`, 150 Stdout: "bob\n", 151 }, 152 { 153 Block: ` 154 out \ # comment 155 bob`, 156 Stdout: "bob\n", 157 }, 158 ///// 159 { 160 Block: ` 161 out # comment \ 162 bob`, 163 Stdout: "bob\n", 164 }, 165 } 166 167 test.RunMurexTests(tests, t) 168 } 169 170 func TestParseBlockEqu(t *testing.T) { 171 tests := []test.MurexTest{ 172 { 173 Block: `= true`, 174 Stdout: `true`, 175 }, 176 } 177 178 test.RunMurexTests(tests, t) 179 } 180 181 func TestParseBlockPipeOverwriteFile1(t *testing.T) { 182 filename := fmt.Sprintf("%s-%d.testfile", t.Name(), time.Now().UnixNano()) 183 tests := []test.MurexTest{ 184 { 185 Block: fmt.Sprintf(`> %s; open %s; rm %s`, filename, filename, filename), 186 Stdout: ``, 187 }, 188 } 189 190 test.RunMurexTests(tests, t) 191 } 192 193 func TestParseBlockPipeOverwriteFile2(t *testing.T) { 194 filename := fmt.Sprintf("%s-%d.testfile", t.Name(), time.Now().UnixNano()) 195 tests := []test.MurexTest{ 196 { 197 Block: fmt.Sprintf(`%%(%s) |> %s; open %s; rm %s`, filename, filename, filename, filename), 198 Stdout: filename, 199 }, 200 } 201 202 test.RunMurexTests(tests, t) 203 } 204 205 func TestParseBlockPipeAppendFile1(t *testing.T) { 206 filename := fmt.Sprintf("%s-%d.testfile", t.Name(), time.Now().UnixNano()) 207 tests := []test.MurexTest{ 208 { 209 Block: fmt.Sprintf(`%%(%s) >> %s; %%(%s) >> %s; open %s; rm %s`, filename, filename, filename, filename, filename, filename), 210 Stdout: filename + filename, 211 }, 212 } 213 214 test.RunMurexTests(tests, t) 215 } 216 217 func TestParseBlockPipeAppendFile2(t *testing.T) { 218 filename := fmt.Sprintf("%s-%d.testfile", t.Name(), time.Now().UnixNano()) 219 tests := []test.MurexTest{ 220 { 221 Block: fmt.Sprintf(`echo %s >> %s; echo %s >> %s; open %s; rm %s`, filename, filename, filename, filename, filename, filename), 222 Stdout: fmt.Sprintf("%s\n%s\n", filename, filename), 223 }, 224 } 225 226 test.RunMurexTests(tests, t) 227 } 228 229 func TestParseBlockLogicOperators(t *testing.T) { 230 tests := []test.MurexTest{ 231 { 232 Block: `out 1 && out 2 && false && out 3`, 233 Stdout: "1\n2\n", 234 ExitNum: 1, 235 }, 236 { 237 Block: `out 1 && out 2 && false || out 3`, 238 Stdout: "1\n2\n3\n", 239 ExitNum: 0, 240 }, 241 // 242 { 243 Block: `out 1 || out 2 || false || out 3`, 244 Stdout: "1\n", 245 ExitNum: 0, 246 }, 247 { 248 Block: `out 1 || out 2 || false && out 3`, 249 Stdout: "1\n", 250 ExitNum: 0, 251 }, 252 ///// 253 { 254 Block: `out 1 && out 2 && true && out 3`, 255 Stdout: "1\n2\n3\n", 256 ExitNum: 0, 257 }, 258 { 259 Block: `out 1 && out 2 && true || out 3`, 260 Stdout: "1\n2\n", 261 ExitNum: 0, 262 }, 263 // 264 { 265 Block: `out 1 || out 2 || true || out 3`, 266 Stdout: "1\n", 267 ExitNum: 0, 268 }, 269 { 270 Block: `out 1 || out 2 || true && out 3`, 271 Stdout: "1\n", 272 ExitNum: 0, 273 }, 274 } 275 276 test.RunMurexTests(tests, t) 277 } 278 279 func TestParseBlockAmpersand(t *testing.T) { 280 count.Tests(t, 1) 281 282 block := "&foobar" 283 284 tree, err := expressions.ParseBlock([]rune(block)) 285 if err != nil { 286 t.Fatalf("Unexpected error: %v", err.Error()) 287 } 288 289 if len(*tree) != 1 { 290 t.Fatalf("Invalid tree length: %v", len(*tree)) 291 } 292 293 if string((*tree)[0].Command) != block { 294 t.Error("Invalid tree:") 295 t.Logf(" Command: '%s'", string((*tree)[0].Command)) 296 t.Logf(" Named Pipes: %v", json.LazyLogging(((*tree)[0].NamedPipes))) 297 t.Logf(" Parameters: %v", ((*tree)[0].Parameters)) 298 } 299 } 300 301 func TestParseBlockHyphen(t *testing.T) { 302 count.Tests(t, 1) 303 304 block := "-abc" 305 306 tree, err := expressions.ParseBlock([]rune(block)) 307 if err != nil { 308 t.Fatalf("Unexpected error: %v", err.Error()) 309 } 310 311 if len(*tree) != 1 { 312 t.Fatalf("Invalid tree length: %v", len(*tree)) 313 } 314 315 if string((*tree)[0].Command) != block { 316 t.Error("Invalid tree:") 317 t.Logf(" Command: '%s'", string((*tree)[0].Command)) 318 t.Logf(" Named Pipes: %v", json.LazyLogging(((*tree)[0].NamedPipes))) 319 t.Logf(" Parameters: %v", ((*tree)[0].Parameters)) 320 } 321 } 322 323 func TestParseBlockCommentHash(t *testing.T) { 324 tests := []test.MurexTest{ 325 { 326 Block: ` 327 out: 1 328 # out 2 329 out 3 330 `, 331 Stdout: "1\n3\n", 332 }, 333 } 334 335 test.RunMurexTests(tests, t) 336 } 337 338 func TestParseBlockArrayPanicBugFix(t *testing.T) { 339 tests := []test.MurexTest{ 340 { 341 Block: `TestParseBlockArrayPanicBugFix0 = @TestParseBlockArrayPanicBugFix0[0]`, 342 Stderr: `Error`, 343 ExitNum: 1, 344 }, 345 { 346 Block: `@TestParseBlockArrayPanicBugFix1[1]`, 347 Stderr: `Error`, 348 ExitNum: 1, 349 }, 350 { 351 Block: `echo @TestParseBlockArrayPanicBugFix2[22]`, 352 Stderr: `Error`, 353 ExitNum: 1, 354 }, 355 { 356 Block: `echo @3[333]`, 357 Stderr: `Error`, 358 ExitNum: 1, 359 }, 360 { 361 Block: `echo @44[44]`, 362 Stderr: `Error`, 363 ExitNum: 1, 364 }, 365 { 366 Block: `echo @555[5]`, 367 Stderr: `Error`, 368 ExitNum: 1, 369 }, 370 { 371 Block: `echo @6666[]`, 372 Stderr: `Error`, 373 ExitNum: 1, 374 }, 375 } 376 377 test.RunMurexTestsRx(tests, t) 378 }