blob: b079765c38b69ec495f8d3ee088e69731b80e5cf [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.persistence.datacache;
import java.util.ArrayList;
import javax.persistence.EntityManager;
import org.apache.openjpa.persistence.ArgumentException;
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
import org.apache.openjpa.util.UserException;
public class TestJPACache extends SingleEMFTestCase {
@Override
public void setUp() {
super.setUp(CachedPerson.class, CachedManager.class, CachedEmployee.class, "openjpa.DataCache", "true",
"openjpa.RemoteCommitProvider", "sjvm");
}
private void populate() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
CachedPerson p = new CachedPerson();
p.setFirstName("John");
p.setLastName("Doe");
p.setId(10);
em.persist(p);
p = new CachedPerson();
p.setFirstName("Jane");
p.setLastName("Doe");
p.setId(11);
em.persist(p);
CachedManager m = new CachedManager();
m.setFirstName("Joan");
m.setLastName("Baker");
m.setId(12);
m.setEmployees(new ArrayList<>());
em.persist(m);
CachedEmployee e = new CachedEmployee();
e.setFirstName("Jim");
e.setFirstName("Smith");
e.setManager(m);
e.setId(13);
m.getEmployees().add(e);
em.persist(e);
e = new CachedEmployee();
e.setFirstName("Jeff");
e.setFirstName("Parker");
e.setId(14);
e.setManager(m);
m.getEmployees().add(e);
em.persist(e);
em.getTransaction().commit();
em.close();
}
/**
* Ensure the cached returned by emf.getCache supports the JPA and OpenJPA interfaces. Expected interfaces are
* <ul>
* <li>javax.persistence.Cache</li>
* <li>org.apache.openjpa.persistence.StoreCache</li>
* </ul>
*/
public void testInterfacesReturned() {
Object cache = emf.getCache();
assertNotNull("Cache is not enabled", cache);
assertTrue(cache instanceof javax.persistence.Cache);
assertTrue(cache instanceof org.apache.openjpa.persistence.StoreCache);
}
/**
* Ensure that an Entity is not inserted in the cache until the transaction commits.
*/
public void testContains() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
CachedPerson p = new CachedPerson();
p.setFirstName("John");
p.setLastName("Doe");
p.setId(1);
assertNotInCache(CachedPerson.class, 1);
em.persist(p);
assertNotInCache(CachedPerson.class, 1);
em.flush();
assertNotInCache(CachedPerson.class, 1);
em.getTransaction().commit();
assertInCache(CachedPerson.class, 1);
em.close();
}
/**
* Evict a single entity instance of type CachedPerson from the cache. Testcase will fail if
* <ul>
* <li>CachedPerson id:10 and 11 are not in the cache when the test starts.</li>
* <li>CachedPerson id:1 <b>is</b> found in the cache when the test starts.</li>
* <li>CachedPerson id:10 is not found in the cache after evicting CachedPerson id:11</li>
* <li>CachedPerson id:11 is found in the cache after evicting CachedPerson id:11</li>
* <li>CachedPerson id:1 is found in the cache after evicting CachedPerson id:11</li>
* </ul>
*/
public void testEvictInstance() {
populate();
assertInCache(CachedPerson.class, 10);
assertInCache(CachedPerson.class, 11);
assertNotInCache(CachedPerson.class, 1);
emf.getCache().evict(CachedPerson.class, 11);
assertInCache(CachedPerson.class, 10);
assertNotInCache(CachedPerson.class, 11);
assertNotInCache(CachedPerson.class, 1);
}
/**
* Ensure that evict(Class cls) evicts the specified class and any subclasses. This test will fail if
* <ul>
* <li>Any of the entites created in populate() are not found in the cache before calling evict()</li>
* <li>Any instance of CachedPerson from populate() is found in the cache after
* calling evict(CachedPerson.class)</li>
* <li>Any instance of CachedManager or CachedEmployee is found in the cache after calling evict()</li>
* </ul>
*/
public void testEvictClass() {
populate();
assertInCache(CachedPerson.class, 10);
assertInCache(CachedPerson.class, 11);
assertInCache(CachedEmployee.class, 13);
assertInCache(CachedEmployee.class, 14);
assertInCache(CachedManager.class, 12);
emf.getCache().evict(CachedPerson.class);
assertNotInCache(CachedPerson.class, 10);
assertNotInCache(CachedPerson.class, 11);
assertNotInCache(CachedEmployee.class, 13);
assertNotInCache(CachedEmployee.class, 14);
assertNotInCache(CachedManager.class, 12);
}
/**
* Ensure the cache is cleared after calling evictAll. This test will fail if :
* <ul>
* <li>Any of the entities created in populate() are not found in the cache</li>
* <li>Any of the entities which were in the cache before calling evictAll() are still in the cache after calling
* evictAll()</li>
* </ul>
*
*/
public void testEvictAll() {
populate();
assertInCache(CachedPerson.class, 10);
assertInCache(CachedPerson.class, 11);
assertInCache(CachedEmployee.class, 13);
assertInCache(CachedEmployee.class, 14);
assertInCache(CachedManager.class, 12);
emf.getCache().evictAll();
assertNotInCache(CachedPerson.class, 10);
assertNotInCache(CachedPerson.class, 11);
assertNotInCache(CachedEmployee.class, 13);
assertNotInCache(CachedEmployee.class, 14);
assertNotInCache(CachedManager.class, 12);
}
// test methods for bad input.
public void testContainsNullEntity() {
try {
emf.getCache().contains(null, 1);
fail("Expected ArgumentException when calling " + "contains(<null>, <nonNull>)");
} catch (ArgumentException ae) {
// normal
}
}
public void testContainsNonEntityClass() {
try {
emf.getCache().contains(Object.class, 1);
fail("Expected ArgumentException when calling " + "contains(<nonEntityClass>, <nonNull>");
} catch (ArgumentException ae) {
// expected exception
}
}
public void testContainsNullPrimaryKey() {
assertFalse(emf.getCache().contains(CachedPerson.class, null));
}
public void testContainsNegativePrimaryKey() {
assertFalse(emf.getCache().contains(CachedPerson.class, -1));
}
public void testContainsInvalidPrimaryKeyType() {
try{
emf.getCache().contains(CachedPerson.class, "abcd");
fail();
}catch(UserException ue){
//expected
}
}
public void testEvictNullInstance() {
try {
emf.getCache().evict(null, 1);
fail("Expected ArgumentException when calling " + "evict(<null>, <id");
} catch (ArgumentException ae) {
// expected exception
}
}
public void testEvictNonEntityInstance() {
try {
emf.getCache().evict(Object.class, 1);
fail("Expected ArgumentException when calling " + "evict(<null>, <id");
} catch (ArgumentException ae) {
// expected exception
}
}
public void testEvictNullPrimaryKey() {
emf.getCache().evict(CachedPerson.class, null);
}
public void testEvictNegativePrimaryKey() {
emf.getCache().evict(CachedPerson.class, -1);
}
public void testEvictInvalidPrimaryKeyType() {
try{
emf.getCache().evict(CachedPerson.class, "abcd");
fail();
}catch(UserException ue){
//expected
}
}
public void testEvictNullClass() {
try {
emf.getCache().evict(null);
fail("Expected ArgumentException when calling " + "evict(<null>");
} catch (ArgumentException ae) {
// expected exception
}
}
public void testEvictNonEntity() {
try {
emf.getCache().evict(Object.class);
fail("Expected ArgumentException when calling " + "evict(<nonEntity>");
} catch (ArgumentException ae) {
// expected exception
}
}
public void testIllegalStateExceptionAfterClose() {
emf.close();
try {
emf.getCache();
fail("Expected IllegalStateException");
}
catch(IllegalStateException ise) {
// expected
}
}
public void testIllegalStateExceptionGetAfterClose() {
emf.getCache(); // populate the EntityManagerFactoryImpl's wrapper for the StoreCache.
emf.close();
try {
emf.getCache();
fail("Expected IllegalStateException");
}
catch(IllegalStateException ise) {
// expected
}
}
/**
* Convenience method. Asserts that the class & primary key do exist in the cache
*
* @param cls
* Entity class.
* @param primaryKey
* PrimaryKey of the entity.
*/
private void assertInCache(Class<?> cls, Object primaryKey) {
assertTrue(String.format("%s:%s should exist in cache", cls.toString(), primaryKey.toString()), emf.getCache()
.contains(cls, primaryKey));
}
/**
* Convenience method. Assert that the class and primary key do not exist in the cache
*
* @param cls
* Entity class.
* @param primaryKey
* PrimaryKey of the entity.
*/
private void assertNotInCache(Class<?> cls, Object primaryKey) {
assertFalse(String.format("%s:%s should not exist in cache", cls.toString(), primaryKey.toString()), emf
.getCache().contains(cls, primaryKey));
}
}