BUG-865: deprecate DataTreeFactor.create()
[yangtools.git] / yang / yang-data-impl / src / test / java / org / opendaylight / yangtools / yang / data / impl / schema / tree / ConcurrentTreeModificationTest.java
1 package org.opendaylight.yangtools.yang.data.impl.schema.tree;
2
3 import static org.junit.Assert.assertFalse;
4 import static org.junit.Assert.assertNotNull;
5 import static org.junit.Assert.assertTrue;
6 import static org.junit.Assert.fail;
7 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
8 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
9 import com.google.common.base.Optional;
10 import org.junit.Before;
11 import org.junit.Test;
12 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
13 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
14 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
15 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
16 import org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificationAppliedException;
17 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
18 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
19 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
20 import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
21 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
22 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
23 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27 public class ConcurrentTreeModificationTest {
28     private static final Logger LOG = LoggerFactory.getLogger(ConcurrentTreeModificationTest.class);
29
30     private static final Short ONE_ID = 1;
31     private static final Short TWO_ID = 2;
32
33     private static final YangInstanceIdentifier OUTER_LIST_1_PATH = YangInstanceIdentifier.builder(TestModel.OUTER_LIST_PATH)
34             .nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, ONE_ID) //
35             .build();
36
37     private static final YangInstanceIdentifier OUTER_LIST_2_PATH = YangInstanceIdentifier.builder(TestModel.OUTER_LIST_PATH)
38             .nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, TWO_ID) //
39             .build();
40
41     private static final MapEntryNode FOO_NODE = mapEntryBuilder(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, ONE_ID) //
42             .withChild(mapNodeBuilder(TestModel.INNER_LIST_QNAME) //
43                     .build()) //
44             .build();
45
46     private static final MapEntryNode BAR_NODE = mapEntryBuilder(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, TWO_ID) //
47             .withChild(mapNodeBuilder(TestModel.INNER_LIST_QNAME) //
48                     .build()) //
49             .build();
50
51     private SchemaContext schemaContext;
52     private InMemoryDataTree inMemoryDataTree;
53
54     @Before
55     public void prepare() {
56         schemaContext = TestModel.createTestContext();
57         assertNotNull("Schema context must not be null.", schemaContext);
58         inMemoryDataTree = (InMemoryDataTree) InMemoryDataTreeFactory.getInstance().create(TreeType.OPERATIONAL);
59         inMemoryDataTree.setSchemaContext(schemaContext);
60     }
61
62     private static ContainerNode createFooTestContainerNode() {
63         return ImmutableContainerNodeBuilder
64                 .create()
65                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TestModel.TEST_QNAME))
66                 .withChild(
67                         mapNodeBuilder(TestModel.OUTER_LIST_QNAME)
68                                 .withChild(FOO_NODE).build()).build();
69     }
70
71     private static ContainerNode createBarTestContainerNode() {
72         return ImmutableContainerNodeBuilder
73                 .create()
74                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TestModel.TEST_QNAME))
75                 .withChild(
76                         mapNodeBuilder(TestModel.OUTER_LIST_QNAME)
77                                 .withChild(BAR_NODE).build()).build();
78     }
79
80     private static <T> T assertPresentAndType(final Optional<?> potential, final Class<T> type) {
81         assertNotNull(potential);
82         assertTrue(potential.isPresent());
83         assertTrue(type.isInstance(potential.get()));
84         return type.cast(potential.get());
85     }
86
87     @Test
88     public void writeWrite1stLevelEmptyTreeTest() throws DataValidationFailedException {
89         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
90
91         final DataTreeModification modificationTree1 = initialDataTreeSnapshot.newModification();
92         final DataTreeModification modificationTree2 = initialDataTreeSnapshot.newModification();
93
94         modificationTree1.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
95         modificationTree2.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
96
97         modificationTree1.ready();
98         modificationTree2.ready();
99         inMemoryDataTree.validate(modificationTree1);
100         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
101         inMemoryDataTree.commit(prepare1);
102
103         try {
104             inMemoryDataTree.validate(modificationTree2);
105             fail("Exception should have been thrown.");
106         } catch (final ConflictingModificationAppliedException ex) {
107             LOG.debug("ConflictingModificationAppliedException - '{}' was thrown as expected.");
108         }
109         final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
110         inMemoryDataTree.commit(prepare2);
111
112         final Optional<NormalizedNode<?, ?>> testNodeAfterCommits = modificationTree1.readNode(TestModel.TEST_PATH);
113         assertPresentAndType(testNodeAfterCommits, ContainerNode.class);
114     }
115
116     @Test
117     public void writeMerge1stLevelEmptyTreeTest() throws DataValidationFailedException {
118         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
119
120         final DataTreeModification modificationTree1 = initialDataTreeSnapshot.newModification();
121         final DataTreeModification modificationTree2 = initialDataTreeSnapshot.newModification();
122
123         modificationTree1.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
124         modificationTree2.merge(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
125
126         modificationTree1.ready();
127         modificationTree2.ready();
128
129         inMemoryDataTree.validate(modificationTree1);
130         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
131         inMemoryDataTree.commit(prepare1);
132
133         inMemoryDataTree.validate(modificationTree2);
134         final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
135         inMemoryDataTree.commit(prepare2);
136
137         final Optional<NormalizedNode<?, ?>> testNodeAfterCommits = modificationTree1.readNode(TestModel.TEST_PATH);
138         assertPresentAndType(testNodeAfterCommits, ContainerNode.class);
139     }
140
141     @Test
142     public void writeWriteFooBar1stLevelEmptyTreeTest() throws DataValidationFailedException {
143         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
144
145         final DataTreeModification modificationTree1 = initialDataTreeSnapshot.newModification();
146         final DataTreeModification modificationTree2 = initialDataTreeSnapshot.newModification();
147
148         modificationTree1.write(TestModel.TEST_PATH, createFooTestContainerNode());
149         modificationTree2.write(TestModel.TEST_PATH, createBarTestContainerNode());
150         modificationTree1.ready();
151         modificationTree2.ready();
152
153         inMemoryDataTree.validate(modificationTree1);
154         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
155         inMemoryDataTree.commit(prepare1);
156
157         try {
158             inMemoryDataTree.validate(modificationTree2);
159             fail("Exception should have been thrown.");
160             final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
161             inMemoryDataTree.commit(prepare2);
162         } catch (final ConflictingModificationAppliedException ex) {
163             LOG.debug("ConflictingModificationAppliedException - '{}' was thrown as expected.");
164         }
165
166         final InMemoryDataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
167         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_1_PATH), MapEntryNode.class);
168         assertFalse(snapshotAfterCommits.readNode(OUTER_LIST_2_PATH).isPresent());
169     }
170
171     @Test
172     public void writeMergeFooBar1stLevelEmptyTreeTest() throws DataValidationFailedException {
173         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
174
175         final DataTreeModification modificationTree1 = initialDataTreeSnapshot.newModification();
176         final DataTreeModification modificationTree2 = initialDataTreeSnapshot.newModification();
177
178         modificationTree1.write(TestModel.TEST_PATH, createFooTestContainerNode());
179         modificationTree2.merge(TestModel.TEST_PATH, createBarTestContainerNode());
180         modificationTree1.ready();
181         modificationTree2.ready();
182
183         inMemoryDataTree.validate(modificationTree1);
184         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
185         inMemoryDataTree.commit(prepare1);
186
187         inMemoryDataTree.validate(modificationTree2);
188         final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
189         inMemoryDataTree.commit(prepare2);
190
191         final InMemoryDataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
192         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_1_PATH), MapEntryNode.class);
193         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_2_PATH), MapEntryNode.class);
194     }
195
196     @Test
197     public void mergeWriteFooBar1stLevelEmptyTreeTest() throws DataValidationFailedException {
198         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
199
200         final DataTreeModification modificationTree1 = initialDataTreeSnapshot.newModification();
201         final DataTreeModification modificationTree2 = initialDataTreeSnapshot.newModification();
202
203         modificationTree1.merge(TestModel.TEST_PATH, createFooTestContainerNode());
204         modificationTree2.write(TestModel.TEST_PATH, createBarTestContainerNode());
205         modificationTree1.ready();
206         modificationTree2.ready();
207
208         inMemoryDataTree.validate(modificationTree1);
209         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
210         inMemoryDataTree.commit(prepare1);
211
212         try {
213             inMemoryDataTree.validate(modificationTree2);
214             fail("Exception should have been thrown.");
215             final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
216             inMemoryDataTree.commit(prepare2);
217         } catch (final ConflictingModificationAppliedException ex) {
218             LOG.debug("ConflictingModificationAppliedException - '{}' was thrown as expected.");
219         }
220
221         final InMemoryDataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
222         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_1_PATH), MapEntryNode.class);
223         assertFalse(snapshotAfterCommits.readNode(OUTER_LIST_2_PATH).isPresent());
224     }
225
226     @Test
227     public void mergeMergeFooBar1stLevelEmptyTreeTest() throws DataValidationFailedException {
228         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
229
230         final DataTreeModification modificationTree1 = initialDataTreeSnapshot.newModification();
231         final DataTreeModification modificationTree2 = initialDataTreeSnapshot.newModification();
232
233         modificationTree1.merge(TestModel.TEST_PATH, createFooTestContainerNode());
234         modificationTree2.merge(TestModel.TEST_PATH, createBarTestContainerNode());
235         modificationTree1.ready();
236         modificationTree2.ready();
237
238         inMemoryDataTree.validate(modificationTree1);
239         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
240         inMemoryDataTree.commit(prepare1);
241
242         inMemoryDataTree.validate(modificationTree2);
243         final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
244         inMemoryDataTree.commit(prepare2);
245
246         final InMemoryDataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
247         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_1_PATH), MapEntryNode.class);
248         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_2_PATH), MapEntryNode.class);
249     }
250
251     @Test
252     public void writeWriteFooBar1stLevelEmptyContainerTest() throws DataValidationFailedException {
253         final DataTreeModification initialDataTreeModification = inMemoryDataTree.takeSnapshot().newModification();
254         initialDataTreeModification.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
255         initialDataTreeModification.ready();
256         inMemoryDataTree.commit(inMemoryDataTree.prepare(initialDataTreeModification));
257         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
258
259         final DataTreeModification modificationTree1 = initialDataTreeSnapshot.newModification();
260         final DataTreeModification modificationTree2 = initialDataTreeSnapshot.newModification();
261
262         modificationTree1.write(TestModel.TEST_PATH, createFooTestContainerNode());
263         modificationTree2.write(TestModel.TEST_PATH, createBarTestContainerNode());
264         modificationTree1.ready();
265         modificationTree2.ready();
266
267         inMemoryDataTree.validate(modificationTree1);
268         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
269         inMemoryDataTree.commit(prepare1);
270
271         try {
272             inMemoryDataTree.validate(modificationTree2);
273             fail("Exception should have been thrown.");
274             final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
275             inMemoryDataTree.commit(prepare2);
276         } catch (final ConflictingModificationAppliedException ex) {
277             LOG.debug("ConflictingModificationAppliedException - '{}' was thrown as expected.");
278         }
279
280         final InMemoryDataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
281         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_1_PATH), MapEntryNode.class);
282         assertFalse(snapshotAfterCommits.readNode(OUTER_LIST_2_PATH).isPresent());
283     }
284
285     @Test
286     public void writeMergeFooBar1stLevelEmptyContainerTest() throws DataValidationFailedException {
287         final DataTreeModification initialDataTreeModification = inMemoryDataTree.takeSnapshot().newModification();
288         initialDataTreeModification.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
289         initialDataTreeModification.ready();
290         inMemoryDataTree.commit(inMemoryDataTree.prepare(initialDataTreeModification));
291         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
292
293         final DataTreeModification modificationTree1 = initialDataTreeSnapshot.newModification();
294         final DataTreeModification modificationTree2 = initialDataTreeSnapshot.newModification();
295
296         modificationTree1.write(TestModel.TEST_PATH, createFooTestContainerNode());
297         modificationTree2.merge(TestModel.TEST_PATH, createBarTestContainerNode());
298         modificationTree1.ready();
299         modificationTree2.ready();
300
301         inMemoryDataTree.validate(modificationTree1);
302         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
303         inMemoryDataTree.commit(prepare1);
304
305         inMemoryDataTree.validate(modificationTree2);
306         final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
307         inMemoryDataTree.commit(prepare2);
308
309         final InMemoryDataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
310         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_1_PATH), MapEntryNode.class);
311         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_2_PATH), MapEntryNode.class);
312     }
313
314     @Test
315     public void mergeWriteFooBar1stLevelEmptyContainerTest() throws DataValidationFailedException {
316         final DataTreeModification initialDataTreeModification = inMemoryDataTree.takeSnapshot().newModification();
317         initialDataTreeModification.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
318         initialDataTreeModification.ready();
319         inMemoryDataTree.commit(inMemoryDataTree.prepare(initialDataTreeModification));
320         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
321
322         final DataTreeModification modificationTree1 = initialDataTreeSnapshot.newModification();
323         final DataTreeModification modificationTree2 = initialDataTreeSnapshot.newModification();
324
325         modificationTree1.merge(TestModel.TEST_PATH, createFooTestContainerNode());
326         modificationTree2.write(TestModel.TEST_PATH, createBarTestContainerNode());
327         modificationTree1.ready();
328         modificationTree2.ready();
329
330         inMemoryDataTree.validate(modificationTree1);
331         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
332         inMemoryDataTree.commit(prepare1);
333
334         try {
335             inMemoryDataTree.validate(modificationTree2);
336             fail("Exception should have been thrown.");
337             final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
338             inMemoryDataTree.commit(prepare2);
339         } catch (final ConflictingModificationAppliedException ex) {
340             LOG.debug("ConflictingModificationAppliedException - '{}' was thrown as expected.");
341         }
342
343
344         final InMemoryDataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
345         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_1_PATH), MapEntryNode.class);
346         assertFalse(snapshotAfterCommits.readNode(OUTER_LIST_2_PATH).isPresent());
347     }
348
349     @Test
350     public void mergeMergeFooBar1stLevelEmptyContainerTest() throws DataValidationFailedException {
351         final DataTreeModification initialDataTreeModification = inMemoryDataTree.takeSnapshot().newModification();
352         initialDataTreeModification.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
353         initialDataTreeModification.ready();
354         inMemoryDataTree.commit(inMemoryDataTree.prepare(initialDataTreeModification));
355         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
356
357         final DataTreeModification modificationTree1 = initialDataTreeSnapshot.newModification();
358         final DataTreeModification modificationTree2 = initialDataTreeSnapshot.newModification();
359
360         modificationTree1.merge(TestModel.TEST_PATH, createFooTestContainerNode());
361         modificationTree2.merge(TestModel.TEST_PATH, createBarTestContainerNode());
362         modificationTree1.ready();
363         modificationTree2.ready();
364
365         inMemoryDataTree.validate(modificationTree1);
366         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
367         inMemoryDataTree.commit(prepare1);
368
369         inMemoryDataTree.validate(modificationTree2);
370         final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
371         inMemoryDataTree.commit(prepare2);
372
373         final InMemoryDataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
374         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_1_PATH), MapEntryNode.class);
375         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_2_PATH), MapEntryNode.class);
376     }
377
378     @Test
379     public void deleteWriteFooBar1stLevelEmptyContainerTest() throws DataValidationFailedException {
380         final DataTreeModification initialDataTreeModification = inMemoryDataTree.takeSnapshot().newModification();
381         initialDataTreeModification.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
382         initialDataTreeModification.ready();
383         inMemoryDataTree.commit(inMemoryDataTree.prepare(initialDataTreeModification));
384         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
385
386         final DataTreeModification modificationTree1 = initialDataTreeSnapshot.newModification();
387         final DataTreeModification modificationTree2 = initialDataTreeSnapshot.newModification();
388
389         modificationTree1.delete(TestModel.TEST_PATH);
390         modificationTree2.write(TestModel.TEST_PATH, createBarTestContainerNode());
391         modificationTree1.ready();
392         modificationTree2.ready();
393
394         inMemoryDataTree.validate(modificationTree1);
395         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
396         inMemoryDataTree.commit(prepare1);
397
398         try {
399             inMemoryDataTree.validate(modificationTree2);
400             fail("Exception should have been thrown.");
401             final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
402             inMemoryDataTree.commit(prepare2);
403         } catch (final ConflictingModificationAppliedException ex) {
404             LOG.debug("ConflictingModificationAppliedException - '{}' was thrown as expected.");
405         }
406
407
408         final InMemoryDataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
409         assertFalse(snapshotAfterCommits.readNode(TestModel.TEST_PATH).isPresent());
410     }
411
412     @Test
413     public void deleteMergeFooBar1stLevelEmptyContainerTest() throws DataValidationFailedException {
414         final DataTreeModification initialDataTreeModification = inMemoryDataTree.takeSnapshot().newModification();
415         initialDataTreeModification.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
416         initialDataTreeModification.ready();
417         inMemoryDataTree.commit(inMemoryDataTree.prepare(initialDataTreeModification));
418         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
419
420         final DataTreeModification modificationTree1 = initialDataTreeSnapshot.newModification();
421         final DataTreeModification modificationTree2 = initialDataTreeSnapshot.newModification();
422
423         modificationTree1.delete(TestModel.TEST_PATH);
424         modificationTree2.merge(TestModel.TEST_PATH, createBarTestContainerNode());
425         modificationTree1.ready();
426         modificationTree2.ready();
427
428         inMemoryDataTree.validate(modificationTree1);
429         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
430         inMemoryDataTree.commit(prepare1);
431
432         inMemoryDataTree.validate(modificationTree2);
433         final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
434         inMemoryDataTree.commit(prepare2);
435
436         final InMemoryDataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
437         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_2_PATH), MapEntryNode.class);
438     }
439
440     @Test
441     public void writeWriteFooBar2ndLevelEmptyContainerTest() throws DataValidationFailedException {
442         final DataTreeModification initialDataTreeModification = inMemoryDataTree.takeSnapshot().newModification();
443         initialDataTreeModification.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
444         initialDataTreeModification.write(TestModel.OUTER_LIST_PATH, mapNodeBuilder(TestModel.OUTER_LIST_QNAME).build());
445         initialDataTreeModification.ready();
446         inMemoryDataTree.commit(inMemoryDataTree.prepare(initialDataTreeModification));
447         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
448
449         final DataTreeModification modificationTree1 = initialDataTreeSnapshot.newModification();
450         final DataTreeModification modificationTree2 = initialDataTreeSnapshot.newModification();
451
452         modificationTree1.write(OUTER_LIST_1_PATH, FOO_NODE);
453         modificationTree2.write(OUTER_LIST_2_PATH, BAR_NODE);
454         modificationTree1.ready();
455         modificationTree2.ready();
456
457         inMemoryDataTree.validate(modificationTree1);
458         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
459         inMemoryDataTree.commit(prepare1);
460
461         inMemoryDataTree.validate(modificationTree2);
462         final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
463         inMemoryDataTree.commit(prepare2);
464
465         final InMemoryDataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
466         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_1_PATH), MapEntryNode.class);
467         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_2_PATH), MapEntryNode.class);
468     }
469
470     @Test
471     public void writeMergeFooBar2ndLevelEmptyContainerTest() throws DataValidationFailedException {
472         final DataTreeModification initialDataTreeModification = inMemoryDataTree.takeSnapshot().newModification();
473         initialDataTreeModification.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
474         initialDataTreeModification.write(TestModel.OUTER_LIST_PATH, mapNodeBuilder(TestModel.OUTER_LIST_QNAME).build());
475         initialDataTreeModification.ready();
476         inMemoryDataTree.commit(inMemoryDataTree.prepare(initialDataTreeModification));
477         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
478
479         final DataTreeModification modificationTree1 = initialDataTreeSnapshot.newModification();
480         final DataTreeModification modificationTree2 = initialDataTreeSnapshot.newModification();
481
482         modificationTree1.write(OUTER_LIST_1_PATH, FOO_NODE);
483         modificationTree2.merge(OUTER_LIST_2_PATH, BAR_NODE);
484         modificationTree1.ready();
485         modificationTree2.ready();
486
487         inMemoryDataTree.validate(modificationTree1);
488         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
489         inMemoryDataTree.commit(prepare1);
490
491         inMemoryDataTree.validate(modificationTree2);
492         final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
493         inMemoryDataTree.commit(prepare2);
494
495         final InMemoryDataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
496         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_1_PATH), MapEntryNode.class);
497         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_2_PATH), MapEntryNode.class);
498     }
499
500     @Test
501     public void mergeWriteFooBar2ndLevelEmptyContainerTest() throws DataValidationFailedException {
502         final DataTreeModification initialDataTreeModification = inMemoryDataTree.takeSnapshot().newModification();
503         initialDataTreeModification.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
504         initialDataTreeModification.write(TestModel.OUTER_LIST_PATH, mapNodeBuilder(TestModel.OUTER_LIST_QNAME).build());
505         initialDataTreeModification.ready();
506         inMemoryDataTree.commit(inMemoryDataTree.prepare(initialDataTreeModification));
507         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
508
509         final DataTreeModification modificationTree1 = initialDataTreeSnapshot.newModification();
510         final DataTreeModification modificationTree2 = initialDataTreeSnapshot.newModification();
511
512         modificationTree1.merge(OUTER_LIST_1_PATH, FOO_NODE);
513         modificationTree2.write(OUTER_LIST_2_PATH, BAR_NODE);
514         modificationTree1.ready();
515         modificationTree2.ready();
516
517         inMemoryDataTree.validate(modificationTree1);
518         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
519         inMemoryDataTree.commit(prepare1);
520
521         inMemoryDataTree.validate(modificationTree2);
522         final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
523         inMemoryDataTree.commit(prepare2);
524
525         final InMemoryDataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
526         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_1_PATH), MapEntryNode.class);
527         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_2_PATH), MapEntryNode.class);
528     }
529
530     @Test
531     public void mergeMergeFooBar2ndLevelEmptyContainerTest() throws DataValidationFailedException {
532         final DataTreeModification initialDataTreeModification = inMemoryDataTree.takeSnapshot().newModification();
533         initialDataTreeModification.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
534         initialDataTreeModification.write(TestModel.OUTER_LIST_PATH, mapNodeBuilder(TestModel.OUTER_LIST_QNAME).build());
535         initialDataTreeModification.ready();
536         inMemoryDataTree.commit(inMemoryDataTree.prepare(initialDataTreeModification));
537         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
538
539         final DataTreeModification modificationTree1 = initialDataTreeSnapshot.newModification();
540         final DataTreeModification modificationTree2 = initialDataTreeSnapshot.newModification();
541
542         modificationTree1.merge(OUTER_LIST_1_PATH, FOO_NODE);
543         modificationTree2.merge(OUTER_LIST_2_PATH, BAR_NODE);
544         modificationTree1.ready();
545         modificationTree2.ready();
546
547         inMemoryDataTree.validate(modificationTree1);
548         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
549         inMemoryDataTree.commit(prepare1);
550
551         inMemoryDataTree.validate(modificationTree2);
552         final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
553         inMemoryDataTree.commit(prepare2);
554
555         final InMemoryDataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
556         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_1_PATH), MapEntryNode.class);
557         assertPresentAndType(snapshotAfterCommits.readNode(OUTER_LIST_2_PATH), MapEntryNode.class);
558     }
559
560     @Test
561     public void deleteWriteFooBar2ndLevelEmptyContainerTest() throws DataValidationFailedException {
562         final DataTreeModification initialDataTreeModification = inMemoryDataTree.takeSnapshot().newModification();
563         initialDataTreeModification.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
564         initialDataTreeModification.write(TestModel.OUTER_LIST_PATH, mapNodeBuilder(TestModel.OUTER_LIST_QNAME).build());
565         initialDataTreeModification.ready();
566         inMemoryDataTree.commit(inMemoryDataTree.prepare(initialDataTreeModification));
567         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
568
569         final DataTreeModification modificationTree1 = initialDataTreeSnapshot.newModification();
570         final DataTreeModification modificationTree2 = initialDataTreeSnapshot.newModification();
571
572         modificationTree1.delete(TestModel.TEST_PATH);
573         modificationTree2.merge(OUTER_LIST_2_PATH, BAR_NODE);
574         modificationTree1.ready();
575         modificationTree2.ready();
576
577         inMemoryDataTree.validate(modificationTree1);
578         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
579         inMemoryDataTree.commit(prepare1);
580
581         try {
582             inMemoryDataTree.validate(modificationTree2);
583             final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
584             inMemoryDataTree.commit(prepare2);
585             fail("Exception should have been thrown");
586         } catch (final Exception e) {
587             LOG.debug("Exception was thrown because path no longer exist in tree");
588         }
589
590         final InMemoryDataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
591         assertFalse(snapshotAfterCommits.readNode(TestModel.TEST_PATH).isPresent());
592     }
593
594     @Test
595     public void deleteMergeFooBar2ndLevelEmptyContainerTest() throws DataValidationFailedException {
596         final DataTreeModification initialDataTreeModification = inMemoryDataTree.takeSnapshot().newModification();
597         initialDataTreeModification.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
598         initialDataTreeModification.write(TestModel.OUTER_LIST_PATH, mapNodeBuilder(TestModel.OUTER_LIST_QNAME).build());
599         initialDataTreeModification.ready();
600         inMemoryDataTree.commit(inMemoryDataTree.prepare(initialDataTreeModification));
601         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
602
603         final DataTreeModification modificationTree1 = initialDataTreeSnapshot.newModification();
604         final DataTreeModification modificationTree2 = initialDataTreeSnapshot.newModification();
605
606         modificationTree1.delete(TestModel.TEST_PATH);
607         modificationTree2.merge(OUTER_LIST_2_PATH, BAR_NODE);
608         modificationTree1.ready();
609         modificationTree2.ready();
610
611         inMemoryDataTree.validate(modificationTree1);
612         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
613         inMemoryDataTree.commit(prepare1);
614
615         try {
616             inMemoryDataTree.validate(modificationTree2);
617             final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
618             inMemoryDataTree.commit(prepare2);
619             fail("Exception should have been thrown");
620         } catch (final Exception e) {
621             LOG.debug("Exception was thrown because path no longer exist in tree");
622         }
623
624         final InMemoryDataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
625         assertFalse(snapshotAfterCommits.readNode(TestModel.TEST_PATH).isPresent());
626     }
627 }