/* * Copyright (c) 2010, SQL Power Group Inc. */ package ca.sqlpower.dao; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.Random; import java.util.concurrent.CountDownLatch; import junit.framework.TestCase; import ca.sqlpower.dao.SPPersistenceException; import ca.sqlpower.dao.SPPersister; import ca.sqlpower.dao.SPPersister.DataType; /** * A base class for testing methods of persistence. Classes that extend this must define the * persister variable that will be used for testing in order for any of the tests to pass. */ public abstract class PersisterTest extends TestCase { /** * The persister for which these tests will be applied. Subclasses must define the specific * persister, as it is not defined here. */ protected SPPersister persister; protected byte[] receivedData = new byte[1024]; protected boolean receivedBoolean; protected int receivedInt; protected long receivedLong; protected double receivedDouble; protected String receivedString; protected String receivedCareer; protected String receivedReference; protected int numObjects = 0; protected CountDownLatch receiverLatch; protected SPPersister receiver = new SPPersister(){ private int transactionCount; public void begin() throws SPPersistenceException { transactionCount++; } public void commit() throws SPPersistenceException { transactionCount--; if (transactionCount == 0 && receiverLatch != null) { receiverLatch.countDown(); } } public void persistObject(String parentUUID, String type, String uuid, int index) throws SPPersistenceException { System.out.println("Received Object " + type + "(" + uuid + ") as child of (" + parentUUID + ")"); numObjects++; } public void persistProperty(String uuid, String propertyName, DataType propertyType, Object oldValue, Object newValue) throws SPPersistenceException {} public void persistProperty(String uuid, String propertyName, DataType propertyType, Object newValue) throws SPPersistenceException { System.out.println("Received property " + propertyName + " as type " + propertyType.getTypeName()); if (propertyType == DataType.PNG_IMG) { assertEquals("image", propertyName); try { ((InputStream) newValue).read(receivedData); } catch (IOException e) { throw new RuntimeException(e); } } else if (propertyType == DataType.REFERENCE) { assertEquals("reference", propertyName); receivedReference = (String) newValue; } else if (propertyName.equals("Career")) { receivedCareer = (String) newValue; } else if (propertyName.equals("name")) { receivedString = (String) newValue; } else if (propertyType == DataType.INTEGER) { assertEquals("integer", propertyName); receivedInt = (Integer) newValue; } else if (propertyType == DataType.DOUBLE) { assertEquals("double", propertyName); receivedDouble = (Double) newValue; } else if (propertyType == DataType.BOOLEAN) { assertEquals("bool", propertyName); receivedBoolean = (Boolean) newValue; } else if (propertyType == DataType.LONG) { assertEquals("long", propertyName); receivedLong = (Long) newValue; } } public void removeObject(String parentUUID, String uuid) throws SPPersistenceException { numObjects--; } public void rollback() { // TODO Auto-generated method stub } }; protected SPPersister orderChecker = new SPPersister() { public void begin() throws SPPersistenceException { } public void commit() throws SPPersistenceException { } public void persistObject(String parentUUID, String type, String uuid, int index) throws SPPersistenceException { if (type.equals("ca.sqlpower.testutil.SPObjectRoot")) return; assertEquals(index, Integer.parseInt(uuid)); } public void persistProperty(String uuid, String propertyName, DataType propertyType, Object oldValue, Object newValue) throws SPPersistenceException { } public void persistProperty(String uuid, String propertyName, DataType propertyType, Object newValue) throws SPPersistenceException { if (uuid.equals(workspaceId)) return; assertEquals(uuid, newValue); } public void removeObject(String parentUUID, String uuid) throws SPPersistenceException { } public void rollback() { } }; protected String workspaceId; public PersisterTest() { super(); } public PersisterTest(String name) { super(name); } public void testBegin() throws Exception { System.out.println("\n\nTesting Begin:"); persister.begin(); } public void testPersistObject() throws Exception { System.out.println("\n\nTesting Persist Object:"); persister.begin(); persister.persistObject(workspaceId, "ca.sqlpower.sqlobject.SQLColumn", "child", 0); persister.persistProperty("child", "name", DataType.STRING, "name"); persister.commit(); persister.begin(); persister.persistObject(workspaceId, "ca.sqlpower.sqlobject.SQLColumn", "otherchild", 0); persister.persistProperty("otherchild", "name", DataType.STRING, "name"); persister.commit(); loadWorkspace(); assertEquals(3, numObjects); } public void testPersistProperty() throws Exception { System.out.println("\n\nTesting Persist Property:"); persister.begin(); persister.persistObject(workspaceId, "ca.sqlpower.sqlobject.SQLColumn", "child", 0); persister.persistProperty("child", "name", DataType.STRING, "Chart Name"); persister.persistProperty("child", "integer", DataType.INTEGER, 8); persister.persistProperty("child", "double", DataType.DOUBLE, 5.15); persister.persistProperty("child", "bool", DataType.BOOLEAN, true); persister.commit(); loadWorkspace(); assertEquals("Chart Name", receivedString); assertEquals(8, receivedInt); assertTrue(Math.abs(receivedDouble - 5.15) <= .001); assertEquals(true, receivedBoolean); } /** * Since the JCR stores integers in long fields we need to confirm the value * that is retrieved from the JCR is the correct value we put in. Note that this test * is not specific to the JCR persistence layer. */ public void testPersistNegativeInteger() throws Exception { persister.begin(); persister.persistObject(workspaceId, "ca.sqlpower.testutil.SPObjectRoot", "child", 0); persister.persistProperty("child", "name", DataType.STRING, "test negative int"); persister.persistProperty("child", "integer", DataType.INTEGER, Integer.valueOf(-1)); persister.commit(); receivedInt = 0; loadWorkspace(); assertEquals(-1, receivedInt); } /** * Since the JCR stores integers in long fields we need to confirm the value * that is retrieved from the JCR is the correct value we put in. Note that this test * is not specific to the JCR persistence layer. */ public void testPersistNegativeLong() throws Exception { persister.begin(); persister.persistObject(workspaceId, "ca.sqlpower.testutil.SPObjectRoot", "child", 0); persister.persistProperty("child", "name", DataType.STRING, "test negative int"); persister.persistProperty("child", "long", DataType.LONG, Long.valueOf(-1)); persister.commit(); loadWorkspace(); assertEquals(-1, receivedLong); } public void testPersistNull() throws Exception { System.out.println("\n\nTesting Persist Null"); persister.begin(); persister.persistObject(workspaceId, "ca.sqlpower.sqlobject.SQLColumn", "child", 0); persister.persistProperty("child", "name", DataType.STRING, "Name"); persister.persistProperty("child", "integer", DataType.INTEGER, 42); persister.commit(); persister.begin(); persister.persistProperty("child", "integer", DataType.NULL, null); persister.commit(); loadWorkspace(); assertEquals(0, receivedInt); } public void testConditionalPersistProperty() throws Exception { System.out.println("\n\nTesting Conditional Persist Property:"); persister.begin(); persister.persistObject(workspaceId, "ca.sqlpower.sqlobject.SQLColumn", "child", 0); persister.persistProperty("child", "name", DataType.STRING, "Chart Name"); persister.persistProperty("child", "integer", DataType.INTEGER, 8); persister.commit(); loadWorkspace(); assertEquals("Chart Name", receivedString); assertEquals(8, receivedInt); persister.begin(); persister.persistProperty("child", "name", DataType.STRING, "Chart Name", "Another Name"); persister.persistProperty("child", "integer", DataType.INTEGER, 42); persister.commit(); loadWorkspace(); assertEquals("Another Name", receivedString); assertEquals(42, receivedInt); try { persister.begin(); persister.persistProperty("child", "name", DataType.STRING, "Chart Name", "Yet Another Name"); fail("Persister allowed property \"name\" to be changed without correct old value"); } catch (SPPersistenceException e) { } try { persister.begin(); persister.persistProperty("child", "integer", DataType.INTEGER, 99, 108); fail("Persister allowed property \"integer\" to be changed without correct old value"); } catch (SPPersistenceException e) { } } public void testPersistReference() throws Exception { System.out.println("\n\nTesting Persist Reference:"); persister.begin(); persister.persistObject(workspaceId, "ca.sqlpower.sqlobject.SQLColumn", "child", 0); persister.persistProperty("child", "name", DataType.STRING, "Chart Name"); persister.persistProperty("child", "reference", DataType.REFERENCE, "Other Wabit Object"); persister.commit(); loadWorkspace(); assertEquals("Other Wabit Object", receivedReference); } public void testPersistStream() throws Exception { System.out.println("\n\nTesting Persist Stream:"); persister.begin(); persister.persistObject(workspaceId, "ca.sqlpower.testutil.SPObjectRoot", "child", 0); persister.persistProperty("child", "name", DataType.STRING, "Image Name"); byte[] bytes = new byte[receivedData.length]; Random random = new Random(); random.nextBytes(bytes); persister.persistProperty("child", "image", DataType.PNG_IMG, new ByteArrayInputStream(bytes)); // Not really a PNG, but it's the only one that's a stream persister.commit(); loadWorkspace(); assertTrue(Arrays.equals(bytes, receivedData)); } public void testRemoveObject() throws Exception { System.out.println("\n\nTesting Remove Object:"); persister.begin(); persister.persistObject(workspaceId, "ca.sqlpower.sqlobject.SQLColumn", "child", 0); persister.persistProperty("child", "name", DataType.STRING, "Chart Name"); persister.persistObject(workspaceId, "ca.sqlpower.sqlobject.SQLColumn", "child2", 0); persister.persistProperty("child2", "name", DataType.STRING, "Chart 2 Name"); persister.commit(); persister.begin(); persister.removeObject(workspaceId, "child"); persister.commit(); loadWorkspace(); assertEquals(2, numObjects); assertEquals("Chart 2 Name", receivedString); } protected abstract void loadWorkspace() throws Exception; public void testRollback() throws Exception { System.out.println("\n\nTesting Rollback:"); persister.begin(); persister.persistObject(workspaceId, "ca.sqlpower.sqlobject.SQLColumn", "child", 0); persister.rollback(); loadWorkspace(); assertEquals(1, numObjects); } }