2024-03-26 08:45:18 +01:00
|
|
|
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
|
|
|
// All rights reserved.
|
|
|
|
|
2024-03-26 07:00:53 +01:00
|
|
|
// parser_test.go
|
|
|
|
package expr
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestParser(t *testing.T) {
|
|
|
|
type inputType struct {
|
|
|
|
source string
|
|
|
|
wantResult any
|
|
|
|
wantErr error
|
|
|
|
}
|
|
|
|
|
|
|
|
inputs := []inputType{
|
2024-03-31 06:10:27 +02:00
|
|
|
/* 1 */ {`1+/*5*/2`, int64(3), nil},
|
|
|
|
/* 2 */ {`3 == 4`, false, nil},
|
|
|
|
/* 3 */ {`3 != 4`, true, nil},
|
|
|
|
/* 4 */ {`4 == (3-1)*(10/5)`, true, nil},
|
|
|
|
/* 5 */ {`3 <= 4`, true, nil},
|
|
|
|
/* 6 */ {`3 < 4`, true, nil},
|
|
|
|
/* 7 */ {`4 < 3`, false, nil},
|
|
|
|
/* 8 */ {`1+5 < 4`, false, nil},
|
|
|
|
/* 9 */ {`3 > 4`, false, nil},
|
|
|
|
/* 10 */ {`4 >= 4`, true, nil},
|
|
|
|
/* 11 */ {`4 > 3`, true, nil},
|
|
|
|
/* 12 */ {`1+5 > 4`, true, nil},
|
|
|
|
/* 13 */ {`true`, true, nil},
|
|
|
|
/* 14 */ {`not true`, false, nil},
|
|
|
|
/* 15 */ {`true and false`, false, nil},
|
|
|
|
/* 16 */ {`true or false`, true, nil},
|
|
|
|
/* 17 */ {`"uno" + "due"`, `unodue`, nil},
|
|
|
|
/* 18 */ {`"uno" + 2`, `uno2`, nil},
|
|
|
|
/* 19 */ {`"uno" + (2+1)`, `uno3`, nil},
|
|
|
|
/* 20 */ {`"uno" * (2+1)`, `unounouno`, nil},
|
|
|
|
/* 21 */ {"1", int64(1), nil},
|
|
|
|
/* 22 */ {"1.5", float64(1.5), nil},
|
|
|
|
/* 23 */ {"1.5*2", float64(3.0), nil},
|
|
|
|
/* 24 */ {"+1", int64(1), nil},
|
|
|
|
/* 25 */ {"-1", int64(-1), nil},
|
|
|
|
/* 26 */ {"435 + 105 * 2 - 1", int64(644), nil},
|
|
|
|
/* 27 */ {"200 / 2 - 1", int64(99), nil},
|
|
|
|
/* 28 */ {"(1+1)", int64(2), nil},
|
|
|
|
/* 29 */ {"-(1+1)", int64(-2), nil},
|
|
|
|
/* 30 */ {"-(-2+1)", int64(1), nil},
|
|
|
|
/* 31 */ {"(1+1)*5", int64(10), nil},
|
|
|
|
/* 32 */ {"200 / (1+1) - 1", int64(99), nil},
|
|
|
|
/* 33 */ {`add(1,2,3)`, int64(6), nil},
|
|
|
|
/* 34 */ {`mulX(1,2,3)`, nil, errors.New(`unknown function mulX()`)},
|
|
|
|
/* 35 */ {`add(1+4,3+2,5*(3-2))`, int64(15), nil},
|
|
|
|
/* 36 */ {`add(add(1+4),3+2,5*(3-2))`, int64(15), nil},
|
|
|
|
/* 37 */ {`add(add(1,4),/*3+2,*/5*(3-2))`, int64(10), nil},
|
|
|
|
/* 38 */ {`1+(1+(1+(1)+1)+1)+1`, int64(7), nil},
|
|
|
|
/* 39 */ {`(((1)))`, int64(1), nil},
|
|
|
|
/* 40 */ {`"uno_" + var2`, `uno_abc`, nil},
|
|
|
|
/* 41 */ {`0 || 0.0 && "hello"`, false, nil},
|
2024-04-02 04:36:03 +02:00
|
|
|
/* 42 */ {`"s" + true`, nil, errors.New(`[1:6] left operand 's' [string] and right operand 'true' [bool] are not compatible with operator "+"`)},
|
|
|
|
/* 43 */ {`+false`, nil, errors.New(`[1:2] prefix/postfix operator "+" do not support operand 'false' [bool]`)},
|
2024-03-31 06:10:27 +02:00
|
|
|
/* 44 */ {`false // very simple expression`, false, nil},
|
2024-04-02 04:36:03 +02:00
|
|
|
/* 45 */ {`1 + // Missing right operator`, nil, errors.New(`[1:4] infix operator "+" requires two operands, got 1`)},
|
2024-03-31 06:10:27 +02:00
|
|
|
/* 46 */ {"", nil, errors.New(`empty expression`)},
|
|
|
|
/* 47 */ {"4!", int64(24), nil},
|
|
|
|
/* 48 */ {"(-4)!", nil, errors.New(`factorial of a negative integer (-4) is not allowed`)},
|
|
|
|
/* 49 */ {"-4!", int64(-24), nil},
|
|
|
|
/* 50 */ {"1.5 < 7", true, nil},
|
|
|
|
/* 51 */ {"1.5 > 7", false, nil},
|
|
|
|
/* 52 */ {"1.5 <= 7", true, nil},
|
|
|
|
/* 53 */ {"1.5 >= 7", false, nil},
|
|
|
|
/* 54 */ {"1.5 != 7", true, nil},
|
|
|
|
/* 55 */ {"1.5 == 7", false, nil},
|
|
|
|
/* 56 */ {`"1.5" < "7"`, true, nil},
|
|
|
|
/* 57 */ {`"1.5" > "7"`, false, nil},
|
|
|
|
/* 58 */ {`"1.5" == "7"`, false, nil},
|
|
|
|
/* 59 */ {`"1.5" != "7"`, true, nil},
|
2024-04-02 04:36:03 +02:00
|
|
|
/* 60 */ {"1.5 < ", nil, errors.New(`[1:6] infix operator "<" requires two operands, got 1`)},
|
|
|
|
/* 61 */ {"1.5 > ", nil, errors.New(`[1:6] infix operator ">" requires two operands, got 1`)},
|
|
|
|
/* 62 */ {"1.5 <= ", nil, errors.New(`[1:6] infix operator "<=" requires two operands, got 1`)},
|
|
|
|
/* 63 */ {"1.5 >= ", nil, errors.New(`[1:6] infix operator ">=" requires two operands, got 1`)},
|
|
|
|
/* 64 */ {"1.5 != ", nil, errors.New(`[1:6] infix operator "!=" requires two operands, got 1`)},
|
|
|
|
/* 65 */ {"1.5 == ", nil, errors.New(`[1:6] infix operator "==" requires two operands, got 1`)},
|
|
|
|
/* 66 */ {`"1.5" < `, nil, errors.New(`[1:8] infix operator "<" requires two operands, got 1`)},
|
|
|
|
/* 67 */ {`"1.5" > `, nil, errors.New(`[1:8] infix operator ">" requires two operands, got 1`)},
|
|
|
|
/* 68 */ {`"1.5" == `, nil, errors.New(`[1:8] infix operator "==" requires two operands, got 1`)},
|
|
|
|
/* 69 */ {`"1.5" != `, nil, errors.New(`[1:8] infix operator "!=" requires two operands, got 1`)},
|
2024-03-31 06:10:27 +02:00
|
|
|
/* 70 */ {"+1.5", float64(1.5), nil},
|
2024-04-02 04:36:03 +02:00
|
|
|
/* 71 */ {"+", nil, errors.New(`[1:2] prefix operator "+" requires one operand`)},
|
2024-03-31 06:10:27 +02:00
|
|
|
/* 72 */ {"4 / 0", nil, errors.New(`division by zero`)},
|
|
|
|
/* 73 */ {"4.0 / 0", nil, errors.New(`division by zero`)},
|
|
|
|
/* 74 */ {"4.0 / \n2", float64(2.0), nil},
|
|
|
|
/* 75 */ {`123`, int64(123), nil},
|
|
|
|
/* 76 */ {`1.`, float64(1.0), nil},
|
|
|
|
/* 77 */ {`1.E-2`, float64(0.01), nil},
|
|
|
|
/* 78 */ {`1E2`, float64(100), nil},
|
|
|
|
/* 79 */ {`1 / 2`, int64(0), nil},
|
|
|
|
/* 80 */ {`1.0 / 2`, float64(0.5), nil},
|
|
|
|
/* 81 */ {`1 ./ 2`, float64(0.5), nil},
|
|
|
|
/* 82 */ {`5 % 2`, int64(1), nil},
|
|
|
|
/* 83 */ {`5 % (-2)`, int64(1), nil},
|
|
|
|
/* 84 */ {`-5 % 2`, int64(-1), nil},
|
2024-04-02 04:36:03 +02:00
|
|
|
/* 85 */ {`5 % 2.0`, nil, errors.New(`[1:4] left operand '5' [int64] and right operand '2' [float64] are not compatible with operator "%"`)},
|
2024-03-31 06:10:27 +02:00
|
|
|
/* 86 */ {`"a" < "b" AND NOT (2 < 1)`, true, nil},
|
|
|
|
/* 87 */ {`"a" < "b" AND NOT (2 == 1)`, true, nil},
|
|
|
|
/* 88 */ {`"a" < "b" AND ~ 2 == 1`, true, nil},
|
|
|
|
/* 89 */ {`~ 2 > 1`, false, nil},
|
|
|
|
/* 90 */ {`~ true && true`, false, nil},
|
|
|
|
/* 91 */ {`~ false || true`, true, nil},
|
|
|
|
/* 92 */ {`false but true`, true, nil},
|
|
|
|
/* 93 */ {`2+3 but 5*2`, int64(10), nil},
|
|
|
|
/* 94 */ {`add(1,2) but var2`, "abc", nil},
|
|
|
|
/* 95 */ {`x=2`, int64(2), nil},
|
|
|
|
/* 96 */ {`x=2 but x*10`, int64(20), nil},
|
|
|
|
/* 97 */ {`false and true`, false, nil},
|
|
|
|
/* 98 */ {`false and (x==2)`, false, nil},
|
|
|
|
/* 99 */ {`false and (x=2 but x==2) or x==2`, nil, errors.New(`undefined variable "x"`)},
|
|
|
|
/* 100 */ {`false or true`, true, nil},
|
|
|
|
/* 101 */ {`false or (x==2)`, nil, errors.New(`undefined variable "x"`)},
|
|
|
|
/* 102 */ {`a=5; a`, int64(5), nil},
|
|
|
|
/* 103 */ {`a=5; b=2; add(a, b*3)`, int64(11), nil},
|
2024-03-31 06:38:46 +02:00
|
|
|
/* 104 */ {`2=5`, nil, errors.New(`assign operator ("=") must be preceded by a variable`)},
|
2024-04-02 04:36:03 +02:00
|
|
|
/* 105 */ {`2+a=5`, nil, errors.New(`[1:3] left operand of "=" must be a variable`)},
|
2024-03-31 06:38:46 +02:00
|
|
|
/* 106 */ {`2+(a=5)`, int64(7), nil},
|
2024-04-02 04:36:03 +02:00
|
|
|
/* 107 */ {`two=func(){2}; two()`, int64(2), nil},
|
|
|
|
/* 108 */ {`double=func(x) {2*x}; (double(3))`, int64(6), nil},
|
|
|
|
/* 109 */ {`double=func(x){2*x}; double(3)`, int64(6), nil},
|
|
|
|
/* 110 */ {`double=func(x){2*x}; a=5; double(3+a) + 1`, int64(17), nil},
|
|
|
|
/* 111 */ {`double=func(x){2*x}; a=5; two=func() {2}; (double(3+a) + 1) * two()`, int64(34), nil},
|
2024-04-02 06:49:16 +02:00
|
|
|
/* 112 */ {`import("./test-funcs.expr"); (double(3+a) + 1) * two()`, int64(34), nil},
|
|
|
|
/* 113 */ {`import("test-funcs.expr"); (double(3+a) + 1) * two()`, int64(34), nil},
|
2024-04-03 13:15:25 +02:00
|
|
|
/* 114 */ {`x ?? "default"`, "default", nil},
|
|
|
|
/* 115 */ {`x="hello"; x ?? "default"`, "hello", nil},
|
|
|
|
/* 116 */ {`x ?? func(){}"`, nil, errors.New(`[1:15] the right operand of a coalescing operation cannot be a function definition`)},
|
|
|
|
/* 117 */ {`x ?= "default"; x`, "default", nil},
|
|
|
|
/* 118 */ {`x="hello"; x ?= "default"; x`, "hello", nil},
|
2024-04-04 12:54:26 +02:00
|
|
|
/* 119 */ {`@x="hello"; @x`, nil, errors.New(`[1:3] variable references are not allowed in top level expressions: "@x"`)},
|
|
|
|
/* 120 */ {`f=func(){@x="hello"}; f(); x`, "hello", nil},
|
2024-04-06 01:00:29 +02:00
|
|
|
/* 121 */ {`f=func(@y){@y=@y+1}; f(2); y`, int64(3), nil},
|
|
|
|
/* 122 */ {`f=func(@y){g=func(){@x=5}; @y=@y+g()}; f(2); y+x`, nil, errors.New(`undefined variable "x"`)},
|
|
|
|
/* 123 */ {`f=func(@y){g=func(){@x=5}; @z=g(); @y=@y+@z}; f(2); y+z`, int64(12), nil},
|
|
|
|
/* 124 */ {`f=func(@y){g=func(){@x=5}; g(); @z=x; @y=@y+@z}; f(2); y+z`, int64(12), nil},
|
|
|
|
/* 125 */ {`f=func(@y){g=func(){@x=5}; g(); @z=x; @x=@y+@z}; f(2); y+x`, int64(9), nil},
|
2024-03-26 07:00:53 +01:00
|
|
|
}
|
2024-04-02 06:49:16 +02:00
|
|
|
check_env_expr_path := 113
|
|
|
|
|
2024-03-28 06:30:45 +01:00
|
|
|
succeeded := 0
|
|
|
|
failed := 0
|
|
|
|
|
2024-04-02 04:36:03 +02:00
|
|
|
// inputs1 := []inputType{
|
2024-04-06 01:00:29 +02:00
|
|
|
// {`f=func(@y){g=func(){@x=5}; g(); @z=x}; f(2)`, int64(5), nil},
|
2024-04-04 12:54:26 +02:00
|
|
|
// {`f=func(@y){@y=@y+1}; f(2); y`, int64(3), nil},
|
2024-04-02 06:49:16 +02:00
|
|
|
// {`import("./test-funcs.expr"); (double(3+a) + 1) * two()`, int64(34), nil},
|
2024-04-02 04:36:03 +02:00
|
|
|
// {`add(1,2,3)`, int64(6), nil},
|
|
|
|
// {`a=5; a`, int64(5), nil},
|
|
|
|
// {`a=5; b=2; add(a, b*3)`, int64(11), nil},
|
|
|
|
// {`"a" < "b" AND ~ 2 == 1`, true, nil},
|
|
|
|
// }
|
|
|
|
|
2024-03-26 07:00:53 +01:00
|
|
|
for i, input := range inputs {
|
|
|
|
var expr *ast
|
|
|
|
var gotResult any
|
|
|
|
var gotErr error
|
|
|
|
|
2024-03-31 05:09:24 +02:00
|
|
|
ctx := NewSimpleFuncStore()
|
2024-04-03 06:29:57 +02:00
|
|
|
ctx.SetVar("var1", int64(123))
|
|
|
|
ctx.SetVar("var2", "abc")
|
2024-03-31 05:09:24 +02:00
|
|
|
importMathFuncs(ctx)
|
2024-04-02 06:49:16 +02:00
|
|
|
importImportFunc(ctx)
|
2024-03-31 05:09:24 +02:00
|
|
|
parser := NewParser(ctx)
|
|
|
|
|
2024-03-30 08:09:41 +01:00
|
|
|
logTest(t, i+1, input.source, input.wantResult, input.wantErr)
|
2024-03-26 07:00:53 +01:00
|
|
|
|
|
|
|
r := strings.NewReader(input.source)
|
|
|
|
scanner := NewScanner(r, DefaultTranslations())
|
|
|
|
|
2024-03-28 06:30:45 +01:00
|
|
|
good := true
|
2024-03-26 07:00:53 +01:00
|
|
|
if expr, gotErr = parser.parse(scanner); gotErr == nil {
|
2024-04-02 04:36:03 +02:00
|
|
|
gotResult, gotErr = expr.Eval(ctx, true)
|
2024-03-26 07:00:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if gotResult != input.wantResult {
|
|
|
|
t.Errorf("%d: %q -> result = %v [%T], want %v [%T]", i+1, input.source, gotResult, gotResult, input.wantResult, input.wantResult)
|
2024-03-28 06:30:45 +01:00
|
|
|
good = false
|
2024-03-26 07:00:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if gotErr != input.wantErr {
|
|
|
|
if input.wantErr == nil || gotErr == nil || (gotErr.Error() != input.wantErr.Error()) {
|
2024-04-06 01:00:29 +02:00
|
|
|
t.Errorf("%d: %q -> err = <%v>, want <%v>", i+1, input.source, gotErr, input.wantErr)
|
2024-03-28 06:30:45 +01:00
|
|
|
good = false
|
2024-03-26 07:00:53 +01:00
|
|
|
}
|
|
|
|
}
|
2024-03-28 06:30:45 +01:00
|
|
|
|
|
|
|
if good {
|
|
|
|
succeeded++
|
|
|
|
} else {
|
|
|
|
failed++
|
2024-04-02 06:49:16 +02:00
|
|
|
if i+1 == check_env_expr_path {
|
|
|
|
t.Logf(`NOTICE: Test nr %d requires EXPR_PATH environment variable with value "."`, check_env_expr_path)
|
|
|
|
}
|
2024-03-28 06:30:45 +01:00
|
|
|
}
|
2024-03-26 07:00:53 +01:00
|
|
|
}
|
2024-03-28 06:30:45 +01:00
|
|
|
t.Log(fmt.Sprintf("test count: %d, succeeded count: %d, failed count: %d", len(inputs), succeeded, failed))
|
2024-03-28 08:52:54 +01:00
|
|
|
}
|
|
|
|
|
2024-04-06 01:00:29 +02:00
|
|
|
func TestListParser(t *testing.T) {
|
2024-03-28 08:52:54 +01:00
|
|
|
type inputType struct {
|
|
|
|
source string
|
|
|
|
wantResult any
|
|
|
|
wantErr error
|
|
|
|
}
|
|
|
|
|
|
|
|
// inputs1 := []inputType{
|
|
|
|
// {`add(1,2,3)`, int64(6), nil},
|
|
|
|
// }
|
|
|
|
|
|
|
|
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},
|
2024-03-30 07:05:22 +01:00
|
|
|
/* 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 has wrong type string, number expected`)},
|
2024-03-30 08:09:41 +01:00
|
|
|
/* 11 */ {`[a=1,b=2,c=3] but a+b+c`, int64(6), nil},
|
2024-03-30 07:05:22 +01: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-03-28 08:52:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
succeeded := 0
|
|
|
|
failed := 0
|
|
|
|
|
|
|
|
for i, input := range inputs {
|
|
|
|
var expr *ast
|
|
|
|
var gotResult any
|
|
|
|
var gotErr error
|
|
|
|
|
2024-04-02 06:49:16 +02:00
|
|
|
ctx := NewSimpleFuncStore()
|
2024-04-03 06:29:57 +02:00
|
|
|
ctx.SetVar("var1", int64(123))
|
|
|
|
ctx.SetVar("var2", "abc")
|
2024-04-02 06:49:16 +02:00
|
|
|
importMathFuncs(ctx)
|
|
|
|
parser := NewParser(ctx)
|
|
|
|
|
2024-03-30 08:09:41 +01:00
|
|
|
logTest(t, i+1, input.source, input.wantResult, input.wantErr)
|
2024-03-28 08:52:54 +01:00
|
|
|
|
|
|
|
r := strings.NewReader(input.source)
|
|
|
|
scanner := NewScanner(r, DefaultTranslations())
|
|
|
|
|
|
|
|
good := true
|
|
|
|
if expr, gotErr = parser.parse(scanner); gotErr == nil {
|
2024-04-02 04:36:03 +02:00
|
|
|
gotResult, gotErr = expr.Eval(ctx, true)
|
2024-03-28 08:52:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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.Log(fmt.Sprintf("test count: %d, succeeded count: %d, failed count: %d", len(inputs), succeeded, failed))
|
2024-03-26 07:00:53 +01:00
|
|
|
}
|
2024-03-30 08:09:41 +01:00
|
|
|
|
|
|
|
func logTest(t *testing.T, n int, source string, wantResult any, wantErr error) {
|
|
|
|
if wantErr == nil {
|
2024-03-31 06:10:27 +02:00
|
|
|
t.Log(fmt.Sprintf("[+]Test nr %3d -- %q --> %v", n, source, wantResult))
|
2024-03-30 08:09:41 +01:00
|
|
|
} else {
|
2024-03-31 06:10:27 +02:00
|
|
|
t.Log(fmt.Sprintf("[-]Test nr %3d -- %q --> %v", n, source, wantErr))
|
2024-03-30 08:09:41 +01:00
|
|
|
}
|
|
|
|
}
|