1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jexl3;
18
19 import java.io.IOException;
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.Collection;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Collections;
26 import java.util.concurrent.atomic.AtomicInteger;
27
28 import org.apache.commons.jexl3.jexl342.OptionalArithmetic;
29 import org.apache.commons.jexl3.junit.Asserter;
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.junit.Assert;
33 import org.junit.Before;
34 import org.junit.Test;
35
36
37
38
39
40
41
42 @SuppressWarnings({"UnnecessaryBoxing", "AssertEqualsBetweenInconvertibleTypes"})
43 public class SideEffectTest extends JexlTestCase {
44
45 private Asserter asserter;
46
47 public SideEffectTest() {
48 super("SideEffectTest");
49 }
50
51 @Override
52 @Before
53 public void setUp() {
54 asserter = new Asserter(JEXL);
55 }
56
57 @Test
58 public void testSideEffectVar() throws Exception {
59 final Map<String,Object> context = asserter.getVariables();
60 final Integer i41 = Integer.valueOf(4141);
61 final Object foo = i41;
62
63 context.put("foo", foo);
64 asserter.assertExpression("foo += 2", i41 + 2);
65 Assert.assertEquals(context.get("foo"), i41 + 2);
66
67 context.put("foo", foo);
68 asserter.assertExpression("foo -= 2", i41 - 2);
69 Assert.assertEquals(context.get("foo"), i41 - 2);
70
71 context.put("foo", foo);
72 asserter.assertExpression("foo *= 2", i41 * 2);
73 Assert.assertEquals(context.get("foo"), i41 * 2);
74
75 context.put("foo", foo);
76 asserter.assertExpression("foo /= 2", i41 / 2);
77 Assert.assertEquals(context.get("foo"), i41 / 2);
78
79 context.put("foo", foo);
80 asserter.assertExpression("foo %= 2", i41 % 2);
81 Assert.assertEquals(context.get("foo"), i41 % 2);
82
83 context.put("foo", foo);
84 asserter.assertExpression("foo &= 3", (long) (i41 & 3));
85 Assert.assertEquals(context.get("foo"), (long)(i41 & 3));
86
87 context.put("foo", foo);
88 asserter.assertExpression("foo |= 2", (long)(i41 | 2));
89 Assert.assertEquals(context.get("foo"), (long)(i41 | 2));
90
91 context.put("foo", foo);
92 asserter.assertExpression("foo ^= 2", (long)(i41 ^ 2));
93 Assert.assertEquals(context.get("foo"), (long)(i41 ^ 2));
94
95 context.put("foo", foo);
96 asserter.assertExpression("foo <<= 2", (long)(i41 << 2));
97 Assert.assertEquals(context.get("foo"), (long)(i41 << 2));
98
99 context.put("foo", foo);
100 asserter.assertExpression("foo >>= 2", (long)(i41 >> 2));
101 Assert.assertEquals(context.get("foo"), (long)(i41 >> 2));
102
103 context.put("foo", foo);
104 asserter.assertExpression("foo >>>= 2", (long)(i41 >>> 2));
105 Assert.assertEquals(context.get("foo"), (long)(i41 >>> 2));
106 }
107
108 @Test
109 public void testSideEffectVarDots() throws Exception {
110 final Map<String,Object> context = asserter.getVariables();
111 final Integer i41 = Integer.valueOf(4141);
112 final Object foo = i41;
113
114 context.put("foo.bar.quux", foo);
115 asserter.assertExpression("foo.bar.quux += 2", i41 + 2);
116 Assert.assertEquals(context.get("foo.bar.quux"), i41 + 2);
117
118 context.put("foo.bar.quux", foo);
119 asserter.assertExpression("foo.bar.quux -= 2", i41 - 2);
120 Assert.assertEquals(context.get("foo.bar.quux"), i41 - 2);
121
122 context.put("foo.bar.quux", foo);
123 asserter.assertExpression("foo.bar.quux *= 2", i41 * 2);
124 Assert.assertEquals(context.get("foo.bar.quux"), i41 * 2);
125
126 context.put("foo.bar.quux", foo);
127 asserter.assertExpression("foo.bar.quux /= 2", i41 / 2);
128 Assert.assertEquals(context.get("foo.bar.quux"), i41 / 2);
129
130 context.put("foo.bar.quux", foo);
131 asserter.assertExpression("foo.bar.quux %= 2", i41 % 2);
132 Assert.assertEquals(context.get("foo.bar.quux"), i41 % 2);
133
134 context.put("foo.bar.quux", foo);
135 asserter.assertExpression("foo.bar.quux &= 3", (long) (i41 & 3));
136 Assert.assertEquals(context.get("foo.bar.quux"), (long)(i41 & 3));
137
138 context.put("foo.bar.quux", foo);
139 asserter.assertExpression("foo.bar.quux |= 2", (long)(i41 | 2));
140 Assert.assertEquals(context.get("foo.bar.quux"), (long)(i41 | 2));
141
142 context.put("foo.bar.quux", foo);
143 asserter.assertExpression("foo.bar.quux ^= 2", (long)(i41 ^ 2));
144 Assert.assertEquals(context.get("foo.bar.quux"), (long)(i41 ^ 2));
145 }
146
147 @Test
148 public void testSideEffectArray() throws Exception {
149 final Integer i41 = Integer.valueOf(4141);
150 final Integer i42 = Integer.valueOf(42);
151 final Integer i43 = Integer.valueOf(43);
152 final String s42 = "fourty-two";
153 final String s43 = "fourty-three";
154 final Object[] foo = new Object[3];
155 foo[1] = i42;
156 foo[2] = i43;
157 asserter.setVariable("foo", foo);
158 foo[0] = i41;
159 asserter.assertExpression("foo[0] += 2", i41 + 2);
160 Assert.assertEquals(foo[0], i41 + 2);
161 foo[0] = i41;
162 asserter.assertExpression("foo[0] -= 2", i41 - 2);
163 Assert.assertEquals(foo[0], i41 - 2);
164 foo[0] = i41;
165 asserter.assertExpression("foo[0] *= 2", i41 * 2);
166 Assert.assertEquals(foo[0], i41 * 2);
167 foo[0] = i41;
168 asserter.assertExpression("foo[0] /= 2", i41 / 2);
169 Assert.assertEquals(foo[0], i41 / 2);
170 foo[0] = i41;
171 asserter.assertExpression("foo[0] %= 2", i41 % 2);
172 Assert.assertEquals(foo[0], i41 % 2);
173 foo[0] = i41;
174 asserter.assertExpression("foo[0] &= 3", (long) (i41 & 3));
175 Assert.assertEquals(foo[0], (long)(i41 & 3));
176 foo[0] = i41;
177 asserter.assertExpression("foo[0] |= 2", (long)(i41 | 2));
178 Assert.assertEquals(foo[0], (long)(i41 | 2));
179 foo[0] = i41;
180 asserter.assertExpression("foo[0] ^= 2", (long)(i41 ^ 2));
181 Assert.assertEquals(foo[0], (long)(i41 ^ 2));
182 }
183
184 @Test
185 public void testSideEffectDotArray() throws Exception {
186 final Integer i41 = Integer.valueOf(4141);
187 final Integer i42 = Integer.valueOf(42);
188 final Integer i43 = Integer.valueOf(43);
189 final String s42 = "fourty-two";
190 final String s43 = "fourty-three";
191 final Object[] foo = new Object[3];
192 foo[1] = i42;
193 foo[2] = i43;
194 asserter.setVariable("foo", foo);
195 foo[0] = i41;
196 asserter.assertExpression("foo.0 += 2", i41 + 2);
197 Assert.assertEquals(foo[0], i41 + 2);
198 foo[0] = i41;
199 asserter.assertExpression("foo.0 -= 2", i41 - 2);
200 Assert.assertEquals(foo[0], i41 - 2);
201 foo[0] = i41;
202 asserter.assertExpression("foo.0 *= 2", i41 * 2);
203 Assert.assertEquals(foo[0], i41 * 2);
204 foo[0] = i41;
205 asserter.assertExpression("foo.0 /= 2", i41 / 2);
206 Assert.assertEquals(foo[0], i41 / 2);
207 foo[0] = i41;
208 asserter.assertExpression("foo.0 %= 2", i41 % 2);
209 Assert.assertEquals(foo[0], i41 % 2);
210 foo[0] = i41;
211 asserter.assertExpression("foo.0 &= 3", (long) (i41 & 3));
212 Assert.assertEquals(foo[0], (long)(i41 & 3));
213 foo[0] = i41;
214 asserter.assertExpression("foo.0 |= 2", (long)(i41 | 2));
215 Assert.assertEquals(foo[0], (long)(i41 | 2));
216 foo[0] = i41;
217 asserter.assertExpression("foo.0 ^= 2", (long)(i41 ^ 2));
218 Assert.assertEquals(foo[0], (long)(i41 ^ 2));
219 }
220
221 @Test
222 public void testSideEffectAntishArray() throws Exception {
223 final Integer i41 = Integer.valueOf(4141);
224 final Integer i42 = Integer.valueOf(42);
225 final Integer i43 = Integer.valueOf(43);
226 final Object[] foo = new Object[3];
227 foo[1] = i42;
228 foo[2] = i43;
229 asserter.setVariable("foo.bar", foo);
230 foo[0] = i41;
231 asserter.assertExpression("foo.bar[0] += 2", i41 + 2);
232 Assert.assertEquals(foo[0], i41 + 2);
233 foo[0] = i41;
234 asserter.assertExpression("foo.bar[0] -= 2", i41 - 2);
235 Assert.assertEquals(foo[0], i41 - 2);
236 foo[0] = i41;
237 asserter.assertExpression("foo.bar[0] *= 2", i41 * 2);
238 Assert.assertEquals(foo[0], i41 * 2);
239 foo[0] = i41;
240 asserter.assertExpression("foo.bar[0] /= 2", i41 / 2);
241 Assert.assertEquals(foo[0], i41 / 2);
242 foo[0] = i41;
243 asserter.assertExpression("foo.bar[0] %= 2", i41 % 2);
244 Assert.assertEquals(foo[0], i41 % 2);
245 foo[0] = i41;
246 asserter.assertExpression("foo.bar[0] &= 3", (long) (i41 & 3));
247 Assert.assertEquals(foo[0], (long)(i41 & 3));
248 foo[0] = i41;
249 asserter.assertExpression("foo.bar[0] |= 2", (long)(i41 | 2));
250 Assert.assertEquals(foo[0], (long)(i41 | 2));
251 foo[0] = i41;
252 asserter.assertExpression("foo.bar[0] ^= 2", (long)(i41 ^ 2));
253 Assert.assertEquals(foo[0], (long)(i41 ^ 2));
254 }
255
256 public static class Foo {
257 int value;
258 Foo(final int v) {
259 value = v;
260 }
261
262 @Override
263 public String toString() {
264 return Integer.toString(value);
265 }
266
267 public void setValue(final long v) {
268 value = (int) v;
269 }
270 public int getValue() {
271 return value;
272 }
273
274 public void setBar(final int x, final long v) {
275 value = (int) v + x;
276 }
277
278 public int getBar(final int x) {
279 return value + x;
280 }
281 }
282
283 @Test
284 public void testSideEffectBean() throws Exception {
285 final Integer i41 = Integer.valueOf(4141);
286 final Foo foo = new Foo(0);
287 asserter.setVariable("foo", foo);
288 foo.value = i41;
289 asserter.assertExpression("foo.value += 2", i41 + 2);
290 Assert.assertEquals(foo.value, i41 + 2);
291 foo.value = i41;
292 asserter.assertExpression("foo.value -= 2", i41 - 2);
293 Assert.assertEquals(foo.value, i41 - 2);
294 foo.value = i41;
295 asserter.assertExpression("foo.value *= 2", i41 * 2);
296 Assert.assertEquals(foo.value, i41 * 2);
297 foo.value = i41;
298 asserter.assertExpression("foo.value /= 2", i41 / 2);
299 Assert.assertEquals(foo.value, i41 / 2);
300 foo.value = i41;
301 asserter.assertExpression("foo.value %= 2", i41 % 2);
302 Assert.assertEquals(foo.value, i41 % 2);
303 foo.value = i41;
304 asserter.assertExpression("foo.value &= 3", (long) (i41 & 3));
305 Assert.assertEquals(foo.value, i41 & 3);
306 foo.value = i41;
307 asserter.assertExpression("foo.value |= 2", (long)(i41 | 2));
308 Assert.assertEquals(foo.value, i41 | 2);
309 foo.value = i41;
310 asserter.assertExpression("foo.value ^= 2", (long)(i41 ^ 2));
311 Assert.assertEquals(foo.value, i41 ^ 2);
312 }
313
314 @Test
315 public void testSideEffectBeanContainer() throws Exception {
316 final Integer i41 = Integer.valueOf(4141);
317 final Foo foo = new Foo(0);
318 asserter.setVariable("foo", foo);
319 foo.value = i41;
320 asserter.assertExpression("foo.bar[0] += 2", i41 + 2);
321 Assert.assertEquals(foo.value, i41 + 2);
322 foo.value = i41;
323 asserter.assertExpression("foo.bar[1] += 2", i41 + 3);
324 Assert.assertEquals(foo.value, i41 + 4);
325 foo.value = i41;
326 asserter.assertExpression("foo.bar[0] -= 2", i41 - 2);
327 Assert.assertEquals(foo.value, i41 - 2);
328 foo.value = i41;
329 asserter.assertExpression("foo.bar[0] *= 2", i41 * 2);
330 Assert.assertEquals(foo.value, i41 * 2);
331 foo.value = i41;
332 asserter.assertExpression("foo.bar[0] /= 2", i41 / 2);
333 Assert.assertEquals(foo.value, i41 / 2);
334 foo.value = i41;
335 asserter.assertExpression("foo.bar[0] %= 2", i41 % 2);
336 Assert.assertEquals(foo.value, i41 % 2);
337 foo.value = i41;
338 asserter.assertExpression("foo.bar[0] &= 3", (long) (i41 & 3));
339 Assert.assertEquals(foo.value, i41 & 3);
340 foo.value = i41;
341 asserter.assertExpression("foo.bar[0] |= 2", (long)(i41 | 2));
342 Assert.assertEquals(foo.value, i41 | 2);
343 foo.value = i41;
344 asserter.assertExpression("foo.bar[0] ^= 2", (long)(i41 ^ 2));
345 Assert.assertEquals(foo.value, i41 ^ 2);
346 }
347
348 @Test
349 public void testArithmeticSelf() throws Exception {
350 final JexlEngine jexl = new JexlBuilder().cache(64).arithmetic(new SelfArithmetic(false)).create();
351 final JexlContext jc = null;
352 runSelfOverload(jexl, jc);
353 runSelfOverload(jexl, jc);
354 }
355
356 @Test
357 public void testArithmeticSelfNoCache() throws Exception {
358 final JexlEngine jexl = new JexlBuilder().cache(0).arithmetic(new SelfArithmetic(false)).create();
359 final JexlContext jc = null;
360 runSelfOverload(jexl, jc);
361 }
362
363 protected void runSelfOverload(final JexlEngine jexl, final JexlContext jc) {
364 JexlScript script;
365 Object result;
366 script = jexl.createScript("(x, y)->{ x += y }");
367 result = script.execute(jc, 3115, 15);
368 Assert.assertEquals(3115 + 15, result);
369 final Var v0 = new Var(3115);
370 result = script.execute(jc, v0, new Var(15));
371 Assert.assertEquals(result, v0);
372 Assert.assertEquals(3115 + 15, v0.value);
373
374 script = jexl.createScript("(x, y)->{ x -= y}");
375 result = script.execute(jc, 3115, 15);
376 Assert.assertEquals(3115 - 15, result);
377 final Var v1 = new Var(3115);
378 result = script.execute(jc, v1, new Var(15));
379 Assert.assertNotEquals(result, v1);
380 Assert.assertEquals(3115 - 15, ((Var) result).value);
381
382 script = jexl.createScript("(x, y)->{ x *= y }");
383 result = script.execute(jc, 3115, 15);
384 Assert.assertEquals(3115 * 15, result);
385 final Var v2 = new Var(3115);
386 result = script.execute(jc, v2, new Var(15));
387 Assert.assertEquals(result, v2);
388 Assert.assertEquals(3115 * 15, v2.value);
389
390 script = jexl.createScript("(x, y)->{ x /= y }");
391 result = script.execute(jc, 3115, 15);
392 Assert.assertEquals(3115 / 15, result);
393 final Var v3 = new Var(3115);
394 result = script.execute(jc, v3, new Var(15));
395 Assert.assertEquals(result, v3);
396 Assert.assertEquals(3115 / 15, v3.value);
397
398 script = jexl.createScript("(x, y)->{ x %= y }");
399 result = script.execute(jc, 3115, 15);
400 Assert.assertEquals(3115 % 15, result);
401 final Var v4 = new Var(3115);
402 result = script.execute(jc, v4, new Var(15));
403 Assert.assertEquals(result, v4);
404 Assert.assertEquals(3115 % 15, v4.value);
405
406 script = jexl.createScript("(x, y)->{ x &= y }");
407 result = script.execute(jc, 3115, 15);
408 Assert.assertEquals(3115L & 15, result);
409 final Var v5 = new Var(3115);
410 result = script.execute(jc, v5, new Var(15));
411 Assert.assertEquals(result, v5);
412 Assert.assertEquals(3115 & 15, v5.value);
413
414 script = jexl.createScript("(x, y)->{ x |= y }");
415 result = script.execute(jc, 3115, 15);
416 Assert.assertEquals(3115L | 15, result);
417 final Var v6 = new Var(3115);
418 result = script.execute(jc, v6, new Var(15));
419 Assert.assertEquals(result, v6);
420 Assert.assertEquals(3115L | 15, v6.value);
421
422 script = jexl.createScript("(x, y)->{ x ^= y }");
423 result = script.execute(jc, 3115, 15);
424 Assert.assertEquals(3115L ^ 15, result);
425 final Var v7 = new Var(3115);
426 result = script.execute(jc, v7, new Var(15));
427 Assert.assertEquals(result, v7);
428 Assert.assertEquals(3115L ^ 15, v7.value);
429
430 script = jexl.createScript("(x, y)->{ x >>>= y }");
431 result = script.execute(jc, 234453115, 5);
432 Assert.assertEquals(234453115L >>> 5, result);
433 final Var v8 = new Var(234453115);
434 result = script.execute(jc, v8, 5);
435 Assert.assertEquals(result, v8);
436 Assert.assertEquals(234453115L >>> 5, v8.value);
437
438 script = jexl.createScript("(x, y)->{ x >>= y }");
439 result = script.execute(jc, 435566788L, 7);
440 Assert.assertEquals(435566788L >> 7, result);
441 final Var v9 = new Var(435566788);
442 result = script.execute(jc, v9, 7);
443 Assert.assertEquals(result, v9);
444 Assert.assertEquals(435566788L >> 7, v9.value);
445
446 script = jexl.createScript("(x, y)->{ x <<= y }");
447 result = script.execute(jc, 3115, 2);
448 Assert.assertEquals(3115L << 2, result);
449 final Var v10 = new Var(3115);
450 result = script.execute(jc, v10, 2);
451 Assert.assertEquals(result, v10);
452 Assert.assertEquals(3115L << 2, v10.value);
453 }
454
455
456 @Test
457 public void testIncrementSelf() throws Exception {
458 final JexlEngine jexl = new JexlBuilder().cache(64).arithmetic(new SelfArithmetic(false)).create();
459 final JexlContext jc = null;
460 runSelfIncrement(jexl, jc);
461 runSelfIncrement(jexl, jc);
462 }
463
464 @Test
465 public void testIncrementSelfNoCache() throws Exception {
466 final JexlEngine jexl = new JexlBuilder().cache(0).arithmetic(new SelfArithmetic(false)).create();
467 final JexlContext jc = null;
468 runSelfIncrement(jexl, jc);
469 }
470
471 protected void runSelfIncrement(final JexlEngine jexl, final JexlContext jc) {
472 JexlScript script = jexl.createScript("x -> [+x, +(x++), +x]");
473 final Var v11 = new Var(3115);
474 final AtomicInteger i11 = new AtomicInteger(3115);
475 for(Object v : Arrays.asList(v11, i11)) {
476 Object result = script.execute(jc, v);
477 Assert.assertTrue(result instanceof int[]);
478 int[] r = (int[]) result;
479 Assert.assertEquals(3115, r[0]);
480 Assert.assertEquals(3115, r[1]);
481 Assert.assertEquals(3116, r[2]);
482 }
483
484 script = jexl.createScript("x -> [+x, +(++x), +x]");
485 final Var v12 = new Var(3189);
486 final AtomicInteger i12 = new AtomicInteger(3189);
487 for(Object v : Arrays.asList(v12, i12)) {
488 Object result = script.execute(jc, v);
489 Assert.assertTrue(result instanceof int[]);
490 int[] r = (int[]) result;
491 Assert.assertEquals(3189, r[0]);
492 Assert.assertEquals(3190, r[1]);
493 Assert.assertEquals(3190, r[2]);
494 }
495
496 script = jexl.createScript("x -> [+x, +(x--), +x]");
497 final Var v13 = new Var(3115);
498 for(Object v : Arrays.asList(v13)) {
499 Object result = script.execute(jc, v13);
500 Assert.assertTrue(result instanceof int[]);
501 int[] r = (int[]) result;
502 Assert.assertEquals(3115, r[0]);
503 Assert.assertEquals(3115, r[1]);
504 Assert.assertEquals(3114, r[2]);
505 }
506
507 script = jexl.createScript("x -> [+x, +(--x), +x]");
508 final Var v14 = new Var(3189);
509 for(Object v : Arrays.asList(v14)) {
510 Object result = script.execute(jc, v);
511 Assert.assertTrue(result instanceof int[]);
512 int[] r = (int[]) result;
513 Assert.assertEquals(3189, r[0]);
514 Assert.assertEquals(3188, r[1]);
515 Assert.assertEquals(3188, r[2]);
516 }
517 }
518
519 @Test
520 public void testOverrideGetSet() throws Exception {
521 final JexlEngine jexl = new JexlBuilder().cache(64).arithmetic(new SelfArithmetic(false)).create();
522 final JexlContext jc = null;
523
524 JexlScript script;
525 Object result;
526 final Var v0 = new Var(3115);
527 script = jexl.createScript("(x)->{ x.value}");
528 result = script.execute(jc, v0);
529 Assert.assertEquals(3115, result);
530 script = jexl.createScript("(x)->{ x['VALUE']}");
531 result = script.execute(jc, v0);
532 Assert.assertEquals(3115, result);
533 script = jexl.createScript("(x,y)->{ x.value = y}");
534 result = script.execute(jc, v0, 42);
535 Assert.assertEquals(42, result);
536 script = jexl.createScript("(x,y)->{ x['VALUE'] = y}");
537 result = script.execute(jc, v0, 169);
538 Assert.assertEquals(169, result);
539 }
540
541 public static class Var {
542 int value;
543
544 Var(final int v) {
545 value = v;
546 }
547
548 @Override public String toString() {
549 return Integer.toString(value);
550 }
551 }
552
553
554 public static class SelfArithmetic extends OptionalArithmetic {
555 public SelfArithmetic(final boolean strict) {
556 super(strict);
557 }
558
559 public Object propertyGet(final Var var, final String property) {
560 return "value".equals(property)? var.value : JexlEngine.TRY_FAILED;
561 }
562
563 public Object propertySet(final Var var, final String property, final int v) {
564 return "value".equals(property)? var.value = v : JexlEngine.TRY_FAILED;
565 }
566
567 public Object arrayGet(final Var var, final String property) {
568 return "VALUE".equals(property)? var.value : JexlEngine.TRY_FAILED;
569 }
570
571 public Object arraySet(final Var var, final String property, final int v) {
572 return "VALUE".equals(property)? var.value = v : JexlEngine.TRY_FAILED;
573 }
574
575 public Var selfAdd(final Var lhs, final Var rhs) {
576 lhs.value += rhs.value;
577 return lhs;
578 }
579
580
581 public Var selfSubtract(final Var lhs, final Var rhs) {
582 return new Var(lhs.value - rhs.value);
583 }
584
585 public Var selfDivide(final Var lhs, final Var rhs) {
586 lhs.value /= rhs.value;
587 return lhs;
588 }
589
590 public Var selfMultiply(final Var lhs, final Var rhs) {
591 lhs.value *= rhs.value;
592 return lhs;
593 }
594
595 public Var selfMod(final Var lhs, final Var rhs) {
596 lhs.value %= rhs.value;
597 return lhs;
598 }
599
600 public Var and(final Var lhs, final Var rhs) {
601 return new Var(lhs.value & rhs.value);
602 }
603
604 public Var selfAnd(final Var lhs, final Var rhs) {
605 lhs.value &= rhs.value;
606 return lhs;
607 }
608
609 public Var or(final Var lhs, final Var rhs) {
610 return new Var(lhs.value | rhs.value);
611 }
612
613 public Var selfOr(final Var lhs, final Var rhs) {
614 lhs.value |= rhs.value;
615 return lhs;
616 }
617
618 public Var xor(final Var lhs, final Var rhs) {
619 return new Var(lhs.value ^ rhs.value);
620 }
621
622 public Var selfXor(final Var lhs, final Var rhs) {
623 lhs.value ^= rhs.value;
624 return lhs;
625 }
626
627 public Var shiftLeft(final Var lhs, final int rhs) {
628 return new Var(lhs.value << rhs);
629 }
630
631 public Var selfShiftLeft(final Var lhs, final int rhs) {
632 lhs.value <<= rhs;
633 return lhs;
634 }
635
636 public Var shiftRight(final Var lhs, final int rhs) {
637 return new Var(lhs.value >> rhs);
638 }
639
640 public Var selfShiftRight(final Var lhs, final int rhs) {
641 lhs.value >>= rhs;
642 return lhs;
643 }
644
645 public Var shiftRightUnsigned(final Var lhs, final int rhs) {
646 return new Var(lhs.value >>> rhs);
647 }
648
649 public Var selfShiftRightUnsigned(final Var lhs, final int rhs) {
650 lhs.value >>>= rhs;
651 return lhs;
652 }
653
654 public int increment(final Var lhs) {
655 return lhs.value + 1;
656 }
657
658 public int decrement(final Var lhs) {
659 return lhs.value - 1;
660 }
661
662 public int incrementAndGet(AtomicInteger i) {
663 return i.incrementAndGet();
664 }
665
666 public int getAndIncrement(AtomicInteger i) {
667 return i.getAndIncrement();
668 }
669
670 public int positivize(Var n) {
671 return n.value;
672 }
673
674 public int positivize(Number n) {
675 return n.intValue();
676 }
677 }
678
679
680
681
682 public static class Arithmetic246 extends JexlArithmetic {
683 public Arithmetic246(final boolean astrict) {
684 super(astrict);
685 }
686
687 public Object selfAdd(final Collection<String> c, final String item) throws IOException {
688 c.add(item);
689 return c;
690 }
691
692 public Object selfAdd(final Appendable c, final String item) throws IOException {
693 c.append(item);
694 return c;
695 }
696
697 @Override
698 public Object add(final Object right, final Object left) {
699 return super.add(left, right);
700 }
701 }
702
703 public static class Arithmetic246b extends Arithmetic246 {
704 public Arithmetic246b(final boolean astrict) {
705 super(astrict);
706 }
707
708 public Object selfAdd(final Object c, final String item) throws IOException {
709 if (c == null) {
710 return new ArrayList<>(Collections.singletonList(item));
711 }
712 if (c instanceof Appendable) {
713 ((Appendable) c).append(item);
714 return c;
715 }
716 return JexlEngine.TRY_FAILED;
717 }
718 }
719
720 @Test
721 public void test246() throws Exception {
722 run246(new Arithmetic246(true));
723 }
724
725 @Test
726 public void test246b() throws Exception {
727 run246(new Arithmetic246b(true));
728 }
729
730 private void run246(final JexlArithmetic j246) throws Exception {
731 final Log log246 = LogFactory.getLog(SideEffectTest.class);
732
733 final java.util.logging.Logger ll246 = java.util.logging.LogManager.getLogManager().getLogger(SideEffectTest.class.getName());
734
735 final JexlEngine jexl = new JexlBuilder().arithmetic(j246).cache(32).debug(true).logger(log246).create();
736 final JexlScript script = jexl.createScript("z += x", "x");
737 final MapContext ctx = new MapContext();
738 List<String> z = new ArrayList<>(1);
739
740
741 ctx.set("z", z);
742 Object zz = script.execute(ctx, "42");
743 Assert.assertSame(zz, z);
744 Assert.assertEquals(1, z.size());
745 z.clear();
746
747 boolean t246 = false;
748
749 try {
750 script.execute(ctx, "42");
751 zz = ctx.get("z");
752 Assert.assertTrue(zz instanceof List<?>);
753 z = (List<String>) zz;
754 Assert.assertEquals(1, z.size());
755 } catch(JexlException | ArithmeticException xjexl) {
756 t246 = true;
757 Assert.assertEquals(j246.getClass(), Arithmetic246.class);
758 }
759 ctx.clear();
760
761
762 ctx.set("z", z);
763 zz = script.execute(ctx, "-42");
764 Assert.assertSame(zz, z);
765 Assert.assertEquals(t246? 1 : 2, z.size());
766 }
767
768
769 public static class Arithmetic248 extends JexlArithmetic {
770 public Arithmetic248(final boolean strict) {
771 super(strict);
772 }
773
774 public Object arrayGet(final List<?> list, final Collection<Integer> range) {
775 final List<Object> rl = new ArrayList<>(range.size());
776 for(final int i : range) {
777 rl.add(list.get(i));
778 }
779 return rl;
780 }
781
782 public Object arraySet(final List<Object> list, final Collection<Integer> range, final Object value) {
783 for(final int i : range) {
784 list.set(i, value);
785 }
786 return list;
787 }
788 }
789
790 @Test
791 public void test248() throws Exception {
792 final MapContext ctx = new MapContext();
793 final List<Object> foo = new ArrayList<>(Arrays.asList(10, 20, 30, 40));
794 ctx.set("foo", foo);
795
796 final JexlEngine engine = new JexlBuilder().arithmetic(new Arithmetic248(true)).create();
797 final JexlScript foo12 = engine.createScript("foo[1..2]");
798 try {
799 final Object r = foo12.execute(ctx);
800 Assert.assertEquals(Arrays.asList(20, 30), r);
801 } catch (final JexlException xp) {
802 Assert.assertTrue(xp instanceof JexlException.Property);
803 }
804
805 final JexlScript foo12assign = engine.createScript("foo[1..2] = x", "x");
806 try {
807 final Object r = foo12assign.execute(ctx, 25);
808 Assert.assertEquals(25, r);
809 Assert.assertEquals(Arrays.asList(10, 25, 25, 40), foo);
810 } catch (final JexlException xp) {
811 Assert.assertTrue(xp instanceof JexlException.Property);
812 }
813 }
814
815 }