8cc990ce7c98168261779a9fc803ec3d890f0555
[controller.git] / opendaylight / md-sal / cds-access-client / src / test / java / org / opendaylight / controller / cluster / access / client / SequencedQueueEntryTest.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.assertNull;
13 import static org.junit.Assert.assertSame;
14 import static org.junit.Assert.assertTrue;
15 import static org.mockito.Matchers.any;
16 import static org.mockito.Mockito.doReturn;
17 import static org.mockito.Mockito.verify;
18
19 import akka.actor.ActorRef;
20 import akka.actor.ActorSystem;
21 import akka.testkit.TestProbe;
22 import java.util.concurrent.ThreadLocalRandom;
23 import java.util.concurrent.TimeUnit;
24 import org.junit.After;
25 import org.junit.AfterClass;
26 import org.junit.Before;
27 import org.junit.BeforeClass;
28 import org.junit.Test;
29 import org.mockito.ArgumentCaptor;
30 import org.mockito.Mock;
31 import org.mockito.MockitoAnnotations;
32 import org.opendaylight.controller.cluster.access.ABIVersion;
33 import org.opendaylight.controller.cluster.access.concepts.AbstractRequestFailureProxy;
34 import org.opendaylight.controller.cluster.access.concepts.AbstractRequestProxy;
35 import org.opendaylight.controller.cluster.access.concepts.Request;
36 import org.opendaylight.controller.cluster.access.concepts.RequestEnvelope;
37 import org.opendaylight.controller.cluster.access.concepts.RequestException;
38 import org.opendaylight.controller.cluster.access.concepts.RequestFailure;
39 import org.opendaylight.controller.cluster.access.concepts.Response;
40 import org.opendaylight.controller.cluster.common.actor.TestTicker;
41 import org.opendaylight.yangtools.concepts.WritableIdentifier;
42 import scala.concurrent.duration.Duration;
43
44 /**
45  * Test suite covering logic contained in {@link SequencedQueueEntry}.
46  *
47  * @author Robert Varga
48  */
49 public class SequencedQueueEntryTest {
50     private static class MockFailure extends RequestFailure<WritableIdentifier, MockFailure> {
51         private static final long serialVersionUID = 1L;
52
53         MockFailure(final WritableIdentifier target, final RequestException cause) {
54             super(target, 0, cause);
55         }
56
57         @Override
58         protected AbstractRequestFailureProxy<WritableIdentifier, MockFailure> externalizableProxy(
59                 final ABIVersion version) {
60             return null;
61         }
62
63         @Override
64         protected MockFailure cloneAsVersion(final ABIVersion version) {
65             return this;
66         }
67     }
68
69     private static class MockRequest extends Request<WritableIdentifier, MockRequest> {
70         private static final long serialVersionUID = 1L;
71
72         MockRequest(final WritableIdentifier target, final ActorRef replyTo) {
73             super(target, 0, replyTo);
74         }
75
76         @Override
77         public RequestFailure<WritableIdentifier, ?> toRequestFailure(final RequestException cause) {
78             return new MockFailure(getTarget(), cause);
79         }
80
81         @Override
82         protected AbstractRequestProxy<WritableIdentifier, MockRequest> externalizableProxy(final ABIVersion version) {
83             return null;
84         }
85
86         @Override
87         protected MockRequest cloneAsVersion(final ABIVersion version) {
88             return this;
89         }
90     }
91
92     @Mock
93     private ActorRef mockReplyTo;
94     @Mock
95     private WritableIdentifier mockIdentifier;
96     @Mock
97     private RequestException mockCause;
98     @Mock
99     private RequestCallback mockCallback;
100     @Mock
101     private ClientActorBehavior mockBehavior;
102
103     private TestTicker ticker;
104     private BackendInfo mockBackendInfo;
105     private Request<WritableIdentifier, ?> mockRequest;
106     private Response<WritableIdentifier, ?> mockResponse;
107
108     private static ActorSystem actorSystem;
109     private TestProbe mockActor;
110
111     private SequencedQueueEntry entry;
112
113     @BeforeClass
114     public static void setupClass() {
115         actorSystem = ActorSystem.apply();
116     }
117
118     @AfterClass
119     public static void teardownClass() {
120         actorSystem.terminate();
121     }
122
123     @Before
124     public void setup() {
125         MockitoAnnotations.initMocks(this);
126
127         doReturn(mockBehavior).when(mockCallback).complete(any(MockFailure.class));
128
129         ticker = new TestTicker();
130         ticker.increment(ThreadLocalRandom.current().nextLong());
131
132         mockActor = TestProbe.apply(actorSystem);
133         mockBackendInfo = new BackendInfo(mockActor.ref(), 0, ABIVersion.current(), 5);
134         mockRequest = new MockRequest(mockIdentifier, mockReplyTo);
135         mockResponse = mockRequest.toRequestFailure(mockCause);
136
137         entry = new SequencedQueueEntry(mockRequest, mockCallback, ticker.read());
138     }
139
140     @After
141     public void teardown() {
142         actorSystem.stop(mockActor.ref());
143     }
144
145     @Test
146     public void testGetTxDetails() {
147         assertNull(entry.getTxDetails());
148         entry.retransmit(mockBackendInfo, 0, ticker.read());
149         assertEquals(0, entry.getTxDetails().getTxSequence());
150         entry.retransmit(mockBackendInfo, 1, ticker.read());
151         assertEquals(1, entry.getTxDetails().getTxSequence());
152         entry.retransmit(mockBackendInfo, 3, ticker.read());
153         assertEquals(3, entry.getTxDetails().getTxSequence());
154     }
155
156     @Test
157     public void testComplete() {
158         entry.complete(mockResponse);
159         verify(mockCallback).complete(mockResponse);
160     }
161
162     @Test
163     public void testPoison() {
164         entry.poison(mockCause);
165
166         final ArgumentCaptor<MockFailure> captor = ArgumentCaptor.forClass(MockFailure.class);
167         verify(mockCallback).complete(captor.capture());
168         assertSame(mockCause, captor.getValue().getCause());
169     }
170
171     @Test
172     public void testIsTimedOut() {
173         assertTrue(entry.isTimedOut(ticker.read(), 0));
174         assertFalse(entry.isTimedOut(ticker.read(), 1));
175
176         entry.retransmit(mockBackendInfo, 0, ticker.read());
177         assertTrue(entry.isTimedOut(ticker.read(), 0));
178         ticker.increment(10);
179         assertTrue(entry.isTimedOut(ticker.read(), 10));
180         assertFalse(entry.isTimedOut(ticker.read(), 20));
181
182         entry.retransmit(mockBackendInfo, 1, ticker.read());
183         assertTrue(entry.isTimedOut(ticker.read(), 0));
184         ticker.increment(10);
185         assertTrue(entry.isTimedOut(ticker.read(), 10));
186         assertFalse(entry.isTimedOut(ticker.read(), 11));
187     }
188
189     @Test
190     public void testRetransmit() {
191         assertFalse(mockActor.msgAvailable());
192         entry.retransmit(mockBackendInfo, 0, ticker.read());
193
194         assertTrue(mockActor.msgAvailable());
195         assertRequestEquals(mockRequest, mockActor.receiveOne(Duration.apply(5, TimeUnit.SECONDS)));
196     }
197
198     private static void assertRequestEquals(final Request<?, ?> expected, final Object obj) {
199         assertTrue(obj instanceof RequestEnvelope);
200
201         final RequestEnvelope actual = (RequestEnvelope) obj;
202         assertEquals(0, actual.getSessionId());
203         assertEquals(0, actual.getTxSequence());
204         assertEquals(expected.getTarget(), actual.getMessage().getTarget());
205     }
206 }