*/
package org.opendaylight.genius.lockmanager.tests;
-import static com.google.common.truth.Truth.assertThat;
+import static org.opendaylight.genius.tools.mdsal.testutils.TestFutureRpcResults.assertRpcErrorCause;
+import static org.opendaylight.genius.tools.mdsal.testutils.TestFutureRpcResults.assertRpcErrorWithoutCausesOrMessages;
+import static org.opendaylight.genius.tools.mdsal.testutils.TestFutureRpcResults.assertRpcSuccess;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-
import javax.inject.Inject;
-
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.MethodRule;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.test.AbstractConcurrentDataBrokerTest;
-import org.opendaylight.genius.lockmanager.LockManager;
+import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.genius.datastoreutils.testutils.DataBrokerFailures;
+import org.opendaylight.genius.datastoreutils.testutils.DataBrokerFailuresModule;
+import org.opendaylight.genius.lockmanager.impl.LockManagerServiceImpl;
+import org.opendaylight.genius.lockmanager.impl.LockManagerUtils;
import org.opendaylight.infrautils.inject.guice.testutils.GuiceRule;
import org.opendaylight.infrautils.testutils.LogCaptureRule;
import org.opendaylight.infrautils.testutils.LogRule;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockInputBuilder;
-import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
- * Test for {@link LockManager}.
+ * Test for {@link LockManagerServiceImpl}.
+ *
* @author Michael Vorburger.ch
*/
public class LockManagerTest extends AbstractConcurrentDataBrokerTest {
+ private static final Logger LOG = LoggerFactory.getLogger(LockManagerTest.class);
+
public @Rule LogRule logRule = new LogRule();
public @Rule LogCaptureRule logCaptureRule = new LogCaptureRule();
- public @Rule MethodRule guice = new GuiceRule(new LockManagerTestModule());
+ public @Rule MethodRule guice = new GuiceRule(LockManagerTestModule.class, DataBrokerFailuresModule.class);
- @Inject DataBroker dataBroker;
+ @Inject DataBrokerFailures dbFailureSimulator;
@Inject LockManagerService lockManager;
+ @Inject LockManagerUtils lockManagerUtils;
@Test
public void testLockAndUnLock() throws InterruptedException, ExecutionException, TimeoutException {
LockInput lockInput = new LockInputBuilder().setLockName("testLock").build();
- assertSuccessfulFutureRpcResult(lockManager.lock(lockInput));
+ assertRpcSuccess(lockManager.lock(lockInput));
UnlockInput unlockInput = new UnlockInputBuilder().setLockName("testLock").build();
- assertSuccessfulFutureRpcResult(lockManager.unlock(unlockInput));
+ assertRpcSuccess(lockManager.unlock(unlockInput));
}
@Test
public void testUnLockOfUnknownShouldNotFail() throws InterruptedException, ExecutionException, TimeoutException {
UnlockInput unlockInput = new UnlockInputBuilder().setLockName("unknownLock").build();
- assertSuccessfulFutureRpcResult(lockManager.unlock(unlockInput));
+ assertRpcSuccess(lockManager.unlock(unlockInput));
}
@Test
// lock() RPC will infinitely retry, and it will only come out when the key is unlocked
public void testLockAndReLockSameAgain() throws InterruptedException, ExecutionException, TimeoutException {
LockInput lockInput = new LockInputBuilder().setLockName("testLock").build();
- assertSuccessfulFutureRpcResult(lockManager.lock(lockInput));
+ assertRpcSuccess(lockManager.lock(lockInput));
runUnlockTimerTask("testLock", 3000);
// This will retry infinitely since the other lock is not released!
// After 5 seconds, the parallel thread will unlock the key, and the below TC will pass
- assertSuccessfulFutureRpcResult(lockManager.lock(lockInput));
+ assertRpcSuccess(lockManager.lock(lockInput));
}
@Test
// test re-lock of already locked key using tryLock() RPC.
// tryLock() RPC will retry only specific number of times, and it will only return after that
public void testTryLock() throws InterruptedException, ExecutionException, TimeoutException {
- logCaptureRule.expectError("Failed to get lock testTryLock after 3 retries");
+ String uniqueId = lockManagerUtils.getBladeId() + ":2";
+ logCaptureRule.expectError("Failed to get lock testTryLock owner " + uniqueId + " after 3 retries");
TryLockInput lockInput = new TryLockInputBuilder().setLockName("testTryLock").setTime(3L)
- .setTimeUnit(TimeUnits.Seconds).build();
- assertSuccessfulFutureRpcResult(lockManager.tryLock(lockInput));
+ .setTimeUnit(TimeUnits.Seconds).build();
+ assertRpcSuccess(lockManager.tryLock(lockInput));
// The second acquireLock request will retry for 3 seconds
// and since the first lock is not unlocked, the request will fail.
lockInput = new TryLockInputBuilder().setLockName("testTryLock").setTime(3000L)
- .setTimeUnit(TimeUnits.Milliseconds).build();
- assertFailedFutureRpcResult(lockManager.tryLock(lockInput));
+ .setTimeUnit(TimeUnits.Milliseconds).build();
+ assertRpcErrorWithoutCausesOrMessages(lockManager.tryLock(lockInput));
// Try to unlock the key in a separate thread before retry expires, and see
// if lock gets acquired.
runUnlockTimerTask("testTryLock", 2000);
lockInput = new TryLockInputBuilder().setLockName("testTryLock").setTime(4000000L)
- .setTimeUnit(TimeUnits.Microseconds).build();
- assertSuccessfulFutureRpcResult(lockManager.tryLock(lockInput));
+ .setTimeUnit(TimeUnits.Microseconds).build();
+ assertRpcSuccess(lockManager.tryLock(lockInput));
}
-
- private void assertSuccessfulFutureRpcResult(Future<RpcResult<Void>> futureRpcResult)
+ @Test
+ public void test3sOptimisticLockFailedExceptionOnLock()
throws InterruptedException, ExecutionException, TimeoutException {
- assertThat(futureRpcResult.get(5, TimeUnit.SECONDS).isSuccessful()).isTrue();
- assertThat(futureRpcResult.get(5, TimeUnit.SECONDS).getErrors()).isEmpty();
+ dbFailureSimulator.failSubmits(new OptimisticLockFailedException("bada boum bam!"));
+ LockInput lockInput = new LockInputBuilder().setLockName("testLock").build();
+ runUnfailSubmitsTimerTask(3000); // see other tests above
+ assertRpcSuccess(lockManager.lock(lockInput));
+ }
+
+ @Test
+ public void testAskTimeOutException() throws InterruptedException, ExecutionException, TimeoutException {
+ String lockName = "testLock";
+ logCaptureRule.expectError("Unable to acquire lock for " + lockName + ", try 1", 1);
+ dbFailureSimulator.failButSubmitsAnyways();
+ LockInput lockInput = new LockInputBuilder().setLockName(lockName).build();
+ assertRpcErrorCause(lockManager.lock(lockInput), TransactionCommitFailedException.class,
+ "caused by simulated AskTimeoutException");
}
- private void assertFailedFutureRpcResult(Future<RpcResult<Void>> futureRpcResult)
+ @Test
+ public void testEternalTransactionCommitFailedExceptionOnLock()
throws InterruptedException, ExecutionException, TimeoutException {
- assertThat(futureRpcResult.get(5, TimeUnit.SECONDS).isSuccessful()).isFalse();
+ logCaptureRule.expectError("RPC lock() failed; input = LockInput{_lockName=testLock, augmentation=[]}");
+ dbFailureSimulator.failSubmits(new TransactionCommitFailedException("bada boum bam!"));
+ LockInput lockInput = new LockInputBuilder().setLockName("testLock").build();
+ assertRpcErrorCause(lockManager.lock(lockInput), TransactionCommitFailedException.class, "bada boum bam!");
}
+ // TODO testEternalReadFailedExceptionOnLock() throws InterruptedException, ExecutionException, TimeoutException {
+
+ // TODO test3sOptimisticLockFailedExceptionOnUnLock()
+ // TODO testEternalReadFailedExceptionOnUnLock()
+ // TODO testEternalTransactionCommitFailedExceptionOnUnLock()
+
+ // TODO test3sOptimisticLockFailedExceptionOnTryLock()
+ // TODO testEternalReadFailedExceptionOnTryLock()
+ // TODO testEternalTransactionCommitFailedExceptionOnTryLock()
+
private void runUnlockTimerTask(String lockKey, long delay) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
UnlockInput unlockInput = new UnlockInputBuilder().setLockName(lockKey).build();
try {
- assertSuccessfulFutureRpcResult(lockManager.unlock(unlockInput));
+ assertRpcSuccess(lockManager.unlock(unlockInput));
} catch (InterruptedException | ExecutionException | TimeoutException e) {
- throw new RuntimeException(e);
+ LOG.error("runUnlockTimerTask() failed", e);
+ // throw new RuntimeException(e) is useless here, as this in a BG Thread, and it would go nowhere
}
}
}, delay);
}
+
+ private void runUnfailSubmitsTimerTask(long delay) {
+ Timer timer = new Timer();
+ timer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ dbFailureSimulator.unfailSubmits();
+ }
+ }, delay);
+ }
+
}