/** * Copyright (C) 2010 dennis zhuang (killme2008@gmail.com) * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * **/ package com.googlecode.aviator.code.asm; import static org.junit.Assert.*; import java.lang.reflect.InvocationTargetException; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.junit.Before; import org.junit.Test; import com.googlecode.aviator.Expression; import com.googlecode.aviator.lexer.token.NumberToken; import com.googlecode.aviator.lexer.token.OperatorType; import com.googlecode.aviator.lexer.token.PatternToken; import com.googlecode.aviator.lexer.token.StringToken; import com.googlecode.aviator.lexer.token.Variable; import com.googlecode.aviator.parser.AviatorClassLoader; public class ASMCodeGeneratorUnitTest { private ASMCodeGenerator codeGenerator; @Before public void setUp() { final AviatorClassLoader classloader = AccessController.doPrivileged(new PrivilegedAction<AviatorClassLoader>() { public AviatorClassLoader run() { return new AviatorClassLoader(Thread.currentThread().getContextClassLoader()); } }); this.codeGenerator = new ASMCodeGenerator(classloader,System.out, true); this.codeGenerator.start(); } @Test public void testOnConstant_Nil() throws Exception { this.codeGenerator.onConstant(Variable.NIL); Expression exp = this.codeGenerator.getResult(); Object result = exp.execute(); assertNull(result); } @Test public void testOnConstant_Long() throws Exception { this.codeGenerator.onConstant(new NumberToken(3L, "3")); Expression exp = this.codeGenerator.getResult(); Object result = exp.execute(); assertEquals(3L, result); } @Test public void testOnConstant_Double() throws Exception { this.codeGenerator.onConstant(new NumberToken(3.3D, "3.3")); Expression exp = this.codeGenerator.getResult(); Object result = exp.execute(); assertEquals(3.3D, result); } @Test public void testOnConstant_Boolean_False() throws Exception { this.codeGenerator.onConstant(Variable.FALSE); Expression exp = this.codeGenerator.getResult(); Object result = exp.execute(); assertEquals(Boolean.FALSE, result); } @Test public void testOnConstant_Boolean_True() throws Exception { this.codeGenerator.onConstant(Variable.TRUE); Expression exp = this.codeGenerator.getResult(); Object result = exp.execute(); assertEquals(Boolean.TRUE, result); } @Test public void testOnConstant_String() throws Exception { this.codeGenerator.onConstant(new StringToken("hello", 0)); Expression exp = this.codeGenerator.getResult(); Object result = exp.execute(); assertEquals("hello", result); } @Test public void testOnConstant_Pattern() throws Exception { this.codeGenerator.onConstant(new PatternToken("[a-z_A-Z]+", 0)); Expression exp = this.codeGenerator.getResult(); Object result = exp.execute(); assertEquals("/[a-z_A-Z]+/", result); } @Test public void testOnConstant_Variable() throws Exception { this.codeGenerator.onConstant(new Variable("a", 0)); Expression exp = this.codeGenerator.getResult(); HashMap<String, Object> env = new HashMap<String, Object>(); long now = System.currentTimeMillis(); env.put("a", now); Object result = exp.execute(env); assertEquals(now, result); } @Test public void testOnAdd() throws Exception { this.doArithOpTest(OperatorType.ADD); } @Test public void testOnSub() throws Exception { this.doArithOpTest(OperatorType.SUB); } @Test public void testOnMult() throws Exception { this.doArithOpTest(OperatorType.MULT); } @Test public void testOnDiv() throws Exception { this.doArithOpTest(OperatorType.DIV); } @Test public void testOnMod() throws Exception { this.doArithOpTest(OperatorType.MOD); } @Test public void testOnBitAnd() throws Exception { this.doArithOpTest(OperatorType.BIT_AND); } @Test public void testOnBitOr() throws Exception { this.doArithOpTest(OperatorType.BIT_OR); } @Test public void testOnBitXor() throws Exception { this.doArithOpTest(OperatorType.BIT_XOR); } @Test public void testOnShiftLeft() throws Exception { this.doArithOpTest(OperatorType.SHIFT_LEFT); } @Test public void testOnShiftRight() throws Exception { this.doArithOpTest(OperatorType.SHIFT_RIGHT); } @Test public void testOnUnsignedShiftRight() throws Exception { this.doArithOpTest(OperatorType.U_SHIFT_RIGHT); } public void doArithOpTest(OperatorType operatorType) throws Exception { NumberToken a = new NumberToken(3L, "3"); NumberToken b = new NumberToken(3.5d, "3.5"); Map<String, Object> env = new HashMap<String, Object>(); env.put("c", 9L); this.codeGenerator.onConstant(new Variable("c", 0)); this.codeGenerator.onConstant(a); this.codeGenerator.onConstant(b); switch (operatorType) { case ADD: this.codeGenerator.onAdd(null); this.codeGenerator.onAdd(null); Object result = this.eval(env); assertEquals(15.5, (Double) result, 0.001); break; case SUB: this.codeGenerator.onSub(null); this.codeGenerator.onSub(null); result = this.eval(env); assertEquals(9.5, (Double) result, 0.001); break; case MULT: this.codeGenerator.onMult(null); this.codeGenerator.onMult(null); result = this.eval(env); assertEquals(94.5, (Double) result, 0.001); break; case DIV: this.codeGenerator.onDiv(null); this.codeGenerator.onDiv(null); result = this.eval(env); assertEquals(10.50, (Double) result, 0.001); break; case MOD: this.codeGenerator.onMod(null); this.codeGenerator.onMod(null); result = this.eval(env); assertEquals(0.0, (Double) result, 0.001); break; } } public void doBitOpTests(OperatorType operatorType) throws Exception { NumberToken a = new NumberToken(99L, "3"); NumberToken b = new NumberToken(2, "2"); Map<String, Object> env = new HashMap<String, Object>(); env.put("c", 9L); this.codeGenerator.onConstant(new Variable("c", 7)); this.codeGenerator.onConstant(a); this.codeGenerator.onConstant(b); switch (operatorType) { case BIT_OR: this.codeGenerator.onBitOr(null); this.codeGenerator.onBitOr(null); Object result = this.eval(env); assertEquals(7 | 3 | 2, result); break; case BIT_AND: this.codeGenerator.onBitAnd(null); this.codeGenerator.onBitAnd(null); result = this.eval(env); assertEquals(7 & 3 & 2, result); break; case BIT_XOR: this.codeGenerator.onBitXor(null); this.codeGenerator.onBitXor(null); result = this.eval(env); assertEquals(7 ^ 3 ^ 2, result); break; case SHIFT_LEFT: this.codeGenerator.onShiftLeft(null); this.codeGenerator.onShiftLeft(null); result = this.eval(env); assertEquals(7 << 3 << 2, result); break; case SHIFT_RIGHT: this.codeGenerator.onShiftRight(null); this.codeGenerator.onShiftRight(null); result = this.eval(env); assertEquals(7 >> 3 >> 2, result); break; case U_SHIFT_RIGHT: this.codeGenerator.onUnsignedShiftRight(null); this.codeGenerator.onUnsignedShiftRight(null); result = this.eval(env); assertEquals(7 >>> 3 >>> 2, result); break; } } private Object eval(Map<String, Object> env) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Expression exp = this.codeGenerator.getResult(); return exp.execute(env); } @Test public void testOnAnd_False() throws Exception { this.codeGenerator.onConstant(Variable.TRUE); this.codeGenerator.onAndLeft(null); this.codeGenerator.onConstant(Variable.FALSE); this.codeGenerator.onAndRight(null); Object result = this.eval(new HashMap<String, Object>()); assertEquals(Boolean.FALSE, result); } @Test public void testOnAnd_True() throws Exception { this.codeGenerator.onConstant(Variable.TRUE); this.codeGenerator.onAndLeft(null); this.codeGenerator.onConstant(Variable.TRUE); this.codeGenerator.onAndRight(null); Object result = this.eval(new HashMap<String, Object>()); assertEquals(Boolean.TRUE, result); } @Test public void testOnJoin_True() throws Exception { this.codeGenerator.onConstant(Variable.TRUE); this.codeGenerator.onJoinLeft(null); this.codeGenerator.onConstant(Variable.FALSE); this.codeGenerator.onJoinRight(null); Object result = this.eval(new HashMap<String, Object>()); assertEquals(Boolean.TRUE, result); } @Test public void testOnJoin_False() throws Exception { this.codeGenerator.onConstant(Variable.FALSE); this.codeGenerator.onJoinLeft(null); this.codeGenerator.onConstant(Variable.FALSE); this.codeGenerator.onJoinRight(null); Object result = this.eval(new HashMap<String, Object>()); assertEquals(Boolean.FALSE, result); } @Test public void testOnNot_True() throws Exception { this.codeGenerator.onConstant(Variable.FALSE); this.codeGenerator.onNot(null); Object result = this.eval(new HashMap<String, Object>()); assertEquals(Boolean.TRUE, result); } @Test public void testOnNot_False() throws Exception { this.codeGenerator.onConstant(Variable.TRUE); this.codeGenerator.onNot(null); Object result = this.eval(new HashMap<String, Object>()); assertEquals(Boolean.FALSE, result); } @Test public void testOnNeg_Long() throws Exception { this.codeGenerator.onConstant(new NumberToken(3L, "3")); this.codeGenerator.onNeg(null); Object result = this.eval(new HashMap<String, Object>()); assertEquals(-3L, result); } @Test public void testOnBitNot1() throws Exception { this.codeGenerator.onConstant(new NumberToken(-3L, "-3")); this.codeGenerator.onBitNot(null); Object result = this.eval(new HashMap<String, Object>()); assertEquals(2, result); } @Test public void testOnBitNot2() throws Exception { this.codeGenerator.onConstant(new NumberToken(3L, "3")); this.codeGenerator.onBitNot(null); Object result = this.eval(new HashMap<String, Object>()); assertEquals(-4L, result); } @Test public void testOnNeg_Double() throws Exception { this.codeGenerator.onConstant(new NumberToken(-3.3d, "-3.3")); this.codeGenerator.onNeg(null); Object result = this.eval(new HashMap<String, Object>()); assertEquals(3.3, result); } @Test public void testOnEq() throws Exception { this.doLogicOpTest(OperatorType.EQ); } @Test public void testOnNeq() throws Exception { this.doLogicOpTest(OperatorType.NEQ); } @Test public void testOnGt() throws Exception { this.doLogicOpTest(OperatorType.GT); } @Test public void testOnGe() throws Exception { this.doLogicOpTest(OperatorType.GE); } @Test public void testOnLt() throws Exception { this.doLogicOpTest(OperatorType.LT); } @Test public void testOnLe() throws Exception { this.doLogicOpTest(OperatorType.LE); } public void doLogicOpTest(OperatorType operatorType) throws Exception { NumberToken a = new NumberToken(3L, "3"); NumberToken b = new NumberToken(3L, "3"); Map<String, Object> env = new HashMap<String, Object>(); env.put("c", 9L); switch (operatorType) { case EQ: this.codeGenerator.onConstant(a); this.codeGenerator.onConstant(b); this.codeGenerator.onEq(null); Object result = this.eval(env); assertEquals(Boolean.TRUE, result); break; case NEQ: this.codeGenerator.onConstant(a); this.codeGenerator.onConstant(b); this.codeGenerator.onNeq(null); result = this.eval(env); assertEquals(Boolean.FALSE, result); break; case GT: this.codeGenerator.onConstant(a); this.codeGenerator.onConstant(b); this.codeGenerator.onGt(null); result = this.eval(env); assertEquals(Boolean.FALSE, result); break; case GE: this.codeGenerator.onConstant(a); this.codeGenerator.onConstant(b); this.codeGenerator.onGe(null); result = this.eval(env); assertEquals(Boolean.TRUE, result); break; case LT: this.codeGenerator.onConstant(a); this.codeGenerator.onConstant(new Variable("c", 0)); this.codeGenerator.onLt(null); result = this.eval(env); assertEquals(Boolean.TRUE, result); break; case LE: this.codeGenerator.onConstant(a); this.codeGenerator.onConstant(b); this.codeGenerator.onLe(null); result = this.eval(env); assertEquals(Boolean.TRUE, result); break; } } @Test public void testOnMatch() throws Exception { this.codeGenerator.onConstant(new StringToken("killme2008@gmail.com", 0)); this.codeGenerator.onConstant(new PatternToken("^[\\w\\-]([\\.\\w])+[\\w]+@([\\w\\-]+\\.)+[a-z]{2,4}$", 1)); this.codeGenerator.onMatch(null); Object result = this.eval(new HashMap<String, Object>()); assertEquals(Boolean.TRUE, result); } @Test public void testOnMethod_withoutArguments() throws Exception { this.codeGenerator.onMethodName(new Variable("sysdate", -1)); this.codeGenerator.onMethodInvoke(null); Object result = this.eval(new HashMap<String, Object>()); assertNotNull(result); assertTrue(result instanceof Date); } @Test public void testOnMethod_withTwoArguments() throws Exception { this.codeGenerator.onMethodName(new Variable("string.substring", -1)); this.codeGenerator.onConstant(new StringToken("hello", -1)); this.codeGenerator.onMethodParameter(null); this.codeGenerator.onConstant(new NumberToken(2L, "2")); this.codeGenerator.onMethodParameter(null); this.codeGenerator.onConstant(new NumberToken(5L, "5")); this.codeGenerator.onMethodParameter(null); this.codeGenerator.onMethodInvoke(null); Object result = this.eval(new HashMap<String, Object>()); assertEquals("llo", result); } }