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