1
0
mirror of https://github.com/MontFerret/ferret.git synced 2024-12-14 11:23:02 +02:00
ferret/pkg/runtime/collections/tap_test.go

129 lines
3.1 KiB
Go
Raw Normal View History

2018-10-28 07:45:26 +02:00
package collections_test
import (
"context"
"github.com/MontFerret/ferret/pkg/runtime/collections"
"github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values"
. "github.com/smartystreets/goconvey/convey"
"testing"
)
func tapIterator(values collections.Iterator, predicate core.Expression) collections.Iterator {
iter, _ := collections.NewTapIterator(values, predicate)
return iter
}
type TestExpression struct {
fn func(ctx context.Context, scope *core.Scope) (core.Value, error)
}
func (exp *TestExpression) Exec(ctx context.Context, scope *core.Scope) (core.Value, error) {
return exp.fn(ctx, scope)
}
type ErrorIterator struct{}
func (iterator *ErrorIterator) Next(ctx context.Context, scope *core.Scope) (*core.Scope, error) {
return nil, core.ErrInvalidOperation
}
func TestTapIterator(t *testing.T) {
Convey("Should iterate over a given iterator and execute a predicate", t, func() {
arr := values.NewArrayWith(
values.NewInt(1),
values.NewInt(2),
values.NewInt(3),
values.NewInt(4),
values.NewInt(5),
)
counter := 0
iter := tapIterator(arrayIterator(arr), &TestExpression{
fn: func(ctx context.Context, scope *core.Scope) (core.Value, error) {
counter++
return values.None, nil
},
})
ctx := context.Background()
scope, _ := core.NewRootScope()
res, err := collections.ToSlice(ctx, scope, iter)
So(err, ShouldBeNil)
So(res, ShouldHaveLength, int(arr.Length()))
So(counter, ShouldEqual, int(arr.Length()))
})
Convey("Should stop when a predicate return an error", t, func() {
arr := values.NewArrayWith(
values.NewInt(1),
values.NewInt(2),
values.NewInt(3),
values.NewInt(4),
values.NewInt(5),
)
counter := 0
iter := tapIterator(arrayIterator(arr), &TestExpression{
fn: func(ctx context.Context, scope *core.Scope) (core.Value, error) {
counter++
return values.None, core.ErrInvalidOperation
},
})
ctx := context.Background()
scope, _ := core.NewRootScope()
_, err := collections.ToSlice(ctx, scope, iter)
So(err, ShouldNotBeNil)
So(counter, ShouldEqual, 1)
})
Convey("Should not invoke a predicate when underlying iterator returns error", t, func() {
counter := 0
iter := tapIterator(&ErrorIterator{}, &TestExpression{
fn: func(ctx context.Context, scope *core.Scope) (core.Value, error) {
counter++
return values.None, core.ErrInvalidOperation
},
})
ctx := context.Background()
scope, _ := core.NewRootScope()
_, err := collections.ToSlice(ctx, scope, iter)
So(err, ShouldNotBeNil)
So(counter, ShouldEqual, 0)
})
Convey("Should not invoke a predicate when underlying iterator is empty", t, func() {
arr := values.NewArray(0)
counter := 0
iter := tapIterator(arrayIterator(arr), &TestExpression{
fn: func(ctx context.Context, scope *core.Scope) (core.Value, error) {
counter++
return values.None, core.ErrInvalidOperation
},
})
ctx := context.Background()
scope, _ := core.NewRootScope()
res, err := collections.ToSlice(ctx, scope, iter)
So(err, ShouldBeNil)
So(res, ShouldHaveLength, 0)
So(counter, ShouldEqual, 0)
})
}