HHH-5942 - Migrate to JUnit 4

This commit is contained in:
Steve Ebersole 2011-03-11 00:12:58 -06:00
parent fd3fb8b316
commit a6f8767a3c
28 changed files with 1413 additions and 1661 deletions

View File

@ -43,7 +43,15 @@ import org.hibernate.impl.SessionImpl;
import org.hibernate.jdbc.Work; import org.hibernate.jdbc.Work;
import org.hibernate.mapping.SimpleAuxiliaryDatabaseObject; import org.hibernate.mapping.SimpleAuxiliaryDatabaseObject;
import org.hibernate.service.spi.ServiceRegistry; import org.hibernate.service.spi.ServiceRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.hibernate.testing.ServiceRegistryBuilder; import org.hibernate.testing.ServiceRegistryBuilder;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import static org.junit.Assert.assertEquals;
/** /**
* I went back to 3.3 source and grabbed the code/logic as it existed back then and crafted this * I went back to 3.3 source and grabbed the code/logic as it existed back then and crafted this
@ -62,8 +70,6 @@ public class SequenceHiLoGeneratorNoIncrementTest extends BaseUnitTestCase {
@Before @Before
protected void setUp() throws Exception { protected void setUp() throws Exception {
super.setUp();
Properties properties = new Properties(); Properties properties = new Properties();
properties.setProperty( SequenceGenerator.SEQUENCE, TEST_SEQUENCE ); properties.setProperty( SequenceGenerator.SEQUENCE, TEST_SEQUENCE );
properties.setProperty( SequenceHiLoGenerator.MAX_LO, "0" ); // JPA allocationSize of 1 properties.setProperty( SequenceHiLoGenerator.MAX_LO, "0" ); // JPA allocationSize of 1
@ -108,7 +114,6 @@ public class SequenceHiLoGeneratorNoIncrementTest extends BaseUnitTestCase {
if ( serviceRegistry != null ) { if ( serviceRegistry != null ) {
ServiceRegistryBuilder.destroy( serviceRegistry ); ServiceRegistryBuilder.destroy( serviceRegistry );
} }
super.tearDown();
} }
@Test @Test

View File

@ -27,6 +27,7 @@ import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Properties;
import org.hibernate.Hibernate; import org.hibernate.Hibernate;
import org.hibernate.Session; import org.hibernate.Session;

View File

@ -69,7 +69,7 @@ public class MigrationTest extends BaseUnitTestCase {
v1cfg.addResource( resource1 ); v1cfg.addResource( resource1 );
new SchemaExport( v1cfg ).execute( false, true, true, false ); new SchemaExport( v1cfg ).execute( false, true, true, false );
SchemaUpdate v1schemaUpdate = new SchemaUpdate( getJdbcServices( v1cfg.getProperties() ), v1cfg ); SchemaUpdate v1schemaUpdate = new SchemaUpdate( getJdbcServices(), v1cfg );
v1schemaUpdate.execute( true, true ); v1schemaUpdate.execute( true, true );
assertEquals( 0, v1schemaUpdate.getExceptions().size() ); assertEquals( 0, v1schemaUpdate.getExceptions().size() );
@ -77,11 +77,11 @@ public class MigrationTest extends BaseUnitTestCase {
Configuration v2cfg = new Configuration(); Configuration v2cfg = new Configuration();
v2cfg.addResource( resource2 ); v2cfg.addResource( resource2 );
SchemaUpdate v2schemaUpdate = new SchemaUpdate( getJdbcServices( v2cfg.getProperties() ), v2cfg ); SchemaUpdate v2schemaUpdate = new SchemaUpdate( getJdbcServices(), v2cfg );
v2schemaUpdate.execute( true, true ); v2schemaUpdate.execute( true, true );
assertEquals( 0, v2schemaUpdate.getExceptions().size() ); assertEquals( 0, v2schemaUpdate.getExceptions().size() );
new SchemaExport( getJdbcServices( v2cfg.getProperties() ), v2cfg ).drop( false, true ); new SchemaExport( getJdbcServices(), v2cfg ).drop( false, true );
} }

View File

@ -1,191 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat Inc. 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 Inc.
*
* 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.testing.junit;
import static org.hibernate.TestLogger.LOG;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import junit.framework.AssertionFailedError;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.hibernate.AssertionFailure;
import org.hibernate.TestLogger;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.service.spi.ServiceRegistry;
import org.hibernate.testing.ServiceRegistryBuilder;
import org.jboss.logging.Logger;
/**
* A basic JUnit {@link junit.framework.TestCase} subclass for
* adding some Hibernate specific behavior and functionality.
*
* @author Steve Ebersole
*/
public abstract class UnitTestCase extends junit.framework.TestCase {
private ServiceRegistry serviceRegistry;
private Properties serviceRegistryProperties;
public UnitTestCase(String string) {
super( string );
}
/**
* runBare overridden in order to apply FailureExpected validations
* as well as start/complete logging
*
* @throws Throwable
*/
@Override
public void runBare() throws Throwable {
final boolean doValidate = getName().endsWith( "FailureExpected" ) && Boolean.getBoolean( "hibernate.test.validatefailureexpected" );
try {
Logger.getMessageLogger(TestLogger.class, TestLogger.class.getName()).info("Starting test [" + fullTestName() + "]");
super.runBare();
if ( doValidate ) {
throw new FailureExpectedTestPassedException();
}
}
catch ( FailureExpectedTestPassedException t ) {
throw t;
}
catch( Throwable t ) {
if ( doValidate ) {
skipExpectedFailure( t );
}
else {
throw t;
}
}
finally {
LOG.info("Completed test [" + fullTestName() + "]");
}
}
@Override
protected void tearDown() throws Exception {
if ( serviceRegistry != null ) {
ServiceRegistryBuilder.destroy( serviceRegistry );
serviceRegistry = null;
}
}
protected ServiceRegistry getServiceRegistry(Properties properties) {
if ( serviceRegistry == null ) {
serviceRegistryProperties = properties;
serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( properties );
}
else if ( ! properties.equals( serviceRegistryProperties ) ) {
throw new AssertionFailure( "ServiceRegistry was already build using different properties." );
}
return serviceRegistry;
}
protected JdbcServices getJdbcServices(Properties properties) {
return getServiceRegistry( properties ).getService( JdbcServices.class );
}
private static class FailureExpectedTestPassedException extends Exception {
public FailureExpectedTestPassedException() {
super( "Test marked as FailureExpected, but did not fail!" );
}
}
protected void skipExpectedFailure(Throwable error) {
reportSkip( "ignoring *FailuredExpected methods", "Failed with: " + error.toString() );
}
// additional assertions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public static void assertElementTypeAssignability(java.util.Collection collection, Class clazz) throws AssertionFailedError {
for ( Object aCollection : collection ) {
assertClassAssignability( aCollection.getClass(), clazz );
}
}
public static void assertClassAssignability(Class source, Class target) throws AssertionFailedError {
if ( !target.isAssignableFrom( source ) ) {
throw new AssertionFailedError(
"Classes were not assignment-compatible : source<" + source.getName() +
"> target<" + target.getName() + ">"
);
}
}
// test skipping ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public String fullTestName() {
return this.getClass().getName() + "#" + this.getName();
}
protected void reportSkip(String reason, String testDescription) {
LOG.warn("*** skipping [" + fullTestName() + "] - " + testDescription + " : " + reason, new Exception());
}
// testsuite utitities ---------------------------------------------------
/**
* Supports easy creation of TestSuites where a subclass' "FailureExpected"
* version of a base test is included in the suite, while the base test
* is excluded. E.g. test class FooTestCase includes method testBar(), while test
* class SubFooTestCase extends FooTestCase includes method testBarFailureExcluded().
* Passing SubFooTestCase.class to this method will return a suite that
* does not include testBar().
*/
public static TestSuite createFailureExpectedSuite(Class testClass) {
TestSuite allTests = new TestSuite(testClass);
Set failureExpected = new HashSet();
Enumeration tests = allTests.tests();
while (tests.hasMoreElements()) {
Test t = (Test) tests.nextElement();
if (t instanceof TestCase) {
String name = ((TestCase) t).getName();
if (name.endsWith("FailureExpected"))
failureExpected.add(name);
}
}
TestSuite result = new TestSuite();
tests = allTests.tests();
while (tests.hasMoreElements()) {
Test t = (Test) tests.nextElement();
if (t instanceof TestCase) {
String name = ((TestCase) t).getName();
if (!failureExpected.contains(name + "FailureExpected")) {
result.addTest(t);
}
}
}
return result;
}
}

View File

