package dk.silverbullet.telemed.questionnaire.expression; import com.google.gson.annotations.Expose; import dk.silverbullet.telemed.questionnaire.node.AssignmentNode; import dk.silverbullet.telemed.utils.Json; import org.junit.Test; import java.util.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; public class TestExpression { @Test public void testValueSerialisation() { Constant<?> v; v = new Constant<Integer>(124); testReserialisation(Integer.class, v, v.getType(), 124); v = new Constant<Float>(124f); testReserialisation(Float.class, v, v.getType(), 124F); v = new Constant<Long>(123L); testReserialisation(Long.class, v, v.getType(), 123L); v = new Constant<Double>(123.456); testReserialisation(Double.class, v, v.getType(), 123.456); Object[] test = new Integer[] { 1, 2, 4 }; v = new Constant<Integer[]>((Integer[]) test); testReserialisation(Integer[].class, v, v.getType(), (Integer[]) test); test = new String[] { "Her", "er", "en", "test" }; v = new Constant<String[]>((String[]) test); testReserialisation(String[].class, v, v.getType(), (String[]) test); } @SuppressWarnings("unchecked") @Test public void testAddMulSubDiv() throws Exception { // Test evaluating this expression: // (4*a+24)/(b-12) // using integer and double values for variables a and b. Expression<Number> n4 = new Constant<Number>(4); Expression<Number> n24 = new Constant<Number>(24); Expression<Number> n12 = new Constant<Number>(12); Variable<Number> a = new Variable<Number>("A", 42); Variable<Number> b = new Variable<Number>("B", 67); Expression<Number> ex = new DivideExpression<Number>(new AddExpression<Number>(new MultiplyExpression<Number>( n4, a), n24), new SubtractExpression<Number>(b, n12)); System.out.println(ex + "=" + ex.evaluate()); String s = Json.print(ex, Expression.class); System.out.println("*********** JSON Expression for " + ex + ":"); System.out.println(s); ex = (Expression<Number>) Json.parse(s, Expression.class); System.out.println("*********** JSON Expression parsed " + ex); Map<String, Variable<?>> varPool = new HashMap<String, Variable<?>>(); varPool.put(a.getName(), a); varPool.put(b.getName(), b); ex.link(varPool); // Test expression using integers: for (int aValue = 5; aValue < 1000; aValue *= 2) { a.setValue(aValue); for (int bValue = 100; bValue > 21; bValue -= 5) { b.setValue(bValue); assertEquals((4 * aValue + 24) / (bValue - 12), ((Integer) ex.evaluate()).intValue()); } } // Test same unmodified expression using double: for (double aValue = 5.355434345432; aValue < 100; aValue *= 12.34) { a.setValue(aValue); for (double bValue = 32.432; bValue > 21; bValue *= 0.8983) { b.setValue(bValue); assertEquals((4 * aValue + 24) / (bValue - 12), ((Double) ex.evaluate()).doubleValue(), 0); // DELTA? :) } } } @Test public void testVariableLink() throws VariableLinkFailedException { Variable<Integer> poolA = new Variable<Integer>("A", Integer.class); Variable<Integer> a1 = new Variable<Integer>("A", Integer.class); Variable<Integer> a2 = new Variable<Integer>("A", Integer.class); Map<String, Variable<?>> variablePool = new HashMap<String, Variable<?>>(); variablePool.put(poolA.getName(), poolA); Expression<Integer> e = new AddExpression<Integer>(a1, a2); e.link(variablePool); poolA.setValue(new Constant<Integer>(42)); assertEquals(84, e.evaluate().intValue()); } class Blob { @Expose Expression<?> e; } // @Ignore @SuppressWarnings("unchecked") @Test public void testGsonSerialise() { Expression<Integer> n24 = new Constant<Integer>(24); Constant<Integer> n12 = new Constant<Integer>(12); Variable<Integer> v1 = new Variable<Integer>("CoolFactor", Integer.class); Expression<Integer> a = new AddExpression<Integer>(n12, n24); Expression<Integer> s = new SubtractExpression<Integer>(a, v1); // v1.setValue(1000); System.out.println(v1); System.out.println("getValue: " + n12.getValue()); String js = Json.print(s, Expression.class); System.out.println("JS= " + js); Expression<?> e = Json.parse(js, Expression.class); System.out.println(e); System.out.println(); List<Integer> il = new LinkedList<Integer>(); il.add(10); il.add(20); il.add(40); il.add(40); Integer[] ia = new Integer[] { 11, 22, 33 }; String ias = Json.print(ia); System.out.println("JSON array: " + ias); System.out.println("Int array type: " + ia.getClass().getName()); System.out.println(); Constant<Integer[]> v = new Constant<Integer[]>(ia); System.out.println("v=" + v.toString()); System.out.println("v.type=" + v.getType()); js = Json.print(v, Expression.class); System.out.println("int array: " + js); Constant<Integer[]> v0 = (Constant<Integer[]>) Json.parse(js, Expression.class); System.out.println(v0); Integer[] zz = (Integer[]) v0.getValue(); for (Integer integer : zz) { System.out.println(integer); } System.out.println(); System.out.println(Json.print(v1)); System.out.println(Json.print(e)); AssignmentNode<Integer> anode = new AssignmentNode<Integer>(null, null, v1, (Expression<Integer>) e); System.out.println("***********' ASSIGNMENT:"); System.out.println(Json.print(anode)); Blob b = new Blob(); b.e = e; System.out.println("***********' BLOB:"); System.out.println(Json.print(b)); assertTrue(true); } @SuppressWarnings("unchecked") private <T> void testReserialisation(Class<T> expectedClass, Constant<?> v, String typeName, T expectedValue) { typeName = expectedClass.getName().replaceAll(".*\\.", "").replaceAll(";\\z", ""); if (expectedClass.isArray()) typeName += "[]"; assertEquals("Type name check", typeName, v.getType()); assertEquals("Value getValue type check", v.getValue().getClass(), expectedValue.getClass()); if (expectedClass.isArray()) { assertTrue("Array compare", Arrays.equals((T[]) v.getValue(), (T[]) expectedValue)); } else { assertEquals("Value getValue check", v.getValue(), expectedValue); } // Serialise String s = Json.print(v, Expression.class); System.out.println("*** " + s); // ..and de-serialise from the string Constant<?> v2 = (Constant<?>) Json.parse(s, Expression.class); // Re-check the de-serialised value: assertEquals("Type name check", typeName, v2.getType()); assertEquals("Value getValue type check", v2.getValue().getClass(), expectedValue.getClass()); if (expectedClass.isArray()) { assertTrue("Array compare", Arrays.equals((T[]) v2.getValue(), (T[]) expectedValue)); } else { assertEquals("Value getValue check", v2.getValue(), expectedValue); } } }