2 * Copyright (c) 2015 Cisco Systems, Inc. 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
9 package org.opendaylight.controller.cluster.datastore;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.mockito.Mockito.doReturn;
14 import static org.opendaylight.controller.cluster.datastore.ShardDataTreeMocking.immediateCanCommit;
15 import static org.opendaylight.controller.cluster.datastore.ShardDataTreeMocking.immediateCommit;
16 import static org.opendaylight.controller.cluster.datastore.ShardDataTreeMocking.immediatePreCommit;
17 import com.google.common.base.Optional;
18 import com.google.common.base.Ticker;
19 import java.math.BigInteger;
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.concurrent.ExecutionException;
23 import org.junit.Before;
24 import org.junit.Test;
25 import org.mockito.Mockito;
26 import org.opendaylight.controller.cluster.datastore.jmx.mbeans.shard.ShardStats;
27 import org.opendaylight.controller.md.cluster.datastore.model.CarsModel;
28 import org.opendaylight.controller.md.cluster.datastore.model.PeopleModel;
29 import org.opendaylight.controller.md.cluster.datastore.model.SchemaContextHelper;
30 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateTip;
32 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidates;
33 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
34 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
35 import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
36 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
38 public class ShardDataTreeTest extends AbstractTest {
40 private final Shard mockShard = Mockito.mock(Shard.class);
43 private SchemaContext fullSchema;
47 doReturn(true).when(mockShard).canSkipPayload();
48 doReturn(Ticker.systemTicker()).when(mockShard).ticker();
49 doReturn(Mockito.mock(ShardStats.class)).when(mockShard).getShardMBean();
51 fullSchema = SchemaContextHelper.full();
55 public void testWrite() throws ExecutionException, InterruptedException {
56 modify(new ShardDataTree(mockShard, fullSchema, TreeType.OPERATIONAL), false, true, true);
60 public void testMerge() throws ExecutionException, InterruptedException {
61 modify(new ShardDataTree(mockShard, fullSchema, TreeType.OPERATIONAL), true, true, true);
65 private void modify(final ShardDataTree shardDataTree, final boolean merge, final boolean expectedCarsPresent, final boolean expectedPeoplePresent) throws ExecutionException, InterruptedException {
67 assertEquals(fullSchema, shardDataTree.getSchemaContext());
69 final ReadWriteShardDataTreeTransaction transaction = shardDataTree.newReadWriteTransaction(nextTransactionId());
71 final DataTreeModification snapshot = transaction.getSnapshot();
73 assertNotNull(snapshot);
76 snapshot.merge(CarsModel.BASE_PATH, CarsModel.create());
77 snapshot.merge(PeopleModel.BASE_PATH, PeopleModel.create());
79 snapshot.write(CarsModel.BASE_PATH, CarsModel.create());
80 snapshot.write(PeopleModel.BASE_PATH, PeopleModel.create());
83 final ShardDataTreeCohort cohort = shardDataTree.finishTransaction(transaction);
85 immediateCanCommit(cohort);
86 immediatePreCommit(cohort);
87 immediateCommit(cohort);
89 final ReadOnlyShardDataTreeTransaction readOnlyShardDataTreeTransaction = shardDataTree.newReadOnlyTransaction(nextTransactionId());
91 final DataTreeSnapshot snapshot1 = readOnlyShardDataTreeTransaction.getSnapshot();
93 final Optional<NormalizedNode<?, ?>> optional = snapshot1.readNode(CarsModel.BASE_PATH);
95 assertEquals(expectedCarsPresent, optional.isPresent());
97 final Optional<NormalizedNode<?, ?>> optional1 = snapshot1.readNode(PeopleModel.BASE_PATH);
99 assertEquals(expectedPeoplePresent, optional1.isPresent());
104 public void bug4359AddRemoveCarOnce() throws ExecutionException, InterruptedException {
105 final ShardDataTree shardDataTree = new ShardDataTree(mockShard, fullSchema, TreeType.OPERATIONAL);
107 final List<DataTreeCandidateTip> candidates = new ArrayList<>();
108 candidates.add(addCar(shardDataTree));
109 candidates.add(removeCar(shardDataTree));
111 final NormalizedNode<?, ?> expected = getCars(shardDataTree);
113 applyCandidates(shardDataTree, candidates);
115 final NormalizedNode<?, ?> actual = getCars(shardDataTree);
117 assertEquals(expected, actual);
121 public void bug4359AddRemoveCarTwice() throws ExecutionException, InterruptedException {
122 final ShardDataTree shardDataTree = new ShardDataTree(mockShard, fullSchema, TreeType.OPERATIONAL);
124 final List<DataTreeCandidateTip> candidates = new ArrayList<>();
125 candidates.add(addCar(shardDataTree));
126 candidates.add(removeCar(shardDataTree));
127 candidates.add(addCar(shardDataTree));
128 candidates.add(removeCar(shardDataTree));
130 final NormalizedNode<?, ?> expected = getCars(shardDataTree);
132 applyCandidates(shardDataTree, candidates);
134 final NormalizedNode<?, ?> actual = getCars(shardDataTree);
136 assertEquals(expected, actual);
139 private static NormalizedNode<?, ?> getCars(final ShardDataTree shardDataTree) {
140 final ReadOnlyShardDataTreeTransaction readOnlyShardDataTreeTransaction = shardDataTree.newReadOnlyTransaction(nextTransactionId());
141 final DataTreeSnapshot snapshot1 = readOnlyShardDataTreeTransaction.getSnapshot();
143 final Optional<NormalizedNode<?, ?>> optional = snapshot1.readNode(CarsModel.BASE_PATH);
145 assertEquals(true, optional.isPresent());
147 return optional.get();
150 private static DataTreeCandidateTip addCar(final ShardDataTree shardDataTree) throws ExecutionException, InterruptedException {
151 return doTransaction(shardDataTree, snapshot -> {
152 snapshot.merge(CarsModel.BASE_PATH, CarsModel.emptyContainer());
153 snapshot.merge(CarsModel.CAR_LIST_PATH, CarsModel.newCarMapNode());
154 snapshot.write(CarsModel.newCarPath("altima"), CarsModel.newCarEntry("altima", new BigInteger("100")));
158 private static DataTreeCandidateTip removeCar(final ShardDataTree shardDataTree) throws ExecutionException, InterruptedException {
159 return doTransaction(shardDataTree, snapshot -> snapshot.delete(CarsModel.newCarPath("altima")));
163 private static interface DataTreeOperation {
164 void execute(DataTreeModification snapshot);
167 private static DataTreeCandidateTip doTransaction(final ShardDataTree shardDataTree, final DataTreeOperation operation)
168 throws ExecutionException, InterruptedException {
169 final ReadWriteShardDataTreeTransaction transaction = shardDataTree.newReadWriteTransaction(nextTransactionId());
170 final DataTreeModification snapshot = transaction.getSnapshot();
171 operation.execute(snapshot);
172 final ShardDataTreeCohort cohort = shardDataTree.finishTransaction(transaction);
174 immediateCanCommit(cohort);
175 immediatePreCommit(cohort);
176 final DataTreeCandidateTip candidate = cohort.getCandidate();
177 immediateCommit(cohort);
182 private static DataTreeCandidateTip applyCandidates(final ShardDataTree shardDataTree, final List<DataTreeCandidateTip> candidates)
183 throws ExecutionException, InterruptedException {
184 final ReadWriteShardDataTreeTransaction transaction = shardDataTree.newReadWriteTransaction(nextTransactionId());
185 final DataTreeModification snapshot = transaction.getSnapshot();
186 for(final DataTreeCandidateTip candidateTip : candidates){
187 DataTreeCandidates.applyToModification(snapshot, candidateTip);
189 final ShardDataTreeCohort cohort = shardDataTree.finishTransaction(transaction);
191 immediateCanCommit(cohort);
192 immediatePreCommit(cohort);
193 final DataTreeCandidateTip candidate = cohort.getCandidate();
194 immediateCommit(cohort);