@ -29,10 +29,15 @@ import org.hibernate.cache.TransactionalDataRegion;
import org.hibernate.cache.access.AccessType; import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.infinispan.InfinispanRegionFactory; import org.hibernate.cache.infinispan.InfinispanRegionFactory;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.service.jta.platform.internal.JtaPlatformInitiator; import org.hibernate.service.jta.platform.internal.JtaPlatformInitiator;
import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
import org.hibernate.testing.ServiceRegistryBuilder; import org.hibernate.testing.ServiceRegistryBuilder;
import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/** /**
* Base class for tests of EntityRegion and CollectionRegion implementations. * Base class for tests of EntityRegion and CollectionRegion implementations.
@ -41,16 +46,6 @@ import org.hibernate.testing.ServiceRegistryBuilder;
* @since 3.5 * @since 3.5
*/ */
public abstract class AbstractEntityCollectionRegionTestCase extends AbstractRegionImplTestCase { public abstract class AbstractEntityCollectionRegionTestCase extends AbstractRegionImplTestCase {
/**
* Create a new EntityCollectionRegionTestCaseBase.
*
* @param name
*/
public AbstractEntityCollectionRegionTestCase(String name) {
super(name);
}
/** /**
* Creates a Region backed by an PESSIMISTIC locking JBoss Cache, and then ensures that it * Creates a Region backed by an PESSIMISTIC locking JBoss Cache, and then ensures that it
* handles calls to buildAccessStrategy as expected when all the various {@link AccessType}s are * handles calls to buildAccessStrategy as expected when all the various {@link AccessType}s are

View File

@ -23,16 +23,25 @@
*/ */
package org.hibernate.test.cache.infinispan; package org.hibernate.test.cache.infinispan;
import static org.hibernate.TestLogger.LOG;
import java.util.Set; import java.util.Set;
import org.infinispan.transaction.tm.BatchModeTransactionManager;
import org.hibernate.cache.GeneralDataRegion; import org.hibernate.cache.GeneralDataRegion;
import org.hibernate.cache.QueryResultsRegion; import org.hibernate.cache.QueryResultsRegion;
import org.hibernate.cache.Region; import org.hibernate.cache.Region;
import org.hibernate.cache.infinispan.InfinispanRegionFactory; import org.hibernate.cache.infinispan.InfinispanRegionFactory;
import org.hibernate.cache.infinispan.util.CacheAdapter; import org.hibernate.cache.infinispan.util.CacheAdapter;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
import org.hibernate.service.internal.ServiceRegistryImpl;
import org.junit.Test;
import org.hibernate.test.cache.infinispan.util.CacheTestUtil; import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
import org.infinispan.transaction.tm.BatchModeTransactionManager;
import static org.hibernate.TestLogger.LOG;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
/** /**
* Base class for tests of QueryResultsRegion and TimestampsRegion. * Base class for tests of QueryResultsRegion and TimestampsRegion.
@ -41,162 +50,175 @@ import org.infinispan.transaction.tm.BatchModeTransactionManager;
* @since 3.5 * @since 3.5
*/ */
public abstract class AbstractGeneralDataRegionTestCase extends AbstractRegionImplTestCase { public abstract class AbstractGeneralDataRegionTestCase extends AbstractRegionImplTestCase {
protected static final String KEY = "Key"; protected static final String KEY = "Key";
protected static final String VALUE1 = "value1"; protected static final String VALUE1 = "value1";
protected static final String VALUE2 = "value2"; protected static final String VALUE2 = "value2";
public AbstractGeneralDataRegionTestCase(String name) { protected Configuration createConfiguration() {
super(name); return CacheTestUtil.buildConfiguration( "test", InfinispanRegionFactory.class, false, true );
} }
@Override @Override
protected void putInRegion(Region region, Object key, Object value) { protected void putInRegion(Region region, Object key, Object value) {
((GeneralDataRegion) region).put(key, value); ((GeneralDataRegion) region).put( key, value );
} }
@Override @Override
protected void removeFromRegion(Region region, Object key) { protected void removeFromRegion(Region region, Object key) {
((GeneralDataRegion) region).evict(key); ((GeneralDataRegion) region).evict( key );
} }
/** @Test
* Test method for {@link QueryResultsRegion#evict(java.lang.Object)}. public void testEvict() throws Exception {
* evictOrRemoveTest();
* FIXME add testing of the "immediately without regard for transaction isolation" bit in the }
* CollectionRegionAccessStrategy API.
*/
public void testEvict() throws Exception {
evictOrRemoveTest();
}
private void evictOrRemoveTest() throws Exception { private void evictOrRemoveTest() throws Exception {
Configuration cfg = createConfiguration(); Configuration cfg = createConfiguration();
InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory( InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(
getServiceRegistry( cfg.getProperties() ), cfg, getCacheTestSupport() new ServiceRegistryImpl( cfg.getProperties() ),
); cfg,
CacheAdapter localCache = getInfinispanCache(regionFactory); getCacheTestSupport()
boolean invalidation = localCache.isClusteredInvalidation(); );
CacheAdapter localCache = getInfinispanCache( regionFactory );
boolean invalidation = localCache.isClusteredInvalidation();
// Sleep a bit to avoid concurrent FLUSH problem // Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush(); avoidConcurrentFlush();
GeneralDataRegion localRegion = (GeneralDataRegion) createRegion(regionFactory, GeneralDataRegion localRegion = (GeneralDataRegion) createRegion(
getStandardRegionName(REGION_PREFIX), cfg.getProperties(), null); regionFactory,
getStandardRegionName( REGION_PREFIX ), cfg.getProperties(), null
);
cfg = createConfiguration(); cfg = createConfiguration();
regionFactory = CacheTestUtil.startRegionFactory( regionFactory = CacheTestUtil.startRegionFactory(
getServiceRegistry( cfg.getProperties() ), cfg, getCacheTestSupport() new ServiceRegistryImpl( cfg.getProperties() ),
); cfg,
getCacheTestSupport()
);
GeneralDataRegion remoteRegion = (GeneralDataRegion) createRegion(regionFactory, GeneralDataRegion remoteRegion = (GeneralDataRegion) createRegion(
getStandardRegionName(REGION_PREFIX), cfg.getProperties(), null); regionFactory,
getStandardRegionName( REGION_PREFIX ),
cfg.getProperties(),
null
);
assertNull("local is clean", localRegion.get(KEY)); assertNull( "local is clean", localRegion.get( KEY ) );
assertNull("remote is clean", remoteRegion.get(KEY)); assertNull( "remote is clean", remoteRegion.get( KEY ) );
localRegion.put(KEY, VALUE1); localRegion.put( KEY, VALUE1 );
assertEquals(VALUE1, localRegion.get(KEY)); assertEquals( VALUE1, localRegion.get( KEY ) );
// allow async propagation // allow async propagation
sleep(250); sleep( 250 );
Object expected = invalidation ? null : VALUE1; Object expected = invalidation ? null : VALUE1;
assertEquals(expected, remoteRegion.get(KEY)); assertEquals( expected, remoteRegion.get( KEY ) );
localRegion.evict(KEY); localRegion.evict( KEY );
// allow async propagation // allow async propagation
sleep(250); sleep( 250 );
assertEquals(null, localRegion.get(KEY)); assertEquals( null, localRegion.get( KEY ) );
assertEquals(null, remoteRegion.get(KEY)); assertEquals( null, remoteRegion.get( KEY ) );
} }
protected abstract String getStandardRegionName(String regionPrefix); protected abstract String getStandardRegionName(String regionPrefix);
/** /**
* Test method for {@link QueryResultsRegion#evictAll()}. * Test method for {@link QueryResultsRegion#evictAll()}.
* * <p/>
* FIXME add testing of the "immediately without regard for transaction isolation" bit in the * FIXME add testing of the "immediately without regard for transaction isolation" bit in the
* CollectionRegionAccessStrategy API. * CollectionRegionAccessStrategy API.
*/ */
public void testEvictAll() throws Exception { public void testEvictAll() throws Exception {
evictOrRemoveAllTest("entity"); evictOrRemoveAllTest( "entity" );
} }
private void evictOrRemoveAllTest(String configName) throws Exception { private void evictOrRemoveAllTest(String configName) throws Exception {
Configuration cfg = createConfiguration(); Configuration cfg = createConfiguration();
InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory( InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(
getServiceRegistry( cfg.getProperties() ), cfg, getCacheTestSupport() new ServiceRegistryImpl( cfg.getProperties() ),
); cfg,
CacheAdapter localCache = getInfinispanCache(regionFactory); getCacheTestSupport()
);
CacheAdapter localCache = getInfinispanCache( regionFactory );
// Sleep a bit to avoid concurrent FLUSH problem // Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush(); avoidConcurrentFlush();
GeneralDataRegion localRegion = (GeneralDataRegion) createRegion(regionFactory, GeneralDataRegion localRegion = (GeneralDataRegion) createRegion(
getStandardRegionName(REGION_PREFIX), cfg.getProperties(), null); regionFactory,
getStandardRegionName( REGION_PREFIX ),
cfg.getProperties(),
null
);
cfg = createConfiguration(); cfg = createConfiguration();
regionFactory = CacheTestUtil.startRegionFactory( regionFactory = CacheTestUtil.startRegionFactory(
getServiceRegistry( cfg.getProperties() ), cfg, getCacheTestSupport() new ServiceRegistryImpl( cfg.getProperties() ),
); cfg,
CacheAdapter remoteCache = getInfinispanCache(regionFactory); getCacheTestSupport()
);
CacheAdapter remoteCache = getInfinispanCache( regionFactory );
// Sleep a bit to avoid concurrent FLUSH problem // Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush(); avoidConcurrentFlush();
GeneralDataRegion remoteRegion = (GeneralDataRegion) createRegion(regionFactory, GeneralDataRegion remoteRegion = (GeneralDataRegion) createRegion(
getStandardRegionName(REGION_PREFIX), cfg.getProperties(), null); regionFactory,
getStandardRegionName( REGION_PREFIX ),
cfg.getProperties(),
null
);
Set keys = localCache.keySet(); Set keys = localCache.keySet();
assertEquals("No valid children in " + keys, 0, getValidKeyCount(keys)); assertEquals( "No valid children in " + keys, 0, getValidKeyCount( keys ) );
keys = remoteCache.keySet(); keys = remoteCache.keySet();
assertEquals("No valid children in " + keys, 0, getValidKeyCount(keys)); assertEquals( "No valid children in " + keys, 0, getValidKeyCount( keys ) );
assertNull("local is clean", localRegion.get(KEY)); assertNull( "local is clean", localRegion.get( KEY ) );
assertNull("remote is clean", remoteRegion.get(KEY)); assertNull( "remote is clean", remoteRegion.get( KEY ) );
localRegion.put(KEY, VALUE1); localRegion.put( KEY, VALUE1 );
assertEquals(VALUE1, localRegion.get(KEY)); assertEquals( VALUE1, localRegion.get( KEY ) );
// Allow async propagation // Allow async propagation
sleep(250); sleep( 250 );
remoteRegion.put(KEY, VALUE1); remoteRegion.put( KEY, VALUE1 );
assertEquals(VALUE1, remoteRegion.get(KEY)); assertEquals( VALUE1, remoteRegion.get( KEY ) );
// Allow async propagation // Allow async propagation
sleep(250); sleep( 250 );
localRegion.evictAll(); localRegion.evictAll();
// allow async propagation // allow async propagation
sleep(250); sleep( 250 );
// This should re-establish the region root node in the optimistic case // This should re-establish the region root node in the optimistic case
assertNull(localRegion.get(KEY)); assertNull( localRegion.get( KEY ) );
assertEquals("No valid children in " + keys, 0, getValidKeyCount(localCache.keySet())); assertEquals( "No valid children in " + keys, 0, getValidKeyCount( localCache.keySet() ) );
// Re-establishing the region root on the local node doesn't // Re-establishing the region root on the local node doesn't
// propagate it to other nodes. Do a get on the remote node to re-establish // propagate it to other nodes. Do a get on the remote node to re-establish
// This only adds a node in the case of optimistic locking // This only adds a node in the case of optimistic locking
assertEquals(null, remoteRegion.get(KEY)); assertEquals( null, remoteRegion.get( KEY ) );
assertEquals("No valid children in " + keys, 0, getValidKeyCount(remoteCache.keySet())); assertEquals( "No valid children in " + keys, 0, getValidKeyCount( remoteCache.keySet() ) );
assertEquals("local is clean", null, localRegion.get(KEY)); assertEquals( "local is clean", null, localRegion.get( KEY ) );
assertEquals("remote is clean", null, remoteRegion.get(KEY)); assertEquals( "remote is clean", null, remoteRegion.get( KEY ) );
} }
protected Configuration createConfiguration() { protected void rollback() {
Configuration cfg = CacheTestUtil.buildConfiguration("test", InfinispanRegionFactory.class, false, true); try {
return cfg; BatchModeTransactionManager.getInstance().rollback();
} }
catch (Exception e) {
protected void rollback() { LOG.error( e.getMessage(), e );
try { }
BatchModeTransactionManager.getInstance().rollback(); }
} catch (Exception e) { }
LOG.error(e.getMessage(), e);
}
}
}

View File

@ -23,13 +23,19 @@
*/ */
package org.hibernate.test.cache.infinispan; package org.hibernate.test.cache.infinispan;
import static org.hibernate.TestLogger.LOG;
import java.util.Set; import java.util.Set;
import org.infinispan.Cache;
import org.hibernate.cache.RegionFactory; import org.hibernate.cache.RegionFactory;
import org.hibernate.cache.infinispan.util.CacheHelper; import org.hibernate.cache.infinispan.util.CacheHelper;
import org.junit.After;
import org.junit.Before;
import org.hibernate.test.cache.infinispan.util.CacheTestSupport; import org.hibernate.test.cache.infinispan.util.CacheTestSupport;
import org.hibernate.testing.junit.UnitTestCase;
import org.infinispan.Cache; import static org.hibernate.TestLogger.LOG;
/** /**
* Base class for all non-functional tests of Infinispan integration. * Base class for all non-functional tests of Infinispan integration.
@ -37,29 +43,32 @@ import org.infinispan.Cache;
* @author Galder Zamarreño * @author Galder Zamarreño
* @since 3.5 * @since 3.5
*/ */
public abstract class AbstractNonFunctionalTestCase extends UnitTestCase { public abstract class AbstractNonFunctionalTestCase extends org.hibernate.testing.junit4.BaseUnitTestCase {
public static final String REGION_PREFIX = "test"; public static final String REGION_PREFIX = "test";
private CacheTestSupport testSupport; private static final String PREFER_IPV4STACK = "java.net.preferIPv4Stack";
private String preferIPv4Stack;
public AbstractNonFunctionalTestCase(String name) { private CacheTestSupport testSupport = new CacheTestSupport();
super(name);
testSupport = new CacheTestSupport();
}
@Override @Before
protected void setUp() throws Exception { public void prepareCacheSupport() throws Exception {
super.setUp(); preferIPv4Stack = System.getProperty( PREFER_IPV4STACK );
System.setProperty( PREFER_IPV4STACK, "true" );
testSupport.setUp(); testSupport.setUp();
} }
@Override @After
protected void tearDown() throws Exception { public void releaseCachSupport() throws Exception {
super.tearDown();
testSupport.tearDown(); testSupport.tearDown();
if ( preferIPv4Stack == null ) {
System.clearProperty( PREFER_IPV4STACK );
}
else {
System.setProperty( PREFER_IPV4STACK, preferIPv4Stack );
}
} }
protected void registerCache(Cache cache) { protected void registerCache(Cache cache) {

View File

@ -38,10 +38,6 @@ import org.hibernate.internal.util.compare.ComparableComparator;
*/ */
public abstract class AbstractRegionImplTestCase extends AbstractNonFunctionalTestCase { public abstract class AbstractRegionImplTestCase extends AbstractNonFunctionalTestCase {
public AbstractRegionImplTestCase(String name) {
super(name);
}
protected abstract CacheAdapter getInfinispanCache(InfinispanRegionFactory regionFactory); protected abstract CacheAdapter getInfinispanCache(InfinispanRegionFactory regionFactory);
protected abstract Region createRegion(InfinispanRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd); protected abstract Region createRegion(InfinispanRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd);

View File

@ -0,0 +1,138 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. 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 Inc.
*
* 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.test.cache.infinispan;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.infinispan.InfinispanRegionFactory;
import org.hibernate.cache.infinispan.collection.CollectionRegionImpl;
import org.hibernate.cache.infinispan.entity.EntityRegionImpl;
import org.hibernate.cache.infinispan.util.FlagAdapter;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.internal.ServiceRegistryImpl;
import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
/**
* Defines the environment for a node.
*
* @author Steve Ebersole
*/
public class NodeEnvironment {
private final Configuration configuration;
private ServiceRegistryImpl serviceRegistry;
private InfinispanRegionFactory regionFactory;
private Map<String,EntityRegionImpl> entityRegionMap;
private Map<String,CollectionRegionImpl> collectionRegionMap;
public NodeEnvironment(Configuration configuration) {
this.configuration = configuration;
}
public Configuration getConfiguration() {
return configuration;
}
public ServiceRegistryImpl getServiceRegistry() {
return serviceRegistry;
}
public EntityRegionImpl getEntityRegion(String name, CacheDataDescription cacheDataDescription) {
if ( entityRegionMap == null ) {
entityRegionMap = new HashMap<String, EntityRegionImpl>();
return buildAndStoreEntityRegion( name, cacheDataDescription );
}
EntityRegionImpl region = entityRegionMap.get( name );
if ( region == null ) {
region = buildAndStoreEntityRegion( name, cacheDataDescription );
}
return region;
}
private EntityRegionImpl buildAndStoreEntityRegion(String name, CacheDataDescription cacheDataDescription) {
EntityRegionImpl region = (EntityRegionImpl) regionFactory.buildEntityRegion(
name,
configuration.getProperties(),
cacheDataDescription
);
entityRegionMap.put( name, region );
return region;
}
public CollectionRegionImpl getCollectionRegion(String name, CacheDataDescription cacheDataDescription) {
if ( collectionRegionMap == null ) {
collectionRegionMap = new HashMap<String, CollectionRegionImpl>();
return buildAndStoreCollectionRegion( name, cacheDataDescription );
}
CollectionRegionImpl region = collectionRegionMap.get( name );
if ( region == null ) {
region = buildAndStoreCollectionRegion( name, cacheDataDescription );
collectionRegionMap.put( name, region );
}
return region;
}
private CollectionRegionImpl buildAndStoreCollectionRegion(String name, CacheDataDescription cacheDataDescription) {
CollectionRegionImpl region;
region = (CollectionRegionImpl) regionFactory.buildCollectionRegion(
name,
configuration.getProperties(),
cacheDataDescription
);
return region;
}
public void prepare() throws Exception {
serviceRegistry = new ServiceRegistryImpl( configuration.getProperties() );
regionFactory = CacheTestUtil.startRegionFactory( serviceRegistry, configuration );
}
public void release() throws Exception {
if ( entityRegionMap != null ) {
for ( EntityRegionImpl region : entityRegionMap.values() ) {
region.getCacheAdapter().withFlags( FlagAdapter.CACHE_MODE_LOCAL ).clear();
region.getCacheAdapter().stop();
}
entityRegionMap.clear();
}
if ( collectionRegionMap != null ) {
for ( CollectionRegionImpl collectionRegion : collectionRegionMap.values() ) {
collectionRegion.getCacheAdapter().withFlags( FlagAdapter.CACHE_MODE_LOCAL ).clear();
collectionRegion.getCacheAdapter().stop();
}
collectionRegionMap.clear();
}
if ( regionFactory != null ) {
// Currently the RegionFactory is shutdown by its registration with the CacheTestSetup from CacheTestUtil when built
regionFactory.stop();
}
if ( serviceRegistry != null ) {
serviceRegistry.destroy();
}
}
}

View File

@ -23,20 +23,17 @@
*/ */
package org.hibernate.test.cache.infinispan.collection; package org.hibernate.test.cache.infinispan.collection;
import static org.hibernate.TestLogger.LOG; import javax.transaction.TransactionManager;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.transaction.TransactionManager;
import junit.extensions.TestSetup; import org.infinispan.transaction.tm.BatchModeTransactionManager;
import junit.framework.AssertionFailedError;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.hibernate.cache.CacheDataDescription; import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.CollectionRegion;
import org.hibernate.cache.access.AccessType; import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.access.CollectionRegionAccessStrategy; import org.hibernate.cache.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.impl.CacheDataDescriptionImpl; import org.hibernate.cache.impl.CacheDataDescriptionImpl;
@ -44,17 +41,24 @@ import org.hibernate.cache.infinispan.InfinispanRegionFactory;
import org.hibernate.cache.infinispan.access.PutFromLoadValidator; import org.hibernate.cache.infinispan.access.PutFromLoadValidator;
import org.hibernate.cache.infinispan.access.TransactionalAccessDelegate; import org.hibernate.cache.infinispan.access.TransactionalAccessDelegate;
import org.hibernate.cache.infinispan.collection.CollectionRegionImpl; import org.hibernate.cache.infinispan.collection.CollectionRegionImpl;
import org.hibernate.cache.infinispan.impl.BaseRegion;
import org.hibernate.cache.infinispan.util.CacheAdapter;
import org.hibernate.cache.infinispan.util.FlagAdapter;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
import org.hibernate.internal.util.compare.ComparableComparator; import org.hibernate.internal.util.compare.ComparableComparator;
import org.hibernate.service.spi.ServiceRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import junit.framework.AssertionFailedError;
import org.hibernate.test.cache.infinispan.AbstractNonFunctionalTestCase; import org.hibernate.test.cache.infinispan.AbstractNonFunctionalTestCase;
import org.hibernate.test.cache.infinispan.NodeEnvironment;
import org.hibernate.test.cache.infinispan.functional.cluster.DualNodeJtaTransactionManagerImpl; import org.hibernate.test.cache.infinispan.functional.cluster.DualNodeJtaTransactionManagerImpl;
import org.hibernate.test.cache.infinispan.util.CacheTestUtil; import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
import org.hibernate.testing.ServiceRegistryBuilder;
import org.infinispan.transaction.tm.BatchModeTransactionManager; import static org.hibernate.TestLogger.LOG;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/** /**
* Base class for tests of CollectionRegionAccessStrategy impls. * Base class for tests of CollectionRegionAccessStrategy impls.
@ -64,513 +68,401 @@ import org.infinispan.transaction.tm.BatchModeTransactionManager;
*/ */
public abstract class AbstractCollectionRegionAccessStrategyTestCase extends AbstractNonFunctionalTestCase { public abstract class AbstractCollectionRegionAccessStrategyTestCase extends AbstractNonFunctionalTestCase {
public static final String REGION_NAME = "test/com.foo.test"; public static final String REGION_NAME = "test/com.foo.test";
public static final String KEY_BASE = "KEY"; public static final String KEY_BASE = "KEY";
public static final String VALUE1 = "VALUE1"; public static final String VALUE1 = "VALUE1";
public static final String VALUE2 = "VALUE2"; public static final String VALUE2 = "VALUE2";
protected static int testCount; protected static int testCount;
protected static Configuration localCfg; protected NodeEnvironment localEnvironment;
protected static InfinispanRegionFactory localRegionFactory; protected CollectionRegionImpl localCollectionRegion;
protected CacheAdapter localCache; protected CollectionRegionAccessStrategy localAccessStrategy;
protected static Configuration remoteCfg;
protected static InfinispanRegionFactory remoteRegionFactory; protected NodeEnvironment remoteEnvironment;
protected CacheAdapter remoteCache; protected CollectionRegionImpl remoteCollectionRegion;
protected CollectionRegionAccessStrategy remoteAccessStrategy;
protected CollectionRegion localCollectionRegion;
protected CollectionRegionAccessStrategy localAccessStrategy; protected boolean invalidation;
protected boolean synchronous;
protected CollectionRegion remoteCollectionRegion;
protected CollectionRegionAccessStrategy remoteAccessStrategy; protected Exception node1Exception;
protected Exception node2Exception;
protected boolean invalidation;
protected boolean synchronous; protected AssertionFailedError node1Failure;
protected AssertionFailedError node2Failure;
protected Exception node1Exception;
protected Exception node2Exception; protected abstract AccessType getAccessType();
protected AssertionFailedError node1Failure; @Before
protected AssertionFailedError node2Failure; public void prepareResources() throws Exception {
// to mimic exactly the old code results, both environments here are exactly the same...
public static Test getTestSetup( Class testClass, Configuration cfg = createConfiguration( getConfigurationName() );
String configName ) { localEnvironment = new NodeEnvironment( cfg );
TestSuite suite = new TestSuite(testClass); localEnvironment.prepare();
return new AccessStrategyTestSetup(suite, configName);
} localCollectionRegion = localEnvironment.getCollectionRegion( REGION_NAME, getCacheDataDescription() );
localAccessStrategy = localCollectionRegion.buildAccessStrategy( getAccessType() );
public static Test getTestSetup( Test test,
String configName ) { invalidation = localCollectionRegion.getCacheAdapter().isClusteredInvalidation();
return new AccessStrategyTestSetup(test, configName); synchronous = localCollectionRegion.getCacheAdapter().isSynchronous();
}
// Sleep a bit to avoid concurrent FLUSH problem
/** avoidConcurrentFlush();
* Create a new TransactionalAccessTestCase.
* remoteEnvironment = new NodeEnvironment( cfg );
* @param name remoteEnvironment.prepare();
*/
public AbstractCollectionRegionAccessStrategyTestCase( String name ) { remoteCollectionRegion = remoteEnvironment.getCollectionRegion( REGION_NAME, getCacheDataDescription() );
super(name); remoteAccessStrategy = remoteCollectionRegion.buildAccessStrategy( getAccessType() );
} }
protected abstract AccessType getAccessType(); protected abstract String getConfigurationName();
@Override protected static Configuration createConfiguration(String configName) {
protected void setUp() throws Exception { Configuration cfg = CacheTestUtil.buildConfiguration(
super.setUp(); REGION_PREFIX, InfinispanRegionFactory.class, true, false
);
// Sleep a bit to avoid concurrent FLUSH problem cfg.setProperty( InfinispanRegionFactory.ENTITY_CACHE_RESOURCE_PROP, configName );
avoidConcurrentFlush(); return cfg;
}
localCollectionRegion = localRegionFactory.buildCollectionRegion(REGION_NAME,
localCfg.getProperties(), protected CacheDataDescription getCacheDataDescription() {
getCacheDataDescription()); return new CacheDataDescriptionImpl( true, true, ComparableComparator.INSTANCE );
localCache = ((BaseRegion)localCollectionRegion).getCacheAdapter(); }
localAccessStrategy = localCollectionRegion.buildAccessStrategy(getAccessType());
invalidation = localCache.isClusteredInvalidation(); @After
synchronous = localCache.isSynchronous(); public void releaseResources() throws Exception {
if ( localEnvironment != null ) {
// Sleep a bit to avoid concurrent FLUSH problem localEnvironment.release();
avoidConcurrentFlush(); }
if ( remoteEnvironment != null ) {
remoteCollectionRegion = remoteRegionFactory.buildCollectionRegion(REGION_NAME, remoteEnvironment.release();
remoteCfg.getProperties(), }
getCacheDataDescription()); }
remoteCache = ((BaseRegion)remoteCollectionRegion).getCacheAdapter();
remoteAccessStrategy = remoteCollectionRegion.buildAccessStrategy(getAccessType()); protected boolean isUsingInvalidation() {
return invalidation;
node1Exception = null; }
node2Exception = null;
protected boolean isSynchronous() {
node1Failure = null; return synchronous;
node2Failure = null; }
}
@Test
@Override public abstract void testCacheConfiguration();
protected void tearDown() throws Exception {
@Test
super.tearDown(); public void testGetRegion() {
assertEquals( "Correct region", localCollectionRegion, localAccessStrategy.getRegion() );
try { }
localCache.withFlags(FlagAdapter.CACHE_MODE_LOCAL).clear();
} catch (Exception e) { @Test
LOG.error("Problem purging local cache", e); public void testPutFromLoadRemoveDoesNotProduceStaleData() throws Exception {
} final CountDownLatch pferLatch = new CountDownLatch( 1 );
final CountDownLatch removeLatch = new CountDownLatch( 1 );
try { TransactionManager tm = DualNodeJtaTransactionManagerImpl.getInstance( "test1234" );
remoteCache.withFlags(FlagAdapter.CACHE_MODE_LOCAL).clear(); PutFromLoadValidator validator = new PutFromLoadValidator( tm ) {
} catch (Exception e) { @Override
LOG.error("Problem purging remote cache", e); public boolean acquirePutFromLoadLock(Object key) {
} boolean acquired = super.acquirePutFromLoadLock( key );
try {
node1Exception = null; removeLatch.countDown();
node2Exception = null; pferLatch.await( 2, TimeUnit.SECONDS );
}
node1Failure = null; catch (InterruptedException e) {
node2Failure = null; LOG.debug( "Interrupted" );
} Thread.currentThread().interrupt();
}
protected static Configuration createConfiguration( String configName, catch (Exception e) {
String configResource ) { LOG.error( "Error", e );
Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, InfinispanRegionFactory.class, true, false); throw new RuntimeException( "Error", e );
cfg.setProperty(InfinispanRegionFactory.ENTITY_CACHE_RESOURCE_PROP, configName); }
return cfg; return acquired;
} }
};
protected CacheDataDescription getCacheDataDescription() { final TransactionalAccessDelegate delegate = new TransactionalAccessDelegate(
return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE); (CollectionRegionImpl) localCollectionRegion, validator
} );
protected boolean isUsingInvalidation() { Callable<Void> pferCallable = new Callable<Void>() {
return invalidation; public Void call() throws Exception {
} delegate.putFromLoad( "k1", "v1", 0, null );
return null;
protected boolean isSynchronous() { }
return synchronous; };
}
Callable<Void> removeCallable = new Callable<Void>() {
/** public Void call() throws Exception {
* This is just a setup test where we assert that the cache config is as we expected. removeLatch.await();
*/ delegate.remove( "k1" );
public abstract void testCacheConfiguration(); pferLatch.countDown();
return null;
/** }
* Test method for {@link CollectionRegionAccessStrategy#getRegion()}. };
*/
public void testGetRegion() { ExecutorService executorService = Executors.newCachedThreadPool();
assertEquals("Correct region", localCollectionRegion, localAccessStrategy.getRegion()); Future<Void> pferFuture = executorService.submit( pferCallable );
} Future<Void> removeFuture = executorService.submit( removeCallable );
public void testPutFromLoadRemoveDoesNotProduceStaleData() throws Exception { pferFuture.get();
final CountDownLatch pferLatch = new CountDownLatch(1); removeFuture.get();
final CountDownLatch removeLatch = new CountDownLatch(1);
TransactionManager tm = DualNodeJtaTransactionManagerImpl.getInstance("test1234"); assertFalse( localCollectionRegion.getCacheAdapter().containsKey( "k1" ) );
PutFromLoadValidator validator = new PutFromLoadValidator(tm) { }
@Override
public boolean acquirePutFromLoadLock( Object key ) { @Test
boolean acquired = super.acquirePutFromLoadLock(key); public void testPutFromLoad() throws Exception {
try { putFromLoadTest( false );
removeLatch.countDown(); }
pferLatch.await(2, TimeUnit.SECONDS);
} catch (InterruptedException e) { @Test
LOG.debug("Interrupted"); public void testPutFromLoadMinimal() throws Exception {
Thread.currentThread().interrupt(); putFromLoadTest( true );
} catch (Exception e) { }
LOG.error("Error", e);
throw new RuntimeException("Error", e); private void putFromLoadTest(final boolean useMinimalAPI) throws Exception {
}
return acquired; final String KEY = KEY_BASE + testCount++;
}
}; final CountDownLatch writeLatch1 = new CountDownLatch( 1 );
final TransactionalAccessDelegate delegate = new TransactionalAccessDelegate((CollectionRegionImpl)localCollectionRegion, final CountDownLatch writeLatch2 = new CountDownLatch( 1 );
validator); final CountDownLatch completionLatch = new CountDownLatch( 2 );
Callable<Void> pferCallable = new Callable<Void>() { Thread node1 = new Thread() {
public Void call() throws Exception {
delegate.putFromLoad("k1", "v1", 0, null); public void run() {
return null;
} try {
}; long txTimestamp = System.currentTimeMillis();
BatchModeTransactionManager.getInstance().begin();
Callable<Void> removeCallable = new Callable<Void>() {
public Void call() throws Exception { assertEquals( "node1 starts clean", null, localAccessStrategy.get( KEY, txTimestamp ) );
removeLatch.await();
delegate.remove("k1"); writeLatch1.await();
pferLatch.countDown();
return null; if ( useMinimalAPI ) {
} localAccessStrategy.putFromLoad( KEY, VALUE2, txTimestamp, new Integer( 2 ), true );
}; }
else {
ExecutorService executorService = Executors.newCachedThreadPool(); localAccessStrategy.putFromLoad( KEY, VALUE2, txTimestamp, new Integer( 2 ) );
Future<Void> pferFuture = executorService.submit(pferCallable); }
Future<Void> removeFuture = executorService.submit(removeCallable);
BatchModeTransactionManager.getInstance().commit();
pferFuture.get(); }
removeFuture.get(); catch (Exception e) {
LOG.error( "node1 caught exception", e );
assertFalse(localCache.containsKey("k1")); node1Exception = e;
} rollback();
}
/** catch (AssertionFailedError e) {
* Test method for node1Failure = e;
* {@link CollectionRegionAccessStrategy#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object)} . rollback();
*/ }
public void testPutFromLoad() throws Exception { finally {
putFromLoadTest(false); // Let node2 write
} writeLatch2.countDown();
completionLatch.countDown();
/** }
* Test method for }
* {@link CollectionRegionAccessStrategy#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object, boolean)} . };
*/
public void testPutFromLoadMinimal() throws Exception { Thread node2 = new Thread() {
putFromLoadTest(true);
} public void run() {
/** try {
* Simulate 2 nodes, both start, tx do a get, experience a cache miss, then 'read from db.' First does a putFromLoad, then an long txTimestamp = System.currentTimeMillis();
* evict (to represent a change). Second tries to do a putFromLoad with stale data (i.e. it took longer to read from the db). BatchModeTransactionManager.getInstance().begin();
* Both commit their tx. Then both start a new tx and get. First should see the updated data; second should either see the
* updated data (isInvalidation()( == false) or null (isInvalidation() == true). assertNull( "node2 starts clean", remoteAccessStrategy.get( KEY, txTimestamp ) );
*
* @param useMinimalAPI // Let node1 write
* @throws Exception writeLatch1.countDown();
*/ // Wait for node1 to finish
private void putFromLoadTest( final boolean useMinimalAPI ) throws Exception { writeLatch2.await();
final String KEY = KEY_BASE + testCount++; // Let the first PFER propagate
sleep( 200 );
final CountDownLatch writeLatch1 = new CountDownLatch(1);
final CountDownLatch writeLatch2 = new CountDownLatch(1); if ( useMinimalAPI ) {
final CountDownLatch completionLatch = new CountDownLatch(2); remoteAccessStrategy.putFromLoad( KEY, VALUE1, txTimestamp, new Integer( 1 ), true );
}
Thread node1 = new Thread() { else {
remoteAccessStrategy.putFromLoad( KEY, VALUE1, txTimestamp, new Integer( 1 ) );
@Override }
public void run() {
BatchModeTransactionManager.getInstance().commit();
try { }
long txTimestamp = System.currentTimeMillis(); catch (Exception e) {
BatchModeTransactionManager.getInstance().begin(); LOG.error( "node2 caught exception", e );
node2Exception = e;
assertEquals("node1 starts clean", null, localAccessStrategy.get(KEY, txTimestamp)); rollback();
}
writeLatch1.await(); catch (AssertionFailedError e) {
node2Failure = e;
if (useMinimalAPI) { rollback();
localAccessStrategy.putFromLoad(KEY, VALUE2, txTimestamp, new Integer(2), true); }
} else { finally {
localAccessStrategy.putFromLoad(KEY, VALUE2, txTimestamp, new Integer(2)); completionLatch.countDown();
} }
}
BatchModeTransactionManager.getInstance().commit(); };
} catch (Exception e) {
LOG.error("node1 caught exception", e); node1.setDaemon( true );
node1Exception = e; node2.setDaemon( true );
rollback();
} catch (AssertionFailedError e) { node1.start();
node1Failure = e; node2.start();
rollback();
} finally { assertTrue( "Threads completed", completionLatch.await( 2, TimeUnit.SECONDS ) );
// Let node2 write
writeLatch2.countDown(); if ( node1Failure != null ) {
completionLatch.countDown(); throw node1Failure;
} }
} if ( node2Failure != null ) {
}; throw node2Failure;
}
Thread node2 = new Thread() {
assertEquals( "node1 saw no exceptions", null, node1Exception );
@Override assertEquals( "node2 saw no exceptions", null, node2Exception );
public void run() {
// let the final PFER propagate
try { sleep( 100 );
long txTimestamp = System.currentTimeMillis();
BatchModeTransactionManager.getInstance().begin(); long txTimestamp = System.currentTimeMillis();
String msg1 = "Correct node1 value";
assertNull("node2 starts clean", remoteAccessStrategy.get(KEY, txTimestamp)); String msg2 = "Correct node2 value";
Object expected1 = null;
// Let node1 write Object expected2 = null;
writeLatch1.countDown(); if ( isUsingInvalidation() ) {
// Wait for node1 to finish // PFER does not generate any invalidation, so each node should
writeLatch2.await(); // succeed. We count on database locking and Hibernate removing
// the collection on any update to prevent the situation we have
// Let the first PFER propagate // here where the caches have inconsistent data
sleep(200); expected1 = VALUE2;
expected2 = VALUE1;
if (useMinimalAPI) { }
remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true); else {
} else { // the initial VALUE2 should prevent the node2 put
remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1)); expected1 = VALUE2;
} expected2 = VALUE2;
}
BatchModeTransactionManager.getInstance().commit();
} catch (Exception e) { assertEquals( msg1, expected1, localAccessStrategy.get( KEY, txTimestamp ) );
LOG.error("node2 caught exception", e); assertEquals( msg2, expected2, remoteAccessStrategy.get( KEY, txTimestamp ) );
node2Exception = e; }
rollback();
} catch (AssertionFailedError e) { @Test
node2Failure = e; public void testRemove() {
rollback(); evictOrRemoveTest( false );
} finally { }
completionLatch.countDown();
} @Test
} public void testRemoveAll() {
}; evictOrRemoveAllTest( false );
}
node1.setDaemon(true);
node2.setDaemon(true); @Test
public void testEvict() {
node1.start(); evictOrRemoveTest( true );
node2.start(); }
assertTrue("Threads completed", completionLatch.await(2, TimeUnit.SECONDS)); @Test
public void testEvictAll() {
if (node1Failure != null) throw node1Failure; evictOrRemoveAllTest( true );
if (node2Failure != null) throw node2Failure; }
assertEquals("node1 saw no exceptions", null, node1Exception); private void evictOrRemoveTest(boolean evict) {
assertEquals("node2 saw no exceptions", null, node2Exception);
final String KEY = KEY_BASE + testCount++;
// let the final PFER propagate
sleep(100); assertNull( "local is clean", localAccessStrategy.get( KEY, System.currentTimeMillis() ) );
assertNull( "remote is clean", remoteAccessStrategy.get( KEY, System.currentTimeMillis() ) );
long txTimestamp = System.currentTimeMillis();
String msg1 = "Correct node1 value"; localAccessStrategy.putFromLoad( KEY, VALUE1, System.currentTimeMillis(), new Integer( 1 ) );
String msg2 = "Correct node2 value"; assertEquals( VALUE1, localAccessStrategy.get( KEY, System.currentTimeMillis() ) );
Object expected1 = null; remoteAccessStrategy.putFromLoad( KEY, VALUE1, System.currentTimeMillis(), new Integer( 1 ) );
Object expected2 = null; assertEquals( VALUE1, remoteAccessStrategy.get( KEY, System.currentTimeMillis() ) );
if (isUsingInvalidation()) {
// PFER does not generate any invalidation, so each node should // Wait for async propagation
// succeed. We count on database locking and Hibernate removing sleep( 250 );
// the collection on any update to prevent the situation we have
// here where the caches have inconsistent data if ( evict ) {
expected1 = VALUE2; localAccessStrategy.evict( KEY );
expected2 = VALUE1; }
} else { else {
// the initial VALUE2 should prevent the node2 put localAccessStrategy.remove( KEY );
expected1 = VALUE2; }
expected2 = VALUE2;
} assertEquals( null, localAccessStrategy.get( KEY, System.currentTimeMillis() ) );
assertEquals(msg1, expected1, localAccessStrategy.get(KEY, txTimestamp)); assertEquals( null, remoteAccessStrategy.get( KEY, System.currentTimeMillis() ) );
assertEquals(msg2, expected2, remoteAccessStrategy.get(KEY, txTimestamp)); }
}
private void evictOrRemoveAllTest(boolean evict) {
/**
* Test method for {@link CollectionRegionAccessStrategy#remove(java.lang.Object)}. final String KEY = KEY_BASE + testCount++;
*/
public void testRemove() { assertEquals( 0, getValidKeyCount( localCollectionRegion.getCacheAdapter().keySet() ) );
evictOrRemoveTest(false);
} assertEquals( 0, getValidKeyCount( remoteCollectionRegion.getCacheAdapter().keySet() ) );
/** assertNull( "local is clean", localAccessStrategy.get( KEY, System.currentTimeMillis() ) );
* Test method for {@link CollectionRegionAccessStrategy#removeAll()}. assertNull( "remote is clean", remoteAccessStrategy.get( KEY, System.currentTimeMillis() ) );
*/
public void testRemoveAll() { localAccessStrategy.putFromLoad( KEY, VALUE1, System.currentTimeMillis(), new Integer( 1 ) );
evictOrRemoveAllTest(false); assertEquals( VALUE1, localAccessStrategy.get( KEY, System.currentTimeMillis() ) );
} remoteAccessStrategy.putFromLoad( KEY, VALUE1, System.currentTimeMillis(), new Integer( 1 ) );
assertEquals( VALUE1, remoteAccessStrategy.get( KEY, System.currentTimeMillis() ) );
/**
* Test method for {@link CollectionRegionAccessStrategy#evict(java.lang.Object)}. FIXME add testing of the // Wait for async propagation
* "immediately without regard for transaction isolation" bit in the CollectionRegionAccessStrategy API. sleep( 250 );
*/
public void testEvict() { if ( evict ) {
evictOrRemoveTest(true); localAccessStrategy.evictAll();
} }
else {
localAccessStrategy.removeAll();
}
// This should re-establish the region root node
assertNull( localAccessStrategy.get( KEY, System.currentTimeMillis() ) );
assertEquals( 0, getValidKeyCount( localCollectionRegion.getCacheAdapter().keySet() ) );
// Re-establishing the region root on the local node doesn't
// propagate it to other nodes. Do a get on the remote node to re-establish
assertEquals( null, remoteAccessStrategy.get( KEY, System.currentTimeMillis() ) );
assertEquals( 0, getValidKeyCount( remoteCollectionRegion.getCacheAdapter().keySet() ) );
// Test whether the get above messes up the optimistic version
remoteAccessStrategy.putFromLoad( KEY, VALUE1, System.currentTimeMillis(), new Integer( 1 ) );
assertEquals( VALUE1, remoteAccessStrategy.get( KEY, System.currentTimeMillis() ) );
/** assertEquals( 1, getValidKeyCount( remoteCollectionRegion.getCacheAdapter().keySet() ) );
* Test method for {@link CollectionRegionAccessStrategy#evictAll()}. FIXME add testing of the
* "immediately without regard for transaction isolation" bit in the CollectionRegionAccessStrategy API.
*/
public void testEvictAll() {
evictOrRemoveAllTest(true);
}
private void evictOrRemoveTest( boolean evict ) {
final String KEY = KEY_BASE + testCount++;
assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
// Wait for async propagation
sleep(250);
if (evict) localAccessStrategy.evict(KEY);
else localAccessStrategy.remove(KEY);
assertEquals(null, localAccessStrategy.get(KEY, System.currentTimeMillis()));
assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
}
private void evictOrRemoveAllTest( boolean evict ) {
final String KEY = KEY_BASE + testCount++;
assertEquals(0, getValidKeyCount(localCache.keySet()));
assertEquals(0, getValidKeyCount(remoteCache.keySet()));
assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis())); // Wait for async propagation of the putFromLoad
assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis())); sleep( 250 );
localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1)); assertEquals(
assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis())); "local is correct", (isUsingInvalidation() ? null : VALUE1), localAccessStrategy.get(
remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1)); KEY, System
assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis())); .currentTimeMillis()
)
// Wait for async propagation );
sleep(250); assertEquals( "remote is correct", VALUE1, remoteAccessStrategy.get( KEY, System.currentTimeMillis() ) );
}
if (evict) localAccessStrategy.evictAll();
else localAccessStrategy.removeAll();
// This should re-establish the region root node
assertNull(localAccessStrategy.get(KEY, System.currentTimeMillis()));
assertEquals(0, getValidKeyCount(localCache.keySet()));
// Re-establishing the region root on the local node doesn't
// propagate it to other nodes. Do a get on the remote node to re-establish
assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
assertEquals(0, getValidKeyCount(remoteCache.keySet()));
// Test whether the get above messes up the optimistic version
remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
assertEquals(1, getValidKeyCount(remoteCache.keySet()));
// Wait for async propagation of the putFromLoad
sleep(250);
assertEquals("local is correct", private void rollback() {
(isUsingInvalidation() ? null : VALUE1), try {
localAccessStrategy.get(KEY, System.currentTimeMillis())); BatchModeTransactionManager.getInstance().rollback();
assertEquals("remote is correct", VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis())); }
} catch (Exception e) {
LOG.error( e.getMessage(), e );
}
private void rollback() { }
try {
BatchModeTransactionManager.getInstance().rollback();
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
}
private static class AccessStrategyTestSetup extends TestSetup {
private static final String PREFER_IPV4STACK = "java.net.preferIPv4Stack";
private final String configResource;
private final String configName;
private String preferIPv4Stack;
private ServiceRegistry localServiceRegistry;
private ServiceRegistry remoteServiceRegistry;
public AccessStrategyTestSetup( Test test,
String configName ) {
this(test, configName, null);
}
public AccessStrategyTestSetup( Test test,
String configName,
String configResource ) {
super(test);
this.configName = configName;
this.configResource = configResource;
}
@Override
protected void setUp() throws Exception {
super.setUp();
// Try to ensure we use IPv4; otherwise cluster formation is very slow
preferIPv4Stack = System.getProperty(PREFER_IPV4STACK);
System.setProperty(PREFER_IPV4STACK, "true");
localCfg = createConfiguration(configName, configResource);
localServiceRegistry = ServiceRegistryBuilder.buildServiceRegistry(localCfg.getProperties());
localRegionFactory = CacheTestUtil.startRegionFactory(localServiceRegistry, localCfg);
remoteCfg = createConfiguration(configName, configResource);
remoteServiceRegistry = ServiceRegistryBuilder.buildServiceRegistry(remoteCfg.getProperties());
remoteRegionFactory = CacheTestUtil.startRegionFactory(remoteServiceRegistry, remoteCfg);
}
@Override
protected void tearDown() throws Exception {
try {
super.tearDown();
} finally {
if (preferIPv4Stack == null) System.clearProperty(PREFER_IPV4STACK);
else System.setProperty(PREFER_IPV4STACK, preferIPv4Stack);
}
try {
if (localRegionFactory != null) localRegionFactory.stop();
if (remoteRegionFactory != null) remoteRegionFactory.stop();
} finally {
if (localServiceRegistry != null) {
ServiceRegistryBuilder.destroy(localServiceRegistry);
}
if (remoteServiceRegistry != null) {
ServiceRegistryBuilder.destroy(remoteServiceRegistry);
}
}
}
}
} }

View File

@ -24,20 +24,17 @@
package org.hibernate.test.cache.infinispan.collection; package org.hibernate.test.cache.infinispan.collection;
import org.hibernate.cache.access.AccessType; import org.hibernate.cache.access.AccessType;
import org.junit.Test;
/** /**
* Base class for tests of TRANSACTIONAL access. * Base class for tests of TRANSACTIONAL access.
* *
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a> * @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
*/ */
public abstract class AbstractReadOnlyAccessTestCase extends AbstractCollectionRegionAccessStrategyTestCase { public abstract class AbstractReadOnlyAccessTestCase extends AbstractCollectionRegionAccessStrategyTestCase {
@Test
public AbstractReadOnlyAccessTestCase(String name) {
super(name);
}
@Override @Override
protected AccessType getAccessType() { protected AccessType getAccessType() {
return AccessType.READ_ONLY; return AccessType.READ_ONLY;
} }
} }

View File

@ -30,18 +30,8 @@ import org.hibernate.cache.access.AccessType;
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a> * @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
*/ */
public abstract class AbstractTransactionalAccessTestCase extends AbstractCollectionRegionAccessStrategyTestCase { public abstract class AbstractTransactionalAccessTestCase extends AbstractCollectionRegionAccessStrategyTestCase {
/**
* Create a new AbstractTransactionalAccessTestCase.
*
*/
public AbstractTransactionalAccessTestCase(String name) {
super(name);
}
@Override @Override
protected AccessType getAccessType() { protected AccessType getAccessType() {
return AccessType.TRANSACTIONAL; return AccessType.TRANSACTIONAL;
} }
} }

