/* * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.controller.cluster.datastore; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.mockito.Matchers.any; import static org.mockito.Matchers.same; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import akka.actor.ActorRef; import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.cluster.access.commands.ModifyTransactionRequestBuilder; import org.opendaylight.controller.cluster.access.commands.ReadTransactionRequest; import org.opendaylight.controller.cluster.access.commands.TransactionModification; import org.opendaylight.controller.cluster.access.commands.TransactionRequest; import org.opendaylight.controller.cluster.access.commands.TransactionSuccess; import org.opendaylight.controller.cluster.access.concepts.ClientIdentifier; import org.opendaylight.controller.cluster.access.concepts.FrontendIdentifier; import org.opendaylight.controller.cluster.access.concepts.FrontendType; import org.opendaylight.controller.cluster.access.concepts.LocalHistoryIdentifier; import org.opendaylight.controller.cluster.access.concepts.MemberName; import org.opendaylight.controller.cluster.access.concepts.RequestEnvelope; import org.opendaylight.controller.cluster.access.concepts.RequestException; import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification; public class FrontendReadWriteTransactionTest { private static final ClientIdentifier CLIENT_ID = ClientIdentifier.create(FrontendIdentifier.create( MemberName.forName("mock"), FrontendType.forName("mock")), 0); private static final LocalHistoryIdentifier HISTORY_ID = new LocalHistoryIdentifier(CLIENT_ID, 0); private static final TransactionIdentifier TX_ID = new TransactionIdentifier(HISTORY_ID, 0); private AbstractFrontendHistory mockHistory; private ReadWriteShardDataTreeTransaction shardTransaction; private DataTreeModification mockModification; private ShardDataTreeTransactionParent mockParent; private FrontendReadWriteTransaction openTx; private ShardDataTreeCohort mockCohort; @Before public void setup() { mockHistory = mock(AbstractFrontendHistory.class); mockParent = mock(ShardDataTreeTransactionParent.class); mockModification = mock(DataTreeModification.class); mockCohort = mock(ShardDataTreeCohort.class); shardTransaction = new ReadWriteShardDataTreeTransaction(mockParent, TX_ID, mockModification); openTx = FrontendReadWriteTransaction.createOpen(mockHistory, shardTransaction); when(mockParent.finishTransaction(same(shardTransaction))).thenReturn(mockCohort); } private TransactionSuccess handleRequest(final TransactionRequest request) throws RequestException { return openTx.doHandleRequest(request, new RequestEnvelope(request, 0, 0), 0); } @Test public void testDuplicateModifyAbort() throws RequestException { final ModifyTransactionRequestBuilder b = new ModifyTransactionRequestBuilder(TX_ID, mock(ActorRef.class)); b.setSequence(0); b.setAbort(); final TransactionRequest abortReq = b.build(); assertNull(handleRequest(abortReq)); verify(mockParent).abortTransaction(same(shardTransaction), any(Runnable.class)); assertNull(handleRequest(abortReq)); verifyNoMoreInteractions(mockParent); } @Test public void testDuplicateReady() throws RequestException { final ModifyTransactionRequestBuilder b = new ModifyTransactionRequestBuilder(TX_ID, mock(ActorRef.class)); b.setSequence(0); b.setReady(); final TransactionRequest readyReq = b.build(); assertNotNull(handleRequest(readyReq)); verify(mockParent).finishTransaction(same(shardTransaction)); assertNotNull(handleRequest(readyReq)); verifyNoMoreInteractions(mockParent); } @Test public void testDuplicateDirect() throws RequestException { final ModifyTransactionRequestBuilder b = new ModifyTransactionRequestBuilder(TX_ID, mock(ActorRef.class)); b.setSequence(0); b.setCommit(false); final TransactionRequest readyReq = b.build(); assertNull(handleRequest(readyReq)); verify(mockParent).finishTransaction(same(shardTransaction)); assertNull(handleRequest(readyReq)); verifyNoMoreInteractions(mockParent); } @Test public void testDuplicateCoordinated() throws RequestException { final ModifyTransactionRequestBuilder b = new ModifyTransactionRequestBuilder(TX_ID, mock(ActorRef.class)); b.setSequence(0); b.setCommit(true); final TransactionRequest readyReq = b.build(); assertNull(handleRequest(readyReq)); verify(mockParent).finishTransaction(same(shardTransaction)); assertNull(handleRequest(readyReq)); verifyNoMoreInteractions(mockParent); } @Test(expected = IllegalStateException.class) public void testReadAfterReady() throws RequestException { final ModifyTransactionRequestBuilder b = new ModifyTransactionRequestBuilder(TX_ID, mock(ActorRef.class)); b.setSequence(0); b.setReady(); final TransactionRequest readyReq = b.build(); assertNotNull(handleRequest(readyReq)); verify(mockParent).finishTransaction(same(shardTransaction)); handleRequest(new ReadTransactionRequest(TX_ID, 0, mock(ActorRef.class), YangInstanceIdentifier.EMPTY, true)); } @Test(expected = IllegalStateException.class) public void testModifyAfterReady() throws RequestException { final ModifyTransactionRequestBuilder b = new ModifyTransactionRequestBuilder(TX_ID, mock(ActorRef.class)); b.setSequence(0); b.setReady(); final TransactionRequest readyReq = b.build(); assertNotNull(handleRequest(readyReq)); verify(mockParent).finishTransaction(same(shardTransaction)); b.setSequence(1); b.addModification(mock(TransactionModification.class)); handleRequest(b.build()); } @Test(expected = IllegalStateException.class) public void testReadAfterAbort() throws RequestException { final ModifyTransactionRequestBuilder b = new ModifyTransactionRequestBuilder(TX_ID, mock(ActorRef.class)); b.setSequence(0); b.setAbort(); final TransactionRequest abortReq = b.build(); assertNull(handleRequest(abortReq)); verify(mockParent).abortTransaction(same(shardTransaction), any(Runnable.class)); handleRequest(new ReadTransactionRequest(TX_ID, 0, mock(ActorRef.class), YangInstanceIdentifier.EMPTY, true)); } }