/* * Copyright 2009-2016 Tilmann Zaeschke. All rights reserved. * * This file is part of ZooDB. * * ZooDB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ZooDB 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ZooDB. If not, see <http://www.gnu.org/licenses/>. * * See the README and COPYING files for further information. */ package org.zoodb.test.jdo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.Collection; import java.util.Iterator; import javax.jdo.Extent; import javax.jdo.JDOObjectNotFoundException; import javax.jdo.JDOUserException; import javax.jdo.PersistenceManager; import javax.jdo.Query; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; import org.zoodb.api.impl.ZooPC; import org.zoodb.jdo.ZooJdoHelper; import org.zoodb.jdo.ZooJdoProperties; import org.zoodb.jdo.spi.PersistenceCapableImpl; import org.zoodb.schema.ZooClass; import org.zoodb.schema.ZooField; import org.zoodb.schema.ZooHandle; import org.zoodb.schema.ZooSchema; import org.zoodb.test.testutil.TestTools; public class Test_034_SchemaEvolution { @AfterClass public static void tearDown() { TestTools.closePM(); } @Before public void before() { TestTools.createDb(); } @After public void after() { TestTools.closePM(); TestTools.removeDb(); } @Test public void testSimpleEvolution() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); TestClassTiny t1 = new TestClassTiny(1, 3); TestClassTiny t2 = new TestClassTiny(4, 5); pm.makePersistent(t1); pm.makePersistent(t2); Object oid1 = pm.getObjectId(t1); Object oid2 = pm.getObjectId(t2); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass s1 = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class.getName()); s1.rename(TestClassSmall.class.getName()); // private int myInt; // private long myLong; // private String myString; // private int[] myInts; // private Object refO; // private TestClassTiny refP; s1.getField("_int").remove(); s1.addField("myInt", Integer.TYPE); s1.getField("_long").rename("myLong"); s1.addField("myString", String.class); s1.addField("myInts", Integer[].class); s1.addField("refO", Object.class); ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); s1.addField("refP", TestClassTiny.class); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); TestClassSmall ts1 = (TestClassSmall) pm.getObjectById(oid1); TestClassSmall ts2 = (TestClassSmall) pm.getObjectById(oid2); assertEquals(0, ts1.getMyInt()); assertEquals(3, ts1.getMyLong()); assertEquals(0, ts2.getMyInt()); assertEquals(5, ts2.getMyLong()); pm.currentTransaction().rollback(); TestTools.closePM(); } @Test public void testSimpleEvolutionError_Issue71() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); TestClassTiny t1 = new TestClassTiny(1, 3); TestClassTiny t2 = new TestClassTiny(4, 5); pm.makePersistent(t1); pm.makePersistent(t2); Object oid1 = pm.getObjectId(t1); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass s1 = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class.getName()); s1.rename(TestClassSmall.class.getName()); // private int myInt; // private long myLong; // private String myString; // private int[] myInts; // private Object refO; // private TestClassTiny refP; s1.getField("_int").remove(); s1.addField("myInt", Integer.TYPE); s1.getField("_long").rename("myLong"); s1.addField("myString", String.class); s1.addField("myInts", Integer[].class); s1.addField("refO", Object.class); ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); //Omit one field to trigger error //s1.addField("refP", TestClassTiny.class); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); try { pm.getObjectById(oid1); fail(); } catch (JDOUserException e) { assertFalse(e.getMessage(), e.getMessage().contains("class not found")); assertTrue(e.getMessage(), e.getMessage().contains("field")); assertTrue(e.getMessage(), e.getMessage().contains("mismatch")); } pm.currentTransaction().rollback(); TestTools.closePM(); } @Test public void testSimpleEvolutionViaReference() { //test that evolves objects and then accesses them via hollowForOid() in the deserializer. ZooJdoProperties p = TestTools.getProps(); p.setZooAutoCreateSchema(true); PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); ZooJdoHelper.schema(pm).addClass(TestClassTinyRef.class); TestClassTiny t1 = new TestClassTiny(1, 3); TestClassTinyRef r = new TestClassTinyRef(t1); pm.makePersistent(r); Object oidR = pm.getObjectId(r); pm.currentTransaction().commit(); TestTools.closePM(); //create incompatible schema pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass s1 = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class.getName()); s1.getField("_int").remove(); s1.addField("myInt", Integer.TYPE); s1.addField("myString", String.class); //evolve objects Iterator<ZooHandle> it = s1.getHandleIterator(true); while (it.hasNext()) { ZooHandle h = it.next(); h.setValue("myInt", 123); } pm.currentTransaction().commit(); TestTools.closePM(); //change back to proper schema pm = TestTools.openPM(); pm.currentTransaction().begin(); s1 = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class.getName()); s1.addField("_int", Integer.TYPE); s1.getField("myInt").remove(); s1.getField("myString").remove(); pm.currentTransaction().commit(); TestTools.closePM(); //Load data pm = TestTools.openPM(); pm.currentTransaction().begin(); TestClassTinyRef r2 = (TestClassTinyRef) pm.getObjectById(oidR); assertNotNull(r2.getTiny()); try { assertEquals(0, r2.getTiny().getInt()); assertEquals(3L, r2.getTiny().getLong()); } catch (JDOUserException e) { assertTrue(e.getMessage(), e.getMessage().contains("not been evolved")); } pm.currentTransaction().rollback(); TestTools.closePM(); //Okay, we need to evolve first pm = TestTools.openPM(); pm.currentTransaction().begin(); s1 = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class.getName()); Iterator<ZooHandle> it2 = s1.getHandleIterator(true); while (it2.hasNext()) { ZooHandle h = it2.next(); h.setValue("_int", 2); } pm.currentTransaction().commit(); TestTools.closePM(); //Load data again pm = TestTools.openPM(); pm.currentTransaction().begin(); TestClassTinyRef r3 = (TestClassTinyRef) pm.getObjectById(oidR); assertNotNull(r3.getTiny()); assertEquals(2, r3.getTiny().getInt()); assertEquals(3L, r3.getTiny().getLong()); pm.currentTransaction().rollback(); TestTools.closePM(); } @Test public void testDataMigration() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); TestClassTiny t1 = new TestClassTiny(1, 3); TestClassTiny t2 = new TestClassTiny(4, 5); pm.makePersistent(t1); pm.makePersistent(t2); Object oid1 = pm.getObjectId(t1); Object oid2 = pm.getObjectId(t2); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass s1 = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class.getName()); s1.rename(TestClassSmall.class.getName()); // private int myInt; // private long myLong; // private String myString; // private int[] myInts; // private Object refO; // private TestClassTiny refP; //additive changes s1.addField("myInt", Integer.TYPE); s1.getField("_long").rename("myLong"); s1.addField("myString", String.class); s1.addField("myInts", Integer[].class); s1.addField("refO", Object.class); ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); s1.addField("refP", TestClassTiny.class); Iterator<ZooHandle> it = s1.getHandleIterator(false); int n = 0; while (it.hasNext()) { //migrate data ZooField f1 = s1.getField("_int"); ZooField f2a = s1.getField("myInt"); //new ZooField f2b = s1.getField("myLong"); //renamed ZooField f2c = s1.getField("myString"); //new String ZooHandle hdl = it.next(); //TODO pass in field instead?!?! int i = (Integer) f1.getValue(hdl); f2a.setValue(hdl, i+1); f2b.setValue(hdl, (long)i+2); f2c.setValue(hdl, String.valueOf(i+3)); assertEquals(i+1, (int)(Integer) f2a.getValue(hdl)); assertEquals(i+2, (long)(Long) f2b.getValue(hdl)); assertEquals(String.valueOf(i+=3), f2c.getValue(hdl)); //batch processing //TODO batch processing of this kind is not possible anymore after removal //of index-level COW. Find alternative... (multi-session...) // pm.currentTransaction().commit(); // pm.currentTransaction().begin(); n++; } pm.currentTransaction().commit(); pm.currentTransaction().begin(); assertEquals(2, n); //destructive changes s1.getField("_int").remove(); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); TestClassSmall ts1 = (TestClassSmall) pm.getObjectById(oid1); TestClassSmall ts2 = (TestClassSmall) pm.getObjectById(oid2); assertEquals(2, ts1.getMyInt()); assertEquals(3, ts1.getMyLong()); assertEquals("4", ts1.getMyString()); assertEquals(5, ts2.getMyInt()); assertEquals(6, ts2.getMyLong()); assertEquals("7", ts2.getMyString()); pm.currentTransaction().rollback(); TestTools.closePM(); } @Test public void testDataMigrationBug1() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); TestClassTiny t1 = new TestClassTiny(1, 3); TestClassTiny t2 = new TestClassTiny(4, 5); pm.makePersistent(t1); pm.makePersistent(t2); Object oid1 = pm.getObjectId(t1); Object oid2 = pm.getObjectId(t2); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass s1 = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class.getName()); s1.rename(TestClassSmall.class.getName()); // private int myInt; // private long myLong; // private String myString; // private int[] myInts; // private Object refO; // private TestClassTiny refP; //additive changes s1.addField("myInt", Integer.TYPE); s1.getField("_long").rename("myLong"); s1.addField("myString", String.class); s1.addField("myInts", Integer[].class); s1.addField("refO", Object.class); ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); s1.addField("refP", TestClassTiny.class); Iterator<ZooHandle> it = s1.getHandleIterator(false); int n = 0; while (it.hasNext()) { //migrate data ZooField f1 = s1.getField("_int"); ZooField f2a = s1.getField("myInt"); //new ZooField f2b = s1.getField("myLong"); //renamed ZooField f2c = s1.getField("myString"); //new String ZooHandle hdl = it.next(); //TODO pass in field instead?!?! int i = (Integer) f1.getValue(hdl); f2a.setValue(hdl, i+1); f2b.setValue(hdl, (long)i+2); f2c.setValue(hdl, String.valueOf(i+3)); assertEquals(i+1, (int)(Integer) f2a.getValue(hdl)); assertEquals(i+2, (long)(Long) f2b.getValue(hdl)); assertEquals(String.valueOf(i+=3), f2c.getValue(hdl)); n++; } assertEquals(2, n); //destructive changes s1.getField("_int").remove(); pm.currentTransaction().commit(); TestTools.closePM(); } /** * This used to fail because the reference to another object contained an old * schema version. This is okay, but the DeSerializer couldn't deal with that. * See issue #69. */ @Test public void testDataMigrationIssue69_RefWithOldSchema() { TestTools.defineSchema(TestClassSmall.class, TestClassSmallA.class, TestClassSmallB.class); PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); TestClassSmallA a1 = new TestClassSmallA(); a1.setMyInt(123); TestClassSmallB b1 = new TestClassSmallB(); b1.setA(a1); pm.makePersistent(a1); pm.makePersistent(b1); Object oidA = pm.getObjectId(a1); Object oidB = pm.getObjectId(b1); pm.currentTransaction().commit(); TestTools.closePM(); //We need an evolved class, so we evolve it back and forth to create two versions. //change A pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass s1 = ZooJdoHelper.schema(pm).getClass(TestClassSmallA.class.getName()); s1.addField("myInt2", Integer.TYPE); //evolve object ZooJdoHelper.schema(pm).getHandle(oidA).setValue("myInt2", 33); pm.currentTransaction().commit(); TestTools.closePM(); //change A back to normal pm = TestTools.openPM(); pm.currentTransaction().begin(); s1 = ZooJdoHelper.schema(pm).getClass(TestClassSmallA.class.getName()); s1.removeField("myInt2"); //evolve object ZooJdoHelper.schema(pm).getHandle(oidA).getValue("myInt"); pm.currentTransaction().commit(); TestTools.closePM(); //TODO actually, loading B should fail because we don't support auto-evolution! //TODO create second tests that loads and evolves the B instance. //Test B pm = TestTools.openPM(); pm.currentTransaction().begin(); TestClassSmallB b = (TestClassSmallB) pm.getObjectById(oidB); assertEquals(123, b.getA().getMyInt()); pm.currentTransaction().rollback(); TestTools.closePM(); } /** * This used to fail because the reference to another object contained an old * schema version. This is okay, but the DeSerializer couldn't deal with that. * See issue #69. */ @Test public void testDataMigrationIssue70_RecognizeUnevolvedObjects() { TestTools.defineSchema(TestClassSmall.class, TestClassSmallA.class, TestClassSmallB.class); PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); TestClassSmallA a1 = new TestClassSmallA(); a1.setMyInt(123); TestClassSmallB b1 = new TestClassSmallB(); b1.setA(a1); pm.makePersistent(a1); pm.makePersistent(b1); Object oidB = pm.getObjectId(b1); pm.currentTransaction().commit(); TestTools.closePM(); //We need an evolved class, so we evolve it back and forth to create two versions. //change A pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass s1 = ZooJdoHelper.schema(pm).getClass(TestClassSmallA.class.getName()); s1.addField("myInt2", Integer.TYPE); pm.currentTransaction().commit(); TestTools.closePM(); //change A back to normal pm = TestTools.openPM(); pm.currentTransaction().begin(); s1 = ZooJdoHelper.schema(pm).getClass(TestClassSmallA.class.getName()); s1.removeField("myInt2"); pm.currentTransaction().commit(); TestTools.closePM(); //TODO actually, loading B should fail because we don't support auto-evolution! //TODO create second tests that loads and evolves the B instance. //Test B pm = TestTools.openPM(); pm.currentTransaction().begin(); try { TestClassSmallB b = (TestClassSmallB) pm.getObjectById(oidB); assertEquals(123, b.getA().getMyInt()); fail(); } catch (JDOUserException e) { //good! } pm.currentTransaction().rollback(); TestTools.closePM(); } @Test public void testSetOid() { TestTools.defineSchema(TestClass.class); TestTools.defineIndex(TestClass.class, "_long", false); PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass cls = ZooJdoHelper.schema(pm).getClass(TestClass.class); TestClass tc = new TestClass(); tc.setInt(1); tc.setLong(2); pm.makePersistent(tc); Object oidc0 = pm.getObjectId(tc); ZooHandle hdlC1 = cls.newInstance(); hdlC1.setValue("_int", 21); hdlC1.setValue("_long", 22L); Object oidc1 = hdlC1.getOid(); Object oidc2 = 10 + (Long)oidc1; ZooHandle hdlC2 = cls.newInstance((Long) oidc2); hdlC2.setValue("_int", 31); hdlC2.setValue("_long", 32L); assertEquals(oidc2, hdlC2.getOid()); pm.currentTransaction().commit(); pm.currentTransaction().begin(); //create objects for testing setOId on new-objects (TODO, use only 1 set of object and //repeat tests? // TestClass t = new TestClass(); // t.setInt(41); // t.setLong(42); // pm.makePersistent(t); // Object oid0 = pm.getObjectId(t); ZooHandle hdl1 = cls.newInstance(); hdl1.setValue("_int", 51); hdl1.setValue("_long", 52L); Object oid1 = hdl1.getOid(); Object oid2 = 10 + (Long)oid1; ZooHandle hdl2 = cls.newInstance((Long) oid2); hdl2.setValue("_int", 61); hdl2.setValue("_long", 62L); assertEquals(oid2, hdl2.getOid()); //Now set OIDs ZooHandle hdlC0 = ZooJdoHelper.schema(pm).getHandle((Long) oidc0); //TODO //test rollback //test swapping OIDs (also between PC and GO pm.currentTransaction().commit(); pm.currentTransaction().begin(); pm.currentTransaction().commit(); TestTools.closePM(); fail(); //TODO //TODO test class change --> index updates //TODO Test circular swap //TODO test multiple setOid() on same object //TODO test multiple setOid() on different objects to same OID } @Test public void testFailForSchemaMismatchOnlyWhenLoadingObjects() { String cName = TestClassSmall.class.getName(); //define class PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooJdoHelper.schema(pm).defineEmptyClass(cName); pm.currentTransaction().commit(); TestTools.closePM(); //create data (do not fail here!) pm = TestTools.openPM(); pm.currentTransaction().begin(); //two new instances with default values ZooClass cls = ZooJdoHelper.schema(pm).getClass(cName); cls.newInstance(); cls.newInstance(); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); //add fields try { Extent<TestClassSmall> ex = pm.getExtent(TestClassSmall.class); ex.iterator().next(); fail(); } catch (JDOUserException e) { //good, here we should fail with schema mismatch } pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testSchemaMismatchInNextTx() { String cName = TestClassSmall.class.getName(); //define class PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass sup = ZooJdoHelper.schema(pm).getClass(PersistenceCapableImpl.class); ZooJdoHelper.schema(pm).defineEmptyClass(cName, sup); pm.currentTransaction().commit(); TestTools.closePM(); //create data pm = TestTools.openPM(); pm.currentTransaction().begin(); //two new instances with default values ZooClass cls = ZooJdoHelper.schema(pm).getClass(cName); cls.newInstance(); cls.newInstance(); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); //add fields cls = ZooJdoHelper.schema(pm).getClass(cName); cls.addField("_int", Integer.TYPE); cls.addField("_long", Long.TYPE); cls.createIndex("_long", false); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); //Schema API access works cls = ZooJdoHelper.schema(pm).getClass(cName); ZooField f1 = cls.getField("_int"); ZooField f2 = cls.getField("_long"); assertNotNull(f1); assertNotNull(f2); assertEquals(2, cls.getLocalFields().size()); //This should fail with (because TestClassSmall has no such fields!): //javax.jdo.JDOUserException: Field name not found: '_int' in org.zoodb.test.TestClassSmall // at org.zoodb.internal.query.QueryParser.parseTerm(QueryParser.java:290) try { Query q = pm.newQuery(TestClassSmall.class, "_int == 0"); q.execute(); fail(); } catch (JDOUserException e) { //good } pm.currentTransaction().commit(); TestTools.closePM(); } /** * Check that non-evolved objects are still returned when a query matches the default value * of a recently added field. */ @SuppressWarnings("unchecked") @Test public void testQueryNonEvolvedObjectsOnDefaultValueWithFieldIndex() { String cName = TestClassTiny.class.getName(); //define class PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass sup = ZooJdoHelper.schema(pm).getClass(PersistenceCapableImpl.class); ZooJdoHelper.schema(pm).defineEmptyClass(cName, sup); pm.currentTransaction().commit(); TestTools.closePM(); //create data pm = TestTools.openPM(); pm.currentTransaction().begin(); //two new instances with default values ZooClass cls = ZooJdoHelper.schema(pm).getClass(cName); cls.newInstance(); cls.newInstance(); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); //add fields cls = ZooJdoHelper.schema(pm).getClass(cName); cls.addField("_int", Integer.TYPE); cls.addField("_long", Long.TYPE); cls.createIndex("_int", false); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); //query _int Query q = pm.newQuery(TestClassTiny.class, "_int == 0"); Collection<TestClassTiny> c = (Collection<TestClassTiny>) q.execute(); assertEquals(2, c.size()); pm.currentTransaction().rollback(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); //query _long with index q = pm.newQuery(TestClassTiny.class, "_long == 0"); c = (Collection<TestClassTiny>) q.execute(); assertEquals(2, c.size()); pm.currentTransaction().rollback(); TestTools.closePM(); } @Test public void testCleanUpOfPreviousVersions() { //query on class oid? //db size? //iterate old pos-index? //iterate value-index? fail(); //TODO //TODO check OID-index (OID queyr/refs), pos-index (extents), attr-index (query), page-count } /** * Test that an object that is evolved becomes rewritten. How can we check this? * a) Without modification, the database should still write pages (change size?) * b) The object should be dirty? (Actually, not necessarily, the user should not notice) * c) Instance callbacks? The same as b) * * --> Enable/disable isEvolved in DataDeSerializer */ @Test public void testEvolutionReWrite() { fail(); //TODO } @Test public void testArrayAttributes() { fail(); //TODO } /** * Ensure that evolution does not occur if set to 'manual'. */ @Test public void testFailIfNotAutomatic() { fail(); //TODO } @Test public void testInctanceCount() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass c1 = ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); ZooClass c2 = ZooJdoHelper.schema(pm).addClass(TestClassTiny2.class); assertEquals(0, c1.instanceCount(false)); assertEquals(0, c1.instanceCount(true)); assertEquals(0, c2.instanceCount(true)); TestClassTiny t1 = new TestClassTiny(1, 3); TestClassTiny t2 = new TestClassTiny(4, 5); assertEquals(0, c1.instanceCount(false)); assertEquals(0, c1.instanceCount(true)); assertEquals(0, c2.instanceCount(true)); pm.makePersistent(t1); pm.makePersistent(t2); assertEquals(0, c1.instanceCount(false)); assertEquals(0, c1.instanceCount(true)); assertEquals(0, c2.instanceCount(true)); pm.currentTransaction().commit(); pm.currentTransaction().begin(); c1 = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); //TODO Implement?!?!? fail(); assertEquals(1, c1.instanceCount(false)); assertEquals(2, c1.instanceCount(true)); assertEquals(1, c2.instanceCount(true)); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); c1 = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); assertEquals(1, c1.instanceCount(false)); assertEquals(2, c1.instanceCount(true)); assertEquals(1, c2.instanceCount(true)); c1.remove(); assertEquals(1, c1.instanceCount(false)); assertEquals(2, c1.instanceCount(true)); assertEquals(1, c2.instanceCount(true)); pm.currentTransaction().commit(); pm.currentTransaction().begin(); assertEquals(0, c1.instanceCount(false)); assertEquals(0, c1.instanceCount(true)); assertEquals(0, c2.instanceCount(true)); pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testFailSetValue() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass c1 = ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); ZooClass c2 = ZooJdoHelper.schema(pm).addClass(TestClassTiny2.class); ZooHandle h1 = c1.newInstance(); ZooHandle h2 = c2.newInstance(); ZooField f1 = c1.getField("_long"); ZooField f2 = c2.getField("i2"); //this should work because f1 is in the super-class of h2. f1.setValue(h2, 3L); try { f2.setValue(h1, 5); fail(); } catch (IllegalArgumentException e) { //ok } try { f1.setValue(h1, 3); fail(); } catch (IllegalArgumentException e) { //ok, because the parameter should be a Long! } pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testNewInstance() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass c1 = ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); ZooClass c2 = ZooJdoHelper.schema(pm).addClass(TestClassTiny2.class); ZooHandle h1 = c1.newInstance(); ZooHandle h2 = c2.newInstance(); ZooHandle hRem = c2.newInstance(); ZooField f1 = c1.getField("_long"); ZooField f2 = c2.getField("i2"); f1.setValue(h1, 3L); f2.setValue(h2, 5); Object oid1 = h1.getOid(); Object oid2 = h2.getOid(); Object oidRem = hRem.getOid(); //remove non-committed object hRem.remove(); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); TestClassTiny t1 = (TestClassTiny) pm.getObjectById(oid1); TestClassTiny2 t2 = (TestClassTiny2) pm.getObjectById(oid2); try { pm.getObjectById(oidRem); fail(); } catch (JDOObjectNotFoundException e) { //good! } assertEquals(3, t1.getLong()); assertEquals(5, t2.getInt2()); pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testHandleValidity() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass c1 = ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); ZooClass c2 = ZooJdoHelper.schema(pm).addClass(TestClassTiny2.class); ZooField f1 = c1.getField("_int"); ZooHandle h1 = c1.newInstance(); ZooHandle h2 = c2.newInstance(); ZooHandle hRem = c2.newInstance(); //remove non-committed object hRem.remove(); try { f1.getValue(hRem); fail(); } catch (IllegalStateException e) { //object is removed } pm.currentTransaction().commit(); TestTools.closePM(); try { h1.getAttrLong("i2"); fail(); } catch (IllegalStateException e) { //outside tx } pm = TestTools.openPM(); pm.currentTransaction().begin(); c1 = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); f1 = c1.getField("_int"); try { h2.getAttrLong("i2"); fail(); } catch (IllegalStateException e) { //wrong session } try { f1.getValue(h2); fail(); } catch (IllegalStateException e) { //object is removed } pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testHandleRemove() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); ZooJdoHelper.schema(pm).addClass(TestClassTiny2.class); TestClassTiny t1 = new TestClassTiny(); TestClassTiny2 t2 = new TestClassTiny2(); pm.makePersistent(t1); pm.makePersistent(t2); Object oid1 = pm.getObjectId(t1); Object oid2 = pm.getObjectId(t2); pm.currentTransaction().commit(); pm.currentTransaction().begin(); ZooHandle h1 = ZooJdoHelper.schema(pm).getHandle((Long)oid1); ZooHandle h2 = ZooJdoHelper.schema(pm).getHandle((Long)oid2); h1.remove(); h2.remove(); //try delete again try { h1.remove(); fail(); } catch (Exception e) { //object is already deleted } pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); try { pm.getObjectById(oid1); fail(); } catch (JDOObjectNotFoundException e) { //good } try { pm.getObjectById(oid2); fail(); } catch (JDOObjectNotFoundException e) { //good } Extent<?> ext = pm.getExtent(TestClassTiny.class); assertFalse(ext.iterator().hasNext()); ext.closeAll(); pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testHandleGetJavaObject() { TestTools.defineSchema(TestClassTiny.class); PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); TestClassTiny t1 = new TestClassTiny(1, 3); TestClassTiny t2 = new TestClassTiny(4, 5); pm.makePersistent(t1); pm.makePersistent(t2); Object oid1 = pm.getObjectId(t1); Object oid2 = pm.getObjectId(t2); pm.currentTransaction().commit(); pm.currentTransaction().begin(); ZooHandle h1 = ZooJdoHelper.schema(pm).getHandle((Long)oid1); ZooHandle h2 = ZooJdoHelper.schema(pm).getHandle((Long)oid2); assertTrue(t1 == h1.getJavaObject()); h1.remove(); try { h1.getJavaObject(); fail(); } catch (IllegalStateException e) { //good, has been deleted } pm.currentTransaction().commit(); TestTools.closePM(); try { h2.getJavaObject(); fail(); } catch (IllegalStateException e) { //good, outside tx } } @Test public void testHandleFromObject() { TestTools.defineSchema(TestClassTiny.class); PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); TestClassTiny t1 = new TestClassTiny(1, 3); TestClassTiny t2 = new TestClassTiny(4, 5); TestClassTiny t3 = new TestClassTiny(7, 8); // not persistent pm.makePersistent(t1); pm.makePersistent(t2); ZooSchema s = ZooJdoHelper.schema(pm); try { s.getHandle(t3); fail(); } catch (JDOUserException e) { //good, it is not persistent yet } try { //ZooHandle h2 = s.getHandle(t2); //h2.remove(); fail(); } catch (UnsupportedOperationException e) { //good, this is not supported yet } pm.currentTransaction().commit(); pm.currentTransaction().begin(); try { s.getHandle(t3); fail(); } catch (JDOUserException e) { } ZooHandle h2x = s.getHandle(t2); assertEquals(5, h2x.getAttrLong("_long")); ZooHandle h1 = s.getHandle(t1); assertEquals(3, h1.getAttrLong("_long")); } @Test public void testHandleGetType() { TestTools.defineSchema(TestClassTiny.class); PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass s = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); TestClassTiny t1 = new TestClassTiny(1, 3); TestClassTiny t2 = new TestClassTiny(4, 5); pm.makePersistent(t1); pm.makePersistent(t2); Object oid1 = pm.getObjectId(t1); Object oid2 = pm.getObjectId(t2); pm.currentTransaction().commit(); pm.currentTransaction().begin(); ZooHandle h1 = ZooJdoHelper.schema(pm).getHandle((Long)oid1); ZooHandle h2 = ZooJdoHelper.schema(pm).getHandle((Long)oid2); assertTrue(s == h1.getType()); h1.remove(); try { h1.getType(); fail(); } catch (IllegalStateException e) { //good, has been deleted } pm.currentTransaction().commit(); TestTools.closePM(); try { h2.getType(); fail(); } catch (IllegalStateException e) { //good, outside tx } } @Test public void testMakePersistent() { getSuperClass(true); } @Test public void testMakePersistentNoCommit() { getSuperClass(false); } private void getSuperClass(boolean commit) { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass clsPC = ZooJdoHelper.schema(pm).getClass(PersistenceCapableImpl.class.getName()); ZooClass c1 = ZooJdoHelper.schema(pm).defineEmptyClass(TestClassTiny.class.getName(), clsPC); c1.addField("_int", Integer.TYPE); c1.addField("_long", Long.TYPE); if (commit) { pm.currentTransaction().commit(); pm.currentTransaction().begin(); } TestClassTiny t1 = new TestClassTiny(); pm.makePersistent(t1); pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testFailClassIncompatibility() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass clsPC = ZooJdoHelper.schema(pm).getClass(PersistenceCapableImpl.class.getName()); ZooClass c1 = ZooJdoHelper.schema(pm).defineEmptyClass(TestClassTiny.class.getName(), clsPC); c1.addField("_int", Integer.TYPE); TestClassTiny t1 = new TestClassTiny(); try { pm.makePersistent(t1); fail(); } catch (JDOUserException e) { //field missing } c1.addField("_long", Integer.TYPE); try { pm.makePersistent(t1); fail(); } catch (JDOUserException e) { //field has wrong type } c1.getField("_long").remove(); c1.addField("_long", Long.TYPE); //now it should work pm.makePersistent(t1); pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testFailDoubleDeclare() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass clsPC = ZooJdoHelper.schema(pm).getClass(PersistenceCapableImpl.class.getName()); ZooClass c1 = ZooJdoHelper.schema(pm).defineEmptyClass(TestClassTiny.class.getName(), clsPC); c1.addField("_int", Integer.TYPE); c1.addField("_long", Long.TYPE); //same tx try { ZooJdoHelper.schema(pm).defineEmptyClass(TestClassTiny.class.getName(), clsPC); fail(); } catch (IllegalArgumentException e) { //already defined } pm.currentTransaction().commit(); pm.currentTransaction().begin(); //new tx try { clsPC = ZooJdoHelper.schema(pm).getClass(PersistenceCapableImpl.class.getName()); ZooJdoHelper.schema(pm).defineEmptyClass(TestClassTiny.class.getName(), clsPC); fail(); } catch (IllegalArgumentException e) { //already defined } pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); //new session try { clsPC = ZooJdoHelper.schema(pm).getClass(PersistenceCapableImpl.class.getName()); ZooJdoHelper.schema(pm).defineEmptyClass(TestClassTiny.class.getName(), clsPC); fail(); } catch (IllegalArgumentException e) { //already defined } pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testLocate() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass clsPC = ZooJdoHelper.schema(pm).getClass(PersistenceCapableImpl.class.getName()); ZooClass c1 = ZooJdoHelper.schema(pm).defineEmptyClass(TestClassTiny.class.getName(), clsPC); c1.addField("_int", Integer.TYPE); c1.addField("_long", Long.TYPE); //same tx assertNotNull(ZooJdoHelper.schema(pm).getClass(TestClassTiny.class)); assertNotNull(ZooJdoHelper.schema(pm).getClass(TestClassTiny.class.getName())); pm.currentTransaction().commit(); pm.currentTransaction().begin(); //new tx assertNotNull(ZooJdoHelper.schema(pm).getClass(TestClassTiny.class)); assertNotNull(ZooJdoHelper.schema(pm).getClass(TestClassTiny.class.getName())); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); //new session assertNotNull(ZooJdoHelper.schema(pm).getClass(TestClassTiny.class)); assertNotNull(ZooJdoHelper.schema(pm).getClass(TestClassTiny.class.getName())); pm.currentTransaction().commit(); TestTools.closePM(); } } class TestClassTinyRef extends ZooPC { private TestClassTiny tiny; @SuppressWarnings("unused") private TestClassTinyRef() { //nothing } public TestClassTinyRef(TestClassTiny tiny) { this.tiny = tiny; } public TestClassTiny getTiny() { zooActivateRead(); return tiny; } }