View File

@ -33,19 +33,18 @@ import org.hibernate.cache.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.infinispan.InfinispanRegionFactory; import org.hibernate.cache.infinispan.InfinispanRegionFactory;
import org.hibernate.cache.infinispan.util.CacheAdapter; import org.hibernate.cache.infinispan.util.CacheAdapter;
import org.hibernate.cache.infinispan.util.CacheAdapterImpl; import org.hibernate.cache.infinispan.util.CacheAdapterImpl;
import org.hibernate.test.cache.infinispan.AbstractEntityCollectionRegionTestCase; import org.hibernate.test.cache.infinispan.AbstractEntityCollectionRegionTestCase;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
/** /**
* Tests of CollectionRegionImpl. * Tests of CollectionRegionImpl.
* *
* @author Galder Zamarreño * @author Galder Zamarreño
*/ */
public class CollectionRegionImplTestCase extends AbstractEntityCollectionRegionTestCase { public class CollectionRegionImplTestCase extends AbstractEntityCollectionRegionTestCase {
public CollectionRegionImplTestCase(String name) {
super(name);
}
@Override @Override
protected void supportedAccessTypeTest(RegionFactory regionFactory, Properties properties) { protected void supportedAccessTypeTest(RegionFactory regionFactory, Properties properties) {
CollectionRegion region = regionFactory.buildCollectionRegion("test", properties, null); CollectionRegion region = regionFactory.buildCollectionRegion("test", properties, null);

View File

@ -20,9 +20,10 @@
* 02110-1301 USA, or see the FSF site: http://www.fsf.org. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/ */
package org.hibernate.test.cache.infinispan.collection; package org.hibernate.test.cache.infinispan.collection;
import junit.framework.Test;
import junit.framework.TestSuite; import org.junit.Test;
import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
import static org.junit.Assert.assertTrue;
/** /**
* InvalidatedTransactionalTestCase. * InvalidatedTransactionalTestCase.
@ -31,19 +32,15 @@ import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
* @since 3.5 * @since 3.5
*/ */
public class InvalidatedTransactionalTestCase extends AbstractTransactionalAccessTestCase { public class InvalidatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
@Test
@Override
public void testCacheConfiguration() {
assertTrue("Using Invalidation", isUsingInvalidation());
assertTrue("Synchronous mode", isSynchronous());
}
public InvalidatedTransactionalTestCase(String name) { @Override
super(name); protected String getConfigurationName() {
} return "entity"; // todo : should this be "collection"? the original code used "entity"...
}
@Override
public void testCacheConfiguration() {
assertTrue("Using Invalidation", isUsingInvalidation());
assertTrue("Synchronous mode", isSynchronous());
}
public static Test suite() throws Exception {
TestSuite suite = CacheTestUtil.createFailureExpectedSuite(InvalidatedTransactionalTestCase.class);
return getTestSetup(suite, "entity");
}
} }

View File

@ -21,59 +21,42 @@
*/ */
package org.hibernate.test.cache.infinispan.collection; package org.hibernate.test.cache.infinispan.collection;
import org.hibernate.cache.access.AccessType; import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
import org.junit.Test;
import static org.junit.Assert.fail;
/** /**
* ReadOnlyExtraAPITestCase. * ReadOnlyExtraAPITestCase.
* *
* @author Galder Zamarreño * @author Galder Zamarreño
* @since 3.5 * @since 3.5
*/ */
public class ReadOnlyExtraAPITestCase extends TransactionalExtraAPITestCase { public class ReadOnlyExtraAPITestCase extends TransactionalExtraAPITestCase {
@Override
protected AccessType getAccessType() {
return AccessType.READ_ONLY;
}
public ReadOnlyExtraAPITestCase(String name) { @Test
super(name); @Override
} public void testLockItem() {
try {
getCollectionAccessStrategy().lockItem( KEY, new Integer( 1 ) );
fail( "Call to lockItem did not throw exception" );
}
catch (UnsupportedOperationException expected) {
}
}
private static CollectionRegionAccessStrategy localAccessStrategy; @Test
@Override
@Override public void testLockRegion() {
protected AccessType getAccessType() { try {
return AccessType.READ_ONLY; getCollectionAccessStrategy().lockRegion();
} fail( "Call to lockRegion did not throw exception" );
}
@Override catch (UnsupportedOperationException expected) {
protected CollectionRegionAccessStrategy getCollectionAccessStrategy() { }
return localAccessStrategy; }
}
@Override
protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) {
localAccessStrategy = strategy;
}
/**
* Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
*/
@Override
public void testLockItem() {
try {
getCollectionAccessStrategy().lockItem(KEY, new Integer(1));
fail("Call to lockItem did not throw exception");
}
catch (UnsupportedOperationException expected) {}
}
/**
* Test method for {@link TransactionalAccess#lockRegion()}.
*/
@Override
public void testLockRegion() {
try {
getCollectionAccessStrategy().lockRegion();
fail("Call to lockRegion did not throw exception");
}
catch (UnsupportedOperationException expected) {}
}
} }

View File

@ -20,9 +20,8 @@
* 02110-1301 USA, or see the FSF site: http://www.fsf.org. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/ */
package org.hibernate.test.cache.infinispan.collection; package org.hibernate.test.cache.infinispan.collection;
import junit.framework.Test;
import junit.framework.TestSuite; import static org.junit.Assert.assertTrue;
import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
/** /**
* Tests READ_ONLY access when invalidation is used. * Tests READ_ONLY access when invalidation is used.
@ -31,19 +30,13 @@ import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
* @since 3.5 * @since 3.5
*/ */
public class ReadOnlyTestCase extends AbstractReadOnlyAccessTestCase { public class ReadOnlyTestCase extends AbstractReadOnlyAccessTestCase {
@Override
public void testCacheConfiguration() {
assertTrue( "Using Invalidation", isUsingInvalidation() );
}
public ReadOnlyTestCase(String name) { @Override
super(name); protected String getConfigurationName() {
} return "entity"; // todo : should this be "collection"? the original code used "entity"...
}
public static Test suite() throws Exception {
TestSuite suite = CacheTestUtil.createFailureExpectedSuite(ReadOnlyTestCase.class);
return getTestSetup(suite, "entity");
}
@Override
public void testCacheConfiguration() {
assertTrue("Using Invalidation", isUsingInvalidation());
}
} }

View File

@ -20,95 +20,96 @@
* 02110-1301 USA, or see the FSF site: http://www.fsf.org. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/ */
package org.hibernate.test.cache.infinispan.collection; package org.hibernate.test.cache.infinispan.collection;
import org.hibernate.cache.CollectionRegion;
import org.hibernate.cache.access.AccessType; import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.access.CollectionRegionAccessStrategy; import org.hibernate.cache.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.access.SoftLock; import org.hibernate.cache.access.SoftLock;
import org.hibernate.cache.infinispan.InfinispanRegionFactory; import org.hibernate.cache.infinispan.InfinispanRegionFactory;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.hibernate.test.cache.infinispan.AbstractNonFunctionalTestCase; import org.hibernate.test.cache.infinispan.AbstractNonFunctionalTestCase;
import org.hibernate.test.cache.infinispan.NodeEnvironment;
import org.hibernate.test.cache.infinispan.util.CacheTestUtil; import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
import static org.junit.Assert.assertNull;
/** /**
* TransactionalExtraAPITestCase. * TransactionalExtraAPITestCase.
* *
* @author Galder Zamarreño * @author Galder Zamarreño
* @since 3.5 * @since 3.5
*/ */
public class TransactionalExtraAPITestCase extends AbstractNonFunctionalTestCase { public class TransactionalExtraAPITestCase extends AbstractNonFunctionalTestCase {
public static final String REGION_NAME = "test/com.foo.test"; public static final String REGION_NAME = "test/com.foo.test";
public static final String KEY = "KEY"; public static final String KEY = "KEY";
public static final String VALUE1 = "VALUE1"; public static final String VALUE1 = "VALUE1";
public static final String VALUE2 = "VALUE2"; public static final String VALUE2 = "VALUE2";
private static CollectionRegionAccessStrategy localAccessStrategy;
public TransactionalExtraAPITestCase(String name) {
super(name);
}
protected void setUp() throws Exception { private NodeEnvironment environment;
super.setUp(); private static CollectionRegionAccessStrategy accessStrategy;
if (getCollectionAccessStrategy() == null) {
Configuration cfg = createConfiguration();
InfinispanRegionFactory rf = CacheTestUtil.startRegionFactory(
getServiceRegistry( cfg.getProperties() ), cfg, getCacheTestSupport()
);
// Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush();
CollectionRegion localCollectionRegion = rf.buildCollectionRegion(REGION_NAME, cfg.getProperties(), null);
setCollectionAccessStrategy(localCollectionRegion.buildAccessStrategy(getAccessType()));
}
}
protected void tearDown() throws Exception { @Before
public final void prepareLocalAccessStrategy() throws Exception {
super.tearDown(); environment = new NodeEnvironment( createConfiguration() );
}
protected Configuration createConfiguration() {
Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, InfinispanRegionFactory.class, true, false);
cfg.setProperty(InfinispanRegionFactory.ENTITY_CACHE_RESOURCE_PROP, getCacheConfigName());
return cfg;
}
protected String getCacheConfigName() {
return "entity";
}
protected AccessType getAccessType() {
return AccessType.TRANSACTIONAL;
}
protected CollectionRegionAccessStrategy getCollectionAccessStrategy() {
return localAccessStrategy;
}
protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) {
localAccessStrategy = strategy;
}
public void testLockItem() { // Sleep a bit to avoid concurrent FLUSH problem
assertNull(getCollectionAccessStrategy().lockItem(KEY, new Integer(1))); avoidConcurrentFlush();
}
public void testLockRegion() { accessStrategy = environment.getCollectionRegion( REGION_NAME, null ).buildAccessStrategy( getAccessType() );
assertNull(getCollectionAccessStrategy().lockRegion()); }
}
public void testUnlockItem() { protected Configuration createConfiguration() {
getCollectionAccessStrategy().unlockItem(KEY, new MockSoftLock()); Configuration cfg = CacheTestUtil.buildConfiguration(
} REGION_PREFIX, InfinispanRegionFactory.class, true, false
);
cfg.setProperty( InfinispanRegionFactory.ENTITY_CACHE_RESOURCE_PROP, getCacheConfigName() );
return cfg;
}
public void testUnlockRegion() { protected String getCacheConfigName() {
getCollectionAccessStrategy().unlockItem(KEY, new MockSoftLock()); return "entity";
} }
public static class MockSoftLock implements SoftLock { protected AccessType getAccessType() {
return AccessType.TRANSACTIONAL;
} }
@After
public final void releaseLocalAccessStrategy() throws Exception {
if ( environment != null ) {
environment.release();
}
}
protected CollectionRegionAccessStrategy getCollectionAccessStrategy() {
return accessStrategy;
}
@Test
public void testLockItem() {
assertNull( getCollectionAccessStrategy().lockItem( KEY, new Integer( 1 ) ) );
}
@Test
public void testLockRegion() {
assertNull( getCollectionAccessStrategy().lockRegion() );
}
@Test
public void testUnlockItem() {
getCollectionAccessStrategy().unlockItem( KEY, new MockSoftLock() );
}
@Test
public void testUnlockRegion() {
getCollectionAccessStrategy().unlockItem( KEY, new MockSoftLock() );
}
public static class MockSoftLock implements SoftLock {
}
} }

