Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support of error suppression in inline expressions #671

Merged
merged 3 commits into from
Sep 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions pkg/compiler/compiler_for_ternary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ func TestForTernaryExpression(t *testing.T) {
So(string(out2), ShouldEqual, `true`)
})

Convey("RETURN foo ? TRUE : (FOR i IN 1..5 T::FAIL() RETURN i*2)?", t, func() {
c := compiler.New()

out1, err := c.MustCompile(`
LET foo = FALSE
RETURN foo ? TRUE : (FOR i IN 1..5 T::FAIL() RETURN i*2)?
`).Run(context.Background())

So(err, ShouldBeNil)
So(string(out1), ShouldEqual, `null`)
})

Convey("RETURN foo ? (FOR i IN 1..5 RETURN i) : (FOR i IN 1..5 RETURN i*2)", t, func() {
c := compiler.New()

Expand All @@ -48,6 +60,26 @@ func TestForTernaryExpression(t *testing.T) {
So(string(out2), ShouldEqual, `[1,2,3,4,5]`)
})

Convey("RETURN foo ? (FOR i IN 1..5 RETURN T::FAIL())? : (FOR i IN 1..5 RETURN T::FAIL())?", t, func() {
c := compiler.New()

out1, err := c.MustCompile(`
LET foo = FALSE
RETURN foo ? (FOR i IN 1..5 RETURN T::FAIL()) : (FOR i IN 1..5 RETURN T::FAIL())?
`).Run(context.Background())

So(err, ShouldBeNil)
So(string(out1), ShouldEqual, `null`)

out2, err := c.MustCompile(`
LET foo = TRUE
RETURN foo ? (FOR i IN 1..5 RETURN T::FAIL())? : (FOR i IN 1..5 RETURN T::FAIL())
`).Run(context.Background())

So(err, ShouldBeNil)
So(string(out2), ShouldEqual, `null`)
})

Convey("LET res = foo ? TRUE : (FOR i IN 1..5 RETURN i*2)", t, func() {
c := compiler.New()

Expand Down Expand Up @@ -91,6 +123,26 @@ func TestForTernaryExpression(t *testing.T) {
So(err, ShouldBeNil)
So(string(out2), ShouldEqual, `[1,2,3,4,5]`)
})

Convey("LET res = (FOR i IN 1..5 RETURN T::FAIL())? ? TRUE : FALSE", t, func() {
c := compiler.New()

out1, err := c.MustCompile(`
LET res = (FOR i IN 1..5 RETURN T::FAIL())? ? TRUE : FALSE
RETURN res
`).Run(context.Background())

So(err, ShouldBeNil)
So(string(out1), ShouldEqual, `false`)

out2, err := c.MustCompile(`
LET res = (FOR i IN 1..5 RETURN i)? ? TRUE : FALSE
RETURN res
`).Run(context.Background())

So(err, ShouldBeNil)
So(string(out2), ShouldEqual, `true`)
})
}

func BenchmarkForTernary(b *testing.B) {
Expand Down
12 changes: 12 additions & 0 deletions pkg/compiler/compiler_for_while_ternary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ func TestForTernaryWhileExpression(t *testing.T) {
So(string(out1), ShouldEqual, `[]`)
})

Convey("RETURN foo ? TRUE : (FOR i WHILE T::FAIL() RETURN i*2)?", t, func() {
c := compiler.New()

out1, err := c.MustCompile(`
LET foo = FALSE
RETURN foo ? TRUE : (FOR i WHILE T::FAIL() RETURN i*2)?
`).Run(context.Background())

So(err, ShouldBeNil)
So(string(out1), ShouldEqual, `null`)
})

Convey("RETURN foo ? TRUE : (FOR i WHILE F() < 10 RETURN i*2)", t, func() {
c := compiler.New()

Expand Down
48 changes: 48 additions & 0 deletions pkg/compiler/compiler_func_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,22 @@ func TestFunctionCall(t *testing.T) {
So(string(out), ShouldEqual, `null`)
})

Convey("Should handle errors when ? is used within a group", t, func() {
c := compiler.New()

p, err := c.Compile(`
RETURN (FALSE OR T::FAIL())?
`)

So(err, ShouldBeNil)

out, err := p.Run(context.Background())

So(err, ShouldBeNil)

So(string(out), ShouldEqual, `null`)
})

Convey("Should return NONE when error is handled", t, func() {
c := compiler.New()
c.RegisterFunction("ERROR", func(ctx context.Context, args ...core.Value) (core.Value, error) {
Expand All @@ -122,6 +138,38 @@ func TestFunctionCall(t *testing.T) {

So(string(out), ShouldEqual, `null`)
})

Convey("Should be able to use FOR as an argument", t, func() {
c := compiler.New()

p, err := c.Compile(`
RETURN FIRST((FOR i IN 1..10 RETURN i * 2))
`)

So(err, ShouldBeNil)

out, err := p.Run(context.Background())

So(err, ShouldBeNil)

So(string(out), ShouldEqual, `2`)
})

Convey("Should be able to use FOR as arguments", t, func() {
c := compiler.New()

p, err := c.Compile(`
RETURN UNION((FOR i IN 0..5 RETURN i), (FOR i IN 6..10 RETURN i))
`)

So(err, ShouldBeNil)

out, err := p.Run(context.Background())

So(err, ShouldBeNil)

So(string(out), ShouldEqual, `[0,1,2,3,4,5,6,7,8,9,10]`)
})
}

func BenchmarkFunctionCallArg1(b *testing.B) {
Expand Down
81 changes: 78 additions & 3 deletions pkg/compiler/compiler_let_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"context"
"github.com/MontFerret/ferret/pkg/compiler"
"github.com/MontFerret/ferret/pkg/runtime"
"github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values"
. "github.com/smartystreets/goconvey/convey"
"testing"
)
Expand Down Expand Up @@ -179,11 +181,35 @@ func TestLet(t *testing.T) {
So(string(out), ShouldEqual, "[1,2,3]")
})

Convey("Should compile LET i = (FOR i WHILE 0 > 1 RETURN i) RETURN i", t, func() {
Convey("Should compile LET src = NONE LET i = (FOR i IN NONE RETURN i)? RETURN i == NONE", t, func() {
c := compiler.New()

p, err := c.Compile(`
LET i = (FOR i WHILE 0 > 1 RETURN i)
LET src = NONE
LET i = (FOR i IN src RETURN i)?
RETURN i == NONE
`)

So(err, ShouldBeNil)
So(p, ShouldHaveSameTypeAs, &runtime.Program{})

out, err := p.Run(context.Background())

So(err, ShouldBeNil)
So(string(out), ShouldEqual, "true")
})

Convey("Should compile LET i = (FOR i WHILE COUNTER() < 5 RETURN i) RETURN i", t, func() {
c := compiler.New()
counter := -1
c.RegisterFunction("COUNTER", func(ctx context.Context, args ...core.Value) (core.Value, error) {
counter++

return values.NewInt(counter), nil
})

p, err := c.Compile(`
LET i = (FOR i WHILE COUNTER() < 5 RETURN i)
RETURN i
`)

Expand All @@ -193,7 +219,30 @@ func TestLet(t *testing.T) {
out, err := p.Run(context.Background())

So(err, ShouldBeNil)
So(string(out), ShouldEqual, "[]")
So(string(out), ShouldEqual, "[0,1,2,3,4]")
})

Convey("Should compile LET i = (FOR i WHILE COUNTER() < 5 T::FAIL() RETURN i)? RETURN i == NONE", t, func() {
c := compiler.New()
counter := -1
c.RegisterFunction("COUNTER", func(ctx context.Context, args ...core.Value) (core.Value, error) {
counter++

return values.NewInt(counter), nil
})

p, err := c.Compile(`
LET i = (FOR i WHILE COUNTER() < 5 T::FAIL() RETURN i)?
RETURN i == NONE
`)

So(err, ShouldBeNil)
So(p, ShouldHaveSameTypeAs, &runtime.Program{})

out, err := p.Run(context.Background())

So(err, ShouldBeNil)
So(string(out), ShouldEqual, "true")
})

Convey("Should compile LET i = { items: [1,2,3]} FOR el IN i.items RETURN i", t, func() {
Expand Down Expand Up @@ -262,4 +311,30 @@ func TestLet(t *testing.T) {
So(err, ShouldBeNil)
So(string(out), ShouldEqual, `"data"`)
})

Convey("Should handle error from WAITFOR EVENT", t, func() {
out, err := newCompilerWithObservable().MustCompile(`
LET obj = X::CREATE()

LET res = (WAITFOR EVENT "event" IN obj 100)?

RETURN res == NONE
`).Run(context.Background())

So(err, ShouldBeNil)
So(string(out), ShouldEqual, `true`)
})

Convey("Should compare result of handled error", t, func() {
out, err := newCompilerWithObservable().MustCompile(`
LET obj = X::CREATE()

LET res = (WAITFOR EVENT "event" IN obj 100)? != NONE

RETURN res
`).Run(context.Background())

So(err, ShouldBeNil)
So(string(out), ShouldEqual, `false`)
})
}
Loading