blob: f4710a381ca83bfd065de29696753610bf15d2f7 [file] [log] [blame]
/*
* 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.slice;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.apache.openjpa.kernel.AbstractBrokerFactory;
import org.apache.openjpa.kernel.Broker;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.persistence.JPAFacadeHelper;
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
import junit.framework.TestCase;
import junit.framework.TestResult;
/**
* Base test class providing persistence utilities.
*/
public abstract class PersistenceTestCase
extends TestCase {
/**
* Marker object you an pass to {@link #setUp} to indicate that the
* database tables should be cleared.
*/
protected static final Object CLEAR_TABLES = new Object();
/**
* The {@link TestResult} instance for the current test run.
*/
protected TestResult testResult;
/**
* Create an entity manager factory. Put {@link #CLEAR_TABLES} in
* this list to tell the test framework to delete all table contents
* before running the tests.
*
* @param props list of persistent types used in testing and/or
* configuration values in the form key,value,key,value...
*/
protected OpenJPAEntityManagerFactorySPI createEMF(Object... props) {
return createNamedEMF(getPersistenceUnitName(), props);
}
/**
* The name of the persistence unit that this test class should use
* by default. This defaults to "test".
*/
protected String getPersistenceUnitName() {
return "test";
}
/**
* Create an entity manager factory for persistence unit <code>pu</code>.
* Put {@link #CLEAR_TABLES} in
* this list to tell the test framework to delete all table contents
* before running the tests.
*
* @param props list of persistent types used in testing and/or
* configuration values in the form key,value,key,value...
*/
protected OpenJPAEntityManagerFactorySPI createNamedEMF(String pu,
Object... props) {
Map map = new HashMap(System.getProperties());
List<Class> types = new ArrayList<>();
boolean prop = false;
for (int i = 0; i < props.length; i++) {
if (prop) {
map.put(props[i - 1], props[i]);
prop = false;
} else if (props[i] == CLEAR_TABLES) {
map.put("openjpa.jdbc.SynchronizeMappings",
"buildSchema(ForeignKeys=true,"
+ "SchemaAction='add,deleteTableContents')");
} else if (props[i] instanceof Class)
types.add((Class) props[i]);
else if (props[i] != null)
prop = true;
}
if (!types.isEmpty()) {
StringBuilder buf = new StringBuilder();
for (Class c : types) {
if (buf.length() > 0)
buf.append(";");
buf.append(c.getName());
}
map.put("openjpa.MetaDataFactory",
"jpa(Types=" + buf.toString() + ")");
}
if (!map.containsKey("openjpa.ConnectionFactoryProperties")) {
map.put("openjpa.ConnectionFactoryProperties", "PrintParameters=true");
}
return (OpenJPAEntityManagerFactorySPI) Persistence.
createEntityManagerFactory(pu, map);
}
@Override
public void run(TestResult testResult) {
this.testResult = testResult;
super.run(testResult);
}
@Override
public void tearDown() throws Exception {
try {
super.tearDown();
} catch (Exception e) {
// if a test failed, swallow any exceptions that happen
// during tear-down, as these just mask the original problem.
if (testResult.wasSuccessful())
throw e;
}
}
/**
* Safely close the given factory.
*/
protected boolean closeEMF(EntityManagerFactory emf) {
if (emf == null || !emf.isOpen())
return false;
closeAllOpenEMs(emf);
emf.close();
return !emf.isOpen();
}
/**
* Closes all open entity managers after first rolling back any open
* transactions.
*/
protected void closeAllOpenEMs(EntityManagerFactory emf) {
if (emf == null || !emf.isOpen())
return;
for (Broker b : ((AbstractBrokerFactory) JPAFacadeHelper
.toBrokerFactory(emf)).getOpenBrokers()) {
if (b != null && !b.isClosed()) {
EntityManager em = JPAFacadeHelper.toEntityManager(b);
if (em.getTransaction().isActive())
em.getTransaction().rollback();
em.close();
}
}
}
/**
* Delete all instances of the given types using bulk delete queries,
* but do not close any open entity managers.
*/
protected void clear(EntityManagerFactory emf, Class... types) {
if (emf == null || types.length == 0)
return;
List<ClassMetaData> metas = new ArrayList<>(types.length);
for (Class c : types) {
ClassMetaData meta = JPAFacadeHelper.getMetaData(emf, c);
if (meta != null)
metas.add(meta);
}
clear(emf, false, metas.toArray(new ClassMetaData[metas.size()]));
}
/**
* Delete all instances of the persistent types registered with the given
* factory using bulk delete queries, after first closing all open entity
* managers (and rolling back any open transactions).
*/
protected void clear(EntityManagerFactory emf) {
if (emf == null)
return;
clear(emf, true, ((OpenJPAEntityManagerFactorySPI) emf).
getConfiguration().getMetaDataRepositoryInstance().getMetaDatas());
}
/**
* Delete all instances of the given types using bulk delete queries.
* @param closeEMs TODO
*/
private void clear(EntityManagerFactory emf, boolean closeEMs,
ClassMetaData... types) {
if (emf == null || types.length == 0)
return;
// prevent deadlock by closing the open entity managers
// and rolling back any open transactions
// before issuing delete statements on a new entity manager.
if (closeEMs)
closeAllOpenEMs(emf);
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
for (ClassMetaData meta : types) {
if (!meta.isMapped() || meta.isEmbeddedOnly()
|| Modifier.isAbstract(meta.getDescribedType().getModifiers()))
continue;
// em.createQuery("DELETE FROM " + meta.getTypeAlias() + " o").
// executeUpdate();
}
em.getTransaction().commit();
em.close();
}
/**
* Return the entity name for the given type.
*/
protected String entityName(EntityManagerFactory emf, Class c) {
ClassMetaData meta = JPAFacadeHelper.getMetaData(emf, c);
return (meta == null) ? null : meta.getTypeAlias();
}
public static void assertNotEquals(Object o1, Object o2) {
if (o1 == o2)
fail("expected args to be different; were the same instance.");
else if (o1 == null || o2 == null)
return;
else if (o1.equals(o2))
fail("expected args to be different; compared equal.");
}
}