View File

@ -23,29 +23,33 @@
*/ */
package org.hibernate.test.cache.infinispan.entity; package org.hibernate.test.cache.infinispan.entity;
import static org.hibernate.TestLogger.LOG;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import junit.extensions.TestSetup;
import junit.framework.AssertionFailedError; import org.infinispan.transaction.tm.BatchModeTransactionManager;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.hibernate.cache.CacheDataDescription; import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.EntityRegion;
import org.hibernate.cache.access.AccessType; import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.access.EntityRegionAccessStrategy; import org.hibernate.cache.access.EntityRegionAccessStrategy;
import org.hibernate.cache.impl.CacheDataDescriptionImpl; import org.hibernate.cache.impl.CacheDataDescriptionImpl;
import org.hibernate.cache.infinispan.InfinispanRegionFactory; import org.hibernate.cache.infinispan.InfinispanRegionFactory;
import org.hibernate.cache.infinispan.impl.BaseRegion; import org.hibernate.cache.infinispan.entity.EntityRegionImpl;
import org.hibernate.cache.infinispan.util.CacheAdapter;
import org.hibernate.cache.infinispan.util.FlagAdapter;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
import org.hibernate.internal.util.compare.ComparableComparator; import org.hibernate.internal.util.compare.ComparableComparator;
import org.hibernate.service.spi.ServiceRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import junit.framework.AssertionFailedError;
import org.hibernate.test.cache.infinispan.AbstractNonFunctionalTestCase; import org.hibernate.test.cache.infinispan.AbstractNonFunctionalTestCase;
import org.hibernate.test.cache.infinispan.NodeEnvironment;
import org.hibernate.test.cache.infinispan.util.CacheTestUtil; import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
import org.hibernate.testing.ServiceRegistryBuilder;
import org.infinispan.transaction.tm.BatchModeTransactionManager; import static org.hibernate.testing.TestingLogger.LOG;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/** /**
* Base class for tests of EntityRegionAccessStrategy impls. * Base class for tests of EntityRegionAccessStrategy impls.
@ -62,113 +66,54 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac
protected static int testCount; protected static int testCount;
protected static Configuration localCfg; protected NodeEnvironment localEnvironment;
protected static InfinispanRegionFactory localRegionFactory; protected EntityRegionImpl localEntityRegion;
protected CacheAdapter localCache; protected EntityRegionAccessStrategy localAccessStrategy;
protected static Configuration remoteCfg;
protected static InfinispanRegionFactory remoteRegionFactory; protected NodeEnvironment remoteEnvironment;
protected CacheAdapter remoteCache; protected EntityRegionImpl remoteEntityRegion;
protected EntityRegionAccessStrategy remoteAccessStrategy;
protected boolean invalidation; protected boolean invalidation;
protected boolean synchronous; protected boolean synchronous;
protected EntityRegion localEntityRegion;
protected EntityRegionAccessStrategy localAccessStrategy;
protected EntityRegion remoteEntityRegion;
protected EntityRegionAccessStrategy remoteAccessStrategy;
protected Exception node1Exception; protected Exception node1Exception;
protected Exception node2Exception; protected Exception node2Exception;
protected AssertionFailedError node1Failure; protected AssertionFailedError node1Failure;
protected AssertionFailedError node2Failure; protected AssertionFailedError node2Failure;
public static Test getTestSetup(Class testClass, String configName) { @Before
TestSuite suite = new TestSuite( testClass ); public void prepareResources() throws Exception {
return new AccessStrategyTestSetup( suite, configName ); // to mimic exactly the old code results, both environments here are exactly the same...
} Configuration cfg = createConfiguration( getConfigurationName() );
localEnvironment = new NodeEnvironment( cfg );
localEnvironment.prepare();
public static Test getTestSetup(Test test, String configName) { localEntityRegion = localEnvironment.getEntityRegion( REGION_NAME, getCacheDataDescription() );
return new AccessStrategyTestSetup( test, configName );
}
/**
* Create a new TransactionalAccessTestCase.
*
* @param name
*/
public AbstractEntityRegionAccessStrategyTestCase(String name) {
super( name );
}
protected abstract AccessType getAccessType();
@Override
protected void setUp() throws Exception {
super.setUp();
// Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush();
localEntityRegion = localRegionFactory.buildEntityRegion(
REGION_NAME, localCfg
.getProperties(), getCacheDataDescription()
);
localAccessStrategy = localEntityRegion.buildAccessStrategy( getAccessType() ); localAccessStrategy = localEntityRegion.buildAccessStrategy( getAccessType() );
localCache = ((BaseRegion) localEntityRegion).getCacheAdapter(); invalidation = localEntityRegion.getCacheAdapter().isClusteredInvalidation();
synchronous = localEntityRegion.getCacheAdapter().isSynchronous();
invalidation = localCache.isClusteredInvalidation();
synchronous = localCache.isSynchronous();
// Sleep a bit to avoid concurrent FLUSH problem // Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush(); avoidConcurrentFlush();
remoteEntityRegion = remoteRegionFactory.buildEntityRegion( remoteEnvironment = new NodeEnvironment( cfg );
REGION_NAME, remoteCfg remoteEnvironment.prepare();
.getProperties(), getCacheDataDescription()
); remoteEntityRegion = remoteEnvironment.getEntityRegion( REGION_NAME, getCacheDataDescription() );
remoteAccessStrategy = remoteEntityRegion.buildAccessStrategy( getAccessType() ); remoteAccessStrategy = remoteEntityRegion.buildAccessStrategy( getAccessType() );
remoteCache = ((BaseRegion) remoteEntityRegion).getCacheAdapter();
node1Exception = null;
node2Exception = null;
node1Failure = null;
node2Failure = null;
} }
@Override protected abstract String getConfigurationName();
protected void tearDown() throws Exception {
super.tearDown();
try {
localCache.withFlags( FlagAdapter.CACHE_MODE_LOCAL ).clear();
}
catch (Exception e) {
LOG.error("Problem purging local cache", e);
}
try {
remoteCache.withFlags( FlagAdapter.CACHE_MODE_LOCAL ).clear();
}
catch (Exception e) {
LOG.error("Problem purging remote cache", e);
}
node1Exception = null;
node2Exception = null;
node1Failure = null;
node2Failure = null;
}
protected static Configuration createConfiguration(String configName) { protected static Configuration createConfiguration(String configName) {
Configuration cfg = CacheTestUtil.buildConfiguration( Configuration cfg = CacheTestUtil.buildConfiguration(
REGION_PREFIX, InfinispanRegionFactory.class, true, false REGION_PREFIX,
InfinispanRegionFactory.class,
true,
false
); );
cfg.setProperty( InfinispanRegionFactory.ENTITY_CACHE_RESOURCE_PROP, configName ); cfg.setProperty( InfinispanRegionFactory.ENTITY_CACHE_RESOURCE_PROP, configName );
return cfg; return cfg;
@ -178,6 +123,18 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac
return new CacheDataDescriptionImpl( true, true, ComparableComparator.INSTANCE ); return new CacheDataDescriptionImpl( true, true, ComparableComparator.INSTANCE );
} }
@After
public void releaseResources() throws Exception {
if ( localEnvironment != null ) {
localEnvironment.release();
}
if ( remoteEnvironment != null ) {
remoteEnvironment.release();
}
}
protected abstract AccessType getAccessType();
protected boolean isUsingInvalidation() { protected boolean isUsingInvalidation() {
return invalidation; return invalidation;
} }
@ -205,19 +162,20 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac
} }
} }
/** @Test
* This is just a setup test where we assert that the cache config is as we expected.
*/
public abstract void testCacheConfiguration(); public abstract void testCacheConfiguration();
@Test
public void testGetRegion() { public void testGetRegion() {
assertEquals( "Correct region", localEntityRegion, localAccessStrategy.getRegion() ); assertEquals( "Correct region", localEntityRegion, localAccessStrategy.getRegion() );
} }
@Test
public void testPutFromLoad() throws Exception { public void testPutFromLoad() throws Exception {
putFromLoadTest( false ); putFromLoadTest( false );
} }
@Test
public void testPutFromLoadMinimal() throws Exception { public void testPutFromLoadMinimal() throws Exception {
putFromLoadTest( true ); putFromLoadTest( true );
} }
@ -344,6 +302,7 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac
} }
} }
@Test
public void testInsert() throws Exception { public void testInsert() throws Exception {
final String KEY = KEY_BASE + testCount++; final String KEY = KEY_BASE + testCount++;
@ -438,6 +397,7 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac
assertEquals( "Correct node2 value", expected, remoteAccessStrategy.get( KEY, txTimestamp ) ); assertEquals( "Correct node2 value", expected, remoteAccessStrategy.get( KEY, txTimestamp ) );
} }
@Test
public void testUpdate() throws Exception { public void testUpdate() throws Exception {
final String KEY = KEY_BASE + testCount++; final String KEY = KEY_BASE + testCount++;
@ -541,26 +501,30 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac
assertEquals( "Correct node2 value", expected, remoteAccessStrategy.get( KEY, txTimestamp ) ); assertEquals( "Correct node2 value", expected, remoteAccessStrategy.get( KEY, txTimestamp ) );
} }
@Test
public void testRemove() { public void testRemove() {
evictOrRemoveTest( false ); evictOrRemoveTest( false );
} }
@Test
public void testRemoveAll() { public void testRemoveAll() {
evictOrRemoveAllTest( false ); evictOrRemoveAllTest( false );
} }
@Test
public void testEvict() { public void testEvict() {
evictOrRemoveTest( true ); evictOrRemoveTest( true );
} }
@Test
public void testEvictAll() { public void testEvictAll() {
evictOrRemoveAllTest( true ); evictOrRemoveAllTest( true );
} }
private void evictOrRemoveTest(boolean evict) { private void evictOrRemoveTest(boolean evict) {
final String KEY = KEY_BASE + testCount++; final String KEY = KEY_BASE + testCount++;
assertEquals( 0, getValidKeyCount( localCache.keySet() ) ); assertEquals( 0, getValidKeyCount( localEntityRegion.getCacheAdapter().keySet() ) );
assertEquals( 0, getValidKeyCount( remoteCache.keySet() ) ); assertEquals( 0, getValidKeyCount( remoteEntityRegion.getCacheAdapter().keySet() ) );
assertNull( "local is clean", localAccessStrategy.get( KEY, System.currentTimeMillis() ) ); assertNull( "local is clean", localAccessStrategy.get( KEY, System.currentTimeMillis() ) );
assertNull( "remote is clean", remoteAccessStrategy.get( KEY, System.currentTimeMillis() ) ); assertNull( "remote is clean", remoteAccessStrategy.get( KEY, System.currentTimeMillis() ) );
@ -578,15 +542,15 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac
} }
assertEquals( null, localAccessStrategy.get( KEY, System.currentTimeMillis() ) ); assertEquals( null, localAccessStrategy.get( KEY, System.currentTimeMillis() ) );
assertEquals( 0, getValidKeyCount( localCache.keySet() ) ); assertEquals( 0, getValidKeyCount( localEntityRegion.getCacheAdapter().keySet() ) );
assertEquals( null, remoteAccessStrategy.get( KEY, System.currentTimeMillis() ) ); assertEquals( null, remoteAccessStrategy.get( KEY, System.currentTimeMillis() ) );
assertEquals( 0, getValidKeyCount( remoteCache.keySet() ) ); assertEquals( 0, getValidKeyCount( remoteEntityRegion.getCacheAdapter().keySet() ) );
} }
private void evictOrRemoveAllTest(boolean evict) { private void evictOrRemoveAllTest(boolean evict) {
final String KEY = KEY_BASE + testCount++; final String KEY = KEY_BASE + testCount++;
assertEquals( 0, getValidKeyCount( localCache.keySet() ) ); assertEquals( 0, getValidKeyCount( localEntityRegion.getCacheAdapter().keySet() ) );
assertEquals( 0, getValidKeyCount( remoteCache.keySet() ) ); assertEquals( 0, getValidKeyCount( remoteEntityRegion.getCacheAdapter().keySet() ) );
assertNull( "local is clean", localAccessStrategy.get( KEY, System.currentTimeMillis() ) ); assertNull( "local is clean", localAccessStrategy.get( KEY, System.currentTimeMillis() ) );
assertNull( "remote is clean", remoteAccessStrategy.get( KEY, System.currentTimeMillis() ) ); assertNull( "remote is clean", remoteAccessStrategy.get( KEY, System.currentTimeMillis() ) );
@ -612,17 +576,17 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac
// This should re-establish the region root node in the optimistic case // This should re-establish the region root node in the optimistic case
assertNull( localAccessStrategy.get( KEY, System.currentTimeMillis() ) ); assertNull( localAccessStrategy.get( KEY, System.currentTimeMillis() ) );
assertEquals( 0, getValidKeyCount( localCache.keySet() ) ); assertEquals( 0, getValidKeyCount( localEntityRegion.getCacheAdapter().keySet() ) );
// Re-establishing the region root on the local node doesn't // Re-establishing the region root on the local node doesn't
// propagate it to other nodes. Do a get on the remote node to re-establish // propagate it to other nodes. Do a get on the remote node to re-establish
assertEquals( null, remoteAccessStrategy.get( KEY, System.currentTimeMillis() ) ); assertEquals( null, remoteAccessStrategy.get( KEY, System.currentTimeMillis() ) );
assertEquals( 0, getValidKeyCount( remoteCache.keySet() ) ); assertEquals( 0, getValidKeyCount( remoteEntityRegion.getCacheAdapter().keySet() ) );
// Test whether the get above messes up the optimistic version // Test whether the get above messes up the optimistic version
remoteAccessStrategy.putFromLoad( KEY, VALUE1, System.currentTimeMillis(), new Integer( 1 ) ); remoteAccessStrategy.putFromLoad( KEY, VALUE1, System.currentTimeMillis(), new Integer( 1 ) );
assertEquals( VALUE1, remoteAccessStrategy.get( KEY, System.currentTimeMillis() ) ); assertEquals( VALUE1, remoteAccessStrategy.get( KEY, System.currentTimeMillis() ) );
assertEquals( 1, getValidKeyCount( remoteCache.keySet() ) ); assertEquals( 1, getValidKeyCount( remoteEntityRegion.getCacheAdapter().keySet() ) );
// Wait for async propagation // Wait for async propagation
sleep( 250 ); sleep( 250 );
@ -647,71 +611,4 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac
LOG.error(e.getMessage(), e); LOG.error(e.getMessage(), e);
} }
} }
private static class AccessStrategyTestSetup extends TestSetup {
private static final String PREFER_IPV4STACK = "java.net.preferIPv4Stack";
private final String configName;
private String preferIPv4Stack;
private ServiceRegistry localServiceRegistry;
private ServiceRegistry remoteServiceRegistry;
public AccessStrategyTestSetup(Test test, String configName) {
super( test );
this.configName = configName;
}
@Override
protected void setUp() throws Exception {
try {
super.tearDown();
}
finally {
if ( preferIPv4Stack == null ) {
System.clearProperty( PREFER_IPV4STACK );
}
else {
System.setProperty( PREFER_IPV4STACK, preferIPv4Stack );
}
}
// Try to ensure we use IPv4; otherwise cluster formation is very slow
preferIPv4Stack = System.getProperty( PREFER_IPV4STACK );
System.setProperty( PREFER_IPV4STACK, "true" );
localCfg = createConfiguration( configName );
localServiceRegistry = ServiceRegistryBuilder.buildServiceRegistry( localCfg.getProperties() );
localRegionFactory = CacheTestUtil.startRegionFactory( localServiceRegistry, localCfg );
remoteCfg = createConfiguration( configName );
remoteServiceRegistry = ServiceRegistryBuilder.buildServiceRegistry( remoteCfg.getProperties() );
remoteRegionFactory = CacheTestUtil.startRegionFactory( remoteServiceRegistry, remoteCfg );
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
try {
if ( localRegionFactory != null ) {
localRegionFactory.stop();
}
if ( remoteRegionFactory != null ) {
remoteRegionFactory.stop();
}
}
finally {
if ( localServiceRegistry != null ) {
ServiceRegistryBuilder.destroy( localServiceRegistry );
}
if ( remoteServiceRegistry != null ) {
ServiceRegistryBuilder.destroy( remoteServiceRegistry );
}
}
}
}
} }

