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