blob: b2be3f355b4218b507f79fdcb9959b4a8c7ddd13 [file] [log] [blame]
/*
* TestIncrementalFlushes.java
*
* Created on October 12, 2006, 11:24 AM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.persistence.kernel;
import org.apache.openjpa.event.AbstractTransactionListener;
import org.apache.openjpa.event.TransactionEvent;
import org.apache.openjpa.kernel.PCState;
import org.apache.openjpa.persistence.OpenJPAEntityManager;
import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI;
import org.apache.openjpa.persistence.kernel.common.apps.
ModInstanceCallbackTests;
import org.apache.openjpa.persistence.kernel.common.apps.ModRuntimeTest1;
public class TestIncrementalFlushes extends BaseKernelTest {
public TestIncrementalFlushes(String str) {
super(str);
}
/**
* Creates a new instance of TestIncrementalFlushes
*/
public TestIncrementalFlushes() {
}
@Override
public void setUp() {
deleteAll(ModRuntimeTest1.class);
// deleteAll(ModInstanceCallbackTests.class);
}
public void testBasicJdoPreStore() {
OpenJPAEntityManager pm = getPM(true, false);
startTx(pm);
ModInstanceCallbackTests a = new ModInstanceCallbackTests("foo", 10);
pm.persist(a);
pm.flush();
assertTrue(a.preStoreCalled);
endTx(pm);
}
public void testNoFlush() {
OpenJPAEntityManager pm = getPM(true, false);
startTx(pm);
ModInstanceCallbackTests a = new ModInstanceCallbackTests("foo", 10);
pm.persist(a);
endTx(pm);
assertTrue(a.preStoreCalled);
}
public void testFlushNoChange() {
OpenJPAEntityManager pm = getPM(true, false);
startTx(pm);
ModInstanceCallbackTests a = new ModInstanceCallbackTests("foo", 10);
pm.persist(a);
pm.flush();
endTx(pm);
assertTrue(a.preStoreCalled);
assertEquals(10, a.getIntField());
}
/**
* Helper method for some common test cases. See utilizations of
* this below.
*/
private void basicHelper(boolean update, boolean multi, boolean dfg,
boolean nonDFG) {
OpenJPAEntityManager pm = getPM(true, false);
startTx(pm);
ModInstanceCallbackTests a = new ModInstanceCallbackTests("foo", 10);
pm.persist(a);
if (update) {
endTx(pm);
Object oid = pm.getObjectId(a);
endEm(pm);
pm = getPM(true, false);
startTx(pm);
a = (ModInstanceCallbackTests) pm
.find(ModInstanceCallbackTests.class, oid);
} else {
pm.flush();
}
if (dfg)
a.setIntField(11);
if (nonDFG)
a.setNonDFGField(11);
if (multi) {
pm.flush();
if (dfg)
a.setIntField(12);
if (nonDFG)
a.setNonDFGField(12);
}
endTx(pm);
// if no changes were made and we're in update mode, then this
// object won't have had jdoPreStore() called.
// if (!(update && (!dfg && !nonDFG)))
// assertTrue("a.prestoreCalled is false", a.preStoreCalled);
if (multi) {
if (dfg)
assertEquals("a.getIntField is not 12", 12, a.getIntField());
if (nonDFG)
assertEquals("a.getNonDFGField is not 12", 12,
a.getNonDFGField());
} else {
if (dfg)
assertEquals("a.getIntField is not 12", 11, a.getIntField());
if (nonDFG)
assertEquals("a.getNonDFGField is not 12", 11,
a.getNonDFGField());
}
}
public void testFlushStorePrimaryDFGChange() {
basicHelper(false, false, true, false);
basicHelper(false, true, true, false);
basicHelper(true, false, true, false);
basicHelper(true, true, true, false);
}
public void testFlushStorePrimaryNonDFGChange() {
basicHelper(false, false, false, true);
basicHelper(false, true, false, true);
basicHelper(true, false, false, true);
basicHelper(true, true, false, true);
}
public void testFlushStorePrimaryNonDFGAndDFGChange() {
basicHelper(false, false, true, true);
basicHelper(false, true, true, true);
basicHelper(true, false, true, true);
basicHelper(true, true, true, true);
}
public void testFlushStorePrimaryNoChanges() {
basicHelper(false, false, false, false);
basicHelper(false, true, false, false);
basicHelper(true, false, false, false);
basicHelper(true, true, false, false);
}
public void testJdoPreStoreWithModificationBeforeFlush() {
tjpswmHelper(true);
}
public void testJdoPreStoreWithModificationAfterFlush() {
tjpswmHelper(false);
}
private void tjpswmHelper(boolean before) {
// set retainvalues to false so that we can ensure that the
// data in the database is correct, and that we're not just
// testing that the JVM data is correct.
OpenJPAEntityManager pm = getPM(true, false);
startTx(pm);
ModInstanceCallbackTests a = new ModInstanceCallbackTests("foo", 10);
pm.persist(a);
// by setting the name to 'bar', the jdoPreStore() invocation
// will set the parent to a new object. This ensures that new
// objects created in jdoPreStore() make their way into the DB
// during commit.
if (before) {
a.setStringField("bar");
pm.flush();
} else {
pm.flush();
a.setStringField("bar");
}
endTx(pm);
assertTrue("a.preStoreCalled is false", a.preStoreCalled);
assertNotNull("a.getOneOne is null", a.getOneOne());
assertTrue("getOneOne().getstrngfld.equals(jdoPrestore) is false",
a.getOneOne().getStringField().equals("jdoPreStore"));
}
public void testOneToOneBefore() {
totoHelper(true, true, false);
totoHelper(true, false, false);
totoHelper(true, true, true);
totoHelper(true, false, true);
}
public void testOneToOneAfter() {
totoHelper(false, true, false);
totoHelper(false, false, false);
totoHelper(false, true, true);
totoHelper(false, false, true);
}
private void totoHelper(boolean before, boolean persist,
boolean multi) {
// set retainvalues to false so that we can ensure that the
// data in the database is correct, and that we're not just
// testing that the JVM data is correct.
OpenJPAEntityManager pm = getPM(true, false);
startTx(pm);
ModInstanceCallbackTests a = new ModInstanceCallbackTests("foo", 10);
pm.persist(a);
ModRuntimeTest1 parent = new ModRuntimeTest1("baz", 11);
if (!before)
pm.flush();
if (persist)
pm.persist(parent);
a.setOneOne(parent);
if (before)
pm.flush();
ModRuntimeTest1 oldParent = null;
if (multi) {
oldParent = parent;
parent = new ModRuntimeTest1("newParent", 12);
if (!before)
pm.flush();
if (persist)
pm.persist(parent);
a.setOneOne(parent);
if (before)
pm.flush();
}
endTx(pm);
assertTrue("a.preStoreCalled is false", a.preStoreCalled);
assertNotNull("a.getOneOne is null", a.getOneOne());
if (!multi)
assertTrue("a.getOneOne().getStringField().equals(baz) is false",
a.getOneOne().getStringField().equals("baz"));
else {
assertTrue(
"a.getOneOne().getStringField().equals(newParent) is false",
a.getOneOne().getStringField().equals("newParent"));
// if multi, then we really should delete the baz
// parent. This isn't happening right now.
// ### should be a bug
//assertTrue (JDOHelper.isDeleted (oldParent));
}
}
private void assertState(Object o, PCState state, OpenJPAEntityManager pm) {
assertEquals(state, getStateManager(o, pm).getPCState());
}
private void commitAndTestDelete(OpenJPAEntityManager pm, Object o) {
Object oid = pm.getObjectId(o);
endTx(pm);
pm = getPM();
try {
pm.find(Object.class, oid);
fail("should not be able to load deleted object");
} catch (Exception e) {
// expected case
}
}
public void testDeleteNew() {
OpenJPAEntityManager pm = getPM(true, false);
startTx(pm);
ModRuntimeTest1 a = new ModRuntimeTest1("foo", 10);
pm.persist(a);
pm.remove(a);
assertState(a, PCState.PNEWDELETED, pm);
}
public void testOptimisticLockGivesCorrectError() {
OpenJPAEntityManager pm1 = getPM(true, false);
OpenJPAEntityManager pm2 = getPM(true, false);
ModRuntimeTest1 a1 = new ModRuntimeTest1("foo", 10);
startTx(pm1);
pm1.persist(a1);
endTx(pm1);
ModRuntimeTest1 a2 = (ModRuntimeTest1)
pm2.find(ModRuntimeTest1.class, pm2.getObjectId(a1));
startTx(pm2);
a2.setStringField("foobar");
endTx(pm2);
startTx(pm1);
a1.setStringField("foobarbaz");
try {
endTx(pm1);
} catch (Exception ole) {
// expected case
} finally {
rollbackTx(pm1);
pm1.close();
pm2.close();
}
}
/**
* Verify that flushes to the datastore are isolated from other
* PersistenceManagers. This is mostly a test of the underlying
* datastore's transactional isolation capabilities.
* <p/>
* Disabled: this hangs on Sybase.
*/
public void XXXtestFlushesAreIsolated() {
final String name = "testFlushesAreIsolated";
deleteAll(ModRuntimeTest1.class);
OpenJPAEntityManager flushPM = getPM(true, false);
startTx(flushPM);
OpenJPAEntityManager readPM = getPM(true, false);
startTx(readPM);
assertSize(0, flushPM.createNativeQuery("stringField == '" + name + "'",
ModRuntimeTest1.class));
assertSize(0, readPM.createNativeQuery("stringField == '" + name + "'",
ModRuntimeTest1.class));
ModRuntimeTest1 a = new ModRuntimeTest1(name, randomInt());
flushPM.persist(a);
assertSize(0, readPM.createNativeQuery("name == '" + name + "'",
ModRuntimeTest1.class));
flushPM.flush();
// make sure the other pm doesn't see the flushed object
assertSize(0, readPM.createNativeQuery("name == '" + name + "'",
ModRuntimeTest1.class));
flushPM.remove(a);
assertSize(0, flushPM.createNativeQuery("name == '" + name + "'",
ModRuntimeTest1.class));
assertSize(0, readPM.createNativeQuery("name == '" + name + "'",
ModRuntimeTest1.class));
endTx(flushPM);
endEm(flushPM);
endTx(readPM);
endEm(readPM);
}
public void testEmptyFlush() {
OpenJPAEntityManager pm = getPM();
TListener listener = new TListener();
((OpenJPAEntityManagerSPI) pm).addTransactionListener(listener);
startTx(pm);
ModRuntimeTest1 pc = new ModRuntimeTest1();
pm.persist(pc);
pm.flush();
assertEquals(1, listener.flushes);
assertEquals(0, listener.commits);
pm.flush();
assertEquals(1, listener.flushes);
assertEquals(0, listener.commits);
pc.setIntField(3);
pm.flush();
assertEquals(2, listener.flushes);
assertEquals(0, listener.commits);
endTx(pm);
assertEquals(2, listener.flushes);
assertEquals(1, listener.commits);
endEm(pm);
}
public void testEmptyRollback() {
OpenJPAEntityManager pm = getPM();
TListener listener = new TListener();
((OpenJPAEntityManagerSPI) pm).addTransactionListener(listener);
startTx(pm);
pm.flush();
rollbackTx(pm);
assertEquals(0, listener.flushes);
assertEquals(0, listener.commits);
endEm(pm);
}
public void testEmptyCommit() {
OpenJPAEntityManager pm = getPM();
TListener listener = new TListener();
((OpenJPAEntityManagerSPI) pm).addTransactionListener(listener);
startTx(pm);
endTx(pm);
assertEquals(0, listener.flushes);
assertEquals(1, listener.commits);
endEm(pm);
}
private static class TListener
extends AbstractTransactionListener {
public int flushes = 0;
public int commits = 0;
@Override
protected void eventOccurred(TransactionEvent event) {
if (event.getType() == TransactionEvent.BEFORE_FLUSH)
flushes++;
else if (event.getType() == TransactionEvent.BEFORE_COMMIT)
commits++;
}
}
}