Bug 7521: Convert byte[] to ShardManagerSnapshot in DatastoreSnapshot
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / test / java / org / opendaylight / controller / cluster / datastore / DataTreeCohortIntegrationTest.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
9 package org.opendaylight.controller.cluster.datastore;
10
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertSame;
14 import static org.junit.Assert.fail;
15 import static org.mockito.Matchers.any;
16 import static org.mockito.Mockito.mock;
17
18 import akka.actor.ActorSystem;
19 import akka.actor.Address;
20 import akka.actor.AddressFromURIString;
21 import akka.cluster.Cluster;
22 import akka.testkit.JavaTestKit;
23 import com.google.common.base.Throwables;
24 import com.google.common.util.concurrent.CheckedFuture;
25 import com.google.common.util.concurrent.Futures;
26 import com.typesafe.config.ConfigFactory;
27 import java.io.IOException;
28 import org.junit.AfterClass;
29 import org.junit.BeforeClass;
30 import org.junit.Ignore;
31 import org.junit.Test;
32 import org.mockito.ArgumentCaptor;
33 import org.mockito.Mockito;
34 import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
35 import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
36 import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
37 import org.opendaylight.mdsal.common.api.DataValidationFailedException;
38 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
39 import org.opendaylight.mdsal.common.api.PostCanCommitStep;
40 import org.opendaylight.mdsal.common.api.ThreePhaseCommitStep;
41 import org.opendaylight.mdsal.dom.api.DOMDataTreeCandidate;
42 import org.opendaylight.mdsal.dom.api.DOMDataTreeCommitCohort;
43 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
44 import org.opendaylight.yangtools.concepts.ObjectRegistration;
45 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
46 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
47 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
48
49 public class DataTreeCohortIntegrationTest {
50
51     private static final DataValidationFailedException FAILED_CAN_COMMIT =
52             new DataValidationFailedException(YangInstanceIdentifier.class, TestModel.TEST_PATH, "Test failure.");
53     private static final CheckedFuture<PostCanCommitStep, DataValidationFailedException> FAILED_CAN_COMMIT_FUTURE =
54             Futures.immediateFailedCheckedFuture(FAILED_CAN_COMMIT);
55
56     private static final DOMDataTreeIdentifier TEST_ID =
57             new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, TestModel.TEST_PATH);
58
59     private static ActorSystem system;
60
61     private final DatastoreContext.Builder datastoreContextBuilder =
62             DatastoreContext.newBuilder().shardHeartbeatIntervalInMillis(100);
63
64     @BeforeClass
65     public static void setUpClass() throws IOException {
66         system = ActorSystem.create("cluster-test", ConfigFactory.load().getConfig("Member1"));
67         final Address member1Address = AddressFromURIString.parse("akka://cluster-test@127.0.0.1:2558");
68         Cluster.get(system).join(member1Address);
69     }
70
71     @AfterClass
72     public static void tearDownClass() throws IOException {
73         JavaTestKit.shutdownActorSystem(system);
74         system = null;
75     }
76
77     protected ActorSystem getSystem() {
78         return system;
79     }
80
81     @Test
82     public void registerNoopCohortTest() throws Exception {
83         final DOMDataTreeCommitCohort cohort = mock(DOMDataTreeCommitCohort.class);
84         Mockito.doReturn(PostCanCommitStep.NOOP_SUCCESS_FUTURE).when(cohort).canCommit(any(Object.class),
85                 any(DOMDataTreeCandidate.class), any(SchemaContext.class));
86         ArgumentCaptor<DOMDataTreeCandidate> candidateCapt = ArgumentCaptor.forClass(DOMDataTreeCandidate.class);
87         new IntegrationTestKit(getSystem(), datastoreContextBuilder) {
88             {
89                 try (AbstractDataStore dataStore = setupDistributedDataStore("transactionIntegrationTest",
90                         "test-1")) {
91                     final ObjectRegistration<DOMDataTreeCommitCohort> cohortReg =
92                             dataStore.registerCommitCohort(TEST_ID, cohort);
93                     Thread.sleep(1000); // Registration is asynchronous
94                     assertNotNull(cohortReg);
95                     testWriteTransaction(dataStore, TestModel.TEST_PATH,
96                         ImmutableNodes.containerNode(TestModel.TEST_QNAME));
97                     Mockito.verify(cohort).canCommit(any(Object.class), candidateCapt.capture(),
98                             any(SchemaContext.class));
99                     DOMDataTreeCandidate candidate = candidateCapt.getValue();
100                     assertNotNull(candidate);
101                     assertEquals(TEST_ID, candidate.getRootPath());
102                     testWriteTransaction(dataStore, TestModel.OUTER_LIST_PATH,
103                         ImmutableNodes.mapNodeBuilder(TestModel.OUTER_LIST_QNAME).build());
104                     Mockito.verify(cohort, Mockito.times(2)).canCommit(any(Object.class),
105                             any(DOMDataTreeCandidate.class), any(SchemaContext.class));
106                     cohortReg.close();
107                     testWriteTransaction(dataStore, TestModel.TEST_PATH,
108                         ImmutableNodes.containerNode(TestModel.TEST_QNAME));
109                     Mockito.verifyNoMoreInteractions(cohort);
110                 }
111             }
112         };
113     }
114
115     @Test
116     @SuppressWarnings("checkstyle:IllegalCatch")
117     public void failCanCommitTest() throws Exception {
118         final DOMDataTreeCommitCohort failedCohort = mock(DOMDataTreeCommitCohort.class);
119
120         Mockito.doReturn(FAILED_CAN_COMMIT_FUTURE).when(failedCohort).canCommit(any(Object.class),
121                 any(DOMDataTreeCandidate.class), any(SchemaContext.class));
122
123         new IntegrationTestKit(getSystem(), datastoreContextBuilder) {
124             {
125                 try (AbstractDataStore dataStore =
126                         setupDistributedDataStore("transactionIntegrationTest", "test-1")) {
127                     dataStore.registerCommitCohort(TEST_ID, failedCohort);
128                     Thread.sleep(1000); // Registration is asynchronous
129
130                     DOMStoreWriteTransaction writeTx = dataStore.newWriteOnlyTransaction();
131                     writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
132                     DOMStoreThreePhaseCommitCohort dsCohort = writeTx.ready();
133                     try {
134                         // FIXME: Weird thing is that invoking canCommit on front-end invokes also
135                         // preCommit on backend.
136                         dsCohort.canCommit().get();
137                         fail("Exception should be raised.");
138                     } catch (Exception e) {
139                         assertSame(FAILED_CAN_COMMIT, Throwables.getRootCause(e));
140                     }
141                 }
142             }
143         };
144     }
145
146     /**
147      * FIXME: Weird thing is that invoking canCommit on front-end invokes also preCommit on backend
148      * so we can not test abort after can commit.
149      */
150     @Test
151     @Ignore
152     public void canCommitSuccessExternallyAborted() throws Exception {
153         final DOMDataTreeCommitCohort cohortToAbort = mock(DOMDataTreeCommitCohort.class);
154         final PostCanCommitStep stepToAbort = mock(PostCanCommitStep.class);
155         Mockito.doReturn(Futures.immediateCheckedFuture(stepToAbort)).when(cohortToAbort).canCommit(any(Object.class),
156                 any(DOMDataTreeCandidate.class), any(SchemaContext.class));
157         Mockito.doReturn(ThreePhaseCommitStep.NOOP_ABORT_FUTURE).when(stepToAbort).abort();
158         new IntegrationTestKit(getSystem(), datastoreContextBuilder) {
159             {
160                 try (AbstractDataStore dataStore =
161                         setupDistributedDataStore("transactionIntegrationTest", "test-1")) {
162                     dataStore.registerCommitCohort(TEST_ID, cohortToAbort);
163                     Thread.sleep(1000); // Registration is asynchronous
164
165                     DOMStoreWriteTransaction writeTx = dataStore.newWriteOnlyTransaction();
166                     writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
167                     DOMStoreThreePhaseCommitCohort dsCohort = writeTx.ready();
168
169                     dsCohort.canCommit().get();
170                     dsCohort.abort().get();
171                     Mockito.verify(stepToAbort, Mockito.times(1)).abort();
172                 }
173             }
174         };
175     }
176 }