X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-distributed-datastore%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fcluster%2Fdatastore%2FDistributedDataStoreRemotingIntegrationTest.java;h=bb2093bcc34f94420a5715b41a8c08784d54d4aa;hp=a8faac46cc408202050c7dc2f3ba6792788ef0ae;hb=e84f63ee098fff5b02cbce1281ca0d1208f966fa;hpb=c7078128d6f35eebee2f98108ff929dcccfc322d diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreRemotingIntegrationTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreRemotingIntegrationTest.java index a8faac46cc..bb2093bcc3 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreRemotingIntegrationTest.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreRemotingIntegrationTest.java @@ -8,10 +8,12 @@ package org.opendaylight.controller.cluster.datastore; import static org.awaitility.Awaitility.await; +import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; @@ -100,6 +102,7 @@ import org.opendaylight.controller.md.cluster.datastore.model.PeopleModel; import org.opendaylight.controller.md.cluster.datastore.model.SchemaContextHelper; import org.opendaylight.controller.md.cluster.datastore.model.TestModel; import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.common.api.OptimisticLockFailedException; import org.opendaylight.mdsal.common.api.TransactionCommitFailedException; import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction; import org.opendaylight.mdsal.dom.api.DOMTransactionChain; @@ -117,12 +120,13 @@ import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.api.schema.SystemMapNode; import org.opendaylight.yangtools.yang.data.api.schema.builder.CollectionNodeBuilder; -import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree; -import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration; -import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification; import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory; +import org.opendaylight.yangtools.yang.data.tree.api.ConflictingModificationAppliedException; +import org.opendaylight.yangtools.yang.data.tree.api.DataTree; +import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration; +import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModification; +import org.opendaylight.yangtools.yang.data.tree.impl.di.InMemoryDataTreeFactory; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import scala.collection.Set; import scala.concurrent.Await; @@ -140,7 +144,7 @@ public class DistributedDataStoreRemotingIntegrationTest extends AbstractTest { @Parameters(name = "{0}") public static Collection data() { return Arrays.asList(new Object[][] { - { TestDistributedDataStore.class, 7}, { TestClientBackedDataStore.class, 12 } + { TestDistributedDataStore.class, 7 }, { TestClientBackedDataStore.class, 12 } }); } @@ -757,7 +761,6 @@ public class DistributedDataStoreRemotingIntegrationTest extends AbstractTest { } } - @SuppressWarnings("unchecked") @Test public void testReadyLocalTransactionForwardedToLeader() throws Exception { initDatastoresWithCars("testReadyLocalTransactionForwardedToLeader"); @@ -822,7 +825,6 @@ public class DistributedDataStoreRemotingIntegrationTest extends AbstractTest { verifyCars(leaderDistributedDataStore.newReadOnlyTransaction(), car1, car2); } - @SuppressWarnings("unchecked") @Test public void testForwardedReadyTransactionForwardedToLeader() throws Exception { initDatastoresWithCars("testForwardedReadyTransactionForwardedToLeader"); @@ -1004,9 +1006,6 @@ public class DistributedDataStoreRemotingIntegrationTest extends AbstractTest { @Test public void testLeadershipTransferOnShutdown() throws Exception { - // FIXME: remove when test passes also for ClientBackedDataStore - assumeTrue(DistributedDataStore.class.isAssignableFrom(testParameter)); - leaderDatastoreContextBuilder.shardBatchedModificationCount(1); followerDatastoreContextBuilder.shardElectionTimeoutFactor(10).customRaftPolicyImplementation(null); final String testName = "testLeadershipTransferOnShutdown"; @@ -1029,16 +1028,21 @@ public class DistributedDataStoreRemotingIntegrationTest extends AbstractTest { writeTx.write(PeopleModel.BASE_PATH, PeopleModel.emptyContainer()); final DOMStoreThreePhaseCommitCohort cohort1 = writeTx.ready(); - IntegrationTestKit.verifyShardStats(leaderDistributedDataStore, "cars", - stats -> assertEquals("getTxCohortCacheSize", 1, stats.getTxCohortCacheSize())); + final var usesCohorts = DistributedDataStore.class.isAssignableFrom(testParameter); + if (usesCohorts) { + IntegrationTestKit.verifyShardStats(leaderDistributedDataStore, "cars", + stats -> assertEquals("getTxCohortCacheSize", 1, stats.getTxCohortCacheSize())); + } writeTx = followerDistributedDataStore.newWriteOnlyTransaction(); final MapEntryNode car = CarsModel.newCarEntry("optima", Uint64.valueOf(20000)); writeTx.write(CarsModel.newCarPath("optima"), car); final DOMStoreThreePhaseCommitCohort cohort2 = writeTx.ready(); - IntegrationTestKit.verifyShardStats(leaderDistributedDataStore, "cars", - stats -> assertEquals("getTxCohortCacheSize", 2, stats.getTxCohortCacheSize())); + if (usesCohorts) { + IntegrationTestKit.verifyShardStats(leaderDistributedDataStore, "cars", + stats -> assertEquals("getTxCohortCacheSize", 2, stats.getTxCohortCacheSize())); + } // Gracefully stop the leader via a Shutdown message. @@ -1070,9 +1074,6 @@ public class DistributedDataStoreRemotingIntegrationTest extends AbstractTest { @Test public void testTransactionWithIsolatedLeader() throws Exception { - // FIXME: CONTROLLER-2018: remove when test passes also for ClientBackedDataStore - assumeTrue(DistributedDataStore.class.isAssignableFrom(testParameter)); - // Set the isolated leader check interval high so we can control the switch to IsolatedLeader. leaderDatastoreContextBuilder.shardIsolatedLeaderCheckIntervalInMillis(10000000); final String testName = "testTransactionWithIsolatedLeader"; @@ -1105,9 +1106,24 @@ public class DistributedDataStoreRemotingIntegrationTest extends AbstractTest { MemberNode.verifyRaftState(leaderDistributedDataStore, "cars", raftState -> assertEquals("getRaftState", "IsolatedLeader", raftState.getRaftState())); - final var ex = assertThrows(ExecutionException.class, - () -> leaderTestKit.doCommit(noShardLeaderWriteTx.ready())); - assertEquals(NoShardLeaderException.class, Throwables.getRootCause(ex).getClass()); + final var noShardLeaderCohort = noShardLeaderWriteTx.ready(); + final ListenableFuture canCommit; + + // There is difference in behavior here: + if (!leaderDistributedDataStore.getActorUtils().getDatastoreContext().isUseTellBasedProtocol()) { + // ask-based canCommit() times out and aborts + final var ex = assertThrows(ExecutionException.class, + () -> leaderTestKit.doCommit(noShardLeaderCohort)).getCause(); + assertThat(ex, instanceOf(NoShardLeaderException.class)); + assertThat(ex.getMessage(), containsString( + "Shard member-1-shard-cars-testTransactionWithIsolatedLeader currently has no leader.")); + canCommit = null; + } else { + // tell-based canCommit() does not have a real timeout and hence continues + canCommit = noShardLeaderCohort.canCommit(); + Uninterruptibles.sleepUninterruptibly(commitTimeout, TimeUnit.SECONDS); + assertFalse(canCommit.isDone()); + } sendDatastoreContextUpdate(leaderDistributedDataStore, leaderDatastoreContextBuilder .shardElectionTimeoutFactor(100)); @@ -1119,6 +1135,19 @@ public class DistributedDataStoreRemotingIntegrationTest extends AbstractTest { leaderTestKit.doCommit(preIsolatedLeaderTxCohort); leaderTestKit.doCommit(successTxCohort); + + // continuation of tell-based protocol: readied transaction will complete commit, but will report an OLFE + if (canCommit != null) { + final var ex = assertThrows(ExecutionException.class, + () -> canCommit.get(commitTimeout, TimeUnit.SECONDS)).getCause(); + assertThat(ex, instanceOf(OptimisticLockFailedException.class)); + assertEquals("Optimistic lock failed for path " + CarsModel.BASE_PATH, ex.getMessage()); + final var cause = ex.getCause(); + assertThat(cause, instanceOf(ConflictingModificationAppliedException.class)); + final var cmae = (ConflictingModificationAppliedException) cause; + assertEquals("Node was created by other transaction.", cmae.getMessage()); + assertEquals(CarsModel.BASE_PATH, cmae.getPath()); + } } @Test