/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.event.internal;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import junit.framework.TestCase;
/**
* 2011/10/20 Unit test for code added in EventCache for performance improvement.
* @author Wim Ockerman @ CISCO
*
*
*
*/
public class EventCacheTest extends TestCase {
public void testEntityToCopyFillFollowedByCopyToEntityMapping() {
EventCache cache = new EventCache();
Object entity = new Simple( 1 );
Object copy = new Simple( 2 );
cache.put(entity, copy);
checkCacheConsistency( cache, 1 );
assertTrue( cache.containsKey( entity ) );
assertFalse( cache.containsKey( copy ) );
assertTrue( cache.containsValue( copy ) );
assertTrue( cache.invertMap().containsKey( copy ) );
assertFalse( cache.invertMap().containsKey( entity ) );
assertTrue( cache.invertMap().containsValue( entity ) );
cache.clear();
checkCacheConsistency( cache, 0 );
assertFalse(cache.containsKey(entity));
assertFalse(cache.invertMap().containsKey(copy));
}
public void testEntityToCopyFillFollowedByCopyToEntityMappingOnRemove() {
EventCache cache = new EventCache();
Object entity = new Simple( 1 );
Object copy = new Simple( 2 );
cache.put(entity, copy);
checkCacheConsistency( cache, 1 );
assertTrue(cache.containsKey(entity));
assertFalse( cache.containsKey( copy ) );
assertTrue( cache.invertMap().containsKey( copy ) );
assertFalse( cache.invertMap().containsKey( entity ) );
cache.remove( entity );
checkCacheConsistency( cache, 0 );
assertFalse(cache.containsKey(entity));
assertFalse(cache.invertMap().containsKey(copy));
}
public void testEntityToCopyFillFollowedByCopyToEntityUsingPutAll() {
EventCache cache = new EventCache();
Map<Object,Object> input = new HashMap<Object,Object>();
Object entity1 = new Simple( 1 );
//
Object copy1 = new Integer( 2 );
input.put(entity1, copy1);
Object entity2 = new Simple( 3 );
Object copy2 = new Integer( 2 );
input.put(entity2, copy2);
cache.putAll(input);
checkCacheConsistency( cache, 2 );
assertTrue(cache.containsKey(entity1));
assertFalse(cache.containsKey(copy1));
assertTrue(cache.containsKey(entity2));
assertFalse(cache.containsKey(copy2));
assertTrue(cache.invertMap().containsKey(copy1));
assertFalse(cache.invertMap().containsKey(entity1));
assertTrue(cache.invertMap().containsKey(copy2));
assertFalse(cache.invertMap().containsKey(entity2));
}
public void testEntityToCopyFillFollowedByCopyToEntityMappingUsingPutWithSetOperatedOnArg() {
EventCache cache = new EventCache();
Object entity = new Simple( 1 );
Object copy = new Simple( 2 );
cache.put(entity, copy, true);
checkCacheConsistency( cache, 1 );
assertTrue(cache.containsKey(entity));
assertFalse( cache.containsKey( copy ) );
assertTrue( cache.invertMap().containsKey( copy ) );
assertFalse( cache.invertMap().containsKey( entity ) );
cache.clear();
checkCacheConsistency( cache, 0 );
cache.put(entity, copy, false);
checkCacheConsistency( cache, 1 );
assertTrue(cache.containsKey(entity));
assertFalse(cache.containsKey(copy));
}
public void testEntityToCopyFillFollowedByIterateEntrySet() {
EventCache cache = new EventCache();
Object entity = new Simple( 1 );
Object copy = new Simple( 2 );
cache.put( entity, copy, true );
checkCacheConsistency( cache, 1 );
Iterator it = cache.entrySet().iterator();
assertTrue( it.hasNext() );
Map.Entry entry = ( Map.Entry ) it.next();
assertSame( entity, entry.getKey() );
assertSame( copy, entry.getValue() );
assertFalse( it.hasNext() );
}
public void testEntityToCopyFillFollowedByModifyEntrySet() {
EventCache cache = new EventCache();
Object entity = new Simple( 1 );
Object copy = new Simple( 2 );
cache.put( entity, copy, true );
Iterator it = cache.entrySet().iterator();
try {
it.remove();
fail( "should have thrown UnsupportedOperationException" );
}
catch ( UnsupportedOperationException ex ) {
// expected
}
Map.Entry entry = (Map.Entry) cache.entrySet().iterator().next();
try {
cache.entrySet().remove( entry );
fail( "should have thrown UnsupportedOperationException" );
}
catch ( UnsupportedOperationException ex ) {
// expected
}
Map.Entry anotherEntry = new Map.Entry() {
private Object key = new Simple( 3 );
private Object value = 4;
@Override
public Object getKey() {
return key;
}
@Override
public Object getValue() {
return value;
}
@Override
public Object setValue(Object value) {
Object oldValue = this.value;
this.value = value;
return oldValue;
}
};
try {
cache.entrySet().add( anotherEntry );
fail( "should have thrown UnsupportedOperationException" );
}
catch ( UnsupportedOperationException ex ) {
// expected
}
}
public void testEntityToCopyFillFollowedByModifyKeys() {
EventCache cache = new EventCache();
Object entity = new Simple( 1 );
Object copy = new Simple( 2 );
cache.put( entity, copy, true );
Iterator it = cache.keySet().iterator();
try {
it.remove();
fail( "should have thrown UnsupportedOperationException" );
}
catch ( UnsupportedOperationException ex ) {
// expected
}
try {
cache.keySet().remove( entity );
fail( "should have thrown UnsupportedOperationException" );
}
catch ( UnsupportedOperationException ex ) {
// expected
}
Object newCopy = new Simple( 3 );
try {
cache.keySet().add( newCopy );
fail( "should have thrown UnsupportedOperationException" );
}
catch ( UnsupportedOperationException ex ) {
// expected
}
}
public void testEntityToCopyFillFollowedByModifyValues() {
EventCache cache = new EventCache();
Object entity = new Simple( 1 );
Object copy = new Simple( 2 );
cache.put( entity, copy, true );
Iterator it = cache.values().iterator();
try {
it.remove();
fail( "should have thrown UnsupportedOperationException" );
}
catch ( UnsupportedOperationException ex ) {
// expected
}
try {
cache.values().remove( copy );
fail( "should have thrown UnsupportedOperationException" );
}
catch ( UnsupportedOperationException ex ) {
// expected
}
Object newCopy = new Simple( 3 );
try {
cache.values().add( newCopy );
fail( "should have thrown UnsupportedOperationException" );
}
catch ( UnsupportedOperationException ex ) {
// expected
}
}
public void testEntityToCopyFillFollowedByModifyKeyOfEntrySetElement() {
EventCache cache = new EventCache();
Simple entity = new Simple( 1 );
Simple copy = new Simple( 0 );
cache.put(entity, copy, true);
Map.Entry entry = (Map.Entry) cache.entrySet().iterator().next();
( ( Simple ) entry.getKey() ).setValue( 2 );
assertEquals( 2, entity.getValue() );
checkCacheConsistency( cache, 1 );
entry = (Map.Entry) cache.entrySet().iterator().next();
assertSame( entity, entry.getKey() );
assertSame( copy, entry.getValue() );
}
public void testEntityToCopyFillFollowedByModifyValueOfEntrySetElement() {
EventCache cache = new EventCache();
Simple entity = new Simple( 1 );
Simple copy = new Simple( 0 );
cache.put(entity, copy, true);
Map.Entry entry = (Map.Entry) cache.entrySet().iterator().next();
( ( Simple ) entry.getValue() ).setValue( 2 );
assertEquals( 2, copy.getValue() );
checkCacheConsistency( cache, 1 );
entry = (Map.Entry) cache.entrySet().iterator().next();
assertSame( entity, entry.getKey() );
assertSame( copy, entry.getValue() );
}
public void testReplaceEntityCopy() {
EventCache cache = new EventCache();
Simple entity = new Simple( 1 );
Simple copy = new Simple( 0 );
cache.put(entity, copy);
Simple copyNew = new Simple( 0 );
assertSame( copy, cache.put( entity, copyNew ) );
assertSame( copyNew, cache.get( entity ) );
checkCacheConsistency( cache, 1 );
copy = copyNew;
copyNew = new Simple( 1 );
assertSame( copy, cache.put( entity, copyNew ) );
assertSame( copyNew, cache.get( entity ) );
checkCacheConsistency( cache, 1 );
}
public void testCopyAssociatedWithNewAndExistingEntity() {
EventCache cache = new EventCache();
Simple entity = new Simple( 1 );
Simple copy = new Simple( 0 );
cache.put(entity, copy);
try {
cache.put( new Simple( 1 ), copy );
fail( "should have thrown IllegalStateException");
}
catch( IllegalStateException ex ) {
// expected
}
}
public void testCopyAssociatedWith2ExistingEntities() {
EventCache cache = new EventCache();
Simple entity1 = new Simple( 1 );
Simple copy1 = new Simple( 0 );
cache.put(entity1, copy1);
Simple entity2 = new Simple( 2 );
Simple copy2 = new Simple( 0 );
cache.put( entity2, copy2 );
try {
cache.put( entity1, copy2 );
fail( "should have thrown IllegalStateException");
}
catch( IllegalStateException ex ) {
// expected
}
}
public void testRemoveNonExistingEntity() {
EventCache cache = new EventCache();
assertNull( cache.remove( new Simple( 1 ) ) );
}
private void checkCacheConsistency(EventCache cache, int expectedSize) {
Set entrySet = cache.entrySet();
Set cacheKeys = cache.keySet();
Collection cacheValues = cache.values();
Map invertedMap = cache.invertMap();
assertEquals( expectedSize, entrySet.size() );
assertEquals( expectedSize, cache.size() );
assertEquals( expectedSize, cacheKeys.size() );
assertEquals( expectedSize, cacheValues.size() );
assertEquals( expectedSize, invertedMap.size() );
for ( Object entry : cache.entrySet() ) {
Map.Entry mapEntry = ( Map.Entry ) entry;
assertSame( cache.get( mapEntry.getKey() ), mapEntry.getValue() );
assertTrue( cacheKeys.contains( mapEntry.getKey() ) );
assertTrue( cacheValues.contains( mapEntry.getValue() ) );
assertSame( mapEntry.getKey(), invertedMap.get( mapEntry.getValue() ) );
}
}
private static class Simple {
private int value;
public Simple(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
}