/* * 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.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.Collection; import javax.jdo.Extent; import javax.jdo.JDOHelper; import javax.jdo.JDOUserException; import javax.jdo.PersistenceManager; import javax.jdo.PersistenceManagerFactory; import javax.jdo.Query; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.zoodb.api.impl.ZooPC; import org.zoodb.jdo.ZooJdoHelper; import org.zoodb.jdo.ZooJdoProperties; import org.zoodb.schema.ZooClass; import org.zoodb.test.testutil.TestTools; public class Test_038_SchemaAutoCreate { private static ZooJdoProperties props; @BeforeClass public static void beforeClass() { props = new ZooJdoProperties(TestTools.getDbName()); props.setZooAutoCreateSchema(true); } @Before public void before() { TestTools.closePM(); TestTools.removeDb(); TestTools.createDb(); } @Test public void testSchemaAutoCreation() { PersistenceManager pm = TestTools.openPM(props); pm.currentTransaction().begin(); ZooClass s01 = ZooJdoHelper.schema(pm).getClass(TestClass.class.getName()); ZooClass s02 = ZooJdoHelper.schema(pm).getClass(TestClass.class); assertNull(s01); assertNull(s02); pm.makePersistent(new TestClass()); ZooClass s1 = ZooJdoHelper.schema(pm).getClass(TestClass.class.getName()); ZooClass s2 = ZooJdoHelper.schema(pm).getClass(TestClass.class); assertTrue(s1 == s2); assertTrue(s1.getJavaClass() == TestClass.class); pm.currentTransaction().commit(); pm.currentTransaction().begin(); s1 = ZooJdoHelper.schema(pm).getClass(TestClass.class.getName()); s2 = ZooJdoHelper.schema(pm).getClass(TestClass.class); assertTrue(s1 == s2); assertTrue(s1.getJavaClass() == TestClass.class); pm.currentTransaction().commit(); pm.close(); TestTools.closePM(); //new session pm = TestTools.openPM(props); pm.currentTransaction().begin(); s1 = ZooJdoHelper.schema(pm).getClass(TestClass.class.getName()); s2 = ZooJdoHelper.schema(pm).getClass(TestClass.class); // System.out.println("STUFF: " + s1 + " - " + s2); assertTrue(s1 == s2); assertTrue(s1.getJavaClass() == TestClass.class); try { //creating an existing schema should fail ZooJdoHelper.schema(pm).addClass(TestClass.class); fail(); } catch (JDOUserException e) { //good } pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testSchemaAutoCreationHierarchy() { PersistenceManager pm = TestTools.openPM(props); pm.currentTransaction().begin(); pm.makePersistent(new TestClassSmallA()); pm.currentTransaction().commit(); pm.currentTransaction().begin(); ZooClass s = ZooJdoHelper.schema(pm).getClass(TestClassSmall.class.getName()); ZooClass s1 = ZooJdoHelper.schema(pm).getClass(TestClassSmallA.class.getName()); ZooClass s2 = ZooJdoHelper.schema(pm).getClass(TestClassSmallB.class.getName()); ZooClass t = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class.getName()); assertNotNull(s); //super class assertNotNull(s1); //instantiated class assertNotNull(s2); //referenced class assertNotNull(t); //referenced in super pm.currentTransaction().commit(); TestTools.closePM(); } /** * Test that persisting class A with a reference to an SCO B <b>fails</b> if the according * setting is enabled in ZooDB. */ @Test public void testSchemaCreationChickenEgg() { PersistenceManager pm = TestTools.openPM(props); pm.currentTransaction().begin(); pm.makePersistent(new TestClassSmallA()); // ZooSchema.defineClass(pm, TestClassTiny.class); // ZooSchema.defineClass(pm, TestClassSmall.class); // ZooSchema.defineClass(pm, TestClassSmallA.class); //should not fail depspite missing schemata pm.currentTransaction().commit(); pm.currentTransaction().begin(); try { ZooJdoHelper.schema(pm).addClass(TestClassSmallB.class); fail(); } catch (JDOUserException e) { //good. should fail because schema was already implicitly defined. } pm.currentTransaction().commit(); pm.close(); TestTools.closePM(); //new session pm = TestTools.openPM(props); pm.currentTransaction().begin(); ZooClass s = ZooJdoHelper.schema(pm).getClass(TestClassSmall.class.getName()); ZooClass s1 = ZooJdoHelper.schema(pm).getClass(TestClassSmallA.class.getName()); ZooClass s2 = ZooJdoHelper.schema(pm).getClass(TestClassSmallB.class.getName()); s1.remove(); try { pm.currentTransaction().commit(); fail(); } catch (JDOUserException e) { //good, can't commit because s2 depends on s1 //Message should contain name of class and one referenced class assertTrue(e.getMessage().contains(TestClassSmallA.class.getSimpleName())); assertTrue(e.getMessage().contains(TestClassSmallB.class.getSimpleName())); } pm.currentTransaction().begin(); s1.remove(); s2.remove(); s.remove(); pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testSchemaCreationWithHierarchy() { PersistenceManager pm = TestTools.openPM(props); pm.currentTransaction().begin(); pm.makePersistent(new TestClassTiny2()); ZooClass s2 = ZooJdoHelper.schema(pm).getClass(TestClassTiny2.class); ZooClass s1 = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); assertNotNull(s1); assertNotNull(s2); assertTrue(s1.getJavaClass() == TestClassTiny.class); assertTrue(s2.getJavaClass() == TestClassTiny2.class); pm.makePersistent(new TestClassTiny()); pm.currentTransaction().commit(); pm.close(); TestTools.closePM(); //new session pm = TestTools.openPM(props); pm.currentTransaction().begin(); try { //creating an existing schema should fail ZooJdoHelper.schema(pm).addClass(TestClassTiny2.class); fail(); } catch (JDOUserException e) { //good } pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testSchemaCreationWithNode() { System.out.println("For now we disable the node-aware tests."); // PersistenceManager pm = TestTools.openPM(props); // pm.currentTransaction().begin(); // // ZooClass s01 = ZooSchema.locateClass(pm, TestClass.class.getName(), DB_NAME); // ZooClass s02 = ZooSchema.locateClass(pm, TestClass.class, DB_NAME); // assertNull(s01); // assertNull(s02); // // ZooSchema.defineClass(pm, TestClass.class, DB_NAME); // // ZooClass s1 = ZooSchema.locateClass(pm, TestClass.class.getName(), DB_NAME); // ZooClass s2 = ZooSchema.locateClass(pm, TestClass.class, DB_NAME); // assertTrue(s1 == s2); // assertTrue(s1.getJavaClass() == TestClass.class); // // pm.currentTransaction().commit(); // // s1 = ZooSchema.locateClass(pm, TestClass.class.getName(), DB_NAME); // s2 = ZooSchema.locateClass(pm, TestClass.class, DB_NAME); // assertTrue(s1 == s2); // assertTrue(s1.getJavaClass() == TestClass.class); // // pm.close(); // TestTools.closePM(); // // //new session // pm = TestTools.openPM(props); // // // s1 = ZooSchema.locateClass(pm, TestClass.class.getName(), DB_NAME); // s2 = ZooSchema.locateClass(pm, TestClass.class, DB_NAME); // // System.out.println("STUFF: " + s1 + " - " + s2); // assertTrue(s1 == s2); // assertTrue(s1.getJavaClass() == TestClass.class); // // try { // //creating an existing schema should fail // ZooSchema.defineClass(pm, TestClass.class, DB_NAME); // fail(); // } catch (JDOUserException e) { // //good // } // // TestTools.closePM(); } @Test public void testSchemaCreationHierarchy() { PersistenceManager pm = TestTools.openPM(props); pm.currentTransaction().begin(); pm.makePersistent(new TestClassTiny()); pm.makePersistent(new TestClassTiny2()); pm.currentTransaction().commit(); TestTools.closePM(); } private class InnerClass extends ZooPC { // } private static class StaticInnerClass extends ZooPC { // } @Test public void testSchemaCreationInnerClass() { PersistenceManager pm = TestTools.openPM(props); pm.currentTransaction().begin(); //member class try { pm.makePersistent(new InnerClass()); fail(); } catch (JDOUserException e) { //should fail } //static inner class try { pm.makePersistent(new StaticInnerClass()); fail(); } catch (JDOUserException e) { //should fail } //anonymous class try { pm.makePersistent(new ZooPC() {}); fail(); } catch (JDOUserException e) { //should fail } //local class class LocalClass extends ZooPC {}; try { pm.makePersistent(new LocalClass()); fail(); } catch (JDOUserException e) { //should fail } pm.currentTransaction().commit(); TestTools.closePM(); } private class InnerClassSCO { // } private static class StaticInnerClassSCO { // } @Test public void testSchemaCreationInnerClassSCO() { PersistenceManager pm = TestTools.openPM(props); pm.currentTransaction().begin(); //member class TestClass tc1 = new TestClass(); tc1.setRef1(new InnerClassSCO()); pm.makePersistent(tc1); try { pm.currentTransaction().commit(); fail(); } catch (JDOUserException e) { //should fail } pm.currentTransaction().begin(); //static inner class TestClass tc2 = new TestClass(); tc2.setRef1(new StaticInnerClassSCO()); pm.makePersistent(tc2); try { pm.currentTransaction().commit(); fail(); } catch (JDOUserException e) { //should fail } pm.currentTransaction().begin(); //anonymous class TestClass tc3 = new TestClass(); tc3.setRef1(new Object() {}); pm.makePersistent(tc3); try { pm.currentTransaction().commit(); fail(); } catch (JDOUserException e) { //should fail } pm.currentTransaction().begin(); //local class class LocalClass {}; TestClass tc4 = new TestClass(); tc4.setRef1(new LocalClass()); pm.makePersistent(tc4); try { pm.currentTransaction().commit(); fail(); } catch (JDOUserException e) { //should fail } pm.currentTransaction().begin(); pm.currentTransaction().commit(); TestTools.closePM(); } /** * Check non-persistent capable classes. */ @Test public void testMakePersistentWithNPC() { PersistenceManager pm = TestTools.openPM(props); pm.currentTransaction().begin(); try { // pm.makePersistent(new RuntimeException()); fail(); } catch (JDOUserException e) { //good } pm.currentTransaction().rollback(); TestTools.closePM(); } @Test public void testAutoCreateSchema() { ZooJdoProperties props = new ZooJdoProperties(TestTools.getDbName()); props.setZooAutoCreateSchema(true); PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props); PersistenceManager pm = pmf.getPersistenceManager(); pm.currentTransaction().begin(); TestClass tc = new TestClass(); assertNull(ZooJdoHelper.schema(pm).getClass(TestClass.class)); //do not create schema first! pm.makePersistent(tc); assertNotNull(ZooJdoHelper.schema(pm).getClass(TestClass.class)); pm.currentTransaction().commit(); pm.currentTransaction().begin(); assertNotNull(ZooJdoHelper.schema(pm).getClass(TestClass.class)); //delete schema ZooClass s01 = ZooJdoHelper.schema(pm).getClass(TestClass.class); s01.remove(); assertNull(ZooJdoHelper.schema(pm).getClass(TestClass.class)); pm.currentTransaction().commit(); pm.currentTransaction().begin(); assertNull(ZooJdoHelper.schema(pm).getClass(TestClass.class)); pm.currentTransaction().rollback(); pm.close(); pmf.close(); //TestTools.closePM(); } @Test public void testQueryWithAuto() { PersistenceManager pm = TestTools.openPM(props); pm.currentTransaction().begin(); try { // pm.newQuery(RuntimeException.class); fail(); } catch (JDOUserException e) { //good } Query q = pm.newQuery(TestClassTiny2.class); assertTrue(((Collection<?>)q.execute()).isEmpty()); Query q2 = pm.newQuery("select from " + TestClassTiny.class.getName()); assertTrue(((Collection<?>)q2.execute()).isEmpty()); assertNull(ZooJdoHelper.schema(pm).getClass(TestClassTiny.class)); assertNull(ZooJdoHelper.schema(pm).getClass(TestClassTiny2.class)); pm.currentTransaction().rollback(); TestTools.closePM(); } /** * Bug #40: NPE in query compile(). */ @Test public void testQueryCompileWithAutoBug_40() { PersistenceManager pm = TestTools.openPM(props); pm.currentTransaction().begin(); Query q = pm.newQuery(TestClassTiny.class, "_int == 123"); q.compile(); assertTrue(((Collection<?>)q.execute()).isEmpty()); assertNull(ZooJdoHelper.schema(pm).getClass(TestClassTiny.class)); assertNull(ZooJdoHelper.schema(pm).getClass(TestClassTiny2.class)); pm.currentTransaction().rollback(); TestTools.closePM(); } @Test public void testExtentWithAuto() { PersistenceManager pm = TestTools.openPM(props); pm.currentTransaction().begin(); try { // pm.getExtent(RuntimeException.class); fail(); } catch (JDOUserException e) { //good } Extent<?> e = pm.getExtent(TestClassTiny2.class); assertFalse(e.iterator().hasNext()); Extent<?> e2 = pm.getExtent(TestClassTiny.class, true); assertFalse(e2.iterator().hasNext()); assertNull(ZooJdoHelper.schema(pm).getClass(TestClassTiny.class)); assertNull(ZooJdoHelper.schema(pm).getClass(TestClassTiny2.class)); pm.currentTransaction().rollback(); TestTools.closePM(); } /** * Fails. * * Requires * - auto-creation of a schema * - rollback of auto-created schema */ @Test public void testSchemaAutoCreationBug_Issue_54() { PersistenceManager pm = TestTools.openPM(props); pm.currentTransaction().begin(); pm.makePersistent(new TestClassTiny()); pm.currentTransaction().commit(); pm.currentTransaction().begin(); ZooClass t = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); t.createIndex("_int", true); //not really necessary to produce error... pm.currentTransaction().commit(); pm.currentTransaction().begin(); TestClassTiny2 tt2 = new TestClassTiny2(); pm.makePersistent(tt2); try { pm.currentTransaction().commit(); fail(); } catch (JDOUserException e) { //Exactly, this is an index violation pm.currentTransaction().begin(); } tt2.setInt(2); pm.makePersistent(tt2); //just another check, since the refresh() schema seemed to swallow the index information... //TODO The schemaToRefresh list in ClientSessionCache.rollback() is never used.... assertTrue(ZooJdoHelper.schema(pm).getClass(TestClassTiny.class).getField("_int").hasIndex()); assertTrue(ZooJdoHelper.schema(pm).getClass(TestClassTiny.class).getField("_int").isIndexUnique()); pm.currentTransaction().commit(); TestTools.closePM(); } }