github.com/MontFerret/ferret@v0.18.0/pkg/compiler/compiler_let_test.go (about) 1 package compiler_test 2 3 import ( 4 "context" 5 "testing" 6 7 . "github.com/smartystreets/goconvey/convey" 8 9 "github.com/MontFerret/ferret/pkg/compiler" 10 "github.com/MontFerret/ferret/pkg/runtime" 11 "github.com/MontFerret/ferret/pkg/runtime/core" 12 "github.com/MontFerret/ferret/pkg/runtime/values" 13 ) 14 15 func TestLet(t *testing.T) { 16 Convey("Should compile LET i = NONE RETURN i", t, func() { 17 c := compiler.New() 18 19 p, err := c.Compile(` 20 LET i = NONE 21 RETURN i 22 `) 23 24 So(err, ShouldBeNil) 25 So(p, ShouldHaveSameTypeAs, &runtime.Program{}) 26 27 out, err := p.Run(context.Background()) 28 29 So(err, ShouldBeNil) 30 So(string(out), ShouldEqual, "null") 31 }) 32 33 Convey("Should compile LET i = TRUE RETURN i", t, func() { 34 c := compiler.New() 35 36 p, err := c.Compile(` 37 LET i = TRUE 38 RETURN i 39 `) 40 41 So(err, ShouldBeNil) 42 So(p, ShouldHaveSameTypeAs, &runtime.Program{}) 43 44 out, err := p.Run(context.Background()) 45 46 So(err, ShouldBeNil) 47 So(string(out), ShouldEqual, "true") 48 }) 49 50 Convey("Should compile LET i = 1 RETURN i", t, func() { 51 c := compiler.New() 52 53 p, err := c.Compile(` 54 LET i = 1 55 RETURN i 56 `) 57 58 So(err, ShouldBeNil) 59 So(p, ShouldHaveSameTypeAs, &runtime.Program{}) 60 61 out, err := p.Run(context.Background()) 62 63 So(err, ShouldBeNil) 64 So(string(out), ShouldEqual, "1") 65 }) 66 67 Convey("Should compile LET i = 1.1 RETURN i", t, func() { 68 c := compiler.New() 69 70 p, err := c.Compile(` 71 LET i = 1.1 72 RETURN i 73 `) 74 75 So(err, ShouldBeNil) 76 So(p, ShouldHaveSameTypeAs, &runtime.Program{}) 77 78 out, err := p.Run(context.Background()) 79 80 So(err, ShouldBeNil) 81 So(string(out), ShouldEqual, "1.1") 82 }) 83 84 Convey("Should compile LET i = 'foo' RETURN i", t, func() { 85 c := compiler.New() 86 87 p, err := c.Compile(` 88 LET i = "foo" 89 RETURN i 90 `) 91 92 So(err, ShouldBeNil) 93 So(p, ShouldHaveSameTypeAs, &runtime.Program{}) 94 95 out, err := p.Run(context.Background()) 96 97 So(err, ShouldBeNil) 98 So(string(out), ShouldEqual, "\"foo\"") 99 }) 100 101 Convey("Should compile LET i = [] RETURN i", t, func() { 102 c := compiler.New() 103 104 p, err := c.Compile(` 105 LET i = [] 106 RETURN i 107 `) 108 109 So(err, ShouldBeNil) 110 So(p, ShouldHaveSameTypeAs, &runtime.Program{}) 111 112 out, err := p.Run(context.Background()) 113 114 So(err, ShouldBeNil) 115 So(string(out), ShouldEqual, "[]") 116 }) 117 118 Convey("Should compile LET i = [1, 2, 3] RETURN i", t, func() { 119 c := compiler.New() 120 121 p, err := c.Compile(` 122 LET i = [1, 2, 3] 123 RETURN i 124 `) 125 126 So(err, ShouldBeNil) 127 So(p, ShouldHaveSameTypeAs, &runtime.Program{}) 128 129 out, err := p.Run(context.Background()) 130 131 So(err, ShouldBeNil) 132 So(string(out), ShouldEqual, "[1,2,3]") 133 }) 134 135 Convey("Should compile LET i = {} RETURN i", t, func() { 136 c := compiler.New() 137 138 p, err := c.Compile(` 139 LET i = {} 140 RETURN i 141 `) 142 143 So(err, ShouldBeNil) 144 So(p, ShouldHaveSameTypeAs, &runtime.Program{}) 145 146 out, err := p.Run(context.Background()) 147 148 So(err, ShouldBeNil) 149 So(string(out), ShouldEqual, "{}") 150 }) 151 152 Convey("Should compile LET i = {a: 'foo', b: 1, c: TRUE, d: [], e: {}} RETURN i", t, func() { 153 c := compiler.New() 154 155 p, err := c.Compile(` 156 LET i = {a: 'foo', b: 1, c: TRUE, d: [], e: {}} 157 RETURN i 158 `) 159 160 So(err, ShouldBeNil) 161 So(p, ShouldHaveSameTypeAs, &runtime.Program{}) 162 163 out, err := p.Run(context.Background()) 164 165 So(err, ShouldBeNil) 166 So(string(out), ShouldEqual, "{\"a\":\"foo\",\"b\":1,\"c\":true,\"d\":[],\"e\":{}}") 167 }) 168 169 Convey("Should compile LET i = (FOR i IN [1,2,3] RETURN i) RETURN i", t, func() { 170 c := compiler.New() 171 172 p, err := c.Compile(` 173 LET i = (FOR i IN [1,2,3] RETURN i) 174 RETURN i 175 `) 176 177 So(err, ShouldBeNil) 178 So(p, ShouldHaveSameTypeAs, &runtime.Program{}) 179 180 out, err := p.Run(context.Background()) 181 182 So(err, ShouldBeNil) 183 So(string(out), ShouldEqual, "[1,2,3]") 184 }) 185 186 Convey("Should compile LET src = NONE LET i = (FOR i IN NONE RETURN i)? RETURN i == NONE", t, func() { 187 c := compiler.New() 188 189 p, err := c.Compile(` 190 LET src = NONE 191 LET i = (FOR i IN src RETURN i)? 192 RETURN i == NONE 193 `) 194 195 So(err, ShouldBeNil) 196 So(p, ShouldHaveSameTypeAs, &runtime.Program{}) 197 198 out, err := p.Run(context.Background()) 199 200 So(err, ShouldBeNil) 201 So(string(out), ShouldEqual, "true") 202 }) 203 204 Convey("Should compile LET i = (FOR i WHILE COUNTER() < 5 RETURN i) RETURN i", t, func() { 205 c := compiler.New() 206 counter := -1 207 c.RegisterFunction("COUNTER", func(ctx context.Context, args ...core.Value) (core.Value, error) { 208 counter++ 209 210 return values.NewInt(counter), nil 211 }) 212 213 p, err := c.Compile(` 214 LET i = (FOR i WHILE COUNTER() < 5 RETURN i) 215 RETURN i 216 `) 217 218 So(err, ShouldBeNil) 219 So(p, ShouldHaveSameTypeAs, &runtime.Program{}) 220 221 out, err := p.Run(context.Background()) 222 223 So(err, ShouldBeNil) 224 So(string(out), ShouldEqual, "[0,1,2,3,4]") 225 }) 226 227 Convey("Should compile LET i = (FOR i WHILE COUNTER() < 5 T::FAIL() RETURN i)? RETURN i == NONE", t, func() { 228 c := compiler.New() 229 counter := -1 230 c.RegisterFunction("COUNTER", func(ctx context.Context, args ...core.Value) (core.Value, error) { 231 counter++ 232 233 return values.NewInt(counter), nil 234 }) 235 236 p, err := c.Compile(` 237 LET i = (FOR i WHILE COUNTER() < 5 T::FAIL() RETURN i)? 238 RETURN i == NONE 239 `) 240 241 So(err, ShouldBeNil) 242 So(p, ShouldHaveSameTypeAs, &runtime.Program{}) 243 244 out, err := p.Run(context.Background()) 245 246 So(err, ShouldBeNil) 247 So(string(out), ShouldEqual, "true") 248 }) 249 250 Convey("Should compile LET i = { items: [1,2,3]} FOR el IN i.items RETURN i", t, func() { 251 c := compiler.New() 252 253 p, err := c.Compile(` 254 LET obj = { items: [1,2,3] } 255 256 FOR i IN obj.items 257 RETURN i 258 `) 259 260 So(err, ShouldBeNil) 261 So(p, ShouldHaveSameTypeAs, &runtime.Program{}) 262 263 out, err := p.Run(context.Background()) 264 265 So(err, ShouldBeNil) 266 So(string(out), ShouldEqual, "[1,2,3]") 267 }) 268 269 Convey("Should not compile FOR foo IN foo", t, func() { 270 c := compiler.New() 271 272 _, err := c.Compile(` 273 FOR foo IN foo 274 RETURN foo 275 `) 276 277 So(err, ShouldNotBeNil) 278 }) 279 280 Convey("Should not compile if a variable not defined", t, func() { 281 c := compiler.New() 282 283 _, err := c.Compile(` 284 RETURN foo 285 `) 286 287 So(err, ShouldNotBeNil) 288 }) 289 290 Convey("Should not compile if a variable is not unique", t, func() { 291 c := compiler.New() 292 293 _, err := c.Compile(` 294 LET foo = "bar" 295 LET foo = "baz" 296 297 RETURN foo 298 `) 299 300 So(err, ShouldNotBeNil) 301 }) 302 303 SkipConvey("Should use value returned from WAITFOR EVENT", t, func() { 304 out, err := newCompilerWithObservable().MustCompile(` 305 LET obj = X::VAL("event", ["data"]) 306 307 LET res = (WAITFOR EVENT "event" IN obj) 308 309 RETURN res 310 `).Run(context.Background()) 311 312 So(err, ShouldBeNil) 313 So(string(out), ShouldEqual, `"data"`) 314 }) 315 316 SkipConvey("Should handle error from WAITFOR EVENT", t, func() { 317 out, err := newCompilerWithObservable().MustCompile(` 318 LET obj = X::VAL("foo", ["data"]) 319 320 LET res = (WAITFOR EVENT "event" IN obj TIMEOUT 100)? 321 322 RETURN res == NONE 323 `).Run(context.Background()) 324 325 So(err, ShouldBeNil) 326 So(string(out), ShouldEqual, `true`) 327 }) 328 329 SkipConvey("Should compare result of handled error", t, func() { 330 out, err := newCompilerWithObservable().MustCompile(` 331 LET obj = X::VAL("event", ["foo"], 1000) 332 333 LET res = (WAITFOR EVENT "event" IN obj TIMEOUT 100)? != NONE 334 335 RETURN res 336 `).Run(context.Background()) 337 338 So(err, ShouldBeNil) 339 So(string(out), ShouldEqual, `false`) 340 }) 341 342 Convey("Should use ignorable variable name", t, func() { 343 out, err := newCompilerWithObservable().MustCompile(` 344 LET _ = (FOR i IN 1..100 RETURN NONE) 345 346 RETURN TRUE 347 `).Run(context.Background()) 348 349 So(err, ShouldBeNil) 350 So(string(out), ShouldEqual, `true`) 351 }) 352 353 Convey("Should allow to declare a variable name using _", t, func() { 354 c := compiler.New() 355 356 out, err := c.MustCompile(` 357 LET _ = (FOR i IN 1..100 RETURN NONE) 358 LET _ = (FOR i IN 1..100 RETURN NONE) 359 360 RETURN TRUE 361 `).Run(context.Background()) 362 363 So(err, ShouldBeNil) 364 So(string(out), ShouldEqual, `true`) 365 }) 366 367 Convey("Should not allow to use ignorable variable name", t, func() { 368 c := compiler.New() 369 370 _, err := c.Compile(` 371 LET _ = (FOR i IN 1..100 RETURN NONE) 372 373 RETURN _ 374 `) 375 376 So(err, ShouldNotBeNil) 377 }) 378 }