View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.jexl3;
18  
19  import static org.junit.jupiter.api.Assertions.assertArrayEquals;
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertInstanceOf;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertThrows;
24  import static org.junit.jupiter.api.Assertions.assertTrue;
25  
26  import java.util.Arrays;
27  import java.util.List;
28  import java.util.Set;
29  import java.util.concurrent.Callable;
30  
31  import org.apache.commons.jexl3.internal.Closure;
32  import org.apache.commons.jexl3.internal.Script;
33  import org.junit.jupiter.api.Assertions;
34  import org.junit.jupiter.api.Test;
35  import org.junit.jupiter.params.ParameterizedTest;
36  import org.junit.jupiter.params.provider.CsvSource;
37  
38  /**
39   * Tests function/lambda/closure features.
40   */
41  @SuppressWarnings({"AssertEqualsBetweenInconvertibleTypes"})
42  class LambdaTest extends JexlTestCase {
43  
44      public LambdaTest() {
45          super("LambdaTest");
46      }
47  
48      @Test void test270() {
49          final JexlEngine jexl = createEngine();
50          final JexlScript base = jexl.createScript("(x, y, z)->{ x + y + z }");
51          final String text = base.toString();
52          JexlScript script = base.curry(5, 15);
53          assertEquals(text, script.toString());
54  
55          final JexlContext ctxt = new JexlEvalContext();
56          ctxt.set("s", base);
57          script = jexl.createScript("return s");
58          Object result = script.execute(ctxt);
59          assertEquals(text, result.toString());
60  
61          script = jexl.createScript("return s.curry(1)");
62          result = script.execute(ctxt);
63          assertEquals(text, result.toString());
64      }
65  
66      @Test void test271a() {
67          final JexlEngine jexl = createEngine();
68          final JexlScript base = jexl.createScript("var base = 1; var x = (a)->{ var y = (b) -> {base + b}; return base + y(a)}; x(40)");
69          final Object result = base.execute(null);
70          assertEquals(42, result);
71      }
72  
73      @Test void test271b() {
74          final JexlEngine jexl = createEngine();
75          final JexlScript base = jexl.createScript("var base = 2; var sum = (x, y, z)->{ base + x + y + z }; var y = sum.curry(1); y(2,3)");
76          final Object result = base.execute(null);
77          assertEquals(8, result);
78      }
79  
80      @Test void test271c() {
81          final JexlEngine jexl = createEngine();
82          final JexlScript base = jexl.createScript("(x, y, z)->{ 2 + x + y + z };");
83          final JexlScript y = base.curry(1);
84          final Object result = y.execute(null, 2, 3);
85          assertEquals(8, result);
86      }
87  
88      @Test void test271d() {
89          final JexlEngine jexl = createEngine();
90          final JexlScript base = jexl.createScript("var base = 2; (x, y, z)->base + x + y + z;");
91          final JexlScript y = ((JexlScript) base.execute(null)).curry(1);
92          final Object result = y.execute(null, 2, 3);
93          assertEquals(8, result);
94      }
95  
96      // Redefining a captured var is not resolved correctly in left-hand side;
97      // declare the var in local frame, resolved in local frame instead of parent.
98      @Test void test271e() {
99          final JexlEngine jexl = createEngine();
100         final JexlScript base = jexl.createScript("var base = 1000; var f = (x, y)->{ var base = x + y + (base?:-1000); base; }; f(100, 20)");
101         final Object result = base.execute(null);
102         assertEquals(1120, result);
103     }
104 
105     @Test void test405a() {
106         final JexlEngine jexl = new JexlBuilder()
107             .cache(4).strict(true).safe(false)
108             .create();
109         final String libSrc = "var theFunction = argFn -> { var fn = argFn; fn() }; { 'theFunction' : theFunction }";
110         final String src1 = "var v0 = 42; var v1 = -42; lib.theFunction(()->{ v1 + v0 }) ";
111         final JexlScript libMap = jexl.createScript(libSrc);
112         final Object theLib = libMap.execute(null);
113         final JexlScript f1 = jexl.createScript(src1, "lib");
114         final Object result = f1.execute(null, theLib);
115         assertEquals(0, result);
116     }
117 
118     @Test void test405b() {
119         final JexlEngine jexl = new JexlBuilder()
120             .cache(4).strict(true).safe(false)
121             .create();
122         final String libSrc = "function theFunction(argFn) { var fn = argFn; fn() }; { 'theFunction' : theFunction }";
123         final String src1 = "var v0 = 42; var v1 = -42; lib.theFunction(()->{ v1 + v0 }) ";
124         final JexlScript libMap = jexl.createScript(libSrc);
125         final Object theLib = libMap.execute(null);
126         final JexlScript f1 = jexl.createScript(src1, "lib");
127         final Object result = f1.execute(null, theLib);
128         assertEquals(0, result);
129     }
130 
131     @Test void testCompareLambdaRecurse() throws Exception {
132         final JexlEngine jexl = createEngine();
133         final String factSrc = "function fact(x) { x < 2? 1 : x * fact(x - 1) }";
134         final JexlScript fact0 = jexl.createScript(factSrc);
135         final JexlScript fact1 = jexl.createScript(fact0.toString());
136         assertEquals(fact0, fact1);
137         final Closure r0 = (Closure) fact0.execute(null);
138         final Closure r1 = (Closure) fact1.execute(null);
139         assertEquals(720, r0.execute(null, 6));
140         assertEquals(720, r1.execute(null, 6));
141         assertEquals(r0, r1);
142         assertEquals(r1, r0);
143         // ensure we did not break anything through equals
144         assertEquals(720, r0.execute(null, 6));
145         assertEquals(720, r1.execute(null, 6));
146     }
147 
148     @Test void testCurry1() {
149         final JexlEngine jexl = createEngine();
150         JexlScript script;
151         Object result;
152         String[] parms;
153 
154         final JexlScript base = jexl.createScript("(x, y, z)->{ x + y + z }");
155         parms = base.getUnboundParameters();
156         assertEquals(3, parms.length);
157         script = base.curry(5);
158         parms = script.getUnboundParameters();
159         assertEquals(2, parms.length);
160         script = script.curry(15);
161         parms = script.getUnboundParameters();
162         assertEquals(1, parms.length);
163         script = script.curry(22);
164         parms = script.getUnboundParameters();
165         assertEquals(0, parms.length);
166         result = script.execute(null);
167         assertEquals(42, result);
168     }
169 
170     @Test void testCurry2() {
171         final JexlEngine jexl = createEngine();
172         JexlScript script;
173         Object result;
174         String[] parms;
175 
176         final JexlScript base = jexl.createScript("(x, y, z)->{ x + y + z }");
177         script = base.curry(5, 15);
178         parms = script.getUnboundParameters();
179         assertEquals(1, parms.length);
180         script = script.curry(22);
181         result = script.execute(null);
182         assertEquals(42, result);
183     }
184 
185     @Test void testCurry3() {
186         final JexlEngine jexl = createEngine();
187         JexlScript script;
188         Object result;
189 
190         final JexlScript base = jexl.createScript("(x, y, z)->{ x + y + z }");
191         script = base.curry(5, 15);
192         result = script.execute(null, 22);
193         assertEquals(42, result);
194     }
195 
196     @Test void testCurry4() {
197         final JexlEngine jexl = createEngine();
198         JexlScript script;
199         Object result;
200 
201         final JexlScript base = jexl.createScript("(x, y, z)->{ x + y + z }");
202         script = base.curry(5);
203         result = script.execute(null, 15, 22);
204         assertEquals(42, result);
205     }
206 
207     @Test void testCurry5() {
208         final JexlEngine jexl = createEngine();
209         JexlScript script;
210         Object result;
211 
212         final JexlScript base = jexl.createScript("var t = x + y + z; return t", "x", "y", "z");
213         script = base.curry(5);
214         result = script.execute(null, 15, 22);
215         assertEquals(42, result);
216     }
217 
218     @ParameterizedTest
219     @CsvSource({
220             "'if (false) function foo(x) { x + x }; var foo = 1', 'function'",
221             "'if (false) let foo = (x) -> { x + x }; var foo = 1', 'let'",
222             "'function foo(x) { x + x }; var foo = 42', 'foo'"
223     })
224     void testFailParseFunc(final String src, final String expectedKeyword) {
225         final JexlEngine jexl = createEngine();
226         final JexlException.Parsing xparse = assertThrows(JexlException.Parsing.class, () -> jexl.createScript(src));
227         assertTrue(xparse.getMessage().contains(expectedKeyword));
228     }
229 
230     @Test void testFatFact0() {
231         final JexlFeatures features = new JexlFeatures();
232         features.fatArrow(true);
233         final String src = "function (a) { const fact = x =>{ x <= 1? 1 : x * fact(x - 1) }; fact(a) }";
234         final JexlEngine jexl = createEngine(features);
235         final JexlScript script = jexl.createScript(src);
236         final Object result = script.execute(null, 6);
237         assertEquals(720, result);
238     }
239 
240     @Test void testFatFact1() {
241         final String src = "function (a) { const fact = (x)=> x <= 1? 1 : x * fact(x - 1) ; fact(a) }";
242         final JexlFeatures features = new JexlFeatures();
243         features.fatArrow(true);
244         final JexlEngine jexl = createEngine(features);
245         final JexlScript script = jexl.createScript(src);
246         final Object result = script.execute(null, 6);
247         assertEquals(720, result);
248         features.fatArrow(false);
249         final JexlEngine jexl1 = createEngine(features);
250         final JexlException.Feature xfeature = assertThrows(JexlException.Feature.class, () -> jexl1.createScript(src));
251         assertTrue(xfeature.getMessage().contains("fat-arrow"));
252     }
253 
254     @Test void testHoistLambda() {
255         final JexlEngine jexl = createEngine();
256         final JexlEvalContext ctx = new JexlEvalContext();
257         ctx.getEngineOptions().setLexical(false);
258         JexlScript s42;
259         Object result;
260         JexlScript s15;
261         String[] localv;
262         Set<List<String>> hvars;
263         String strs;
264 
265         // hosted variables are NOT local variables
266         strs = "(x)->{ (y)->{ x + y } }";
267         s42 = jexl.createScript(strs);
268         result = s42.execute(ctx, 15);
269         assertInstanceOf(JexlScript.class, result);
270         s15 = (JexlScript) result;
271         localv = s15.getLocalVariables();
272         assertEquals(0, localv.length);
273         hvars = s15.getVariables();
274         assertEquals(1, hvars.size());
275 
276         // declaring a local that overrides captured
277         // in 3.1, such a local was considered local
278         // per 3.2, this local is considered captured
279         strs = "(x)->{ (y)->{ var z = 169; var x; x + y } }";
280         s42 = jexl.createScript(strs);
281         result = s42.execute(ctx, 15);
282         assertInstanceOf(JexlScript.class, result);
283         s15 = (JexlScript) result;
284         localv = s15.getLocalVariables();
285         assertNotNull(localv);
286         assertEquals(1, localv.length);
287         hvars = s15.getVariables();
288         assertEquals(1, hvars.size());
289         // evidence this is not (strictly) a local since it inherited a captured value
290         result = s15.execute(ctx, 27);
291         assertEquals(42, result);
292     }
293 
294     @Test void testIdentity() {
295         final JexlEngine jexl = createEngine();
296         JexlScript script;
297         Object result;
298 
299         script = jexl.createScript("(x)->{ x }");
300         assertArrayEquals(new String[]{"x"}, script.getParameters());
301         result = script.execute(null, 42);
302         assertEquals(42, result);
303     }
304 
305     @Test void testLambda() {
306         final JexlEngine jexl = createEngine();
307         String strs = "var s = function(x) { x + x }; s(21)";
308         JexlScript s42 = jexl.createScript(strs);
309         Object result = s42.execute(null);
310         assertEquals(42, result);
311         strs = "var s = function(x, y) { x + y }; s(15, 27)";
312         s42 = jexl.createScript(strs);
313         result = s42.execute(null);
314         assertEquals(42, result);
315     }
316 
317     @Test void testLambdaClosure()  {
318         final JexlEngine jexl = createEngine();
319         String strs = "var t = 20; var s = function(x, y) { x + y + t}; s(15, 7)";
320         JexlScript s42 = jexl.createScript(strs);
321         Object result = s42.execute(null);
322         assertEquals(42, result);
323         strs = "var t = 19; var s = function(x, y) { var t = 20; x + y + t}; s(15, 7)";
324         s42 = jexl.createScript(strs);
325         result = s42.execute(null);
326         assertEquals(42, result);
327         strs = "var t = 20; var s = function(x, y) {x + y + t}; t = 54; s(15, 7)";
328         s42 = jexl.createScript(strs);
329         result = s42.execute(null);
330         assertEquals(42, result);
331         strs = "var t = 19; var s = function(x, y) { var t = 20; x + y + t}; t = 54; s(15, 7)";
332         s42 = jexl.createScript(strs);
333         result = s42.execute(null);
334         assertEquals(42, result);
335     }
336 
337     @Test void testLambdaExpr0() {
338         final String src = "(x, y) -> x + y";
339         final JexlEngine jexl = createEngine();
340         final JexlScript script = jexl.createScript(src);
341         final Object result = script.execute(null, 11, 31);
342         assertEquals(42, result);
343     }
344 
345     @Test void testLambdaExpr1() {
346         final String src = "x -> x + x";
347         final JexlEngine jexl = createEngine();
348         final JexlScript script = jexl.createScript(src);
349         final Object result = script.execute(null, 21);
350         assertEquals(42, result);
351     }
352 
353     @Test void testLambdaExpr10() {
354         final String src = "(a)->{ var x = x -> x + x; x(a) }";
355         final JexlEngine jexl = createEngine();
356         final JexlScript script = jexl.createScript(src);
357         final Object result = script.execute(null, 21);
358         assertEquals(42, result);
359     }
360 
361     @Test void testLambdaExpr2() {
362         final String src = "x -> { { x + x } }";
363         final JexlEngine jexl = createEngine();
364         final JexlScript script = jexl.createScript(src);
365         final Object result = script.execute(null, 21);
366         assertInstanceOf(Set.class, result);
367         final Set<?> set = (Set<?>) result;
368         assertEquals(1, set.size());
369         assertTrue(set.contains(42));
370     }
371 
372     @Test void testLambdaExpr3() {
373         final String src = "x -> ( { x + x } )";
374         final JexlEngine jexl = createEngine();
375         final JexlScript script = jexl.createScript(src);
376         final Object result = script.execute(null, 21);
377         assertInstanceOf(Set.class, result);
378         final Set<?> set = (Set<?>) result;
379         assertEquals(1, set.size());
380         assertTrue(set.contains(42));
381     }
382 
383     @Test void testLambdaLambda() {
384         final JexlEngine jexl = createEngine();
385         String strs = "var t = 19; ( (x, y)->{ var t = 20; x + y + t} )(15, 7);";
386         JexlScript s42 = jexl.createScript(strs);
387         Object result = s42.execute(null);
388         assertEquals(42, result);
389 
390         strs = "( (x, y)->{ ( (xx, yy)->{xx + yy } )(x, y) } )(15, 27)";
391         s42 = jexl.createScript(strs);
392         result = s42.execute(null);
393         assertEquals(42, result);
394 
395         strs = "var t = 19; var s = (x, y)->{ var t = 20; x + y + t}; t = 54; s(15, 7)";
396         s42 = jexl.createScript(strs);
397         result = s42.execute(null);
398         assertEquals(42, result);
399     }
400 
401     @Test void testNamedFunc() {
402         final String src = "(let a)->{ function fact(const x) { x <= 1? 1 : x * fact(x - 1); } fact(a); }";
403         final JexlEngine jexl = createEngine();
404         final JexlScript script = jexl.createScript(src);
405         final Object result = script.execute(null, 6);
406         assertEquals(720, result);
407         final String parsed = simpleWhitespace(script.getParsedText());
408         assertEquals(simpleWhitespace(src), parsed);
409     }
410 
411 
412     @Test void testNestLambada() throws Exception {
413         final JexlEngine jexl = createEngine();
414         final String strs = "(x)->{ (y)->{ x + y } }";
415         final JexlScript s42 = jexl.createScript(strs);
416         final JexlScript s42b = jexl.createScript(s42.toString());
417         assertEquals(s42.hashCode(), s42b.hashCode());
418         assertEquals(s42, s42b);
419         Object result = s42.execute(null, 15);
420         assertInstanceOf(JexlScript.class, result);
421         final Object resultb = s42.execute(null, 15);
422         assertEquals(result.hashCode(), resultb.hashCode());
423         assertEquals(result, resultb);
424         assertEquals(result, jexl.createScript(resultb.toString(), "x").execute(null, 15));
425         final JexlScript s15 = (JexlScript) result;
426         final Callable<Object> s15b = s15.callable(null, 27);
427         result = s15.execute(null, 27);
428         assertEquals(42, result);
429         result = s15b.call();
430         assertEquals(42, result);
431     }
432 
433     @Test void testNestLambda() {
434         final JexlEngine jexl = createEngine();
435         final String strs = "( (x)->{ (y)->{ x + y } })(15)(27)";
436         final JexlScript s42 = jexl.createScript(strs);
437         final Object result = s42.execute(null);
438         assertEquals(42, result);
439     }
440 
441     @Test void testRecurse() {
442         final JexlEngine jexl = createEngine();
443         final JexlContext jc = new MapContext();
444         final JexlScript script = jexl.createScript("var fact = (x)->{ if (x <= 1) 1; else x * fact(x - 1) }; fact(5)");
445         final int result = (Integer) script.execute(jc);
446         assertEquals(120, result);
447     }
448 
449     @Test void testRecurse1() {
450         final JexlEngine jexl = createEngine();
451         final JexlContext jc = new MapContext();
452         final String src = "var fact = (x)-> x <= 1? 1 : x * fact(x - 1);\nfact(5);\n";
453         final JexlScript script = jexl.createScript(src);
454         final int result = (Integer) script.execute(jc);
455         assertEquals(120, result);
456         final String parsed = script.getParsedText();
457         assertEquals(src, parsed);
458     }
459 
460     @Test void testRecurse2() {
461         final JexlEngine jexl = createEngine();
462         final JexlContext jc = new MapContext();
463         // adding some captured vars to get it confused
464         final JexlScript script = jexl.createScript(
465                 "var y = 1; var z = 1; "
466                 +"var fact = (x)->{ if (x <= y) z; else x * fact(x - 1) }; fact(6)");
467         final int result = (Integer) script.execute(jc);
468         assertEquals(720, result);
469     }
470 
471     @Test void testRecurse2b() {
472         final JexlEngine jexl = createEngine();
473         final JexlContext jc = new MapContext();
474         // adding some captured vars to get it confused
475         final JexlScript fact = jexl.createScript(
476                 "var y = 1; var z = 1; "
477                         +"var fact = (x)->{ if (x <= y) z; else x * fact(x - 1) };" +
478                         "fact");
479         final Script func = (Script) fact.execute(jc);
480         final String[] captured = func.getCapturedVariables();
481         assertEquals(3, captured.length);
482         assertTrue(Arrays.asList(captured).containsAll(Arrays.asList("z", "y", "fact")));
483         final int result = (Integer) func.execute(jc, 6);
484         assertEquals(720, result);
485     }
486 
487     @Test void testRecurse3() {
488         final JexlEngine jexl = createEngine();
489         final JexlContext jc = new MapContext();
490         // adding some captured vars to get it confused
491         final JexlScript script = jexl.createScript(
492                 "var y = 1; var z = 1;var foo = (x)->{y + z}; "
493                 +"var fact = (x)->{ if (x <= y) z; else x * fact(x - 1) }; fact(6)");
494         final int result = (Integer) script.execute(jc);
495         assertEquals(720, result);
496     }
497 
498     @Test void testScriptArguments() {
499         final JexlEngine jexl = createEngine();
500         final JexlScript s = jexl.createScript(" x + x ", "x");
501         final JexlScript s42 = jexl.createScript("s(21)", "s");
502         final Object result = s42.execute(null, s);
503         assertEquals(42, result);
504     }
505 
506     @Test void testScriptContext() {
507         final JexlEngine jexl = createEngine();
508         final JexlScript s = jexl.createScript("function(x) { x + x }");
509         final String fsstr = s.getParsedText(0);
510         assertEquals("(x)->{ x + x; }", fsstr);
511         assertEquals(42, s.execute(null, 21));
512         JexlScript s42 = jexl.createScript("s(21)");
513         final JexlContext ctxt = new JexlEvalContext();
514         ctxt.set("s", s);
515         Object result = s42.execute(ctxt);
516         assertEquals(42, result);
517         result = s42.execute(ctxt);
518         assertEquals(42, result);
519         s42 = jexl.createScript("x-> { x + x }");
520         result = s42.execute(ctxt, 21);
521         assertEquals(42, result);
522     }
523 
524     /**
525      * see JEXL-426
526      */
527     @Test void testRefCapture1() {
528         final String src = "let x = 10;\n" +
529                 "let foo = () -> {\n" +
530                 "x += 2;\n" +
531                 "}\n" +
532                 "x = 40;\n" +
533                 "foo();\n" +
534                 "x";
535         final JexlEngine jexl = new JexlBuilder()
536                 .features(new JexlFeatures().referenceCapture(true))
537                 .create();
538         JexlScript script;
539         Object result;
540         script = jexl.createScript(src);
541         result = script.execute(null);
542         assertEquals(42, result);
543     }
544 
545     @Test void testRefCapture2() {
546         final String src = "let x = 10; let f = () -> { x + 2 }; x = 40; f()";
547         final JexlEngine jexl = new JexlBuilder()
548                 .features(new JexlFeatures().constCapture(true).referenceCapture(true))
549                 .create();
550         JexlScript script;
551         Object result;
552         script = jexl.createScript(src);
553         result = script.execute(null);
554         assertEquals(42, result);
555     }
556 
557     @Test void testRefCapture3() {
558         final String src = "let x = 10; let f = () -> { x + 2 }; x = 40; f";
559         final JexlEngine jexl = new JexlBuilder()
560                 .features(new JexlFeatures().constCapture(true).referenceCapture(true))
561                 .create();
562         JexlScript script;
563         Object result;
564         script = jexl.createScript(src);
565         result = script.execute(null);
566         assertInstanceOf(JexlScript.class, result);
567         script = jexl.createScript("f()", "f");
568         result = script.execute(null, result);
569         assertEquals(42, result);
570     }
571 
572     @Test void testRefCapture4() {
573         final String src = "let x = 10; let f = () -> { let x = 142; x }; x = 40; f";
574         final JexlEngine jexl = new JexlBuilder()
575                 .features(new JexlFeatures().referenceCapture(true))
576                 .create();
577         JexlScript script;
578         Object result;
579         script = jexl.createScript(src);
580         result = script.execute(null);
581         assertInstanceOf(JexlScript.class, result);
582         script = jexl.createScript("f()", "f");
583         result = script.execute(null, result);
584         assertEquals(142, result);
585     }
586 
587     @Test void testRefCapture5() {
588         final JexlFeatures f426 = new JexlFeatures().referenceCapture(true);
589         final JexlEngine jexl = new JexlBuilder().features(f426).create();
590         final String src = "let z = 32; let x = 40; function foo() { x += 2; }; function bar() { let x = -169; foo(); x;}; bar();";
591         final JexlScript script = jexl.createScript(src);
592         assertNotNull(script);
593         final Object result = script.execute(null);
594         Assertions.assertEquals(-169, result);
595     }
596 
597     @Test void testRefCapture6() {
598         final JexlFeatures f426 = new JexlFeatures().referenceCapture(true);
599         final JexlEngine jexl = new JexlBuilder().features(f426).create();
600         final String src = "let x = 40; function foo() { x += 2; }; function bar() { x = -169; () -> { foo(); }}; bar();";
601         JexlScript script = jexl.createScript(src);
602         assertNotNull(script);
603         Object result = script.execute(null);
604         assertInstanceOf(JexlScript.class, result);
605         script = jexl.createScript("f()", "f");
606         result = script.execute(null, result);
607         Assertions.assertEquals(-167, result);
608     }
609 }