From a62f27b1048730eb0c36d2fd3296004c2d454d34 Mon Sep 17 00:00:00 2001 From: Celestino Amoroso Date: Thu, 21 May 2026 03:06:52 +0200 Subject: [PATCH] increased test coverage (83.9%) --- global-context.go | 24 +++++++------- int-iterator.go | 4 +++ iter-factory.go | 12 +++---- operator-context.go | 44 +++++++++++++------------ t_common_test.go | 24 ++++++++++++++ t_context_test.go | 34 +++++++++++++++++++ t_dict_test.go | 4 +-- t_expr_test.go | 3 +- t_iterator_test.go | 80 ++++++++++++++++++++++++++++++++++++++++++++- t_operator_test.go | 6 ++++ 10 files changed, 190 insertions(+), 45 deletions(-) diff --git a/global-context.go b/global-context.go index d8fc0ce..c1a721c 100644 --- a/global-context.go +++ b/global-context.go @@ -42,12 +42,16 @@ func ImportInContextByGlobPattern(ctx kern.ExprContext, pattern string) (count i return } +func fixCtrlVar(name string) string { + if !strings.HasPrefix(name, "_") { + name = "_" + name + } + return name +} + func GlobalCtrlSet(ctx kern.ExprContext, name string, newValue any) (currentValue any) { if globalCtx := ctx.GetGlobal(); globalCtx != nil { - if !strings.HasPrefix(name, "_") { - name = "_" + name - } - + name = fixCtrlVar(name) currentValue, _ = globalCtx.GetVar(name) globalCtx.SetVar(name, newValue) } @@ -56,18 +60,14 @@ func GlobalCtrlSet(ctx kern.ExprContext, name string, newValue any) (currentValu func GlobalCtrlGet(ctx kern.ExprContext, name string) (currentValue any) { if globalCtx := ctx.GetGlobal(); globalCtx != nil { - if !strings.HasPrefix(name, "_") { - name = "_" + name - } + name = fixCtrlVar(name) currentValue, _ = globalCtx.GetVar(name) } return currentValue } func CtrlEnable(ctx kern.ExprContext, name string) (currentStatus bool) { - if !strings.HasPrefix(name, "_") { - name = "_" + name - } + name = fixCtrlVar(name) if v, exists := ctx.GetVar(name); exists && kern.IsBool(v) { currentStatus, _ = v.(bool) } @@ -77,9 +77,7 @@ func CtrlEnable(ctx kern.ExprContext, name string) (currentStatus bool) { } func CtrlDisable(ctx kern.ExprContext, name string) (currentStatus bool) { - if !strings.HasPrefix(name, "_") { - name = "_" + name - } + name = fixCtrlVar(name) if v, exists := ctx.GetVar(name); exists && kern.IsBool(v) { currentStatus, _ = v.(bool) } diff --git a/int-iterator.go b/int-iterator.go index 5833913..cf44067 100644 --- a/int-iterator.go +++ b/int-iterator.go @@ -20,6 +20,10 @@ type IntIterator struct { step int64 } +func NewIntIteratorA(args ...any) (it *IntIterator, err error) { + return NewIntIterator(args) +} + func NewIntIterator(args []any) (it *IntIterator, err error) { var argc int = 0 if args != nil { diff --git a/iter-factory.go b/iter-factory.go index 45e5beb..f3e1dc2 100644 --- a/iter-factory.go +++ b/iter-factory.go @@ -38,9 +38,9 @@ func HasIterStandardOperations(name string) bool { return slices.Contains([]string{kern.NextName, kern.ResetName, kern.IndexName, kern.CountName, kern.CurrentName, kern.CleanName}, name) } -func HasIterOperations(name string, ops ...string) bool { - return slices.Contains([]string{ - kern.NextName, kern.ResetName, kern.IndexName, kern.CountName, kern.CurrentName, kern.CleanName, - }, name) || - slices.Contains(ops, name) -} +// func HasIterOperations(name string, ops ...string) bool { +// return slices.Contains([]string{ +// kern.NextName, kern.ResetName, kern.IndexName, kern.CountName, kern.CurrentName, kern.CleanName, +// }, name) || +// slices.Contains(ops, name) +// } diff --git a/operator-context.go b/operator-context.go index d23a002..6b26eed 100644 --- a/operator-context.go +++ b/operator-context.go @@ -40,23 +40,7 @@ func evalContextValue(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error } if sourceCtx != nil { - if formatter, ok := sourceCtx.(kern.DictFormat); ok { - v = formatter.ToDict() - } else if formatter, ok := sourceCtx.(kern.Formatter); ok { - v = formatter.ToString(0) - } else { - // keys := sourceCtx.EnumVars(func(name string) bool { return name[0] != '_' }) - keys := sourceCtx.EnumVars(nil) - d := make(map[string]any) - for _, key := range keys { - d[key], _ = sourceCtx.GetVar(key) - } - keys = sourceCtx.EnumFuncs(func(name string) bool { return true }) - for _, key := range keys { - d[key], _ = sourceCtx.GetFuncInfo(key) - } - v = d - } + v = contextToDict(sourceCtx) } else if childValue != nil { it, ok := childValue.(kern.Iterator) if !ok { @@ -64,18 +48,14 @@ func evalContextValue(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error } if err == nil { var item any - // values := kern.NewListA() values := kern.NewLinkedListA() for item, err = it.Next(); err == nil; item, err = it.Next() { - // values.AppendItem(item) values.PushBack(item) } if err == io.EOF { err = nil v = values } - // } else { - // err = opTerm.ErrIncompatiblePrefixPostfixType(childValue) } } else { err = opTerm.ErrIncompatiblePrefixPostfixType(childValue) @@ -83,6 +63,28 @@ func evalContextValue(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error return } +func contextToDict(ctx kern.ExprContext) (dict *kern.DictType) { + // Variables + keys := ctx.EnumVars(nil) + vars := kern.MakeDict() + for _, key := range keys { + value, _ := ctx.GetVar(key) + vars.SetItem(key, value) + } + // Functions + keys = ctx.EnumFuncs(func(name string) bool { return true }) + funcs := kern.MakeDict() + for _, key := range keys { + funcInfo, _ := ctx.GetFuncInfo(key) + funcs.SetItem(key, funcInfo) + } + + dict = kern.MakeDict() + dict.SetItem("vars", vars) + dict.SetItem("funcs", funcs) + return +} + // init func init() { scan.RegisterTermConstructor(scan.SymDoubleDollar, newContextTerm) diff --git a/t_common_test.go b/t_common_test.go index 54db18d..33740f3 100644 --- a/t_common_test.go +++ b/t_common_test.go @@ -121,3 +121,27 @@ func logTest(t *testing.T, n int, section, source string, wantResult any, wantEr t.Logf("[-]%s nr %3d -- `%s` --> %v", section, n, source, wantErr) } } + +func testIteratorCallOp(t *testing.T, section string, it kern.Iterator) { + if _, err := it.CallOperation("next", map[string]any{}); err != nil { + t.Errorf(`%s -- CallOperation("next") failed: %v`, section, err) + } + if _, err := it.CallOperation("current", map[string]any{}); err != nil { + t.Errorf(`%s -- CallOperation("current") failed: %v`, section, err) + } + if _, err := it.CallOperation("clean", map[string]any{}); err != nil { + t.Errorf(`%s -- CallOperation("clean") failed: %v`, section, err) + } + if _, err := it.CallOperation("index", map[string]any{}); err != nil { + t.Errorf(`%s -- CallOperation("index") failed: %v`, section, err) + } + if _, err := it.CallOperation("count", map[string]any{}); err != nil { + t.Errorf(`%s -- CallOperation("count") failed: %v`, section, err) + } + if _, err := it.CallOperation("reset", map[string]any{}); err != nil { + t.Errorf(`%s -- CallOperation("reset") failed: %v`, section, err) + } + if _, err := it.CallOperation("fake", map[string]any{}); err == nil { + t.Errorf(`%s -- CallOperation("fake") should return error`, section) + } +} diff --git a/t_context_test.go b/t_context_test.go index 3d79469..9bb6beb 100644 --- a/t_context_test.go +++ b/t_context_test.go @@ -6,6 +6,8 @@ package expr import ( "testing" + + "git.portale-stac.it/go-pkg/expr/kern" ) func TestCtrlSet(t *testing.T) { @@ -58,3 +60,35 @@ func TestCtrlGetNotDefined(t *testing.T) { t.Errorf(`%s -- CtrlGet(%q) should have returned nil, got %v`, section, varName, v) } } + +func TestCtrlEnable(t *testing.T) { + section := "Context" + varName := "test_var" + varValue := true + + ctx := NewSimpleStore() + GlobalCtrlSet(ctx, varName, varValue) + if !CtrlEnable(ctx, varName) { + t.Errorf(`%s -- CtrlEnable(ctx, %q) should have returned 'true', got 'false'`, section, varName) + } + + if !CtrlDisable(ctx, varName) { + t.Errorf(`%s -- CtrlEnable(ctx, %q) should have returned 'true', got 'false'`, section, varName) + // t.Errorf(`%s -- CtrlEnable(ctx, %q) should have returned 'false', got 'true'`, section, varName) + } + +} + +func TestList(t *testing.T) { + section := "Context" + + inputs := []inputType{ + /* 1 */ {`$$(5)`, kern.NewLinkedListA(5), nil}, + /* 2 */ {`$$($(2))`, kern.NewLinkedListA(0, 1), nil}, + /* 3 */ {`string(($$global).funcs.bool)`, `bool(value):boolean{}`, nil}, + } + + runTestSuiteSpec(t, section, inputs, 3) + // runTestSuite(t, section, inputs) + +} diff --git a/t_dict_test.go b/t_dict_test.go index 9be5b74..ef335ee 100644 --- a/t_dict_test.go +++ b/t_dict_test.go @@ -47,8 +47,8 @@ func TestDictParser(t *testing.T) { /* 24 */ {`f=func(n){"x"+n}; d={f(5) but "z":10}`, kern.NewDict(map[any]any{"z": int64(10)}), nil}, } - runTestSuiteSpec(t, section, inputs, 1, 23, 24) - // runTestSuite(t, section, inputs) + // runTestSuiteSpec(t, section, inputs, 23, 24) + runTestSuite(t, section, inputs) } func TestAccessSubFields(t *testing.T) { diff --git a/t_expr_test.go b/t_expr_test.go index 21ab428..faa59f0 100644 --- a/t_expr_test.go +++ b/t_expr_test.go @@ -31,8 +31,7 @@ func TestExpr(t *testing.T) { /* 15 */ {`a=3; a*=2)+1; a`, nil, `[1:11] unexpected token ")"`}, /* 16 */ {`v=[2]; a=1; v[a-=1]=5; v[0]`, int64(5), nil}, /* 17 */ {`true ? {"a"} :: {"b"}`, "a", nil}, - /* 18 */ {`$$`, kern.NewDict(map[any]any{"variables": kern.NewDict(nil), "functions": kern.NewDict(nil)}), nil}, - ///* 19 */ {`$$global`, NewDict(map[any]any{"variables": NewDict(nil), "functions": NewDict(nil)}), nil}, + /* 18 */ {`$$`, kern.NewDict(map[any]any{"vars": kern.NewDict(nil), "funcs": kern.NewDict(nil)}), nil}, /* 19 */ {` ds={ "init":func(@end){@current=0 but true}, diff --git a/t_iterator_test.go b/t_iterator_test.go index 1237ca5..5b21bd2 100644 --- a/t_iterator_test.go +++ b/t_iterator_test.go @@ -8,6 +8,7 @@ import ( "testing" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/scan" ) func TestIteratorParser(t *testing.T) { @@ -35,12 +36,89 @@ func TestIteratorParser(t *testing.T) { /* 20 */ {`it=$({1:"one",2:"two",3:"three"}, "default", "value"); it++`, "one", nil}, /* 21 */ {`it=$({1:"one",2:"two",3:"three"}, "desc", "key"); it++`, int64(3), nil}, /* 22 */ {`it=$({1:"one",2:"two",3:"three"}, "asc", "item"); it++`, kern.NewList([]any{int64(1), "one"}), nil}, + /* 23 */ {`$$($(1,4,0))`, nil, `step cannot be zero`}, + /* 24 */ {`$$($(1,4,-1))`, nil, `step cannot be negative when start < stop`}, + /* 25 */ {`$$($(4,1,1))`, nil, `step cannot be positive when start > stop`}, } - // runTestSuiteSpec(t, section, inputs, 1) + // runTestSuiteSpec(t, section, inputs, 25) runTestSuite(t, section, inputs) } +func TestCallOpIntIter(t *testing.T) { + section := "IntIterator-CallOp" + + if it, err := NewIntIteratorA(int64(1), int64(4), int64(1)); err != nil { + t.Errorf(`%s -- NewIntIteratorA() failed: %v`, section, err) + } else { + testIteratorCallOp(t, section, it) + testIterAttrs(t, section, it, "IntIterator", "$(1..4..1)") + } +} + +func TestCallOpIterIter(t *testing.T) { + section := "IterIterator-CallOp" + + ctx := NewSimpleStore() + if inner, err := NewIntIteratorA(int64(1), int64(4), int64(1)); err == nil { + if it, err := NewIterIter(inner, ctx, []*scan.Term{}); err != nil { + t.Errorf(`%s -- NewIterIter() failed: %v`, section, err) + } else { + testIteratorCallOp(t, section, it) + testIterAttrs(t, section, it, "IterIter", "$($(1..4..1))") + } + } else { + t.Errorf(`%s -- can't create inner iterator: %v`, section, err) + } +} + +func TestCallOpDictIter(t *testing.T) { + section := "DictIterator-CallOp" + + inner := kern.NewDict(map[any]any{"a": 1}) + if it, err := NewDictIterator(inner, nil); err != nil { + t.Errorf(`%s -- NewIterIter() failed: %v`, section, err) + } else { + testIteratorCallOp(t, section, it) + testIterAttrs(t, section, it, "DictIterator", "$({#1})") + } +} + +func TestCallOpLinkedListIter(t *testing.T) { + section := "LinkedListIterator-CallOp" + + inner := kern.NewLinkedListA(1, 2, 3) + it := NewLinkedListIterator(inner, nil) + testIteratorCallOp(t, section, it) + + // wanted := "$([<#3>])" + // got := it.String() + // if wanted != got { + // t.Errorf(`%s -- LinkedListIterator.String() failed: expected %q, got %q`, section, wanted, got) + // } + + // wanted = "LinkedListIterator" + // got = it.TypeName() + // if wanted != got { + // t.Errorf(`%s -- LinkedListIterator.TypeName() failed: expected %q, got %q`, section, wanted, got) + // } + testIterAttrs(t, section, it, "LinkedListIterator", "$([<#3>])") +} + +func testIterAttrs(t *testing.T, section string, it kern.Iterator, name, repr string) { + wanted := repr + got := it.String() + if wanted != got { + t.Errorf(`%s -- %s.String() failed: expected %q, got %q`, section, name, wanted, got) + } + + wanted = name + got = it.TypeName() + if wanted != got { + t.Errorf(`%s -- %s.TypeName() failed: expected %q, got %q`, section, name, wanted, got) + } +} + func TestFilterIterator(t *testing.T) { section := "Iterator-Filter" inputs := []inputType{ diff --git a/t_operator_test.go b/t_operator_test.go index 74754ac..4ad67e5 100644 --- a/t_operator_test.go +++ b/t_operator_test.go @@ -35,6 +35,12 @@ func TestOperator(t *testing.T) { /* 20 */ {`a=1; a^=2`, int64(3), nil}, /* 21 */ {`a=1; ++a`, int64(2), nil}, /* 22 */ {`a=1; --a`, int64(0), nil}, + /* 23 */ {`a=1; a++`, int64(1), nil}, + /* 24 */ {`a=1; a--`, int64(1), nil}, + /* 25 */ {`a="1"; ++a`, nil, `[1:9] prefix/postfix operator "++" does not support operand '1' [string]`}, + /* 26 */ {`a="1"; --a`, nil, `[1:9] prefix/postfix operator "--" does not support operand '1' [string]`}, + /* 27 */ {`a="1"; a++`, nil, `[1:10] prefix/postfix operator "++" does not support operand '1' [string]`}, + /* 28 */ {`a="1"; a--`, nil, `[1:10] prefix/postfix operator "--" does not support operand '1' [string]`}, } // t.Setenv("EXPR_PATH", ".")