github.com/MontFerret/ferret@v0.18.0/pkg/compiler/compiler_func_test.go (about) 1 package compiler_test 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/pkg/errors" 8 . "github.com/smartystreets/goconvey/convey" 9 10 "github.com/MontFerret/ferret/pkg/compiler" 11 "github.com/MontFerret/ferret/pkg/runtime/core" 12 "github.com/MontFerret/ferret/pkg/runtime/values" 13 ) 14 15 func TestFunctionCall(t *testing.T) { 16 Convey("Should compile RETURN TYPENAME(1)", t, func() { 17 c := compiler.New() 18 19 p, err := c.Compile(` 20 RETURN TYPENAME(1) 21 `) 22 23 So(err, ShouldBeNil) 24 25 out, err := p.Run(context.Background()) 26 27 So(err, ShouldBeNil) 28 29 So(string(out), ShouldEqual, `"int"`) 30 }) 31 32 Convey("Should compile WAIT(10) RETURN 1", t, func() { 33 c := compiler.New() 34 35 p, err := c.Compile(` 36 WAIT(10) 37 RETURN 1 38 `) 39 40 So(err, ShouldBeNil) 41 42 out, err := p.Run(context.Background()) 43 44 So(err, ShouldBeNil) 45 46 So(string(out), ShouldEqual, `1`) 47 }) 48 49 Convey("Should compile LET duration = 10 WAIT(duration) RETURN 1", t, func() { 50 c := compiler.New() 51 52 p, err := c.Compile(` 53 LET duration = 10 54 55 WAIT(duration) 56 57 RETURN 1 58 `) 59 60 So(err, ShouldBeNil) 61 62 out, err := p.Run(context.Background()) 63 64 So(err, ShouldBeNil) 65 66 So(string(out), ShouldEqual, `1`) 67 }) 68 69 Convey("Should compile function call inside FOR IN statement", t, func() { 70 c := compiler.New() 71 72 p, err := c.Compile(` 73 FOR i IN [1, 2, 3, 4] 74 LET duration = 10 75 76 WAIT(duration) 77 78 RETURN i * 2 79 `) 80 81 So(err, ShouldBeNil) 82 83 out, err := p.Run(context.Background()) 84 85 So(err, ShouldBeNil) 86 87 So(string(out), ShouldEqual, `[2,4,6,8]`) 88 }) 89 90 Convey("Should handle errors when ? is used", t, func() { 91 c := compiler.New() 92 c.RegisterFunction("ERROR", func(ctx context.Context, args ...core.Value) (core.Value, error) { 93 return values.None, errors.New("test error") 94 }) 95 96 p, err := c.Compile(` 97 RETURN ERROR()? 98 `) 99 100 So(err, ShouldBeNil) 101 102 out, err := p.Run(context.Background()) 103 104 So(err, ShouldBeNil) 105 106 So(string(out), ShouldEqual, `null`) 107 }) 108 109 Convey("Should handle errors when ? is used within a group", t, func() { 110 c := compiler.New() 111 112 p, err := c.Compile(` 113 RETURN (FALSE OR T::FAIL())? 114 `) 115 116 So(err, ShouldBeNil) 117 118 out, err := p.Run(context.Background()) 119 120 So(err, ShouldBeNil) 121 122 So(string(out), ShouldEqual, `null`) 123 }) 124 125 Convey("Should return NONE when error is handled", t, func() { 126 c := compiler.New() 127 c.RegisterFunction("ERROR", func(ctx context.Context, args ...core.Value) (core.Value, error) { 128 return values.NewString("booo"), errors.New("test error") 129 }) 130 131 p, err := c.Compile(` 132 RETURN ERROR()? 133 `) 134 135 So(err, ShouldBeNil) 136 137 out, err := p.Run(context.Background()) 138 139 So(err, ShouldBeNil) 140 141 So(string(out), ShouldEqual, `null`) 142 }) 143 144 Convey("Should be able to use FOR as an argument", t, func() { 145 c := compiler.New() 146 147 p, err := c.Compile(` 148 RETURN FIRST((FOR i IN 1..10 RETURN i * 2)) 149 `) 150 151 So(err, ShouldBeNil) 152 153 out, err := p.Run(context.Background()) 154 155 So(err, ShouldBeNil) 156 157 So(string(out), ShouldEqual, `2`) 158 }) 159 160 Convey("Should be able to use FOR as arguments", t, func() { 161 c := compiler.New() 162 163 p, err := c.Compile(` 164 RETURN UNION((FOR i IN 0..5 RETURN i), (FOR i IN 6..10 RETURN i)) 165 `) 166 167 So(err, ShouldBeNil) 168 169 out, err := p.Run(context.Background()) 170 171 So(err, ShouldBeNil) 172 173 So(string(out), ShouldEqual, `[0,1,2,3,4,5,6,7,8,9,10]`) 174 }) 175 } 176 177 func BenchmarkFunctionCallArg1(b *testing.B) { 178 c := compiler.New() 179 180 c.RegisterFunction("TEST", func(ctx context.Context, args ...core.Value) (core.Value, error) { 181 return values.None, nil 182 }) 183 184 p := c.MustCompile(` 185 RETURN TYPENAME(1) 186 `) 187 188 for n := 0; n < b.N; n++ { 189 p.Run(context.Background()) 190 } 191 } 192 193 func BenchmarkFunctionCallArg2(b *testing.B) { 194 c := compiler.New() 195 196 c.RegisterFunction("TEST", func(ctx context.Context, args ...core.Value) (core.Value, error) { 197 return values.None, nil 198 }) 199 200 p := c.MustCompile(` 201 RETURN TYPENAME(1, 2) 202 `) 203 204 for n := 0; n < b.N; n++ { 205 p.Run(context.Background()) 206 } 207 } 208 209 func BenchmarkFunctionCallArg3(b *testing.B) { 210 c := compiler.New() 211 212 c.RegisterFunction("TEST", func(ctx context.Context, args ...core.Value) (core.Value, error) { 213 return values.None, nil 214 }) 215 216 p := c.MustCompile(` 217 RETURN TYPENAME(1, 2, 3) 218 `) 219 220 for n := 0; n < b.N; n++ { 221 p.Run(context.Background()) 222 } 223 } 224 225 func BenchmarkFunctionEmpty(b *testing.B) { 226 c := compiler.New() 227 c.RegisterFunction("TEST", func(ctx context.Context, args ...core.Value) (core.Value, error) { 228 return values.None, nil 229 }) 230 231 p := c.MustCompile(` 232 RETURN TEST() 233 `) 234 235 for n := 0; n < b.N; n++ { 236 p.Run(context.Background()) 237 } 238 }