1 package org.opendaylight.controller.md.sal.dom.store.impl;
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertFalse;
5 import static org.junit.Assert.assertNotNull;
6 import static org.junit.Assert.assertSame;
7 import static org.junit.Assert.assertTrue;
8 import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.ID_QNAME;
9 import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.INNER_LIST_QNAME;
10 import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.NAME_QNAME;
11 import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.OUTER_LIST_PATH;
12 import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.OUTER_LIST_QNAME;
13 import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.TEST_PATH;
14 import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.TEST_QNAME;
15 import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.VALUE_QNAME;
16 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
17 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
18 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
20 import org.junit.Before;
21 import org.junit.Test;
22 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
23 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
24 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
25 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
27 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
28 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
29 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
30 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
31 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
33 import com.google.common.base.Optional;
34 import com.google.common.primitives.UnsignedLong;
38 * Schema structure of document is
63 public class ModificationMetadataTreeTest {
65 private static final Short ONE_ID = 1;
66 private static final Short TWO_ID = 2;
67 private static final String TWO_ONE_NAME = "one";
68 private static final String TWO_TWO_NAME = "two";
70 private static final InstanceIdentifier OUTER_LIST_1_PATH = InstanceIdentifier.builder(OUTER_LIST_PATH)
71 .nodeWithKey(OUTER_LIST_QNAME, ID_QNAME, ONE_ID) //
74 private static final InstanceIdentifier OUTER_LIST_2_PATH = InstanceIdentifier.builder(OUTER_LIST_PATH)
75 .nodeWithKey(OUTER_LIST_QNAME, ID_QNAME, TWO_ID) //
78 private static final InstanceIdentifier TWO_TWO_PATH = InstanceIdentifier.builder(OUTER_LIST_2_PATH)
79 .node(INNER_LIST_QNAME) //
80 .nodeWithKey(INNER_LIST_QNAME, NAME_QNAME, TWO_TWO_NAME) //
83 private static final InstanceIdentifier TWO_TWO_VALUE_PATH = InstanceIdentifier.builder(TWO_TWO_PATH)
87 private static final MapEntryNode BAR_NODE = mapEntryBuilder(OUTER_LIST_QNAME, ID_QNAME, TWO_ID) //
88 .withChild(mapNodeBuilder(INNER_LIST_QNAME) //
89 .withChild(mapEntry(INNER_LIST_QNAME, NAME_QNAME, TWO_ONE_NAME)) //
90 .withChild(mapEntry(INNER_LIST_QNAME, NAME_QNAME, TWO_TWO_NAME)) //
94 private SchemaContext schemaContext;
97 public void prepare() {
98 schemaContext = TestModel.createTestContext();
99 assertNotNull("Schema context must not be null.", schemaContext);
103 * Returns a test document
120 public NormalizedNode<?, ?> createDocumentOne() {
121 return ImmutableContainerNodeBuilder
123 .withNodeIdentifier(new NodeIdentifier(schemaContext.getQName()))
124 .withChild(createTestContainer()).build();
128 private ContainerNode createTestContainer() {
129 return ImmutableContainerNodeBuilder
131 .withNodeIdentifier(new NodeIdentifier(TEST_QNAME))
133 mapNodeBuilder(OUTER_LIST_QNAME)
134 .withChild(mapEntry(OUTER_LIST_QNAME, ID_QNAME, ONE_ID))
135 .withChild(BAR_NODE).build()).build();
139 public void basicReadWrites() {
140 MutableDataTree modificationTree = MutableDataTree.from(new DataTree.Snapshot(schemaContext,
141 StoreMetadataNode.createRecursively(createDocumentOne(), UnsignedLong.valueOf(5))),
142 new SchemaAwareApplyOperationRoot(schemaContext));
143 Optional<NormalizedNode<?, ?>> originalBarNode = modificationTree.read(OUTER_LIST_2_PATH);
144 assertTrue(originalBarNode.isPresent());
145 assertSame(BAR_NODE, originalBarNode.get());
147 // writes node to /outer-list/1/inner_list/two/value
148 modificationTree.write(TWO_TWO_VALUE_PATH, ImmutableNodes.leafNode(VALUE_QNAME, "test"));
150 // reads node to /outer-list/1/inner_list/two/value
151 // and checks if node is already present
152 Optional<NormalizedNode<?, ?>> barTwoCModified = modificationTree.read(TWO_TWO_VALUE_PATH);
153 assertTrue(barTwoCModified.isPresent());
154 assertEquals(ImmutableNodes.leafNode(VALUE_QNAME, "test"), barTwoCModified.get());
156 // delete node to /outer-list/1/inner_list/two/value
157 modificationTree.delete(TWO_TWO_VALUE_PATH);
158 Optional<NormalizedNode<?, ?>> barTwoCAfterDelete = modificationTree.read(TWO_TWO_VALUE_PATH);
159 assertFalse(barTwoCAfterDelete.isPresent());
163 public MutableDataTree createEmptyModificationTree() {
165 * Creates empty Snapshot with associated schema context.
167 DataTree t = DataTree.create(schemaContext);
171 * Creates Mutable Data Tree based on provided snapshot and schema
175 MutableDataTree modificationTree = MutableDataTree.from(t.takeSnapshot(), new SchemaAwareApplyOperationRoot(
177 return modificationTree;
181 public void createFromEmptyState() {
183 MutableDataTree modificationTree = createEmptyModificationTree();
185 * Writes empty container node to /test
188 modificationTree.write(TEST_PATH, ImmutableNodes.containerNode(TEST_QNAME));
191 * Writes empty list node to /test/outer-list
193 modificationTree.write(OUTER_LIST_PATH, ImmutableNodes.mapNodeBuilder(OUTER_LIST_QNAME).build());
196 * Reads list node from /test/outer-list
198 Optional<NormalizedNode<?, ?>> potentialOuterList = modificationTree.read(OUTER_LIST_PATH);
199 assertTrue(potentialOuterList.isPresent());
202 * Reads container node from /test and verifies that it contains test
205 Optional<NormalizedNode<?, ?>> potentialTest = modificationTree.read(TEST_PATH);
206 ContainerNode containerTest = assertPresentAndType(potentialTest, ContainerNode.class);
210 * Gets list from returned snapshot of /test and verifies it contains
214 assertPresentAndType(containerTest.getChild(new NodeIdentifier(OUTER_LIST_QNAME)), MapNode.class);
219 public void writeSubtreeReadChildren() {
220 MutableDataTree modificationTree = createEmptyModificationTree();
221 modificationTree.write(TEST_PATH, createTestContainer());
222 Optional<NormalizedNode<?, ?>> potential = modificationTree.read(TWO_TWO_PATH);
223 MapEntryNode node = assertPresentAndType(potential, MapEntryNode.class);
227 public void writeSubtreeDeleteChildren() {
228 MutableDataTree modificationTree = createEmptyModificationTree();
229 modificationTree.write(TEST_PATH, createTestContainer());
231 // We verify data are present
232 Optional<NormalizedNode<?, ?>> potentialBeforeDelete = modificationTree.read(TWO_TWO_PATH);
233 MapEntryNode node = assertPresentAndType(potentialBeforeDelete, MapEntryNode.class);
235 modificationTree.delete(TWO_TWO_PATH);
236 Optional<NormalizedNode<?, ?>> potentialAfterDelete = modificationTree.read(TWO_TWO_PATH);
237 assertFalse(potentialAfterDelete.isPresent());
241 private static <T> T assertPresentAndType(final Optional<?> potential, final Class<T> type) {
242 assertNotNull(potential);
243 assertTrue(potential.isPresent());
244 assertTrue(type.isInstance(potential.get()));
245 return type.cast(potential.get());