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