Migrate lockmanager to uint types
[genius.git] / lockmanager / lockmanager-impl / src / test / java / org / opendaylight / genius / lockmanager / tests / LockManagerTest.java
1 /*
2  * Copyright (c) 2017 Red Hat, Inc. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.genius.lockmanager.tests;
9
10 import static org.opendaylight.serviceutils.tools.mdsal.testutils.TestFutureRpcResults.assertRpcErrorCause;
11 import static org.opendaylight.serviceutils.tools.mdsal.testutils.TestFutureRpcResults.assertRpcErrorWithoutCausesOrMessages;
12 import static org.opendaylight.serviceutils.tools.mdsal.testutils.TestFutureRpcResults.assertRpcSuccess;
13
14 import java.util.Timer;
15 import java.util.TimerTask;
16 import java.util.concurrent.ExecutionException;
17 import java.util.concurrent.TimeoutException;
18 import javax.inject.Inject;
19 import org.junit.Rule;
20 import org.junit.Test;
21 import org.junit.rules.MethodRule;
22 import org.opendaylight.genius.datastoreutils.testutils.DataBrokerFailures;
23 import org.opendaylight.genius.datastoreutils.testutils.DataBrokerFailuresModule;
24 import org.opendaylight.genius.lockmanager.impl.LockManagerServiceImpl;
25 import org.opendaylight.genius.lockmanager.impl.LockManagerUtils;
26 import org.opendaylight.infrautils.inject.guice.testutils.GuiceRule;
27 import org.opendaylight.infrautils.testutils.LogCaptureRule;
28 import org.opendaylight.infrautils.testutils.LogRule;
29 import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractConcurrentDataBrokerTest;
30 import org.opendaylight.mdsal.common.api.OptimisticLockFailedException;
31 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.LockInput;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.LockInputBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.LockManagerService;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TimeUnits;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockInput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockInputBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockInputBuilder;
40 import org.opendaylight.yangtools.yang.common.Uint32;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 /**
45  * Test for {@link LockManagerServiceImpl}.
46  *
47  * @author Michael Vorburger.ch
48  */
49 public class LockManagerTest extends AbstractConcurrentDataBrokerTest {
50
51     private static final Logger LOG = LoggerFactory.getLogger(LockManagerTest.class);
52
53     public @Rule LogRule logRule = new LogRule();
54     public @Rule LogCaptureRule logCaptureRule = new LogCaptureRule();
55     public @Rule MethodRule guice = new GuiceRule(LockManagerTestModule.class, DataBrokerFailuresModule.class);
56
57     @Inject DataBrokerFailures dbFailureSimulator;
58     @Inject LockManagerService lockManager;
59     @Inject LockManagerUtils lockManagerUtils;
60
61     @Test
62     public void testLockAndUnLock() throws InterruptedException, ExecutionException, TimeoutException {
63         LockInput lockInput = new LockInputBuilder().setLockName("testLock").build();
64         assertRpcSuccess(lockManager.lock(lockInput));
65
66         UnlockInput unlockInput = new UnlockInputBuilder().setLockName("testLock").build();
67         assertRpcSuccess(lockManager.unlock(unlockInput));
68     }
69
70     @Test
71     public void testUnLockOfUnknownShouldNotFail() throws InterruptedException, ExecutionException, TimeoutException {
72         UnlockInput unlockInput = new UnlockInputBuilder().setLockName("unknownLock").build();
73         assertRpcSuccess(lockManager.unlock(unlockInput));
74     }
75
76     @Test
77     // test re-lock of already locked key.
78     // lock() RPC will infinitely retry, and it will only come out when the key is unlocked
79     public void testLockAndReLockSameAgain() throws InterruptedException, ExecutionException, TimeoutException {
80         LockInput lockInput = new LockInputBuilder().setLockName("testLock").build();
81         assertRpcSuccess(lockManager.lock(lockInput));
82         runUnlockTimerTask("testLock", 3000);
83
84         // This will retry infinitely since the other lock is not released!
85         // After 5 seconds, the parallel thread will unlock the key, and the below TC will pass
86         assertRpcSuccess(lockManager.lock(lockInput));
87     }
88
89     @Test
90     // test re-lock of already locked key using tryLock() RPC.
91     // tryLock() RPC will retry only specific number of times, and it will only return after that
92     public void testTryLock() throws InterruptedException, ExecutionException, TimeoutException {
93         String uniqueId = lockManagerUtils.getBladeId() + ":2";
94         logCaptureRule.expectError("Failed to get lock testTryLock owner " + uniqueId + " after 3 retries");
95
96         TryLockInput lockInput = new TryLockInputBuilder().setLockName("testTryLock").setTime(Uint32.valueOf(3))
97                 .setTimeUnit(TimeUnits.Seconds).build();
98         assertRpcSuccess(lockManager.tryLock(lockInput));
99
100         // The second acquireLock request will retry for 3 seconds
101         // and since the first lock is not unlocked, the request will fail.
102         lockInput = new TryLockInputBuilder().setLockName("testTryLock").setTime(Uint32.valueOf(3000))
103                 .setTimeUnit(TimeUnits.Milliseconds).build();
104         assertRpcErrorWithoutCausesOrMessages(lockManager.tryLock(lockInput));
105
106         // Try to unlock the key in a separate thread before retry expires, and see
107         // if lock gets acquired.
108         runUnlockTimerTask("testTryLock", 2000);
109
110         lockInput = new TryLockInputBuilder().setLockName("testTryLock").setTime(Uint32.valueOf(4000000))
111                 .setTimeUnit(TimeUnits.Microseconds).build();
112         assertRpcSuccess(lockManager.tryLock(lockInput));
113     }
114
115     @Test
116     public void test3sOptimisticLockFailedExceptionOnLock()
117             throws InterruptedException, ExecutionException, TimeoutException {
118         dbFailureSimulator.failSubmits(new OptimisticLockFailedException("bada boum bam!"));
119         LockInput lockInput = new LockInputBuilder().setLockName("testLock").build();
120         runUnfailSubmitsTimerTask(3000); // see other tests above
121         assertRpcSuccess(lockManager.lock(lockInput));
122     }
123
124     @Test
125     public void testAskTimeOutException() throws InterruptedException, ExecutionException, TimeoutException {
126         String lockName = "testLock";
127         logCaptureRule.expectError("Unable to acquire lock for " + lockName + ", try 1", 1);
128         dbFailureSimulator.failButSubmitsAnyways();
129         LockInput lockInput = new LockInputBuilder().setLockName(lockName).build();
130         assertRpcErrorCause(lockManager.lock(lockInput), TransactionCommitFailedException.class,
131                 "caused by simulated AskTimeoutException");
132     }
133
134     @Test
135     public void testEternalTransactionCommitFailedExceptionOnLock()
136             throws InterruptedException, ExecutionException, TimeoutException {
137         logCaptureRule.expectError("RPC lock() failed; input = LockInput{lockName=testLock, augmentation=[]}");
138         dbFailureSimulator.failSubmits(new TransactionCommitFailedException("bada boum bam!"));
139         LockInput lockInput = new LockInputBuilder().setLockName("testLock").build();
140         assertRpcErrorCause(lockManager.lock(lockInput), TransactionCommitFailedException.class, "bada boum bam!");
141     }
142
143     // TODO testEternalReadFailedExceptionOnLock() throws InterruptedException, ExecutionException, TimeoutException {
144
145     // TODO test3sOptimisticLockFailedExceptionOnUnLock()
146     // TODO testEternalReadFailedExceptionOnUnLock()
147     // TODO testEternalTransactionCommitFailedExceptionOnUnLock()
148
149     // TODO test3sOptimisticLockFailedExceptionOnTryLock()
150     // TODO testEternalReadFailedExceptionOnTryLock()
151     // TODO testEternalTransactionCommitFailedExceptionOnTryLock()
152
153     private void runUnlockTimerTask(String lockKey, long delay) {
154         Timer timer = new Timer();
155         timer.schedule(new TimerTask() {
156             @Override
157             public void run() {
158                 UnlockInput unlockInput = new UnlockInputBuilder().setLockName(lockKey).build();
159                 try {
160                     assertRpcSuccess(lockManager.unlock(unlockInput));
161                 } catch (InterruptedException | ExecutionException | TimeoutException e) {
162                     LOG.error("runUnlockTimerTask() failed", e);
163                     // throw new RuntimeException(e) is useless here, as this in a BG Thread, and it would go nowhere
164                 }
165             }
166         }, delay);
167     }
168
169     private void runUnfailSubmitsTimerTask(long delay) {
170         Timer timer = new Timer();
171         timer.schedule(new TimerTask() {
172             @Override
173             public void run() {
174                 dbFailureSimulator.unfailSubmits();
175             }
176         }, delay);
177     }
178
179 }