Reverting changes from r1661762 (LANG-1086) for now until we have consensus about this change.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@1662379 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
4975b8903e
commit
61836183b1
|
@ -22,7 +22,6 @@
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<release version="3.4" date="tba" description="tba">
|
<release version="3.4" date="tba" description="tba">
|
||||||
<action issue="LANG-1086" type="update" dev="britter">Remove busy wait from AtomicSafeInitializer.get()</action>
|
|
||||||
<action issue="LANG-1081" type="fix" dev="britter" due-to="Jonathan Baker">DiffBuilder.append(String, Object left, Object right) does not do a left.equals(right) check</action>
|
<action issue="LANG-1081" type="fix" dev="britter" due-to="Jonathan Baker">DiffBuilder.append(String, Object left, Object right) does not do a left.equals(right) check</action>
|
||||||
<action issue="LANG-1055" type="fix" dev="britter" due-to="Jonathan Baker">StrSubstitutor.replaceSystemProperties does not work consistently</action>
|
<action issue="LANG-1055" type="fix" dev="britter" due-to="Jonathan Baker">StrSubstitutor.replaceSystemProperties does not work consistently</action>
|
||||||
<action issue="LANG-1082" type="add" dev="britter" due-to="Jonathan Baker">Add option to disable the "objectsTriviallyEqual" test in DiffBuilder</action>
|
<action issue="LANG-1082" type="add" dev="britter" due-to="Jonathan Baker">Add option to disable the "objectsTriviallyEqual" test in DiffBuilder</action>
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.commons.lang3.concurrent;
|
package org.apache.commons.lang3.concurrent;
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,44 +62,20 @@ public abstract class AtomicSafeInitializer<T> implements
|
||||||
/** Holds the reference to the managed object. */
|
/** Holds the reference to the managed object. */
|
||||||
private final AtomicReference<T> reference = new AtomicReference<T>();
|
private final AtomicReference<T> reference = new AtomicReference<T>();
|
||||||
|
|
||||||
/** Holds the exception that terminated the initialize() method, if an exception was thrown */
|
|
||||||
private final AtomicReference<ConcurrentException> referenceExc = new AtomicReference<ConcurrentException>();
|
|
||||||
|
|
||||||
/** Latch for those threads waiting for initialization to complete. */
|
|
||||||
private final CountDownLatch latch = new CountDownLatch(1);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get (and initialize, if not initialized yet) the required object
|
* Get (and initialize, if not initialized yet) the required object
|
||||||
*
|
*
|
||||||
* @return lazily initialized object
|
* @return lazily initialized object
|
||||||
* @throws ConcurrentException if the initialization of the object causes an
|
* @throws ConcurrentException if the initialization of the object causes an
|
||||||
* exception or the thread is interrupted waiting for another thread to
|
* exception
|
||||||
* complete the initialization
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final T get() throws ConcurrentException {
|
public final T get() throws ConcurrentException {
|
||||||
T result;
|
T result;
|
||||||
|
|
||||||
if ((result = reference.get()) == null) {
|
while ((result = reference.get()) == null) {
|
||||||
if (factory.compareAndSet(null, this)) {
|
if (factory.compareAndSet(null, this)) {
|
||||||
try {
|
reference.set(initialize());
|
||||||
reference.set(result = initialize());
|
|
||||||
} catch ( ConcurrentException exc ) {
|
|
||||||
referenceExc.set(exc);
|
|
||||||
throw exc;
|
|
||||||
} finally {
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
latch.await();
|
|
||||||
if ( referenceExc.get() != null ) {
|
|
||||||
throw new ConcurrentException(referenceExc.get().getMessage(), referenceExc.get().getCause());
|
|
||||||
}
|
|
||||||
result = reference.get();
|
|
||||||
} catch (InterruptedException intExc) {
|
|
||||||
throw new ConcurrentException("interrupted waiting for initialization to complete", intExc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,6 @@ package org.apache.commons.lang3.concurrent;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertSame;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
|
@ -74,41 +72,7 @@ public abstract class AbstractConcurrentInitializerTest {
|
||||||
@Test
|
@Test
|
||||||
public void testGetConcurrent() throws ConcurrentException,
|
public void testGetConcurrent() throws ConcurrentException,
|
||||||
InterruptedException {
|
InterruptedException {
|
||||||
|
final ConcurrentInitializer<Object> initializer = createInitializer();
|
||||||
this.testGetConcurrentOptionallyWithException(false, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the handling of exceptions thrown on the initialized when multiple threads execute concurrently.
|
|
||||||
* Always an exception with the same message and cause should be thrown.
|
|
||||||
*
|
|
||||||
* @throws org.apache.commons.lang3.concurrent.ConcurrentException because the object under test may throw it
|
|
||||||
* @throws java.lang.InterruptedException because the threading API my throw it
|
|
||||||
*/
|
|
||||||
public void testGetConcurrentWithException(String expectedMessage,
|
|
||||||
Exception expectedCause)
|
|
||||||
throws ConcurrentException, InterruptedException {
|
|
||||||
|
|
||||||
this.testGetConcurrentOptionallyWithException(true, expectedMessage, expectedCause);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests whether get() can be invoked from multiple threads concurrently. Supports the exception-handling case
|
|
||||||
* and the normal, non-exception case.
|
|
||||||
*
|
|
||||||
* Always the same object should be returned, or an exception with the same message and cause should be thrown.
|
|
||||||
*
|
|
||||||
* @throws org.apache.commons.lang3.concurrent.ConcurrentException because the object under test may throw it
|
|
||||||
* @throws java.lang.InterruptedException because the threading API my throw it
|
|
||||||
*/
|
|
||||||
protected void testGetConcurrentOptionallyWithException(boolean expectExceptions, String expectedMessage,
|
|
||||||
Exception expectedCause)
|
|
||||||
throws ConcurrentException, InterruptedException {
|
|
||||||
|
|
||||||
final ConcurrentInitializer<Object> initializer = expectExceptions ?
|
|
||||||
createExceptionThrowingInitializer() :
|
|
||||||
createInitializer();
|
|
||||||
|
|
||||||
final int threadCount = 20;
|
final int threadCount = 20;
|
||||||
final CountDownLatch startLatch = new CountDownLatch(1);
|
final CountDownLatch startLatch = new CountDownLatch(1);
|
||||||
class GetThread extends Thread {
|
class GetThread extends Thread {
|
||||||
|
@ -142,18 +106,9 @@ public abstract class AbstractConcurrentInitializerTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check results
|
// check results
|
||||||
if ( expectExceptions ) {
|
final Object managedObject = initializer.get();
|
||||||
for (GetThread t : threads) {
|
for (final GetThread t : threads) {
|
||||||
assertTrue(t.object instanceof Exception);
|
assertEquals("Wrong object", managedObject, t.object);
|
||||||
Exception exc = (Exception) t.object;
|
|
||||||
assertEquals(expectedMessage, exc.getMessage());
|
|
||||||
assertSame(expectedCause, exc.getCause());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final Object managedObject = initializer.get();
|
|
||||||
for (final GetThread t : threads) {
|
|
||||||
assertEquals("Wrong object", managedObject, t.object);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,12 +119,4 @@ public abstract class AbstractConcurrentInitializerTest {
|
||||||
* @return the initializer object to be tested
|
* @return the initializer object to be tested
|
||||||
*/
|
*/
|
||||||
protected abstract ConcurrentInitializer<Object> createInitializer();
|
protected abstract ConcurrentInitializer<Object> createInitializer();
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a {@link ConcurrentInitializer} object that always throws
|
|
||||||
* exceptions.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected abstract ConcurrentInitializer<Object> createExceptionThrowingInitializer();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,29 +16,12 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.commons.lang3.concurrent;
|
package org.apache.commons.lang3.concurrent;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test class for {@code AtomicInitializer}.
|
* Test class for {@code AtomicInitializer}.
|
||||||
*
|
*
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class AtomicInitializerTest extends AbstractConcurrentInitializerTest {
|
public class AtomicInitializerTest extends AbstractConcurrentInitializerTest {
|
||||||
private Exception testCauseException;
|
|
||||||
private String testExceptionMessage;
|
|
||||||
|
|
||||||
public AtomicInitializerTest() {
|
|
||||||
testExceptionMessage = "x-test-exception-message-x";
|
|
||||||
testCauseException = new Exception(testExceptionMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetConcurrentWithException ()
|
|
||||||
throws ConcurrentException, InterruptedException {
|
|
||||||
|
|
||||||
super.testGetConcurrentWithException(testExceptionMessage, testCauseException);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the initializer to be tested.
|
* Returns the initializer to be tested.
|
||||||
*
|
*
|
||||||
|
@ -53,20 +36,4 @@ public class AtomicInitializerTest extends AbstractConcurrentInitializerTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ConcurrentInitializer<Object> createExceptionThrowingInitializer() {
|
|
||||||
return new ExceptionThrowingAtomicSafeInitializerTestImpl();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A concrete test implementation of {@code AtomicSafeInitializer}. This
|
|
||||||
* implementation always throws an exception.
|
|
||||||
*/
|
|
||||||
private class ExceptionThrowingAtomicSafeInitializerTestImpl extends AtomicSafeInitializer<Object> {
|
|
||||||
@Override
|
|
||||||
protected Object initialize() throws ConcurrentException {
|
|
||||||
throw new ConcurrentException(testExceptionMessage, testCauseException);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,7 @@
|
||||||
package org.apache.commons.lang3.concurrent;
|
package org.apache.commons.lang3.concurrent;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertSame;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
@ -34,19 +30,12 @@ import org.junit.Test;
|
||||||
*/
|
*/
|
||||||
public class AtomicSafeInitializerTest extends
|
public class AtomicSafeInitializerTest extends
|
||||||
AbstractConcurrentInitializerTest {
|
AbstractConcurrentInitializerTest {
|
||||||
|
|
||||||
/** The instance to be tested. */
|
/** The instance to be tested. */
|
||||||
private AtomicSafeInitializerTestImpl initializer;
|
private AtomicSafeInitializerTestImpl initializer;
|
||||||
private ExceptionThrowingAtomicSafeInitializerTestImpl exceptionThrowingInitializer;
|
|
||||||
private Exception testCauseException;
|
|
||||||
private String testExceptionMessage;
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
initializer = new AtomicSafeInitializerTestImpl();
|
initializer = new AtomicSafeInitializerTestImpl();
|
||||||
exceptionThrowingInitializer = new ExceptionThrowingAtomicSafeInitializerTestImpl();
|
|
||||||
testExceptionMessage = "x-test-exception-message-x";
|
|
||||||
testCauseException = new Exception(testExceptionMessage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,17 +48,6 @@ public class AtomicSafeInitializerTest extends
|
||||||
return initializer;
|
return initializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the exception-throwing initializer to be tested.
|
|
||||||
*
|
|
||||||
* @return the {@code AtomicSafeInitializer} under test when validating
|
|
||||||
* exception handling
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected ConcurrentInitializer<Object> createExceptionThrowingInitializer() {
|
|
||||||
return exceptionThrowingInitializer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that initialize() is called only once.
|
* Tests that initialize() is called only once.
|
||||||
*
|
*
|
||||||
|
@ -84,92 +62,6 @@ public class AtomicSafeInitializerTest extends
|
||||||
initializer.initCounter.get());
|
initializer.initCounter.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExceptionOnInitialize() throws ConcurrentException,
|
|
||||||
InterruptedException {
|
|
||||||
|
|
||||||
testGetConcurrentWithException(testExceptionMessage, testCauseException);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate the handling of an interrupted exception on a thread waiting for another thread to finish calling the
|
|
||||||
* initialize() method.
|
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
@Test(timeout = 3000)
|
|
||||||
public void testInterruptedWaitingOnInitialize() throws Exception {
|
|
||||||
this.execTestWithWaitingOnInitialize(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test the success path of two threads reaching the initialization point at the same time.
|
|
||||||
*/
|
|
||||||
@Test(timeout = 3000)
|
|
||||||
public void testOneThreadWaitingForAnotherToInitialize () throws Exception {
|
|
||||||
execTestWithWaitingOnInitialize(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a test that requires one thread to be waiting on the initialize() method of another thread. This test
|
|
||||||
* uses latches to guarantee the code path being tested.
|
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
protected void execTestWithWaitingOnInitialize(boolean interruptInd) throws Exception {
|
|
||||||
final CountDownLatch startLatch = new CountDownLatch(1);
|
|
||||||
final CountDownLatch finishLatch = new CountDownLatch(1);
|
|
||||||
final WaitingInitializerTestImpl initializer = new WaitingInitializerTestImpl(startLatch, finishLatch);
|
|
||||||
|
|
||||||
InitializerTestThread execThread1 = new InitializerTestThread(initializer);
|
|
||||||
InitializerTestThread execThread2 = new InitializerTestThread(initializer);
|
|
||||||
|
|
||||||
// Start the first thread and wait for it to get into the initialize method so we are sure it is the thread
|
|
||||||
// executing initialize().
|
|
||||||
execThread1.start();
|
|
||||||
startLatch.await();
|
|
||||||
|
|
||||||
// Start the second thread and interrupt it to force the InterruptedException. There is no need to make sure
|
|
||||||
// the thread reaches the await() call before interrupting it.
|
|
||||||
execThread2.start();
|
|
||||||
|
|
||||||
if ( interruptInd ) {
|
|
||||||
// Interrupt the second thread now and wait for it to complete to ensure it reaches the wait inside the
|
|
||||||
// get() method.
|
|
||||||
execThread2.interrupt();
|
|
||||||
execThread2.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Signal the completion of the initialize method now.
|
|
||||||
finishLatch.countDown();
|
|
||||||
|
|
||||||
// Wait for the initialize() to finish.
|
|
||||||
execThread1.join();
|
|
||||||
|
|
||||||
// Wait for thread2 to finish, if it was not already done
|
|
||||||
if ( ! interruptInd ) {
|
|
||||||
execThread2.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Validate: thread1 should have the valid result; thread2 should have caught an interrupted exception, if
|
|
||||||
// interrupted, or should have the same result otherwise.
|
|
||||||
//
|
|
||||||
assertFalse(execThread1.isCaughtException());
|
|
||||||
assertSame(initializer.getAnswer(), execThread1.getResult());
|
|
||||||
|
|
||||||
if ( interruptInd ) {
|
|
||||||
assertTrue(execThread2.isCaughtException());
|
|
||||||
Exception exc = (Exception) execThread2.getResult();
|
|
||||||
assertTrue(exc.getCause() instanceof InterruptedException);
|
|
||||||
assertEquals("interrupted waiting for initialization to complete", exc.getMessage());
|
|
||||||
} else {
|
|
||||||
assertFalse(execThread2.isCaughtException());
|
|
||||||
assertSame(initializer.getAnswer(), execThread2.getResult());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A concrete test implementation of {@code AtomicSafeInitializer}. This
|
* A concrete test implementation of {@code AtomicSafeInitializer}. This
|
||||||
* implementation also counts the number of invocations of the initialize()
|
* implementation also counts the number of invocations of the initialize()
|
||||||
|
@ -186,90 +78,4 @@ public class AtomicSafeInitializerTest extends
|
||||||
return new Object();
|
return new Object();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A concrete test implementation of {@code AtomicSafeInitializer}. This
|
|
||||||
* implementation always throws an exception.
|
|
||||||
*/
|
|
||||||
private class ExceptionThrowingAtomicSafeInitializerTestImpl extends AtomicSafeInitializer<Object> {
|
|
||||||
@Override
|
|
||||||
protected Object initialize() throws ConcurrentException {
|
|
||||||
throw new ConcurrentException(testExceptionMessage, testCauseException);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializer that signals it has started and waits to complete until signalled in order to enable a guaranteed
|
|
||||||
* order-of-operations. This allows the test code to peg one thread to the initialize method for a period of time
|
|
||||||
* that the test can dictate.
|
|
||||||
*/
|
|
||||||
private class WaitingInitializerTestImpl extends AtomicSafeInitializer<Object> {
|
|
||||||
private final CountDownLatch startedLatch;
|
|
||||||
private final CountDownLatch finishLatch;
|
|
||||||
private final Object answer = new Object();
|
|
||||||
|
|
||||||
public WaitingInitializerTestImpl(CountDownLatch startedLatch, CountDownLatch finishLatch) {
|
|
||||||
this.startedLatch = startedLatch;
|
|
||||||
this.finishLatch = finishLatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object initialize() throws ConcurrentException {
|
|
||||||
this.startedLatch.countDown();
|
|
||||||
try {
|
|
||||||
this.finishLatch.await();
|
|
||||||
} catch (InterruptedException intExc) {
|
|
||||||
throw new ConcurrentException(intExc);
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getAnswer () {
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test executor of the initializer get() operation that captures the result.
|
|
||||||
*/
|
|
||||||
private class InitializerTestThread extends Thread {
|
|
||||||
private AtomicSafeInitializer<Object> initializer;
|
|
||||||
private Object result;
|
|
||||||
private boolean caughtException;
|
|
||||||
|
|
||||||
public InitializerTestThread(AtomicSafeInitializer<Object> initializer) {
|
|
||||||
super("AtomicSafeInitializer test thread");
|
|
||||||
this.initializer = initializer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
this.result = initializer.get();
|
|
||||||
} catch ( ConcurrentException concurrentExc ) {
|
|
||||||
this.caughtException = true;
|
|
||||||
this.result = concurrentExc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resulting object, if the get() method returned successfully, or exception if an exception was thrown.
|
|
||||||
*
|
|
||||||
* @return resulting object or exception from the get() method call.
|
|
||||||
*/
|
|
||||||
public Object getResult () {
|
|
||||||
return this.result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine whether an exception was caught on the get() call. Does not guarantee that the get() method was
|
|
||||||
* called or completed.
|
|
||||||
*
|
|
||||||
* @return true => exception was caught; false => exception was not caught.
|
|
||||||
*/
|
|
||||||
public boolean isCaughtException () {
|
|
||||||
return this.caughtException;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
package org.apache.commons.lang3.concurrent;
|
package org.apache.commons.lang3.concurrent;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test class for {@code LazyInitializer}.
|
* Test class for {@code LazyInitializer}.
|
||||||
|
@ -27,16 +26,10 @@ import org.junit.Test;
|
||||||
public class LazyInitializerTest extends AbstractConcurrentInitializerTest {
|
public class LazyInitializerTest extends AbstractConcurrentInitializerTest {
|
||||||
/** The initializer to be tested. */
|
/** The initializer to be tested. */
|
||||||
private LazyInitializerTestImpl initializer;
|
private LazyInitializerTestImpl initializer;
|
||||||
private ExceptionThrowingLazyInitializerTestImpl exceptionThrowingInitializer;
|
|
||||||
private Exception testCauseException;
|
|
||||||
private String testExceptionMessage;
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
initializer = new LazyInitializerTestImpl();
|
initializer = new LazyInitializerTestImpl();
|
||||||
exceptionThrowingInitializer = new ExceptionThrowingLazyInitializerTestImpl();
|
|
||||||
testExceptionMessage = "x-test-exception-message-x";
|
|
||||||
testCauseException = new Exception(testExceptionMessage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,18 +43,6 @@ public class LazyInitializerTest extends AbstractConcurrentInitializerTest {
|
||||||
return initializer;
|
return initializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ConcurrentInitializer<Object> createExceptionThrowingInitializer() {
|
|
||||||
return exceptionThrowingInitializer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetConcurrentWithException ()
|
|
||||||
throws ConcurrentException, InterruptedException {
|
|
||||||
|
|
||||||
super.testGetConcurrentWithException(testExceptionMessage, testCauseException);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A test implementation of LazyInitializer. This class creates a plain
|
* A test implementation of LazyInitializer. This class creates a plain
|
||||||
* Object. As Object does not provide a specific equals() method, it is easy
|
* Object. As Object does not provide a specific equals() method, it is easy
|
||||||
|
@ -74,16 +55,4 @@ public class LazyInitializerTest extends AbstractConcurrentInitializerTest {
|
||||||
return new Object();
|
return new Object();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A concrete test implementation of {@code AtomicSafeInitializer}. This
|
|
||||||
* implementation always throws an exception.
|
|
||||||
*/
|
|
||||||
private class ExceptionThrowingLazyInitializerTestImpl extends LazyInitializer<Object> {
|
|
||||||
@Override
|
|
||||||
protected Object initialize() throws ConcurrentException {
|
|
||||||
throw new ConcurrentException(testExceptionMessage, testCauseException);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue