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