2024-05-06 05:52:25 +02:00
|
|
|
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
|
|
|
// All rights reserved.
|
|
|
|
|
2024-05-28 07:26:05 +02:00
|
|
|
// t_list_test.go
|
2024-05-06 05:52:25 +02:00
|
|
|
package expr
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestListParser(t *testing.T) {
|
|
|
|
section := "List"
|
|
|
|
|
2024-06-05 05:09:13 +02:00
|
|
|
/* type inputType struct {
|
2024-05-06 05:52:25 +02:00
|
|
|
source string
|
|
|
|
wantResult any
|
|
|
|
wantErr error
|
|
|
|
}
|
2024-06-05 05:09:13 +02:00
|
|
|
*/
|
2024-05-06 05:52:25 +02:00
|
|
|
inputs := []inputType{
|
2024-06-05 05:09:13 +02:00
|
|
|
/* 1 */ {`[]`, newListA(), nil},
|
|
|
|
/* 2 */ {`[1,2,3]`, newListA(int64(1), int64(2), int64(3)), nil},
|
|
|
|
/* 3 */ {`[1,2,"hello"]`, newListA(int64(1), int64(2), "hello"), nil},
|
|
|
|
/* 4 */ {`[1+2, not true, "hello"]`, newListA(int64(3), false, "hello"), nil},
|
|
|
|
/* 5 */ {`[1,2]+[3]`, newListA(int64(1), int64(2), int64(3)), nil},
|
|
|
|
/* 6 */ {`[1,4,3,2]-[3]`, newListA(int64(1), int64(4), int64(2)), nil},
|
2024-05-10 04:45:51 +02:00
|
|
|
/* 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},
|
2024-06-05 05:09:13 +02:00
|
|
|
/* 12 */ {`[1,2,3] << 2+2`, newListA(int64(1), int64(2), int64(3), int64(4)), nil},
|
|
|
|
/* 13 */ {`2-1 >> [2,3]`, newListA(int64(1), int64(2), int64(3)), nil},
|
2024-05-24 22:51:01 +02:00
|
|
|
/* 14 */ {`[1,2,3][1]`, int64(2), nil},
|
2024-05-25 03:28:01 +02:00
|
|
|
/* 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:34] index 10 out of bounds`)},
|
2024-05-10 04:45:51 +02:00
|
|
|
/* 18 */ {`["a", "b", "c"]`, newListA("a", "b", "c"), nil},
|
|
|
|
/* 19 */ {`["a", "b", "c"]`, newList([]any{"a", "b", "c"}), nil},
|
2024-05-10 09:18:32 +02:00
|
|
|
/* 20 */ {`#["a", "b", "c"]`, int64(3), nil},
|
2024-05-18 07:47:41 +02:00
|
|
|
/* 21 */ {`"b" in ["a", "b", "c"]`, true, nil},
|
2024-06-05 05:09:13 +02:00
|
|
|
/* 22 */ {`a=[1,2]; (a)<<3`, newListA(int64(1), int64(2), int64(3)), nil},
|
|
|
|
/* 23 */ {`a=[1,2]; (a)<<3; a`, newListA(int64(1), int64(2)), nil},
|
2024-05-24 22:51:01 +02:00
|
|
|
/* 24 */ {`["a","b","c","d"][1]`, "b", nil},
|
|
|
|
/* 25 */ {`["a","b","c","d"][1,1]`, nil, errors.New(`[1:19] one index only is allowed`)},
|
2024-06-05 05:09:13 +02:00
|
|
|
/* 26 */ {`[0,1,2,3,4][:]`, newListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
|
2024-06-01 16:31:50 +02:00
|
|
|
/* 27 */ {`["a", "b", "c"] << ;`, nil, errors.New(`[1:18] infix operator "<<" requires two non-nil operands, got 1`)},
|
|
|
|
/* 28 */ {`2 << 3;`, nil, errors.New(`[1:4] left operand '2' [integer] and right operand '3' [integer] are not compatible with operator "<<"`)},
|
|
|
|
/* 29 */ {`but >> ["a", "b", "c"]`, nil, errors.New(`[1:6] infix operator ">>" requires two non-nil operands, got 0`)},
|
|
|
|
/* 30 */ {`2 >> 3;`, nil, errors.New(`[1:4] left operand '2' [integer] and right operand '3' [integer] are not compatible with operator ">>"`)},
|
2024-06-05 05:09:13 +02:00
|
|
|
/* 31 */ {`a=[1,2]; a<<3`, newListA(int64(1), int64(2), int64(3)), nil},
|
|
|
|
/* 33 */ {`a=[1,2]; 5>>a`, newListA(int64(5), int64(1), int64(2)), nil},
|
2024-06-04 11:07:35 +02:00
|
|
|
/* 34 */ {`L=[1,2]; L[0]=9; L`, newListA(int64(9),int64(2)), nil},
|
2024-06-05 05:09:13 +02:00
|
|
|
/* 35 */ {`L=[1,2]; L[5]=9; L`, nil, errors.New(`index 5 out of bounds (0, 1)`)},
|
|
|
|
/* 36 */ {`L=[1,2]; L[]=9; L`, nil, errors.New(`[1:12] index/key specification expected, got [] [list]`)},
|
2024-05-06 05:52:25 +02:00
|
|
|
// /* 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},
|
|
|
|
}
|
|
|
|
|
2024-06-05 05:09:13 +02:00
|
|
|
// t.Setenv("EXPR_PATH", ".")
|
|
|
|
|
|
|
|
// parserTestSpec(t, section, inputs, 17)
|
|
|
|
parserTest(t, section, inputs)
|
|
|
|
return
|
2024-05-06 05:52:25 +02:00
|
|
|
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
|
|
|
|
|
2024-05-23 07:46:31 +02:00
|
|
|
ctx := NewSimpleStore()
|
2024-05-06 05:52:25 +02:00
|
|
|
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)
|
|
|
|
}
|