Fix CS warnings in cds-access-client and enable enforcement
[controller.git] / opendaylight / md-sal / cds-access-client / src / test / java / org / opendaylight / controller / cluster / access / client / SequencedQueueTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, 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.controller.cluster.access.client;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.assertSame;
15 import static org.junit.Assert.assertTrue;
16 import static org.mockito.Matchers.any;
17 import static org.mockito.Mockito.doReturn;
18 import static org.mockito.Mockito.verify;
19 import static org.mockito.Mockito.verifyNoMoreInteractions;
20
21 import akka.actor.ActorRef;
22 import akka.actor.ActorSystem;
23 import akka.testkit.TestProbe;
24 import java.util.Optional;
25 import java.util.concurrent.CompletableFuture;
26 import java.util.concurrent.ThreadLocalRandom;
27 import java.util.concurrent.TimeUnit;
28 import org.junit.After;
29 import org.junit.AfterClass;
30 import org.junit.Before;
31 import org.junit.BeforeClass;
32 import org.junit.Test;
33 import org.mockito.ArgumentCaptor;
34 import org.mockito.Mock;
35 import org.mockito.MockitoAnnotations;
36 import org.opendaylight.controller.cluster.access.ABIVersion;
37 import org.opendaylight.controller.cluster.access.concepts.AbstractRequestFailureProxy;
38 import org.opendaylight.controller.cluster.access.concepts.AbstractRequestProxy;
39 import org.opendaylight.controller.cluster.access.concepts.FailureEnvelope;
40 import org.opendaylight.controller.cluster.access.concepts.Request;
41 import org.opendaylight.controller.cluster.access.concepts.RequestEnvelope;
42 import org.opendaylight.controller.cluster.access.concepts.RequestException;
43 import org.opendaylight.controller.cluster.access.concepts.RequestFailure;
44 import org.opendaylight.controller.cluster.common.actor.TestTicker;
45 import org.opendaylight.yangtools.concepts.WritableIdentifier;
46 import scala.concurrent.duration.FiniteDuration;
47
48 /**
49  * Test suite covering logic contained in {@link SequencedQueue}. It assumes {@link SequencedQueueEntryTest} passes.
50  *
51  * @author Robert Varga
52  */
53 public class SequencedQueueTest {
54     private static class MockFailure extends RequestFailure<WritableIdentifier, MockFailure> {
55         private static final long serialVersionUID = 1L;
56
57         MockFailure(final WritableIdentifier target, final RequestException cause) {
58             super(target, 0, cause);
59         }
60
61         @Override
62         protected AbstractRequestFailureProxy<WritableIdentifier, MockFailure> externalizableProxy(
63                 final ABIVersion version) {
64             return null;
65         }
66
67         @Override
68         protected MockFailure cloneAsVersion(final ABIVersion version) {
69             return this;
70         }
71     }
72
73     private static class MockRequest extends Request<WritableIdentifier, MockRequest> {
74         private static final long serialVersionUID = 1L;
75
76         MockRequest(final WritableIdentifier target, final ActorRef replyTo) {
77             super(target, 0, replyTo);
78         }
79
80         @Override
81         public RequestFailure<WritableIdentifier, ?> toRequestFailure(final RequestException cause) {
82             return new MockFailure(getTarget(), cause);
83         }
84
85         @Override
86         protected AbstractRequestProxy<WritableIdentifier, MockRequest> externalizableProxy(final ABIVersion version) {
87             return null;
88         }
89
90         @Override
91         protected MockRequest cloneAsVersion(final ABIVersion version) {
92             return this;
93         }
94     }
95
96     @Mock
97     private ActorRef mockReplyTo;
98     @Mock
99     private WritableIdentifier mockIdentifier;
100     @Mock
101     private RequestException mockCause;
102     @Mock
103     private RequestCallback mockCallback;
104     @Mock
105     private ClientActorBehavior mockBehavior;
106
107     private TestTicker ticker;
108     private BackendInfo mockBackendInfo;
109     private MockRequest mockRequest;
110     private MockRequest mockRequest2;
111     private RequestFailure<WritableIdentifier, ?> mockResponse;
112     private FailureEnvelope mockResponseEnvelope;
113     private Long mockCookie;
114
115     private static ActorSystem actorSystem;
116     private TestProbe mockActor;
117
118     private SequencedQueue queue;
119
120     @BeforeClass
121     public static void setupClass() {
122         actorSystem = ActorSystem.apply();
123     }
124
125     @AfterClass
126     public static void teardownClass() {
127         actorSystem.terminate();
128     }
129
130     @Before
131     public void setup() {
132         MockitoAnnotations.initMocks(this);
133
134         doReturn(mockBehavior).when(mockCallback).complete(any(MockFailure.class));
135
136         ticker = new TestTicker();
137         ticker.increment(ThreadLocalRandom.current().nextLong());
138
139         mockActor = TestProbe.apply(actorSystem);
140         mockBackendInfo = new BackendInfo(mockActor.ref(), 0, ABIVersion.current(), 5);
141         mockRequest = new MockRequest(mockIdentifier, mockReplyTo);
142         mockRequest2 = new MockRequest(mockIdentifier, mockReplyTo);
143         mockResponse = mockRequest.toRequestFailure(mockCause);
144         mockResponseEnvelope = new FailureEnvelope(mockResponse, 0, 0);
145         mockCookie = ThreadLocalRandom.current().nextLong();
146
147         queue = new SequencedQueue(mockCookie, ticker);
148     }
149
150     @After
151     public void teardown() {
152         actorSystem.stop(mockActor.ref());
153     }
154
155     @Test
156     public void testGetCookie() {
157         assertSame(mockCookie, queue.getCookie());
158     }
159
160     @Test
161     public void testEmptyClose() {
162         assertFalse(queue.hasCompleted());
163         queue.close();
164         assertTrue(queue.hasCompleted());
165     }
166
167     @Test(expected = IllegalStateException.class)
168     public void testClosedEnqueueRequest() {
169         queue.close();
170
171         // Kaboom
172         queue.enqueueRequest(mockRequest, mockCallback);
173     }
174
175     @Test
176     public void testCloseIdempotent() {
177         queue.close();
178         queue.close();
179     }
180
181     @Test
182     public void testPoison() {
183         queue.enqueueRequest(mockRequest, mockCallback);
184         queue.poison(mockCause);
185
186         final ArgumentCaptor<MockFailure> captor = ArgumentCaptor.forClass(MockFailure.class);
187         verify(mockCallback).complete(captor.capture());
188         assertSame(mockCause, captor.getValue().getCause());
189     }
190
191     @Test(expected = IllegalStateException.class)
192     public void testPoisonPerformsClose() {
193         // Implies close()
194         queue.poison(mockCause);
195
196         // Kaboom
197         queue.enqueueRequest(mockRequest, mockCallback);
198     }
199
200     @Test
201     public void testPoisonIdempotent() {
202         queue.poison(mockCause);
203         queue.poison(mockCause);
204     }
205
206     @Test
207     public void testEnqueueRequestNeedsBackend() {
208         final Optional<FiniteDuration> ret = queue.enqueueRequest(mockRequest, mockCallback);
209
210         assertNotNull(ret);
211         assertFalse(ret.isPresent());
212     }
213
214     @Test
215     public void testExpectProof() {
216         final CompletableFuture<BackendInfo> proof = new CompletableFuture<>();
217         assertTrue(queue.expectProof(proof));
218         assertFalse(queue.expectProof(proof));
219     }
220
221     @Test(expected = NullPointerException.class)
222     public void testSetBackendNull() {
223         final CompletableFuture<BackendInfo> proof = new CompletableFuture<>();
224         assertTrue(queue.expectProof(proof));
225         queue.setBackendInfo(proof, null);
226     }
227
228     @Test
229     public void testSetBackendWithNoResolution() {
230         queue.enqueueRequest(mockRequest, mockCallback);
231
232         final CompletableFuture<BackendInfo> proof = new CompletableFuture<>();
233         final Optional<FiniteDuration> ret = queue.setBackendInfo(proof, mockBackendInfo);
234         assertNotNull(ret);
235         assertFalse(ret.isPresent());
236     }
237
238     @Test
239     public void testSetBackendWithWrongProof() {
240         queue.enqueueRequest(mockRequest, mockCallback);
241
242         final CompletableFuture<BackendInfo> proof = new CompletableFuture<>();
243         assertTrue(queue.expectProof(proof));
244
245         final Optional<FiniteDuration> ret = queue.setBackendInfo(new CompletableFuture<>(), mockBackendInfo);
246         assertNotNull(ret);
247         assertFalse(ret.isPresent());
248     }
249
250     @Test
251     public void testSetBackendWithNoRequests() {
252         // this utility method covers the entire test
253         setupBackend();
254     }
255
256     @Test
257     public void testSetBackendWithRequestsNoTimer() {
258         queue.enqueueRequest(mockRequest, mockCallback);
259
260         final CompletableFuture<BackendInfo> proof = new CompletableFuture<>();
261         assertTrue(queue.expectProof(proof));
262         assertFalse(mockActor.msgAvailable());
263
264         final Optional<FiniteDuration> ret = queue.setBackendInfo(proof, mockBackendInfo);
265         assertNotNull(ret);
266         assertTrue(ret.isPresent());
267
268         assertTransmit(mockRequest, 0);
269     }
270
271     @Test
272     public void testEnqueueRequestNeedsTimer() {
273         setupBackend();
274
275         final Optional<FiniteDuration> ret = queue.enqueueRequest(mockRequest, mockCallback);
276         assertNotNull(ret);
277         assertTrue(ret.isPresent());
278         assertTransmit(mockRequest, 0);
279     }
280
281     @Test
282     public void testEnqueueRequestWithoutTimer() {
283         setupBackend();
284
285         // First request
286         Optional<FiniteDuration> ret = queue.enqueueRequest(mockRequest, mockCallback);
287         assertNotNull(ret);
288         assertTrue(ret.isPresent());
289         assertTransmit(mockRequest, 0);
290
291         // Second request, no timer fired
292         ret = queue.enqueueRequest(mockRequest2, mockCallback);
293         assertNull(ret);
294         assertTransmit(mockRequest2, 1);
295     }
296
297     @Test
298     public void testRunTimeoutEmpty() throws NoProgressException {
299         final boolean ret = queue.runTimeout();
300         assertFalse(ret);
301     }
302
303     @Test
304     public void testRunTimeoutWithoutShift() throws NoProgressException {
305         queue.enqueueRequest(mockRequest, mockCallback);
306         final boolean ret = queue.runTimeout();
307         assertFalse(ret);
308     }
309
310     @Test
311     public void testRunTimeoutWithTimeoutLess() throws NoProgressException {
312         queue.enqueueRequest(mockRequest, mockCallback);
313
314         ticker.increment(SequencedQueue.REQUEST_TIMEOUT_NANOS - 1);
315
316         final boolean ret = queue.runTimeout();
317         assertFalse(ret);
318     }
319
320     @Test
321     public void testRunTimeoutWithTimeoutExact() throws NoProgressException {
322         setupBackend();
323
324         queue.enqueueRequest(mockRequest, mockCallback);
325
326         ticker.increment(SequencedQueue.REQUEST_TIMEOUT_NANOS);
327
328         final boolean ret = queue.runTimeout();
329         assertTrue(ret);
330     }
331
332     @Test
333     public void testRunTimeoutWithTimeoutMore() throws NoProgressException {
334         setupBackend();
335
336         queue.enqueueRequest(mockRequest, mockCallback);
337
338         ticker.increment(SequencedQueue.REQUEST_TIMEOUT_NANOS + 1);
339
340         final boolean ret = queue.runTimeout();
341         assertTrue(ret);
342     }
343
344     @Test(expected = NoProgressException.class)
345     public void testRunTimeoutWithoutProgressExact() throws NoProgressException {
346         queue.enqueueRequest(mockRequest, mockCallback);
347
348         ticker.increment(SequencedQueue.NO_PROGRESS_TIMEOUT_NANOS);
349
350         // Kaboom
351         queue.runTimeout();
352     }
353
354     @Test(expected = NoProgressException.class)
355     public void testRunTimeoutWithoutProgressMore() throws NoProgressException {
356         queue.enqueueRequest(mockRequest, mockCallback);
357
358         ticker.increment(SequencedQueue.NO_PROGRESS_TIMEOUT_NANOS + 1);
359
360         // Kaboom
361         queue.runTimeout();
362     }
363
364     @Test
365     public void testRunTimeoutEmptyWithoutProgressExact() throws NoProgressException {
366         ticker.increment(SequencedQueue.NO_PROGRESS_TIMEOUT_NANOS);
367
368         // No problem
369         final boolean ret = queue.runTimeout();
370         assertFalse(ret);
371     }
372
373     @Test
374     public void testRunTimeoutEmptyWithoutProgressMore() throws NoProgressException {
375         ticker.increment(SequencedQueue.NO_PROGRESS_TIMEOUT_NANOS + 1);
376
377         // No problem
378         final boolean ret = queue.runTimeout();
379         assertFalse(ret);
380     }
381
382     @Test
383     public void testCompleteEmpty() {
384         final ClientActorBehavior ret = queue.complete(mockBehavior, mockResponseEnvelope);
385         assertSame(mockBehavior, ret);
386         verifyNoMoreInteractions(mockCallback);
387     }
388
389     @Test
390     public void testCompleteSingle() {
391         setupBackend();
392
393         queue.enqueueRequest(mockRequest, mockCallback);
394
395         ClientActorBehavior ret = queue.complete(mockBehavior, mockResponseEnvelope);
396         verify(mockCallback).complete(mockResponse);
397         assertSame(mockBehavior, ret);
398
399         ret = queue.complete(mockBehavior, mockResponseEnvelope);
400         assertSame(mockBehavior, ret);
401         verifyNoMoreInteractions(mockCallback);
402     }
403
404     @Test
405     public void testCompleteNull() {
406         setupBackend();
407
408         queue.enqueueRequest(mockRequest, mockCallback);
409
410         doReturn(null).when(mockCallback).complete(mockResponse);
411
412         ClientActorBehavior ret = queue.complete(mockBehavior, mockResponseEnvelope);
413         verify(mockCallback).complete(mockResponse);
414         assertNull(ret);
415     }
416
417     @Test
418     public void testProgressRecord() throws NoProgressException {
419         setupBackend();
420
421         queue.enqueueRequest(mockRequest, mockCallback);
422
423         ticker.increment(10);
424         queue.enqueueRequest(mockRequest2, mockCallback);
425         queue.complete(mockBehavior, mockResponseEnvelope);
426
427         ticker.increment(SequencedQueue.NO_PROGRESS_TIMEOUT_NANOS - 11);
428         assertTrue(queue.runTimeout());
429     }
430
431     private void setupBackend() {
432         final CompletableFuture<BackendInfo> proof = new CompletableFuture<>();
433         assertTrue(queue.expectProof(proof));
434         final Optional<FiniteDuration> ret = queue.setBackendInfo(proof, mockBackendInfo);
435         assertNotNull(ret);
436         assertFalse(ret.isPresent());
437         assertFalse(mockActor.msgAvailable());
438     }
439
440     private void assertTransmit(final Request<?, ?> expected, final long sequence) {
441         assertTrue(mockActor.msgAvailable());
442         assertRequestEquals(expected, sequence, mockActor.receiveOne(FiniteDuration.apply(5, TimeUnit.SECONDS)));
443     }
444
445     private static void assertRequestEquals(final Request<?, ?> expected, final long sequence, final Object obj) {
446         assertTrue(obj instanceof RequestEnvelope);
447
448         final RequestEnvelope actual = (RequestEnvelope) obj;
449         assertEquals(0, actual.getSessionId());
450         assertEquals(sequence, actual.getTxSequence());
451         assertSame(expected, actual.getMessage());
452     }
453 }