// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). // All rights reserved. // list_test.go package expr import ( "errors" "strings" "testing" ) func TestListParser(t *testing.T) { section := "List" type inputType struct { source string wantResult any wantErr error } inputs := []inputType{ /* 1 */ {`[]`, []any{}, nil}, /* 2 */ {`[1,2,3]`, []any{int64(1), int64(2), int64(3)}, nil}, /* 3 */ {`[1,2,"hello"]`, []any{int64(1), int64(2), "hello"}, nil}, /* 4 */ {`[1+2, not true, "hello"]`, []any{int64(3), false, "hello"}, nil}, /* 5 */ {`[1,2]+[3]`, []any{int64(1), int64(2), int64(3)}, nil}, /* 6 */ {`[1,4,3,2]-[3]`, []any{int64(1), int64(4), int64(2)}, nil}, /* 7 */ {`add([1,4,3,2])`, int64(10), nil}, /* 8 */ {`add([1,[2,2],3,2])`, int64(10), nil}, /* 9 */ {`mul([1,4,3.0,2])`, float64(24.0), nil}, /* 10 */ {`add([1,"hello"])`, nil, errors.New(`add(): param nr 2 (2 in 1) has wrong type string, number expected`)}, /* 11 */ {`[a=1,b=2,c=3] but a+b+c`, int64(6), nil}, /* 12 */ {`[1,2,3] << 2+2`, []any{int64(1), int64(2), int64(3), int64(4)}, nil}, /* 13 */ {`2-1 >> [2,3]`, []any{int64(1), int64(2), int64(3)}, nil}, /* 14 */ {`[1,2,3].1`, int64(2), nil}, /* 15 */ {`ls=[1,2,3] but ls.1`, int64(2), nil}, /* 16 */ {`ls=[1,2,3] but ls.(-1)`, int64(3), nil}, /* 17 */ {`list=["one","two","three"]; list.10`, nil, errors.New(`[1:36] index 10 out of bounds`)}, /* 18 */ {`["a", "b", "c"]`, newListA("a", "b", "c"), nil}, /* 19 */ {`["a", "b", "c"]`, newList([]any{"a", "b", "c"}), nil}, // /* 8 */ {`[int(x)|x=csv("test.csv",1,all(),1)]`, []any{int64(10), int64(40), int64(20)}, nil}, // /* 9 */ {`sum(@[int(x)|x=csv("test.csv",1,all(),1)])`, []any{int64(10), int64(40), int64(20)}, nil}, } succeeded := 0 failed := 0 // inputs1 := []inputType{ // /* 7 */ {`add([1,4,3,2])`, int64(10), nil}, // } for i, input := range inputs { var expr *ast var gotResult any var gotErr error ctx := NewSimpleFuncStore() ctx.SetVar("var1", int64(123)) ctx.SetVar("var2", "abc") ImportMathFuncs(ctx) parser := NewParser(ctx) logTest(t, i+1, "List", input.source, input.wantResult, input.wantErr) r := strings.NewReader(input.source) scanner := NewScanner(r, DefaultTranslations()) good := true if expr, gotErr = parser.Parse(scanner); gotErr == nil { gotResult, gotErr = expr.Eval(ctx) } if (gotResult == nil && input.wantResult != nil) || (gotResult != nil && input.wantResult == nil) { t.Errorf("%d: %q -> result = %v [%T], want %v [%T]", i+1, input.source, gotResult, gotResult, input.wantResult, input.wantResult) good = false } if gotList, okGot := gotResult.([]any); okGot { if wantList, okWant := input.wantResult.([]any); okWant { if (gotList == nil && wantList != nil) || (gotList != nil && wantList == nil) { t.Errorf("%d: %q -> result = %v [%T], want %v [%T]", i+1, input.source, gotResult, gotResult, input.wantResult, input.wantResult) good = false } else { equal := len(gotList) == len(wantList) if equal { for i, gotItem := range gotList { wantItem := wantList[i] equal = gotItem == wantItem if !equal { break } } } if !equal { t.Errorf("%d: %q -> result = %v [%T], want %v [%T]", i+1, input.source, gotResult, gotResult, input.wantResult, input.wantResult) good = false } } } } if gotErr != input.wantErr { if input.wantErr == nil || gotErr == nil || (gotErr.Error() != input.wantErr.Error()) { t.Errorf("%d: %q -> err = <%v>, want <%v>", i+1, input.source, gotErr, input.wantErr) good = false } } if good { succeeded++ } else { failed++ } } t.Logf("%s -- test count: %d, succeeded: %d, failed: %d", section, len(inputs), succeeded, failed) }