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  }