1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 package org.spf4j.zel.vm;
33
34 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
35 import java.io.ByteArrayOutputStream;
36 import java.io.PrintStream;
37 import java.io.UnsupportedEncodingException;
38 import java.math.BigInteger;
39 import java.nio.charset.StandardCharsets;
40 import java.util.concurrent.ExecutionException;
41 import java.util.concurrent.ExecutorService;
42 import java.util.concurrent.Executors;
43 import org.junit.Assert;
44 import org.junit.Test;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48
49
50
51
52 @SuppressFBWarnings("HES_LOCAL_EXECUTOR_SERVICE")
53 public final class ZelTest {
54
55 private static final Logger LOG = LoggerFactory.getLogger(ZelTest.class);
56
57 @Test
58 public void helloWorld()
59 throws CompileException, ExecutionException, InterruptedException, UnsupportedEncodingException {
60 ByteArrayOutputStream bos = new ByteArrayOutputStream();
61 Program.compile("out(\"Hello World\")").execute(new ProcessIOStreams(System.in,
62 new PrintStream(bos, true, StandardCharsets.UTF_8.toString()), System.err));
63 Assert.assertEquals("Hello World", new String(bos.toByteArray(), StandardCharsets.UTF_8));
64 }
65
66 @Test
67 public void testBasicArithmetic()
68 throws CompileException, ExecutionException, InterruptedException {
69 Program prog = Program.compile("// simple expression \n 1+5*4/(1+1)");
70 Number result = (Number) prog.execute();
71 Assert.assertEquals(11, result.intValue());
72 }
73
74 @Test
75 public void testJavaExec()
76 throws CompileException, ExecutionException, InterruptedException {
77 Program prog = Program.compile("a.toString().substring(0, 1 + 1)", "a");
78 String result = (String) prog.execute(Integer.valueOf(100));
79 Assert.assertEquals("100".substring(0, 2), result);
80 }
81
82 @Test
83 public void testJavaExecStatic()
84 throws CompileException, ExecutionException, InterruptedException {
85 Program prog = Program.compile("format(\"Number %d\", 3)", "format");
86 String result = (String) prog.execute(new JavaMethodCall(String.class, "format"));
87 Assert.assertEquals(String.format("Number %d", 3), result);
88 }
89
90 @Test
91 public void testAssignement()
92 throws CompileException, ExecutionException, InterruptedException {
93 Program prog = Program.compile("a = a + 1", "a");
94 Integer result = (Integer) prog.execute(100);
95 Assert.assertEquals(101, result.intValue());
96 }
97
98 @Test
99 public void testFib()
100 throws CompileException, ExecutionException, InterruptedException {
101 String program
102 = "function deterministic fib (x) { fib(x-1) + fib(x-2) };\n"
103 + "fib(0) = 0;\n"
104 + "fib(1) = 1;\n"
105 + "val1 = fib(100);\n"
106 + "val2 = fib(200);\n"
107 + "val3 = fib(1000);\n"
108 + "val = val1 + val2;"
109 + "out(\"fib(50)=\", fib(50));"
110 + "out(val3);"
111 + "val2";
112
113 Program compiledProgram = Program.compile(program);
114 LOG.debug("Program = {}", compiledProgram);
115 Number result = (Number) compiledProgram.execute();
116 Assert.assertEquals(new BigInteger("280571172992510140037611932413038677189525"), result);
117 }
118
119 public BigInteger fibB(final int i) {
120 if (i <= 1) {
121 return BigInteger.valueOf(i);
122 } else {
123 return fibB(i - 1).add(fibB(i - 2));
124 }
125 }
126
127 public long fib(final long i) {
128 if (i <= 1) {
129 return i;
130 } else {
131 return fib(i - 1) + fib(i - 2);
132 }
133 }
134
135 public BigInteger fibBNr(final int i) {
136 if (i <= 1) {
137 return BigInteger.valueOf(i);
138 } else {
139 BigInteger v1 = BigInteger.ZERO;
140 BigInteger v2 = BigInteger.ONE;
141 BigInteger tmp;
142 for (int j = 2; j <= i; j++) {
143 tmp = v2;
144 v2 = v1.add(v2);
145 v1 = tmp;
146 }
147 return v2;
148 }
149 }
150
151 @Test
152 public void testFibPerformance() throws CompileException, ExecutionException, InterruptedException {
153 String fib = "func det fib (x) {fib(x-1) + fib(x-2)}; fib(0) = 0; fib(1) = 1; fib(x)";
154 Program fibZel = Program.compile(fib, "x");
155 long startTime = System.currentTimeMillis();
156 Number zelResult = (Number) fibZel.execute(40);
157 long intTime = System.currentTimeMillis();
158 long javaResult = fib(40);
159 long stopTime = System.currentTimeMillis();
160 Assert.assertEquals(zelResult.longValue(), javaResult);
161 LOG.debug("zel exec {}", (intTime - startTime));
162 LOG.debug("java exec {}", (stopTime - intTime));
163
164 startTime = System.currentTimeMillis();
165 BigInteger zelResult2 = (BigInteger) fibZel.execute(10000);
166 intTime = System.currentTimeMillis();
167 BigInteger javaResult2 = fibBNr(10000);
168 stopTime = System.currentTimeMillis();
169 LOG.debug("fib(10000) = {}", zelResult2);
170 LOG.debug("fib(10000) = {}", javaResult2);
171 Assert.assertEquals(zelResult2, javaResult2);
172 LOG.debug("zel exec {}", (intTime - startTime));
173 LOG.debug("java exec {}", (stopTime - intTime));
174 }
175
176 @Test
177 public void testParallelism() throws CompileException, ExecutionException, InterruptedException {
178 String program = "f1 = func {sleep 5000; 1};"
179 + "f2 = func {sleep 5000; 2};"
180 + "f1() + f2()";
181 Program prog = Program.compile(program);
182 LOG.debug("Program = {}", prog);
183 long startTime = System.currentTimeMillis();
184 Number result = (Number) prog.execute();
185 long endTime = System.currentTimeMillis();
186 Assert.assertEquals(3, result.intValue());
187 Assert.assertTrue("functions need to execute in parallel not in " + (endTime - startTime),
188 endTime - startTime < 5200);
189 }
190
191 @Test
192 public void testParallelism2() throws CompileException, ExecutionException, InterruptedException {
193 String program = "f1 = func {sleep 5000; 1};"
194 + "f2 = func {sleep 5000; 2};"
195 + "f1() + f2()";
196 Program prog = Program.compile(program);
197 LOG.debug("Program = {}", prog);
198 long startTime = System.currentTimeMillis();
199 Number result = (Number) prog.execute(Executors.newSingleThreadExecutor());
200 long endTime = System.currentTimeMillis();
201 Assert.assertEquals(3, result.intValue());
202 Assert.assertTrue("functions need to execute in parallel not in " + (endTime - startTime),
203 endTime - startTime < 5200);
204 }
205
206 @Test
207 @SuppressFBWarnings("PRMC_POSSIBLY_REDUNDANT_METHOD_CALLS")
208 public void testCond() throws CompileException, ExecutionException, InterruptedException {
209 Boolean result = (Boolean) Program.compile("x == 1", "x").execute(1);
210 Assert.assertTrue(result);
211 result = (Boolean) Program.compile("x != 1", "x").execute(1);
212 Assert.assertFalse(result);
213 result = (Boolean) Program.compile("x < 1", "x").execute(1);
214 Assert.assertFalse(result);
215 result = (Boolean) Program.compile("x >= 1", "x").execute(1);
216 Assert.assertTrue(result);
217 result = (Boolean) Program.compile("x <= 1", "x").execute(1);
218 Assert.assertTrue(result);
219 result = (Boolean) Program.compile("x > 1", "x").execute(1);
220 Assert.assertFalse(result);
221 Number n = (Number) Program.compile("min(3, 1, 8)").execute();
222 Assert.assertEquals(1, n.intValue());
223 n = (Number) Program.compile("max(3, 1, 8, 10)").execute();
224 Assert.assertEquals(10, n.intValue());
225 n = (Number) Program.compile("sqrt(4)").execute();
226 Assert.assertEquals(2, n.intValue());
227 n = (Number) Program.compile("log(E)").execute();
228 Assert.assertEquals(1, n.intValue());
229
230 }
231
232 @Test
233 public void testAsync() throws CompileException, ExecutionException, InterruptedException {
234 String prog = "f = func (a, b) {sleep 1000; a + b };"
235 + "f(f(1, 2),f(3, 4))";
236 ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(8);
237 long startTime = System.currentTimeMillis();
238 Number result = (Number) Program.compile(prog).execute(newFixedThreadPool);
239 long elapsed = System.currentTimeMillis() - startTime;
240 LOG.debug("Elapsed = {} ms", elapsed);
241
242 Assert.assertEquals(10, result.intValue());
243 newFixedThreadPool.shutdown();
244 }
245
246 @SuppressFBWarnings("MDM_THREAD_YIELD")
247 private static class TestF {
248
249 public static int f(final int a, final int b) throws InterruptedException {
250 Thread.sleep(1000);
251 return a + b;
252 }
253 }
254
255 @Test
256 public void testAsync2() throws CompileException, ExecutionException, InterruptedException {
257 ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(8);
258 String prog = "f(f(1, 2)&,f(3, 4)&)&";
259 long startTime = System.currentTimeMillis();
260 Number result = (Number) Program.compile(prog, "f")
261 .execute(newFixedThreadPool, new JavaMethodCall(TestF.class, "f"));
262 long elapsed = System.currentTimeMillis() - startTime;
263 LOG.debug("Elapsed = {} ms", elapsed);
264
265 Assert.assertEquals(10, result.intValue());
266 newFixedThreadPool.shutdown();
267 }
268
269 @Test
270 public void testArrays() throws CompileException, ExecutionException, InterruptedException {
271 String result = (String) Program.compile("x.split(\",\")[1]", "x").execute("a,b,c");
272 Assert.assertEquals("b", result);
273 result = (String) Program.compile("x.split(\",\")[1] = \"A\"", "x").execute("a,b,c");
274 Assert.assertEquals("A", result);
275 }
276
277 @Test
278 public void testCond2() throws CompileException, ExecutionException, InterruptedException {
279 Program p = Program.compile("x >= 0 ? \"positive\" : \"negative\" ", "x");
280 LOG.debug("Program = {}", p);
281 String result = (String) p.execute(1);
282 Assert.assertEquals("positive", result);
283 }
284
285 @Test
286 public void testCond3() throws CompileException, ExecutionException, InterruptedException {
287 Program p = Program.compile(" if x >= 0 { \"positive\" } else { \"negative\" } ", "x");
288 LOG.debug("Program = {}", p);
289 String result = (String) p.execute(1);
290 Assert.assertEquals("positive", result);
291 }
292
293 @Test
294 public void testFor() throws CompileException, ExecutionException, InterruptedException {
295 Program p = Program.compile("x = 0; for i=0; i < 10; i++ {out(i); x = x + i}; x ");
296 LOG.debug("Program = {}", p.toAssemblyString());
297 Integer result = (Integer) p.execute(1);
298 Assert.assertEquals(45, result.intValue());
299 }
300
301 @Test
302 @SuppressFBWarnings("SACM_STATIC_ARRAY_CREATED_IN_METHOD")
303 public void testSwap() throws CompileException, ExecutionException, InterruptedException {
304 Program p = Program.compile("x[0] <-> x[1]; x[1]", "x");
305 LOG.debug("Program = {}", p);
306 String[] testArray = new String[]{"a", "b"};
307 String result = (String) p.execute(new Object[]{testArray});
308 Assert.assertEquals("a", result);
309 }
310
311 @Test
312 public void testArray() throws CompileException, ExecutionException, InterruptedException {
313 Program p = Program.compile("x = array(2); x.length");
314 LOG.debug("Program = {}", p);
315 Integer result = (Integer) p.execute();
316 Assert.assertEquals(2, result.intValue());
317 }
318
319 @Test
320 public void testMultiRet() throws CompileException, ExecutionException, InterruptedException {
321 Program p = Program.compile("func test {"
322 + "ret {1, 2} };"
323 + "x,y = test();"
324 + "out(y); ret x");
325 LOG.debug("Program = {}", p);
326 Integer result = (Integer) p.execute();
327 Assert.assertEquals(1, result.intValue());
328 }
329
330 @Test
331 public void testMultiAssignement() throws CompileException, ExecutionException, InterruptedException {
332 Program p = Program.compile("x, y, z = {1, 2, 3}; ret y");
333 LOG.debug("Program = {}", p.toAssemblyString());
334 Integer result = (Integer) p.execute();
335 Assert.assertEquals(2, result.intValue());
336 }
337
338 @Test
339 public void testAbs() throws CompileException, ExecutionException, InterruptedException {
340 Program p = Program.compile("|3 - 5|");
341 LOG.debug("Program = {}", p);
342 Integer result = (Integer) p.execute();
343 Assert.assertEquals(2, result.intValue());
344 }
345
346 @Test
347 public void testDecode() throws CompileException, ExecutionException, InterruptedException {
348 Program p = Program.compile("decode(1+1, 3, 0, 1, -1, 2, 666, 777)");
349 LOG.debug("Program = {}", p);
350 Integer result = (Integer) p.execute();
351 Assert.assertEquals(666, result.intValue());
352 }
353
354 @Test
355 public void testDecode2() throws CompileException, ExecutionException, InterruptedException {
356 Program p = Program.compile("decode(1+1, 3, 0, 1, -1, 100, 666, 777)");
357 LOG.debug("Program = {}", p);
358 Integer result = (Integer) p.execute();
359 Assert.assertEquals(777, result.intValue());
360 }
361
362 @Test
363 public void testType() throws CompileException, ExecutionException, InterruptedException {
364 Program p = Program.compile("" + Long.MAX_VALUE);
365 LOG.debug("Program = {}", p);
366 Long result = (Long) p.execute();
367 Assert.assertEquals(Long.MAX_VALUE, result.longValue());
368 }
369
370 @Test
371 public void testOverflow() throws CompileException, ExecutionException, InterruptedException {
372 Program p = Program.compile("" + Long.MAX_VALUE + " + " + 1);
373 LOG.debug("Program = {}", p);
374 BigInteger result = (BigInteger) p.execute();
375 Assert.assertEquals(BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE),
376 result);
377 }
378
379 @Test
380 public void testOverflow2() throws CompileException, ExecutionException, InterruptedException {
381 Program p = Program.compile("" + Long.MIN_VALUE + " - " + 1);
382 LOG.debug("Program = {}", p);
383 BigInteger result = (BigInteger) p.execute();
384 Assert.assertEquals(BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.ONE),
385 result);
386 }
387
388 @Test
389 public void testOverflow3() throws CompileException, ExecutionException, InterruptedException {
390 Program p = Program.compile("" + Long.MIN_VALUE + " - " + Long.MAX_VALUE);
391 LOG.debug("Program = {}", p);
392 BigInteger result = (BigInteger) p.execute();
393 Assert.assertEquals(BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.valueOf(Long.MAX_VALUE)),
394 result);
395 }
396
397 }