View File

@ -22,9 +22,17 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
package org.hibernate.test.cache.infinispan.entity; package org.hibernate.test.cache.infinispan.entity;
import org.hibernate.cache.access.AccessType;
import org.infinispan.transaction.tm.BatchModeTransactionManager; import org.infinispan.transaction.tm.BatchModeTransactionManager;
import org.hibernate.cache.access.AccessType;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
/** /**
* Base class for tests of TRANSACTIONAL access. * Base class for tests of TRANSACTIONAL access.
* *
@ -32,25 +40,18 @@ import org.infinispan.transaction.tm.BatchModeTransactionManager;
* @since 3.5 * @since 3.5
*/ */
public abstract class AbstractReadOnlyAccessTestCase extends AbstractEntityRegionAccessStrategyTestCase { public abstract class AbstractReadOnlyAccessTestCase extends AbstractEntityRegionAccessStrategyTestCase {
/**
* Create a new AbstractTransactionalAccessTestCase.
*
*/
public AbstractReadOnlyAccessTestCase(String name) {
super(name);
}
@Override @Override
protected AccessType getAccessType() { protected AccessType getAccessType() {
return AccessType.READ_ONLY; return AccessType.READ_ONLY;
} }
@Test
@Override @Override
public void testPutFromLoad() throws Exception { public void testPutFromLoad() throws Exception {
putFromLoadTest(false); putFromLoadTest(false);
} }
@Test
@Override @Override
public void testPutFromLoadMinimal() throws Exception { public void testPutFromLoadMinimal() throws Exception {
putFromLoadTest(true); putFromLoadTest(true);
@ -77,6 +78,7 @@ public abstract class AbstractReadOnlyAccessTestCase extends AbstractEntityRegio
assertEquals(expected, remoteAccessStrategy.get(KEY, System.currentTimeMillis())); assertEquals(expected, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
} }
@Test
@Override @Override
public void testUpdate() throws Exception { public void testUpdate() throws Exception {

View File

@ -22,13 +22,20 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
package org.hibernate.test.cache.infinispan.entity; package org.hibernate.test.cache.infinispan.entity;
import static org.hibernate.TestLogger.LOG;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import junit.framework.AssertionFailedError;
import org.hibernate.cache.access.AccessType;
import org.infinispan.transaction.tm.BatchModeTransactionManager; import org.infinispan.transaction.tm.BatchModeTransactionManager;
import org.hibernate.cache.access.AccessType;
import junit.framework.AssertionFailedError;
import static org.hibernate.TestLogger.LOG;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/** /**
* Base class for tests of TRANSACTIONAL access. * Base class for tests of TRANSACTIONAL access.
* *
@ -36,15 +43,10 @@ import org.infinispan.transaction.tm.BatchModeTransactionManager;
* @since 3.5 * @since 3.5
*/ */
public abstract class AbstractTransactionalAccessTestCase extends AbstractEntityRegionAccessStrategyTestCase { public abstract class AbstractTransactionalAccessTestCase extends AbstractEntityRegionAccessStrategyTestCase {
@Override
public AbstractTransactionalAccessTestCase( String name ) { protected AccessType getAccessType() {
super(name); return AccessType.TRANSACTIONAL;
} }
@Override
protected AccessType getAccessType() {
return AccessType.TRANSACTIONAL;
}
public void testContestedPutFromLoad() throws Exception { public void testContestedPutFromLoad() throws Exception {

View File

@ -32,8 +32,12 @@ import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.infinispan.InfinispanRegionFactory; import org.hibernate.cache.infinispan.InfinispanRegionFactory;
import org.hibernate.cache.infinispan.util.CacheAdapter; import org.hibernate.cache.infinispan.util.CacheAdapter;
import org.hibernate.cache.infinispan.util.CacheAdapterImpl; import org.hibernate.cache.infinispan.util.CacheAdapterImpl;
import org.hibernate.test.cache.infinispan.AbstractEntityCollectionRegionTestCase; import org.hibernate.test.cache.infinispan.AbstractEntityCollectionRegionTestCase;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
/** /**
* Tests of EntityRegionImpl. * Tests of EntityRegionImpl.
* *
@ -42,10 +46,6 @@ import org.hibernate.test.cache.infinispan.AbstractEntityCollectionRegionTestCas
*/ */
public class EntityRegionImplTestCase extends AbstractEntityCollectionRegionTestCase { public class EntityRegionImplTestCase extends AbstractEntityCollectionRegionTestCase {
public EntityRegionImplTestCase(String name) {
super(name);
}
@Override @Override
protected void supportedAccessTypeTest(RegionFactory regionFactory, Properties properties) { protected void supportedAccessTypeTest(RegionFactory regionFactory, Properties properties) {
EntityRegion region = regionFactory.buildEntityRegion("test", properties, null); EntityRegion region = regionFactory.buildEntityRegion("test", properties, null);

View File

@ -20,9 +20,10 @@
* 02110-1301 USA, or see the FSF site: http://www.fsf.org. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/ */
package org.hibernate.test.cache.infinispan.entity; package org.hibernate.test.cache.infinispan.entity;
import junit.framework.Test;
import junit.framework.TestSuite; import org.junit.Test;
import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
import static org.junit.Assert.assertTrue;
/** /**
* InvalidatedTransactionalTestCase. * InvalidatedTransactionalTestCase.
@ -31,20 +32,15 @@ import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
* @since 3.5 * @since 3.5
*/ */
public class InvalidatedTransactionalTestCase extends AbstractTransactionalAccessTestCase { public class InvalidatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
@Test
@Override
public void testCacheConfiguration() {
assertTrue("Using Invalidation", isUsingInvalidation());
assertTrue("Synchronous mode", isSynchronous());
}
public InvalidatedTransactionalTestCase(String name) { @Override
super(name); protected String getConfigurationName() {
} return "entity";
}
@Override
public void testCacheConfiguration() {
assertTrue("Using Invalidation", isUsingInvalidation());
assertTrue("Synchronous mode", isSynchronous());
}
public static Test suite() throws Exception {
TestSuite suite = CacheTestUtil.createFailureExpectedSuite(InvalidatedTransactionalTestCase.class);
return getTestSetup(suite, "entity");
}
} }

View File

@ -21,74 +21,59 @@
*/ */
package org.hibernate.test.cache.infinispan.entity; package org.hibernate.test.cache.infinispan.entity;
import org.hibernate.cache.access.AccessType; import org.hibernate.cache.access.AccessType;
import org.hibernate.cache.access.EntityRegionAccessStrategy;
import static org.junit.Assert.fail;
/** /**
* Tests for the "extra API" in EntityRegionAccessStrategy; * Tests for the "extra API" in EntityRegionAccessStrategy;
* <p> * <p/>
* By "extra API" we mean those methods that are superfluous to the * By "extra API" we mean those methods that are superfluous to the
* function of the Infinispan integration, where the impl is a no-op or a static * function of the Infinispan integration, where the impl is a no-op or a static
* false return value, UnsupportedOperationException, etc. * false return value, UnsupportedOperationException, etc.
* *
* @author Galder Zamarreño * @author Galder Zamarreño
* @since 3.5 * @since 3.5
*/ */
public class ReadOnlyExtraAPITestCase extends TransactionalExtraAPITestCase { public class ReadOnlyExtraAPITestCase extends TransactionalExtraAPITestCase {
private static EntityRegionAccessStrategy localAccessStrategy; @Override
protected AccessType getAccessType() {
public ReadOnlyExtraAPITestCase(String name) { return AccessType.READ_ONLY;
super(name); }
}
@Override @Override
protected AccessType getAccessType() { public void testLockItem() {
return AccessType.READ_ONLY; try {
} getEntityAccessStrategy().lockItem( KEY, Integer.valueOf( 1 ) );
fail( "Call to lockItem did not throw exception" );
@Override }
protected EntityRegionAccessStrategy getEntityAccessStrategy() { catch (UnsupportedOperationException expected) {
return localAccessStrategy; }
} }
@Override
protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
localAccessStrategy = strategy;
}
/**
* Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
*/
@Override
public void testLockItem() {
try {
getEntityAccessStrategy().lockItem(KEY, new Integer(1));
fail("Call to lockItem did not throw exception");
}
catch (UnsupportedOperationException expected) {}
}
/** @Override
* Test method for {@link TransactionalAccess#lockRegion()}. public void testLockRegion() {
*/ try {
@Override getEntityAccessStrategy().lockRegion();
public void testLockRegion() { fail( "Call to lockRegion did not throw exception" );
try { }
getEntityAccessStrategy().lockRegion(); catch (UnsupportedOperationException expected) {
fail("Call to lockRegion did not throw exception"); }
} }
catch (UnsupportedOperationException expected) {}
}
/** @Override
* Test method for {@link TransactionalAccess#afterUpdate(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, org.hibernate.cache.access.SoftLock)}. public void testAfterUpdate() {
*/ try {
@Override getEntityAccessStrategy().afterUpdate(
public void testAfterUpdate() { KEY,
try { VALUE2,
getEntityAccessStrategy().afterUpdate(KEY, VALUE2, new Integer(1), new Integer(2), new MockSoftLock()); Integer.valueOf( 1 ),
fail("Call to afterUpdate did not throw exception"); Integer.valueOf( 2 ),
} new MockSoftLock()
catch (UnsupportedOperationException expected) {} );
} fail( "Call to afterUpdate did not throw exception" );
}
catch (UnsupportedOperationException expected) {
}
}
} }

View File

@ -22,9 +22,10 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
package org.hibernate.test.cache.infinispan.entity; package org.hibernate.test.cache.infinispan.entity;
import junit.framework.Test;
import junit.framework.TestSuite; import org.junit.Test;
import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
import static org.junit.Assert.assertTrue;
/** /**
* Tests READ_ONLY access when pessimistic locking and invalidation are used. * Tests READ_ONLY access when pessimistic locking and invalidation are used.
@ -33,28 +34,14 @@ import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
* @since 3.5 * @since 3.5
*/ */
public class ReadOnlyTestCase extends AbstractReadOnlyAccessTestCase { public class ReadOnlyTestCase extends AbstractReadOnlyAccessTestCase {
@Override
protected String getConfigurationName() {
return "entity";
}
/** @Test
* Create a new PessimisticTransactionalAccessTestCase. @Override
* public void testCacheConfiguration() {
* @param name assertTrue("Using Invalidation", isUsingInvalidation());
*/ }
public ReadOnlyTestCase(String name) {
super(name);
}
public static Test suite() throws Exception {
TestSuite suite = CacheTestUtil.createFailureExpectedSuite(ReadOnlyTestCase.class);
return getTestSetup(suite, "entity");
}
// Known failures
// Overrides
@Override
public void testCacheConfiguration() {
assertTrue("Using Invalidation", isUsingInvalidation());
}
} }

View File

@ -26,9 +26,19 @@ import org.hibernate.cache.access.EntityRegionAccessStrategy;
import org.hibernate.cache.access.SoftLock; import org.hibernate.cache.access.SoftLock;
import org.hibernate.cache.infinispan.InfinispanRegionFactory; import org.hibernate.cache.infinispan.InfinispanRegionFactory;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
import org.hibernate.service.internal.ServiceRegistryImpl;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.hibernate.test.cache.infinispan.AbstractNonFunctionalTestCase; import org.hibernate.test.cache.infinispan.AbstractNonFunctionalTestCase;
import org.hibernate.test.cache.infinispan.NodeEnvironment;
import org.hibernate.test.cache.infinispan.util.CacheTestUtil; import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
/** /**
* Tests for the "extra API" in EntityRegionAccessStrategy;. * Tests for the "extra API" in EntityRegionAccessStrategy;.
* <p> * <p>
@ -40,91 +50,98 @@ import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
* @since 3.5 * @since 3.5
*/ */
public class TransactionalExtraAPITestCase extends AbstractNonFunctionalTestCase { public class TransactionalExtraAPITestCase extends AbstractNonFunctionalTestCase {
public static final String REGION_NAME = "test/com.foo.test";
public static final String KEY = "KEY";
public static final String VALUE1 = "VALUE1";
public static final String VALUE2 = "VALUE2";
public TransactionalExtraAPITestCase(String name) { private NodeEnvironment environment;
super(name); private EntityRegionAccessStrategy accessStrategy;
}
@Before
public static final String REGION_NAME = "test/com.foo.test"; public final void prepareLocalAccessStrategy() throws Exception {
public static final String KEY = "KEY"; environment = new NodeEnvironment( createConfiguration() );
public static final String VALUE1 = "VALUE1";
public static final String VALUE2 = "VALUE2"; // Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush();
private static EntityRegionAccessStrategy localAccessStrategy;
accessStrategy = environment.getEntityRegion( REGION_NAME, null ).buildAccessStrategy( getAccessType() );
private static boolean optimistic;
protected void setUp() throws Exception {
super.setUp();
if (getEntityAccessStrategy() == null) {
Configuration cfg = createConfiguration();
InfinispanRegionFactory rf = CacheTestUtil.startRegionFactory(
getServiceRegistry( cfg.getProperties() ), cfg, getCacheTestSupport()
);
// Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush();
EntityRegion localEntityRegion = rf.buildEntityRegion(REGION_NAME, cfg.getProperties(), null);
setEntityRegionAccessStrategy(localEntityRegion.buildAccessStrategy(getAccessType()));
}
} }
protected void tearDown() throws Exception { protected Configuration createConfiguration() {
Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, InfinispanRegionFactory.class, true, false);
super.tearDown(); cfg.setProperty(InfinispanRegionFactory.ENTITY_CACHE_RESOURCE_PROP, getCacheConfigName());
} return cfg;
}
protected Configuration createConfiguration() {
Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, InfinispanRegionFactory.class, true, false);
cfg.setProperty(InfinispanRegionFactory.ENTITY_CACHE_RESOURCE_PROP, getCacheConfigName());
return cfg;
}
protected String getCacheConfigName() {
return "entity";
}
protected AccessType getAccessType() {
return AccessType.TRANSACTIONAL;
}
protected EntityRegionAccessStrategy getEntityAccessStrategy() {
return localAccessStrategy;
}
protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
localAccessStrategy = strategy;
}
public void testLockItem() { @After
assertNull(getEntityAccessStrategy().lockItem(KEY, new Integer(1))); public final void releaseLocalAccessStrategy() throws Exception {
} if ( environment != null ) {
environment.release();
}
}
public void testLockRegion() { protected final EntityRegionAccessStrategy getEntityAccessStrategy() {
assertNull(getEntityAccessStrategy().lockRegion()); return accessStrategy;
} }
public void testUnlockItem() { protected String getCacheConfigName() {
getEntityAccessStrategy().unlockItem(KEY, new MockSoftLock()); return "entity";
} }
public void testUnlockRegion() { protected AccessType getAccessType() {
getEntityAccessStrategy().unlockItem(KEY, new MockSoftLock()); return AccessType.TRANSACTIONAL;
} }
public void testAfterInsert() { @Test
assertFalse("afterInsert always returns false", getEntityAccessStrategy().afterInsert(KEY, VALUE1, new Integer(1))); @SuppressWarnings( {"UnnecessaryBoxing"})
} public void testLockItem() {
assertNull( getEntityAccessStrategy().lockItem( KEY, Integer.valueOf( 1 ) ) );
}
public void testAfterUpdate() { @Test
assertFalse("afterInsert always returns false", getEntityAccessStrategy().afterUpdate(KEY, VALUE2, new Integer(1), new Integer(2), new MockSoftLock())); public void testLockRegion() {
} assertNull( getEntityAccessStrategy().lockRegion() );
}
public static class MockSoftLock implements SoftLock {
}
@Test
public void testUnlockItem() {
getEntityAccessStrategy().unlockItem( KEY, new MockSoftLock() );
}
@Test
public void testUnlockRegion() {
getEntityAccessStrategy().unlockItem( KEY, new MockSoftLock() );
}
@Test
@SuppressWarnings( {"UnnecessaryBoxing"})
public void testAfterInsert() {
assertFalse(
"afterInsert always returns false",
getEntityAccessStrategy().afterInsert(
KEY,
VALUE1,
Integer.valueOf( 1 )
)
);
}
@Test
@SuppressWarnings( {"UnnecessaryBoxing"})
public void testAfterUpdate() {
assertFalse(
"afterInsert always returns false",
getEntityAccessStrategy().afterUpdate(
KEY,
VALUE2,
Integer.valueOf( 1 ),
Integer.valueOf( 2 ),
new MockSoftLock()
)
);
}
public static class MockSoftLock implements SoftLock {
}
} }

View File

@ -23,11 +23,16 @@
*/ */
package org.hibernate.test.cache.infinispan.query; package org.hibernate.test.cache.infinispan.query;
import static org.hibernate.TestLogger.LOG;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import junit.framework.AssertionFailedError;
import org.infinispan.notifications.Listener;
import org.infinispan.notifications.cachelistener.annotation.CacheEntryVisited;
import org.infinispan.notifications.cachelistener.event.CacheEntryVisitedEvent;
import org.infinispan.transaction.tm.BatchModeTransactionManager;
import org.infinispan.util.concurrent.IsolationLevel;
import org.hibernate.cache.CacheDataDescription; import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.QueryResultsRegion; import org.hibernate.cache.QueryResultsRegion;
import org.hibernate.cache.Region; import org.hibernate.cache.Region;
@ -36,13 +41,17 @@ import org.hibernate.cache.infinispan.InfinispanRegionFactory;
import org.hibernate.cache.infinispan.util.CacheAdapter; import org.hibernate.cache.infinispan.util.CacheAdapter;
import org.hibernate.cache.infinispan.util.CacheAdapterImpl; import org.hibernate.cache.infinispan.util.CacheAdapterImpl;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
import org.hibernate.service.internal.ServiceRegistryImpl;
import junit.framework.AssertionFailedError;
import org.hibernate.test.cache.infinispan.AbstractGeneralDataRegionTestCase; import org.hibernate.test.cache.infinispan.AbstractGeneralDataRegionTestCase;
import org.hibernate.test.cache.infinispan.util.CacheTestUtil; import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
import org.infinispan.notifications.Listener;
import org.infinispan.notifications.cachelistener.annotation.CacheEntryVisited; import static org.hibernate.TestLogger.LOG;
import org.infinispan.notifications.cachelistener.event.CacheEntryVisitedEvent; import static org.junit.Assert.assertEquals;
import org.infinispan.transaction.tm.BatchModeTransactionManager; import static org.junit.Assert.assertFalse;
import org.infinispan.util.concurrent.IsolationLevel; import static org.junit.Assert.assertTrue;
/** /**
* Tests of QueryResultRegionImpl. * Tests of QueryResultRegionImpl.
@ -52,251 +61,273 @@ import org.infinispan.util.concurrent.IsolationLevel;
*/ */
public class QueryRegionImplTestCase extends AbstractGeneralDataRegionTestCase { public class QueryRegionImplTestCase extends AbstractGeneralDataRegionTestCase {
// protected static final String REGION_NAME = "test/" + StandardQueryCache.class.getName(); @Override
protected Region createRegion(
InfinispanRegionFactory regionFactory,
String regionName,
Properties properties,
CacheDataDescription cdd) {
return regionFactory.buildQueryResultsRegion( regionName, properties );
}
/** @Override
* Create a new EntityRegionImplTestCase. protected String getStandardRegionName(String regionPrefix) {
* return regionPrefix + "/" + StandardQueryCache.class.getName();
* @param name }
*/
public QueryRegionImplTestCase( String name ) {
super(name);
}
@Override @Override
protected Region createRegion( InfinispanRegionFactory regionFactory, protected CacheAdapter getInfinispanCache(InfinispanRegionFactory regionFactory) {
String regionName, return CacheAdapterImpl.newInstance( regionFactory.getCacheManager().getCache( "local-query" ) );
Properties properties, }
CacheDataDescription cdd ) {
return regionFactory.buildQueryResultsRegion(regionName, properties);
}
@Override @Override
protected String getStandardRegionName( String regionPrefix ) { protected Configuration createConfiguration() {
return regionPrefix + "/" + StandardQueryCache.class.getName(); return CacheTestUtil.buildCustomQueryCacheConfiguration( "test", "replicated-query" );
} }
@Override private void putDoesNotBlockGetTest() throws Exception {
protected CacheAdapter getInfinispanCache( InfinispanRegionFactory regionFactory ) { Configuration cfg = createConfiguration();
return CacheAdapterImpl.newInstance(regionFactory.getCacheManager().getCache("local-query")); InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(
} new ServiceRegistryImpl( cfg.getProperties() ),
cfg,
getCacheTestSupport()
);
@Override // Sleep a bit to avoid concurrent FLUSH problem
protected Configuration createConfiguration() { avoidConcurrentFlush();
return CacheTestUtil.buildCustomQueryCacheConfiguration("test", "replicated-query");
}
public void testPutDoesNotBlockGet() throws Exception { final QueryResultsRegion region = regionFactory.buildQueryResultsRegion(
putDoesNotBlockGetTest(); getStandardRegionName( REGION_PREFIX ),
} cfg.getProperties()
);
private void putDoesNotBlockGetTest() throws Exception { region.put( KEY, VALUE1 );
Configuration cfg = createConfiguration(); assertEquals( VALUE1, region.get( KEY ) );
InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(getServiceRegistry(cfg.getProperties()), cfg, getCacheTestSupport());
// Sleep a bit to avoid concurrent FLUSH problem final CountDownLatch readerLatch = new CountDownLatch( 1 );
avoidConcurrentFlush(); final CountDownLatch writerLatch = new CountDownLatch( 1 );
final CountDownLatch completionLatch = new CountDownLatch( 1 );
final ExceptionHolder holder = new ExceptionHolder();
final QueryResultsRegion region = regionFactory.buildQueryResultsRegion(getStandardRegionName(REGION_PREFIX), Thread reader = new Thread() {
cfg.getProperties()); @Override
public void run() {
try {
BatchModeTransactionManager.getInstance().begin();
LOG.debug( "Transaction began, get value for key" );
assertTrue( VALUE2.equals( region.get( KEY ) ) == false );
BatchModeTransactionManager.getInstance().commit();
}
catch (AssertionFailedError e) {
holder.a1 = e;
rollback();
}
catch (Exception e) {
holder.e1 = e;
rollback();
}
finally {
readerLatch.countDown();
}
}
};
region.put(KEY, VALUE1); Thread writer = new Thread() {
assertEquals(VALUE1, region.get(KEY)); @Override
public void run() {
try {
BatchModeTransactionManager.getInstance().begin();
LOG.debug( "Put value2" );
region.put( KEY, VALUE2 );
LOG.debug( "Put finished for value2, await writer latch" );
writerLatch.await();
LOG.debug( "Writer latch finished" );
BatchModeTransactionManager.getInstance().commit();
LOG.debug( "Transaction committed" );
}
catch (Exception e) {
holder.e2 = e;
rollback();
}
finally {
completionLatch.countDown();
}
}
};
final CountDownLatch readerLatch = new CountDownLatch(1); reader.setDaemon( true );
final CountDownLatch writerLatch = new CountDownLatch(1); writer.setDaemon( true );
final CountDownLatch completionLatch = new CountDownLatch(1);
final ExceptionHolder holder = new ExceptionHolder();
Thread reader = new Thread() { writer.start();
@Override assertFalse( "Writer is blocking", completionLatch.await( 100, TimeUnit.MILLISECONDS ) );
public void run() {
try {
BatchModeTransactionManager.getInstance().begin();
LOG.debug("Transaction began, get value for key");
assertTrue(VALUE2.equals(region.get(KEY)) == false);
BatchModeTransactionManager.getInstance().commit();
} catch (AssertionFailedError e) {
holder.a1 = e;
rollback();
} catch (Exception e) {
holder.e1 = e;
rollback();
} finally {
readerLatch.countDown();
}
}
};
Thread writer = new Thread() { // Start the reader
@Override reader.start();
public void run() { assertTrue( "Reader finished promptly", readerLatch.await( 1000000000, TimeUnit.MILLISECONDS ) );
try {
BatchModeTransactionManager.getInstance().begin();
LOG.debug("Put value2");
region.put(KEY, VALUE2);
LOG.debug("Put finished for value2, await writer latch");
writerLatch.await();
LOG.debug("Writer latch finished");
BatchModeTransactionManager.getInstance().commit();
LOG.debug("Transaction committed");
} catch (Exception e) {
holder.e2 = e;
rollback();
} finally {
completionLatch.countDown();
}
}
};
reader.setDaemon(true); writerLatch.countDown();
writer.setDaemon(true); assertTrue( "Reader finished promptly", completionLatch.await( 100, TimeUnit.MILLISECONDS ) );
writer.start(); assertEquals( VALUE2, region.get( KEY ) );
assertFalse("Writer is blocking", completionLatch.await(100, TimeUnit.MILLISECONDS));
// Start the reader if ( holder.a1 != null ) {
reader.start(); throw holder.a1;
assertTrue("Reader finished promptly", readerLatch.await(1000000000, TimeUnit.MILLISECONDS)); }
else if ( holder.a2 != null ) {
throw holder.a2;
}
writerLatch.countDown(); assertEquals( "writer saw no exceptions", null, holder.e1 );
assertTrue("Reader finished promptly", completionLatch.await(100, TimeUnit.MILLISECONDS)); assertEquals( "reader saw no exceptions", null, holder.e2 );
}
assertEquals(VALUE2, region.get(KEY)); public void testGetDoesNotBlockPut() throws Exception {
getDoesNotBlockPutTest();
}
if (holder.a1 != null) throw holder.a1; private void getDoesNotBlockPutTest() throws Exception {
else if (holder.a2 != null) throw holder.a2; Configuration cfg = createConfiguration();
InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(
new ServiceRegistryImpl( cfg.getProperties() ),
cfg,
getCacheTestSupport()
);
assertEquals("writer saw no exceptions", null, holder.e1); // Sleep a bit to avoid concurrent FLUSH problem
assertEquals("reader saw no exceptions", null, holder.e2); avoidConcurrentFlush();
}
public void testGetDoesNotBlockPut() throws Exception { final QueryResultsRegion region = regionFactory.buildQueryResultsRegion(
getDoesNotBlockPutTest(); getStandardRegionName( REGION_PREFIX ),
} cfg.getProperties()
);
private void getDoesNotBlockPutTest() throws Exception { region.put( KEY, VALUE1 );
Configuration cfg = createConfiguration(); assertEquals( VALUE1, region.get( KEY ) );
InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(getServiceRegistry(cfg.getProperties()), cfg, getCacheTestSupport());
// Sleep a bit to avoid concurrent FLUSH problem // final Fqn rootFqn = getRegionFqn(getStandardRegionName(REGION_PREFIX), REGION_PREFIX);
avoidConcurrentFlush(); final CacheAdapter jbc = getInfinispanCache( regionFactory );
final QueryResultsRegion region = regionFactory.buildQueryResultsRegion(getStandardRegionName(REGION_PREFIX), final CountDownLatch blockerLatch = new CountDownLatch( 1 );
cfg.getProperties()); final CountDownLatch writerLatch = new CountDownLatch( 1 );
final CountDownLatch completionLatch = new CountDownLatch( 1 );
final ExceptionHolder holder = new ExceptionHolder();
region.put(KEY, VALUE1); Thread blocker = new Thread() {
assertEquals(VALUE1, region.get(KEY));
// final Fqn rootFqn = getRegionFqn(getStandardRegionName(REGION_PREFIX), REGION_PREFIX); @Override
final CacheAdapter jbc = getInfinispanCache(regionFactory); public void run() {
// Fqn toBlock = new Fqn(rootFqn, KEY);
GetBlocker blocker = new GetBlocker( blockerLatch, KEY );
try {
jbc.addListener( blocker );
final CountDownLatch blockerLatch = new CountDownLatch(1); BatchModeTransactionManager.getInstance().begin();
final CountDownLatch writerLatch = new CountDownLatch(1); region.get( KEY );
final CountDownLatch completionLatch = new CountDownLatch(1); BatchModeTransactionManager.getInstance().commit();
final ExceptionHolder holder = new ExceptionHolder(); }
catch (Exception e) {
holder.e1 = e;
rollback();
}
finally {
jbc.removeListener( blocker );
}
}
};
Thread blocker = new Thread() { Thread writer = new Thread() {
@Override @Override
public void run() { public void run() {
// Fqn toBlock = new Fqn(rootFqn, KEY); try {
GetBlocker blocker = new GetBlocker(blockerLatch, KEY); writerLatch.await();
try {
jbc.addListener(blocker);
BatchModeTransactionManager.getInstance().begin(); BatchModeTransactionManager.getInstance().begin();
region.get(KEY); region.put( KEY, VALUE2 );
BatchModeTransactionManager.getInstance().commit(); BatchModeTransactionManager.getInstance().commit();
} catch (Exception e) { }
holder.e1 = e; catch (Exception e) {
rollback(); holder.e2 = e;
} finally { rollback();
jbc.removeListener(blocker); }
} finally {
} completionLatch.countDown();
}; }
}
};
Thread writer = new Thread() { blocker.setDaemon( true );
writer.setDaemon( true );
@Override boolean unblocked = false;
public void run() { try {
try { blocker.start();
writerLatch.await(); writer.start();
BatchModeTransactionManager.getInstance().begin(); assertFalse( "Blocker is blocking", completionLatch.await( 100, TimeUnit.MILLISECONDS ) );
region.put(KEY, VALUE2); // Start the writer
BatchModeTransactionManager.getInstance().commit(); writerLatch.countDown();
} catch (Exception e) { assertTrue( "Writer finished promptly", completionLatch.await( 100, TimeUnit.MILLISECONDS ) );
holder.e2 = e;
rollback();
} finally {
completionLatch.countDown();
}
}
};
blocker.setDaemon(true); blockerLatch.countDown();
writer.setDaemon(true); unblocked = true;
boolean unblocked = false; if ( IsolationLevel.REPEATABLE_READ.equals( jbc.getConfiguration().getIsolationLevel() ) ) {
try { assertEquals( VALUE1, region.get( KEY ) );
blocker.start(); }
writer.start(); else {
assertEquals( VALUE2, region.get( KEY ) );
}
assertFalse("Blocker is blocking", completionLatch.await(100, TimeUnit.MILLISECONDS)); if ( holder.a1 != null ) {
// Start the writer throw holder.a1;
writerLatch.countDown(); }
assertTrue("Writer finished promptly", completionLatch.await(100, TimeUnit.MILLISECONDS)); else if ( holder.a2 != null ) {
throw holder.a2;
}
blockerLatch.countDown(); assertEquals( "blocker saw no exceptions", null, holder.e1 );
unblocked = true; assertEquals( "writer saw no exceptions", null, holder.e2 );
}
finally {
if ( !unblocked ) {
blockerLatch.countDown();
}
}
}
if (IsolationLevel.REPEATABLE_READ.equals(jbc.getConfiguration().getIsolationLevel())) { @Listener
assertEquals(VALUE1, region.get(KEY)); public class GetBlocker {
} else {
assertEquals(VALUE2, region.get(KEY));
}
if (holder.a1 != null) throw holder.a1; private CountDownLatch latch;
else if (holder.a2 != null) throw holder.a2; // private Fqn fqn;
private Object key;
assertEquals("blocker saw no exceptions", null, holder.e1); GetBlocker(
assertEquals("writer saw no exceptions", null, holder.e2); CountDownLatch latch,
} finally { Object key
if (!unblocked) blockerLatch.countDown(); ) {
} this.latch = latch;
} this.key = key;
}
@Listener @CacheEntryVisited
public class GetBlocker { public void nodeVisisted(CacheEntryVisitedEvent event) {
if ( event.isPre() && event.getKey().equals( key ) ) {
try {
latch.await();
}
catch (InterruptedException e) {
LOG.error( "Interrupted waiting for latch", e );
}
}
}
}
private CountDownLatch latch; private class ExceptionHolder {
// private Fqn fqn; Exception e1;
private Object key; Exception e2;
AssertionFailedError a1;
GetBlocker( CountDownLatch latch, AssertionFailedError a2;
Object key ) { }
this.latch = latch;
this.key = key;
}
@CacheEntryVisited
public void nodeVisisted( CacheEntryVisitedEvent event ) {
if (event.isPre() && event.getKey().equals(key)) {
try {
latch.await();
} catch (InterruptedException e) {
LOG.error("Interrupted waiting for latch", e);
}
}
}
}
private class ExceptionHolder {
Exception e1;
Exception e2;
AssertionFailedError a1;
AssertionFailedError a2;
}
} }

View File

@ -22,22 +22,9 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
package org.hibernate.test.cache.infinispan.timestamp; package org.hibernate.test.cache.infinispan.timestamp;
import java.util.Properties; import java.util.Properties;
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.Region;
import org.hibernate.cache.UpdateTimestampsCache;
import org.hibernate.cache.infinispan.InfinispanRegionFactory;
import org.hibernate.cache.infinispan.impl.ClassLoaderAwareCache;
import org.hibernate.cache.infinispan.timestamp.TimestampsRegionImpl;
import org.hibernate.cache.infinispan.util.CacheAdapter;
import org.hibernate.cache.infinispan.util.CacheAdapterImpl;
import org.hibernate.cache.infinispan.util.FlagAdapter;
import org.hibernate.cfg.Configuration;
import org.hibernate.test.cache.infinispan.AbstractGeneralDataRegionTestCase;
import org.hibernate.test.cache.infinispan.functional.classloader.Account;
import org.hibernate.test.cache.infinispan.functional.classloader.AccountHolder;
import org.hibernate.test.cache.infinispan.functional.classloader.SelectedClassnameClassLoader;
import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
import org.infinispan.AdvancedCache; import org.infinispan.AdvancedCache;
import org.infinispan.notifications.Listener; import org.infinispan.notifications.Listener;
import org.infinispan.notifications.cachelistener.annotation.CacheEntryActivated; import org.infinispan.notifications.cachelistener.annotation.CacheEntryActivated;
@ -51,6 +38,24 @@ import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
import org.infinispan.notifications.cachelistener.annotation.CacheEntryVisited; import org.infinispan.notifications.cachelistener.annotation.CacheEntryVisited;
import org.infinispan.notifications.cachelistener.event.Event; import org.infinispan.notifications.cachelistener.event.Event;
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.Region;
import org.hibernate.cache.UpdateTimestampsCache;
import org.hibernate.cache.infinispan.InfinispanRegionFactory;
import org.hibernate.cache.infinispan.impl.ClassLoaderAwareCache;
import org.hibernate.cache.infinispan.timestamp.TimestampsRegionImpl;
import org.hibernate.cache.infinispan.util.CacheAdapter;
import org.hibernate.cache.infinispan.util.CacheAdapterImpl;
import org.hibernate.cache.infinispan.util.FlagAdapter;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.internal.ServiceRegistryImpl;
import org.hibernate.test.cache.infinispan.AbstractGeneralDataRegionTestCase;
import org.hibernate.test.cache.infinispan.functional.classloader.Account;
import org.hibernate.test.cache.infinispan.functional.classloader.AccountHolder;
import org.hibernate.test.cache.infinispan.functional.classloader.SelectedClassnameClassLoader;
import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
/** /**
* Tests of TimestampsRegionImpl. * Tests of TimestampsRegionImpl.
* *
@ -59,10 +64,6 @@ import org.infinispan.notifications.cachelistener.event.Event;
*/ */
public class TimestampsRegionImplTestCase extends AbstractGeneralDataRegionTestCase { public class TimestampsRegionImplTestCase extends AbstractGeneralDataRegionTestCase {
public TimestampsRegionImplTestCase(String name) {
super(name);
}
@Override @Override
protected String getStandardRegionName(String regionPrefix) { protected String getStandardRegionName(String regionPrefix) {
return regionPrefix + "/" + UpdateTimestampsCache.class.getName(); return regionPrefix + "/" + UpdateTimestampsCache.class.getName();
@ -81,14 +82,18 @@ public class TimestampsRegionImplTestCase extends AbstractGeneralDataRegionTestC
public void testClearTimestampsRegionInIsolated() throws Exception { public void testClearTimestampsRegionInIsolated() throws Exception {
Configuration cfg = createConfiguration(); Configuration cfg = createConfiguration();
InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory( InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(
getServiceRegistry(cfg.getProperties()), cfg, getCacheTestSupport() new ServiceRegistryImpl( cfg.getProperties() ),
cfg,
getCacheTestSupport()
); );
// Sleep a bit to avoid concurrent FLUSH problem // Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush(); avoidConcurrentFlush();
Configuration cfg2 = createConfiguration(); Configuration cfg2 = createConfiguration();
InfinispanRegionFactory regionFactory2 = CacheTestUtil.startRegionFactory( InfinispanRegionFactory regionFactory2 = CacheTestUtil.startRegionFactory(
getServiceRegistry(cfg2.getProperties()), cfg2, getCacheTestSupport() new ServiceRegistryImpl( cfg.getProperties() ),
cfg2,
getCacheTestSupport()
); );
// Sleep a bit to avoid concurrent FLUSH problem // Sleep a bit to avoid concurrent FLUSH problem
avoidConcurrentFlush(); avoidConcurrentFlush();
@ -118,8 +123,7 @@ public class TimestampsRegionImplTestCase extends AbstractGeneralDataRegionTestC
@Override @Override
protected Configuration createConfiguration() { protected Configuration createConfiguration() {
Configuration cfg = CacheTestUtil.buildConfiguration("test", MockInfinispanRegionFactory.class, false, true); return CacheTestUtil.buildConfiguration("test", MockInfinispanRegionFactory.class, false, true);
return cfg;
} }
public static class MockInfinispanRegionFactory extends InfinispanRegionFactory { public static class MockInfinispanRegionFactory extends InfinispanRegionFactory {

View File

@ -22,13 +22,17 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
package org.hibernate.test.cache.infinispan.util; package org.hibernate.test.cache.infinispan.util;
import static org.hibernate.TestLogger.LOG;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set; import java.util.Set;
import org.hibernate.cache.RegionFactory;
import org.infinispan.Cache; import org.infinispan.Cache;
import org.hibernate.cache.RegionFactory;
import static org.hibernate.TestLogger.LOG;
/** /**
* Support class for tracking and cleaning up objects used in tests. * Support class for tracking and cleaning up objects used in tests.
* *
@ -52,11 +56,11 @@ public class CacheTestSupport {
} }
public void unregisterCache(Cache cache) { public void unregisterCache(Cache cache) {
caches.remove(cache); caches.remove( cache );
} }
public void unregisterFactory(RegionFactory factory) { public void unregisterFactory(RegionFactory factory) {
factories.remove(factory); factories.remove( factory );
} }
public void setUp() throws Exception { public void setUp() throws Exception {
@ -83,7 +87,7 @@ public class CacheTestSupport {
public void avoidConcurrentFlush() { public void avoidConcurrentFlush() {
// JG 2.6.1 has a problem where calling flush more than once too quickly // JG 2.6.1 has a problem where calling flush more than once too quickly
// can result in several second delays // can result in several second delays
sleep(100); sleep( 100 );
} }
private void sleep(long ms) { private void sleep(long ms) {