2 * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
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
8 package org.opendaylight.controller.cluster.datastore;
10 import static org.junit.Assert.assertNotNull;
11 import static org.junit.Assert.assertNull;
12 import static org.mockito.Matchers.any;
13 import static org.mockito.Matchers.eq;
14 import static org.mockito.Matchers.same;
15 import static org.mockito.Mockito.mock;
16 import static org.mockito.Mockito.verify;
17 import static org.mockito.Mockito.verifyNoMoreInteractions;
18 import static org.mockito.Mockito.when;
20 import akka.actor.ActorRef;
21 import java.util.Optional;
22 import org.junit.Before;
23 import org.junit.Test;
24 import org.opendaylight.controller.cluster.access.commands.ModifyTransactionRequestBuilder;
25 import org.opendaylight.controller.cluster.access.commands.ReadTransactionRequest;
26 import org.opendaylight.controller.cluster.access.commands.TransactionModification;
27 import org.opendaylight.controller.cluster.access.commands.TransactionRequest;
28 import org.opendaylight.controller.cluster.access.commands.TransactionSuccess;
29 import org.opendaylight.controller.cluster.access.concepts.ClientIdentifier;
30 import org.opendaylight.controller.cluster.access.concepts.FrontendIdentifier;
31 import org.opendaylight.controller.cluster.access.concepts.FrontendType;
32 import org.opendaylight.controller.cluster.access.concepts.LocalHistoryIdentifier;
33 import org.opendaylight.controller.cluster.access.concepts.MemberName;
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.TransactionIdentifier;
37 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
38 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
40 public class FrontendReadWriteTransactionTest {
42 private static final ClientIdentifier CLIENT_ID = ClientIdentifier.create(FrontendIdentifier.create(
43 MemberName.forName("mock"), FrontendType.forName("mock")), 0);
44 private static final LocalHistoryIdentifier HISTORY_ID = new LocalHistoryIdentifier(CLIENT_ID, 0);
45 private static final TransactionIdentifier TX_ID = new TransactionIdentifier(HISTORY_ID, 0);
47 private AbstractFrontendHistory mockHistory;
48 private ReadWriteShardDataTreeTransaction shardTransaction;
49 private DataTreeModification mockModification;
50 private ShardDataTreeTransactionParent mockParent;
51 private FrontendReadWriteTransaction openTx;
52 private ShardDataTreeCohort mockCohort;
56 mockHistory = mock(AbstractFrontendHistory.class);
57 mockParent = mock(ShardDataTreeTransactionParent.class);
58 mockModification = mock(DataTreeModification.class);
59 mockCohort = mock(ShardDataTreeCohort.class);
61 shardTransaction = new ReadWriteShardDataTreeTransaction(mockParent, TX_ID, mockModification);
62 openTx = FrontendReadWriteTransaction.createOpen(mockHistory, shardTransaction);
64 when(mockParent.finishTransaction(same(shardTransaction), eq(Optional.empty()))).thenReturn(mockCohort);
67 private TransactionSuccess<?> handleRequest(final TransactionRequest<?> request) throws RequestException {
68 return openTx.doHandleRequest(request, new RequestEnvelope(request, 0, 0), 0);
72 public void testDuplicateModifyAbort() throws RequestException {
73 final ModifyTransactionRequestBuilder b = new ModifyTransactionRequestBuilder(TX_ID, mock(ActorRef.class));
76 final TransactionRequest<?> abortReq = b.build();
77 assertNull(handleRequest(abortReq));
78 verify(mockParent).abortTransaction(same(shardTransaction), any(Runnable.class));
80 assertNull(handleRequest(abortReq));
81 verifyNoMoreInteractions(mockParent);
85 public void testDuplicateReady() throws RequestException {
86 final ModifyTransactionRequestBuilder b = new ModifyTransactionRequestBuilder(TX_ID, mock(ActorRef.class));
89 final TransactionRequest<?> readyReq = b.build();
91 assertNotNull(handleRequest(readyReq));
92 verify(mockParent).finishTransaction(same(shardTransaction), eq(Optional.empty()));
94 assertNotNull(handleRequest(readyReq));
95 verifyNoMoreInteractions(mockParent);
99 public void testDuplicateDirect() throws RequestException {
100 final ModifyTransactionRequestBuilder b = new ModifyTransactionRequestBuilder(TX_ID, mock(ActorRef.class));
103 final TransactionRequest<?> readyReq = b.build();
105 assertNull(handleRequest(readyReq));
106 verify(mockParent).finishTransaction(same(shardTransaction), eq(Optional.empty()));
108 assertNull(handleRequest(readyReq));
109 verifyNoMoreInteractions(mockParent);
113 public void testDuplicateCoordinated() throws RequestException {
114 final ModifyTransactionRequestBuilder b = new ModifyTransactionRequestBuilder(TX_ID, mock(ActorRef.class));
117 final TransactionRequest<?> readyReq = b.build();
119 assertNull(handleRequest(readyReq));
120 verify(mockParent).finishTransaction(same(shardTransaction), eq(Optional.empty()));
122 assertNull(handleRequest(readyReq));
123 verifyNoMoreInteractions(mockParent);
126 @Test(expected = IllegalStateException.class)
127 public void testReadAfterReady() throws RequestException {
128 final ModifyTransactionRequestBuilder b = new ModifyTransactionRequestBuilder(TX_ID, mock(ActorRef.class));
131 final TransactionRequest<?> readyReq = b.build();
133 assertNotNull(handleRequest(readyReq));
134 verify(mockParent).finishTransaction(same(shardTransaction), eq(Optional.empty()));
136 handleRequest(new ReadTransactionRequest(TX_ID, 0, mock(ActorRef.class), YangInstanceIdentifier.EMPTY, true));
139 @Test(expected = IllegalStateException.class)
140 public void testModifyAfterReady() throws RequestException {
141 final ModifyTransactionRequestBuilder b = new ModifyTransactionRequestBuilder(TX_ID, mock(ActorRef.class));
144 final TransactionRequest<?> readyReq = b.build();
146 assertNotNull(handleRequest(readyReq));
147 verify(mockParent).finishTransaction(same(shardTransaction), eq(Optional.empty()));
150 b.addModification(mock(TransactionModification.class));
151 handleRequest(b.build());
154 @Test(expected = IllegalStateException.class)
155 public void testReadAfterAbort() throws RequestException {
156 final ModifyTransactionRequestBuilder b = new ModifyTransactionRequestBuilder(TX_ID, mock(ActorRef.class));
159 final TransactionRequest<?> abortReq = b.build();
160 assertNull(handleRequest(abortReq));
161 verify(mockParent).abortTransaction(same(shardTransaction), any(Runnable.class));
163 handleRequest(new ReadTransactionRequest(TX_ID, 0, mock(ActorRef.class), YangInstanceIdentifier.EMPTY, true));