package expressions_test import ( "context" "github.com/MontFerret/ferret/pkg/runtime/collections" "testing" "github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/expressions" "github.com/MontFerret/ferret/pkg/runtime/values" . "github.com/smartystreets/goconvey/convey" ) type IterableFn func(ctx context.Context, scope *core.Scope) (collections.Iterator, error) func (f IterableFn) Iterate(ctx context.Context, scope *core.Scope) (collections.Iterator, error) { return f(ctx, scope) } type ExpressionFn func(ctx context.Context, scope *core.Scope) (core.Value, error) func (f ExpressionFn) Exec(ctx context.Context, scope *core.Scope) (core.Value, error) { return f(ctx, scope) } func TestBlock(t *testing.T) { newExp := func(values []core.Value) (*expressions.BlockExpression, error) { iter, err := collections.NewDefaultSliceIterator(values) if err != nil { return nil, err } return expressions.NewBlockExpression(IterableFn(func(ctx context.Context, scope *core.Scope) (collections.Iterator, error) { return iter, nil })) } Convey("Should create a block expression", t, func() { s, err := newExp(make([]core.Value, 0, 10)) So(err, ShouldBeNil) So(s, ShouldHaveSameTypeAs, &expressions.BlockExpression{}) }) Convey("Should add a new expression of a default type", t, func() { s, _ := newExp(make([]core.Value, 0, 10)) sourceMap := core.NewSourceMap("test", 1, 1) exp, err := expressions.NewVariableExpression(sourceMap, "testExp") So(err, ShouldBeNil) s.Add(exp) }) Convey("Should exec a block expression", t, func() { s, _ := newExp(make([]core.Value, 0, 10)) sourceMap := core.NewSourceMap("test", 1, 1) exp, err := expressions.NewVariableDeclarationExpression(sourceMap, "test", ExpressionFn(func(ctx context.Context, scope *core.Scope) (core.Value, error) { return values.NewString("value"), nil })) So(err, ShouldBeNil) s.Add(exp) rootScope, _ := core.NewRootScope() scope := rootScope.Fork() _, err = s.Exec(context.Background(), scope) So(err, ShouldBeNil) val, err := scope.GetVariable("test") So(err, ShouldBeNil) So(val, ShouldEqual, "value") }) Convey("Should not exec a nil block expression", t, func() { s, _ := newExp(make([]core.Value, 0, 10)) sourceMap := core.NewSourceMap("test", 1, 1) exp, err := expressions.NewVariableExpression(sourceMap, "test") So(err, ShouldBeNil) s.Add(exp) So(err, ShouldBeNil) rootScope, fn := core.NewRootScope() scope := rootScope.Fork() scope.SetVariable("test", values.NewString("value")) fn() value, err := s.Exec(context.Background(), scope) So(err, ShouldBeNil) So(value, ShouldHaveSameTypeAs, values.None) }) Convey("Should return an iterator", t, func() { s, _ := newExp([]core.Value{ values.NewInt(1), values.NewInt(2), values.NewInt(3), }) sourceMap := core.NewSourceMap("test", 1, 1) exp, _ := expressions.NewVariableExpression(sourceMap, "test") s.Add(exp) rootScope, _ := core.NewRootScope() scope := rootScope.Fork() scope.SetVariable("test", values.NewString("value")) iter, err := s.Iterate(context.Background(), scope) So(err, ShouldBeNil) items, err := collections.ToSlice(context.Background(), scope, iter) So(err, ShouldBeNil) So(items, ShouldHaveLength, 3) }) Convey("Should stop an execution when context is cancelled", t, func() { s, _ := newExp(make([]core.Value, 0, 10)) sourceMap := core.NewSourceMap("test", 1, 1) exp, _ := expressions.NewVariableExpression(sourceMap, "test") s.Add(exp) rootScope, _ := core.NewRootScope() scope := rootScope.Fork() scope.SetVariable("test", values.NewString("value")) ctx, cancel := context.WithCancel(context.Background()) cancel() _, err := s.Exec(ctx, scope) So(err, ShouldEqual, core.ErrTerminated) }) Convey("Should stop an execution when context is cancelled 2", t, func() { s, _ := newExp([]core.Value{ values.NewInt(1), values.NewInt(2), values.NewInt(3), }) sourceMap := core.NewSourceMap("test", 1, 1) exp, _ := expressions.NewVariableExpression(sourceMap, "test") s.Add(exp) rootScope, _ := core.NewRootScope() scope := rootScope.Fork() scope.SetVariable("test", values.NewString("value")) ctx, cancel := context.WithCancel(context.Background()) cancel() _, err := s.Iterate(ctx, scope) So(err, ShouldEqual, core.ErrTerminated) }) }