Another round of Sonar warnings fixes
[yangtools.git] / data / yang-data-tree-spi / src / test / java / org / opendaylight / yangtools / yang / data / tree / spi / DataTreeCandidatesAggregateTest.java
1 /*
2  * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.spi;
9
10 import static org.junit.jupiter.api.Assertions.assertEquals;
11 import static org.junit.jupiter.api.Assertions.assertNull;
12 import static org.junit.jupiter.api.Assertions.assertThrows;
13 import static org.mockito.Mockito.doReturn;
14 import static org.mockito.Mockito.mock;
15 import static org.opendaylight.yangtools.yang.data.tree.api.ModificationType.APPEARED;
16 import static org.opendaylight.yangtools.yang.data.tree.api.ModificationType.DELETE;
17 import static org.opendaylight.yangtools.yang.data.tree.api.ModificationType.DISAPPEARED;
18 import static org.opendaylight.yangtools.yang.data.tree.api.ModificationType.SUBTREE_MODIFIED;
19 import static org.opendaylight.yangtools.yang.data.tree.api.ModificationType.UNMODIFIED;
20 import static org.opendaylight.yangtools.yang.data.tree.api.ModificationType.WRITE;
21
22 import java.util.List;
23 import org.junit.jupiter.api.Test;
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
26 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
27 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
28 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
29 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidate;
30 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidateNode;
31 import org.opendaylight.yangtools.yang.data.tree.api.ModificationType;
32
33 class DataTreeCandidatesAggregateTest {
34     private static final YangInstanceIdentifier ROOT_PATH = YangInstanceIdentifier.of(QName.create(
35             "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test:container",
36             "2014-03-13", "container"));
37     private static final YangInstanceIdentifier.PathArgument CHILD_ID = new NodeIdentifier(QName.create(
38             "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test:container:data",
39             "2014-03-13", "data"));
40
41     @Test
42     void testLeafUnmodifiedUnmodified() {
43         final var normalizedNode1 = normalizedNode("value1");
44         final var normalizedNode2 = normalizedNode("value1");
45         final var normalizedNode3 = normalizedNode("value1");
46
47         final var node1 = dataTreeCandidateNode(normalizedNode1, normalizedNode2, UNMODIFIED);
48         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
49
50         final var node2 = dataTreeCandidateNode(normalizedNode2, normalizedNode3, UNMODIFIED);
51         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
52
53         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
54
55         assertEquals(UNMODIFIED, aggregationResult.getRootNode().modificationType());
56         assertEquals("value1", aggregationResult.getRootNode().dataBefore().body());
57         assertEquals("value1", aggregationResult.getRootNode().dataAfter().body());
58     }
59
60     @Test
61     void testLeaftUnmodifiedWrite() {
62         final var normalizedNode1 = normalizedNode("value1");
63         final var normalizedNode2 = normalizedNode("value1");
64         final var normalizedNode3 = normalizedNode("value2");
65
66         final var node1 = dataTreeCandidateNode(normalizedNode1, normalizedNode2, UNMODIFIED);
67         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
68
69         final var node2 = dataTreeCandidateNode(normalizedNode2, normalizedNode3, WRITE);
70         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
71
72         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
73
74         assertEquals(WRITE, aggregationResult.getRootNode().modificationType());
75         assertEquals("value1", aggregationResult.getRootNode().dataBefore().body());
76         assertEquals("value2", aggregationResult.getRootNode().dataAfter().body());
77     }
78
79     @Test
80     void testLeafUnmodifiedDelete() {
81         final var normalizedNode1 = normalizedNode("value1");
82         final var normalizedNode2 = normalizedNode("value1");
83
84         final var node1 = dataTreeCandidateNode(normalizedNode1, normalizedNode2, UNMODIFIED);
85         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
86
87         final var node2 = dataTreeCandidateNode(normalizedNode2, null, DELETE);
88         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
89
90         DataTreeCandidate aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
91
92         assertEquals(DELETE, aggregationResult.getRootNode().modificationType());
93         assertEquals("value1", aggregationResult.getRootNode().dataBefore().body());
94         assertNull(aggregationResult.getRootNode().dataAfter());
95     }
96
97     @Test
98     void testLeafUnmodifiedDeleteWithoutDataBefore() {
99         final var node1 = dataTreeCandidateNode(null, null, UNMODIFIED);
100         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
101
102         final var node2 = dataTreeCandidateNode(null, null, DELETE);
103         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
104
105         assertThrows(IllegalArgumentException.class,
106             () -> DataTreeCandidates.aggregate(List.of(candidate1, candidate2)));
107     }
108
109     @Test
110     void testLeafUnmodifiedSubtreeModifiedWithoutDataBefore() {
111         final var node1 = dataTreeCandidateNode(null, null, UNMODIFIED);
112         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
113
114         final var node2 = dataTreeCandidateNode(null, null, SUBTREE_MODIFIED);
115         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
116
117         assertThrows(IllegalArgumentException.class,
118             () -> DataTreeCandidates.aggregate(List.of(candidate1, candidate2)));
119     }
120
121     @Test
122     void testLeafWriteUnmodified() {
123         final var normalizedNode1 = normalizedNode("value1");
124         final var normalizedNode2 = normalizedNode("value2");
125
126         final var node1 = dataTreeCandidateNode(normalizedNode1, normalizedNode2, WRITE);
127         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
128
129         final var node2 = dataTreeCandidateNode(normalizedNode2, normalizedNode2, UNMODIFIED);
130         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
131
132         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
133
134         assertEquals(WRITE, aggregationResult.getRootNode().modificationType());
135         assertEquals("value1", aggregationResult.getRootNode().dataBefore().body());
136         assertEquals("value2", aggregationResult.getRootNode().dataAfter().body());
137     }
138
139     @Test
140     void testLeafWriteWrite() {
141         final var normalizedNode1 = normalizedNode("value1");
142         final var normalizedNode2 = normalizedNode("value2");
143         final var normalizedNode3 = normalizedNode("value3");
144
145         final var node1 = dataTreeCandidateNode(normalizedNode1, normalizedNode2, WRITE);
146         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
147
148         final var node2 = dataTreeCandidateNode(normalizedNode2, normalizedNode3, WRITE);
149         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
150
151         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
152
153         assertEquals(WRITE, aggregationResult.getRootNode().modificationType());
154         assertEquals("value1", aggregationResult.getRootNode().dataBefore().body());
155         assertEquals("value3", aggregationResult.getRootNode().dataAfter().body());
156     }
157
158     @Test
159     void testLeafWriteDeleteWithoutChanges() {
160         final var normalizedNode = normalizedNode("value1");
161
162         final var node1 = dataTreeCandidateNode(null, normalizedNode, WRITE);
163         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
164
165         final var node2 = dataTreeCandidateNode(normalizedNode, null, DELETE);
166         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
167
168         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
169
170         assertEquals(UNMODIFIED, aggregationResult.getRootNode().modificationType());
171         assertNull(aggregationResult.getRootNode().dataBefore());
172         assertNull(aggregationResult.getRootNode().dataAfter());
173     }
174
175     @Test
176     void testLeafWriteDelete() {
177         final var normalizedNode1 = normalizedNode("value1");
178         final var normalizedNode2 = normalizedNode("value2");
179
180         final var node1 = dataTreeCandidateNode(normalizedNode1, normalizedNode2, WRITE);
181         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
182
183         final var node2 = dataTreeCandidateNode(normalizedNode2, null, DELETE);
184         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
185
186         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
187
188         assertEquals(DELETE, aggregationResult.getRootNode().modificationType());
189         assertEquals("value1", aggregationResult.getRootNode().dataBefore().body());
190         assertNull(aggregationResult.getRootNode().dataAfter());
191     }
192
193     @Test
194     void testLeafDeleteUnmodified() {
195         final var normalizedNode = normalizedNode("value");
196
197         final var node1 = dataTreeCandidateNode(normalizedNode, null, DELETE);
198         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
199
200         final var node2 = dataTreeCandidateNode(null, null, UNMODIFIED);
201         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
202
203         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
204
205         assertEquals(DELETE, aggregationResult.getRootNode().modificationType());
206         assertEquals("value", aggregationResult.getRootNode().dataBefore().body());
207         assertNull(aggregationResult.getRootNode().dataAfter());
208     }
209
210     @Test
211     void testLeafDeleteWrite() {
212         final var normalizedNode1 = normalizedNode("value1");
213         final var normalizedNode2 = normalizedNode("value2");
214
215         final var node1 = dataTreeCandidateNode(normalizedNode1, null, DELETE);
216         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
217
218         final var node2 = dataTreeCandidateNode(null, normalizedNode2, WRITE);
219         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
220
221         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
222
223         assertEquals(WRITE, aggregationResult.getRootNode().modificationType());
224         assertEquals("value1", aggregationResult.getRootNode().dataBefore().body());
225         assertEquals("value2", aggregationResult.getRootNode().dataAfter().body());
226     }
227
228     @Test
229     void testLeafDeleteDelete() {
230         final var normalizedNode1 = normalizedNode("value1");
231
232         final var node1 = dataTreeCandidateNode(normalizedNode1, null, DELETE);
233         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
234
235         final var node2 = dataTreeCandidateNode(null, null, DELETE);
236         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
237
238         assertThrows(IllegalArgumentException.class,
239             () -> DataTreeCandidates.aggregate(List.of(candidate1, candidate2)));
240     }
241
242     @Test
243     void testLeafDeleteDisappear() {
244         final var normalizedNode1 = normalizedNode("value1");
245
246         final var node1 = dataTreeCandidateNode(normalizedNode1, null, DELETE);
247         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
248
249         final var node2 = dataTreeCandidateNode(null, null, DISAPPEARED);
250         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
251
252         assertThrows(IllegalArgumentException.class,
253             () -> DataTreeCandidates.aggregate(List.of(candidate1, candidate2)));
254     }
255
256     @Test
257     void testLeafDeleteSubtreeModified() {
258         final var normalizedNode1 = normalizedNode("value1");
259
260         final var node1 = dataTreeCandidateNode(normalizedNode1, null, DELETE);
261         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
262
263         final var node2 = dataTreeCandidateNode(null, null, SUBTREE_MODIFIED);
264         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
265
266         assertThrows(IllegalArgumentException.class,
267             () -> DataTreeCandidates.aggregate(List.of(candidate1, candidate2)));
268     }
269
270     @Test
271     void testUnmodifiedUnmodified() {
272         final var parentNode = normalizedNode("container");
273         final var childNode = normalizedNode("child");
274
275         final var node1 = dataTreeCandidateNode(parentNode, parentNode, UNMODIFIED);
276         final var child1 = dataTreeCandidateNode(childNode, childNode, UNMODIFIED);
277         setChildNodes(node1, List.of(child1));
278         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
279
280         final var node2 = dataTreeCandidateNode(parentNode, parentNode, UNMODIFIED);
281         final var child2 = dataTreeCandidateNode(childNode, childNode, UNMODIFIED);
282         setChildNodes(node2, List.of(child2));
283         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
284
285         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
286
287         assertEquals(UNMODIFIED, aggregationResult.getRootNode().modificationType());
288     }
289
290     @Test
291     void testUnmodifiedDelete() {
292         final var parentNode = normalizedNode("container");
293         final var childNode = normalizedNode("child");
294
295         final var node1 = dataTreeCandidateNode(parentNode, parentNode, UNMODIFIED);
296         final var child1 = dataTreeCandidateNode(childNode, childNode, UNMODIFIED);
297         setChildNodes(node1, List.of(child1));
298         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
299
300         final var node2 = dataTreeCandidateNode(parentNode, null, DELETE);
301         final var child2 = dataTreeCandidateNode(childNode, null, DELETE);
302         setChildNodes(node2, List.of(child2));
303         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
304
305         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
306
307         assertEquals(DELETE, aggregationResult.getRootNode().modificationType());
308     }
309
310     @Test
311     void testUnmodifiedWrite() {
312         final var parentNode1 = normalizedNode("container1");
313         final var childNode1 = normalizedNode("child1");
314         final var parentNode2 = normalizedNode("container2");
315         final var childNode2 = normalizedNode("child2");
316
317         final var node1 = dataTreeCandidateNode(parentNode1, parentNode1, UNMODIFIED);
318         final var child1 = dataTreeCandidateNode(childNode1, childNode1, UNMODIFIED);
319         setChildNodes(node1, List.of(child1));
320         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
321
322         final var node2 = dataTreeCandidateNode(parentNode1, parentNode2, WRITE);
323         final var child2 = dataTreeCandidateNode(childNode1, childNode2, WRITE);
324         setChildNodes(node2, List.of(child2));
325         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
326
327         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
328
329         assertEquals(WRITE, aggregationResult.getRootNode().modificationType());
330     }
331
332     @Test
333     void testUnmodifiedSubtreeModifiedWithoutDataBefore() {
334         final var parentNode = normalizedNode("container");
335         final var childNode = normalizedNode("child");
336
337         final var node1 = dataTreeCandidateNode(null, null, UNMODIFIED);
338         final var child1 = dataTreeCandidateNode(null, null, UNMODIFIED);
339         setChildNodes(node1, List.of(child1));
340         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
341
342         final var node2 = dataTreeCandidateNode(parentNode, parentNode, SUBTREE_MODIFIED);
343         final var child2 = dataTreeCandidateNode(null, childNode, WRITE);
344         setChildNodes(node2, List.of(child2));
345         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
346
347         assertThrows(IllegalArgumentException.class,
348             () -> DataTreeCandidates.aggregate(List.of(candidate1, candidate2)));
349     }
350
351     //FIXME
352     @Test
353     void testUnmodifiedSubtreeModified() {
354         final var parentNode1 = normalizedNode("container1");
355         final var childNode1 = normalizedNode("child1");
356         final var parentNode2 = normalizedNode("container1");
357         final var childNode2 = normalizedNode("child2");
358
359         final var node1 = dataTreeCandidateNode(parentNode1, parentNode1, UNMODIFIED);
360         final var child1 = dataTreeCandidateNode(childNode1, childNode1, UNMODIFIED);
361         setChildNodes(node1, List.of(child1));
362         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
363
364         final var node2 = dataTreeCandidateNode(parentNode1, parentNode2, SUBTREE_MODIFIED);
365         final var child2 = dataTreeCandidateNode(childNode1, childNode2, WRITE);
366         setChildNodes(node2, List.of(child2));
367         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
368
369         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
370
371         assertEquals(SUBTREE_MODIFIED, aggregationResult.getRootNode().modificationType());
372     }
373
374     @Test
375     void testUnmodifiedAppearedWithDataBefore() {
376         final var parentNode1 = normalizedNode("container1");
377         final var childNode1 = normalizedNode("child1");
378         final var parentNode2 = normalizedNode("container1");
379         final var childNode2 = normalizedNode("child2");
380
381         final var node1 = dataTreeCandidateNode(parentNode1, parentNode1, UNMODIFIED);
382         final var child1 = dataTreeCandidateNode(childNode1, childNode1, UNMODIFIED);
383         setChildNodes(node1, List.of(child1));
384         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
385
386         final var node2 = dataTreeCandidateNode(parentNode1, parentNode2, APPEARED);
387         final var child2 = dataTreeCandidateNode(childNode1, childNode2, WRITE);
388         setChildNodes(node2, List.of(child2));
389         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
390
391         assertThrows(IllegalArgumentException.class,
392             () -> DataTreeCandidates.aggregate(List.of(candidate1, candidate2)));
393     }
394
395     //FIXME
396     @Test
397     void testUnmodifiedAppeared() {
398         final var parentNode = normalizedNode("container");
399         final var childNode = normalizedNode("child");
400
401         final var node1 = dataTreeCandidateNode(null, null, UNMODIFIED);
402         final var child1 = dataTreeCandidateNode(null, null, UNMODIFIED);
403         setChildNodes(node1, List.of(child1));
404         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
405
406         final var node2 = dataTreeCandidateNode(parentNode, parentNode, APPEARED);
407         final var child2 = dataTreeCandidateNode(null, childNode, WRITE);
408         setChildNodes(node2, List.of(child2));
409         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
410
411         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
412
413         assertEquals(APPEARED, aggregationResult.getRootNode().modificationType());
414     }
415
416     @Test
417     void testUnmodifiedDisappearWithoutDataBefore() {
418         final var parentNode = normalizedNode("container");
419         final var childNode = normalizedNode("child");
420
421         final var node1 = dataTreeCandidateNode(null, null, UNMODIFIED);
422         final var child1 = dataTreeCandidateNode(null, null, UNMODIFIED);
423         setChildNodes(node1, List.of(child1));
424         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
425
426         final var node2 = dataTreeCandidateNode(parentNode, parentNode, DISAPPEARED);
427         final var child2 = dataTreeCandidateNode(null, childNode, DELETE);
428         setChildNodes(node2, List.of(child2));
429         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
430
431         assertThrows(IllegalArgumentException.class,
432             () -> DataTreeCandidates.aggregate(List.of(candidate1, candidate2)));
433     }
434
435     @Test
436     void testUnmodifiedDisappear() {
437         final var parentNode1 = normalizedNode("container1");
438         final var childNode1 = normalizedNode("child1");
439
440         final var node1 = dataTreeCandidateNode(parentNode1, parentNode1, UNMODIFIED);
441         final var child1 = dataTreeCandidateNode(childNode1, childNode1, UNMODIFIED);
442         setChildNodes(node1, List.of(child1));
443         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
444
445         final var node2 = dataTreeCandidateNode(parentNode1, null, DISAPPEARED);
446         final var child2 = dataTreeCandidateNode(childNode1, null, DELETE);
447         setChildNodes(node2, List.of(child2));
448         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
449
450         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
451
452         assertEquals(DISAPPEARED, aggregationResult.getRootNode().modificationType());
453     }
454
455     @Test
456     void testDeleteUnmodified() {
457         final var parentNode = normalizedNode("container");
458         final var childNode = normalizedNode("child");
459
460         final var node1 = dataTreeCandidateNode(parentNode, null, DELETE);
461         final var child1 = dataTreeCandidateNode(childNode, null, DELETE);
462         setChildNodes(node1, List.of(child1));
463         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
464
465         final var node2 = dataTreeCandidateNode(null, null, UNMODIFIED);
466         final var child2 = dataTreeCandidateNode(null, null, UNMODIFIED);
467         setChildNodes(node2, List.of(child2));
468         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
469
470         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
471
472         assertEquals(DELETE, aggregationResult.getRootNode().modificationType());
473     }
474
475     @Test
476     void testDeleteWrite() {
477         final var parentNode1 = normalizedNode("container1");
478         final var parentNode2 = normalizedNode("container2");
479         final var childNode1 = normalizedNode("child1");
480         final var childNode2 = normalizedNode("child2");
481
482         final var node1 = dataTreeCandidateNode(parentNode1, null, DELETE);
483         final var child1 = dataTreeCandidateNode(childNode1, null, DELETE);
484         setChildNodes(node1, List.of(child1));
485         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
486
487         final var node2 = dataTreeCandidateNode(null, parentNode2, WRITE);
488         final var child2 = dataTreeCandidateNode(null, childNode2, WRITE);
489         setChildNodes(node2, List.of(child2));
490         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
491
492         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
493
494         assertEquals(WRITE, aggregationResult.getRootNode().modificationType());
495     }
496
497     @Test
498     void testDeleteAppear() {
499         final var parentNode1 = normalizedNode("container1");
500         final var parentNode2 = normalizedNode("container2");
501         final var childNode1 = normalizedNode("child1");
502         final var childNode2 = normalizedNode("child2");
503
504         final var node1 = dataTreeCandidateNode(parentNode1, null, DELETE);
505         final var child1 = dataTreeCandidateNode(childNode1, null, DELETE);
506         setChildNodes(node1, List.of(child1));
507         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
508
509         final var node2 = dataTreeCandidateNode(null, parentNode2, APPEARED);
510         final var child2 = dataTreeCandidateNode(null, childNode2, WRITE);
511         setChildNodes(node2, List.of(child2));
512         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
513
514         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
515
516         assertEquals(WRITE, aggregationResult.getRootNode().modificationType());
517     }
518
519     @Test
520     void testWriteUnmodified() {
521         final var parentNode = normalizedNode("container");
522         final var childNode = normalizedNode("child");
523
524         final var node1 = dataTreeCandidateNode(null, parentNode, WRITE);
525         final var child1 = dataTreeCandidateNode(null, childNode, WRITE);
526         setChildNodes(node1, List.of(child1));
527         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
528
529         final var node2 = dataTreeCandidateNode(parentNode, parentNode, UNMODIFIED);
530         final var child2 = dataTreeCandidateNode(childNode, childNode, UNMODIFIED);
531         setChildNodes(node2, List.of(child2));
532         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
533
534         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
535
536         assertEquals(WRITE, aggregationResult.getRootNode().modificationType());
537     }
538
539     @Test
540     void testWriteDeleteWithoutChanges() {
541         final var parentNode = normalizedNode("container");
542         final var childNode = normalizedNode("child");
543
544         final var node1 = dataTreeCandidateNode(null, parentNode, WRITE);
545         final var child1 = dataTreeCandidateNode(null, childNode, WRITE);
546         setChildNodes(node1, List.of(child1));
547         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
548
549         final var node2 = dataTreeCandidateNode(parentNode, null, DELETE);
550         final var child2 = dataTreeCandidateNode(childNode, null, DELETE);
551         setChildNodes(node2, List.of(child2));
552         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
553
554         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
555
556         assertEquals(UNMODIFIED, aggregationResult.getRootNode().modificationType());
557     }
558
559     @Test
560     void testWriteDelete() {
561         final var parentNode1 = normalizedNode("container1");
562         final var parentNode2 = normalizedNode("container2");
563         final var childNode1 = normalizedNode("child1");
564         final var childNode2 = normalizedNode("child2");
565
566         final var node1 = dataTreeCandidateNode(parentNode1, parentNode2, WRITE);
567         final var child1 = dataTreeCandidateNode(childNode1, childNode2, WRITE);
568         setChildNodes(node1, List.of(child1));
569         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
570
571         final var node2 = dataTreeCandidateNode(parentNode2, null, DELETE);
572         final var child2 = dataTreeCandidateNode(childNode2, null, DELETE);
573         setChildNodes(node2, List.of(child2));
574         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
575
576         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
577
578         assertEquals(DELETE, aggregationResult.getRootNode().modificationType());
579     }
580
581     @Test
582     void testWriteWrite() {
583         final var parentNode1 = normalizedNode("container1");
584         final var parentNode2 = normalizedNode("container2");
585         final var childNode1 = normalizedNode("child1");
586         final var childNode2 = normalizedNode("child2");
587
588         final var node1 = dataTreeCandidateNode(null, parentNode1, WRITE);
589         final var child1 = dataTreeCandidateNode(null, childNode1, WRITE);
590         setChildNodes(node1, List.of(child1));
591         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
592
593         final var node2 = dataTreeCandidateNode(parentNode1, parentNode2, WRITE);
594         final var child2 = dataTreeCandidateNode(childNode1, childNode2, WRITE);
595         setChildNodes(node2, List.of(child2));
596         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
597
598         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
599
600         assertEquals(WRITE, aggregationResult.getRootNode().modificationType());
601     }
602
603     @Test
604     void testWriteSubtreeModified() {
605         final var parentNode = normalizedNode("container");
606         final var parentNode1 = normalizedNode("container1");
607         final var parentNode2 = normalizedNode("container1");
608         final var childNode = normalizedNode("child");
609         final var childNode1 = normalizedNode("child1");
610         final var childNode2 = normalizedNode("child2");
611
612         final var node1 = dataTreeCandidateNode(parentNode, parentNode1, WRITE);
613         final var child1 = dataTreeCandidateNode(childNode, childNode1, WRITE);
614         setChildNodes(node1, List.of(child1));
615         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
616
617         final var node2 = dataTreeCandidateNode(parentNode1, parentNode2, SUBTREE_MODIFIED);
618         final var child2 = dataTreeCandidateNode(childNode1, childNode2, WRITE);
619         setChildNodes(node2, List.of(child2));
620         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
621
622         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
623
624         assertEquals(WRITE, aggregationResult.getRootNode().modificationType());
625     }
626
627     @Test
628     void testWriteAppear() {
629         final var parentNode1 = normalizedNode("container1");
630         final var parentNode2 = normalizedNode("container2");
631         final var childNode1 = normalizedNode("child1");
632         final var childNode2 = normalizedNode("child2");
633         final var childNode3 = normalizedNode("child3");
634
635         final var node1 = dataTreeCandidateNode(parentNode1, parentNode2, WRITE);
636         final var child1 = dataTreeCandidateNode(childNode1, childNode2, WRITE);
637         setChildNodes(node1, List.of(child1));
638         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
639
640         final var node2 = dataTreeCandidateNode(parentNode2, parentNode2, APPEARED);
641         final var child2 = dataTreeCandidateNode(childNode2, childNode3, WRITE);
642         setChildNodes(node2, List.of(child2));
643         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
644
645         assertThrows(IllegalArgumentException.class,
646             () -> DataTreeCandidates.aggregate(List.of(candidate1, candidate2)));
647     }
648
649     @Test
650     void testWriteDisappearWithoutChanges() {
651         final var parentNode = normalizedNode("container");
652         final var childNode = normalizedNode("child");
653
654         final var node1 = dataTreeCandidateNode(null, parentNode, WRITE);
655         final var child1 = dataTreeCandidateNode(null, childNode, WRITE);
656         setChildNodes(node1, List.of(child1));
657         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
658
659         final var node2 = dataTreeCandidateNode(parentNode, null, DISAPPEARED);
660         final var child2 = dataTreeCandidateNode(childNode, null, DELETE);
661         setChildNodes(node2, List.of(child2));
662         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
663
664         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
665
666         assertEquals(UNMODIFIED, aggregationResult.getRootNode().modificationType());
667     }
668
669     @Test
670     void testWriteDisappear() {
671         final var parentNode1 = normalizedNode("container1");
672         final var parentNode2 = normalizedNode("container2");
673         final var childNode1 = normalizedNode("child1");
674         final var childNode2 = normalizedNode("child2");
675
676         final var node1 = dataTreeCandidateNode(parentNode1, parentNode2, WRITE);
677         final var child1 = dataTreeCandidateNode(childNode1, childNode2, WRITE);
678         setChildNodes(node1, List.of(child1));
679         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
680
681         final var node2 = dataTreeCandidateNode(parentNode2, null, DISAPPEARED);
682         final var child2 = dataTreeCandidateNode(childNode2, null, DELETE);
683         setChildNodes(node2, List.of(child2));
684         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
685
686         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
687
688         assertEquals(DISAPPEARED, aggregationResult.getRootNode().modificationType());
689     }
690
691     @Test
692     void testSubtreeModifiedUnmodified() {
693         final var parentNode1 = normalizedNode("container1");
694         final var parentNode2 = normalizedNode("container1");
695         final var childNode1 = normalizedNode("child1");
696         final var childNode2 = normalizedNode("child2");
697
698         final var node1 = dataTreeCandidateNode(parentNode1, parentNode2, SUBTREE_MODIFIED);
699         final var child1 = dataTreeCandidateNode(childNode1, childNode2, WRITE);
700         setChildNodes(node1, List.of(child1));
701         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
702
703         final var node2 = dataTreeCandidateNode(parentNode2, parentNode2, UNMODIFIED);
704         final var child2 = dataTreeCandidateNode(childNode2, childNode2, UNMODIFIED);
705         setChildNodes(node2, List.of(child2));
706         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
707
708         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
709
710         assertEquals(SUBTREE_MODIFIED, aggregationResult.getRootNode().modificationType());
711     }
712
713     @Test
714     void testSubtreeModifiedDelete() {
715         final var parentNode1 = normalizedNode("container1");
716         final var parentNode2 = normalizedNode("container1");
717         final var childNode1 = normalizedNode("child1");
718         final var childNode2 = normalizedNode("child2");
719
720         final var node1 = dataTreeCandidateNode(parentNode1, parentNode2, SUBTREE_MODIFIED);
721         final var child1 = dataTreeCandidateNode(childNode1, childNode2, WRITE);
722         setChildNodes(node1, List.of(child1));
723         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
724
725         final var node2 = dataTreeCandidateNode(parentNode2, null, DELETE);
726         final var child2 = dataTreeCandidateNode(childNode2, null, DELETE);
727         setChildNodes(node2, List.of(child2));
728         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
729
730         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
731
732         assertEquals(DELETE, aggregationResult.getRootNode().modificationType());
733     }
734
735     @Test
736     void testSubtreeModifiedWrite() {
737         final var parentNode1 = normalizedNode("container");
738         final var parentNode2 = normalizedNode("value2");
739         final var childNode = normalizedNode("childNode");
740         final var childNode1 = normalizedNode("child1");
741         final var childNode2 = normalizedNode("child2");
742
743         final var node1 = dataTreeCandidateNode(parentNode1, parentNode1, SUBTREE_MODIFIED);
744         final var child1 = dataTreeCandidateNode(childNode, childNode1, WRITE);
745         setChildNodes(node1, List.of(child1));
746         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
747
748         final var node2 = dataTreeCandidateNode(parentNode1, parentNode2, WRITE);
749         final var child2 = dataTreeCandidateNode(childNode1, childNode2, WRITE);
750         setChildNodes(node2, List.of(child2));
751         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
752
753         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
754
755         assertEquals(WRITE, aggregationResult.getRootNode().modificationType());
756     }
757
758     @Test
759     void testSubtreeModifiedSubtreeModified() {
760         final var parentNode1 = normalizedNode("container");
761         final var childNode = normalizedNode("childNode");
762         final var childNode1 = normalizedNode("child1");
763         final var childNode2 = normalizedNode("child2");
764
765         final var node1 = dataTreeCandidateNode(parentNode1, parentNode1, SUBTREE_MODIFIED);
766         final var child1 = dataTreeCandidateNode(childNode, childNode1, WRITE);
767         setChildNodes(node1, List.of(child1));
768         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
769
770         final var node2 = dataTreeCandidateNode(parentNode1, parentNode1, SUBTREE_MODIFIED);
771         final var child2 = dataTreeCandidateNode(childNode1, childNode2, WRITE);
772         setChildNodes(node2, List.of(child2));
773         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
774
775         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
776
777         assertEquals(SUBTREE_MODIFIED, aggregationResult.getRootNode().modificationType());
778     }
779
780     @Test
781     void testSubtreeModifiedAppear() {
782         final var parentNode1 = normalizedNode("container");
783         final var parentNode2 = normalizedNode("value2");
784         final var childNode = normalizedNode("childNode");
785         final var childNode1 = normalizedNode("child1");
786         final var childNode2 = normalizedNode("child2");
787
788         final var node1 = dataTreeCandidateNode(parentNode1, parentNode1, SUBTREE_MODIFIED);
789         final var child1 = dataTreeCandidateNode(childNode, childNode1, WRITE);
790         setChildNodes(node1, List.of(child1));
791         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
792
793         final var node2 = dataTreeCandidateNode(null, parentNode2, APPEARED);
794         final var child2 = dataTreeCandidateNode(null, childNode2, WRITE);
795         setChildNodes(node2, List.of(child2));
796         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
797
798         assertThrows(IllegalArgumentException.class,
799             () -> DataTreeCandidates.aggregate(List.of(candidate1, candidate2)));
800     }
801
802     @Test
803     void testSubtreeModifiedDisappear() {
804         final var parentNode1 = normalizedNode("container");
805         final var childNode = normalizedNode("childNode");
806         final var childNode1 = normalizedNode("child1");
807
808         final var node1 = dataTreeCandidateNode(parentNode1, parentNode1, SUBTREE_MODIFIED);
809         final var child1 = dataTreeCandidateNode(childNode, childNode1, WRITE);
810         setChildNodes(node1, List.of(child1));
811         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
812
813         final var node2 = dataTreeCandidateNode(parentNode1, null, DISAPPEARED);
814         final var child2 = dataTreeCandidateNode(childNode1, null, DELETE);
815         setChildNodes(node2, List.of(child2));
816         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
817
818         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
819
820         assertEquals(DISAPPEARED, aggregationResult.getRootNode().modificationType());
821     }
822
823     @Test
824     void testAppearedUnmodified() {
825         final var parentNode1 = normalizedNode("container");
826         final var childNode1 = normalizedNode("child1");
827
828         final var node1 = dataTreeCandidateNode(null, parentNode1, APPEARED);
829         final var child1 = dataTreeCandidateNode(null, childNode1, WRITE);
830         setChildNodes(node1, List.of(child1));
831         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
832
833         final var node2 = dataTreeCandidateNode(parentNode1, parentNode1, UNMODIFIED);
834         final var child2 = dataTreeCandidateNode(childNode1, childNode1, UNMODIFIED);
835         setChildNodes(node2, List.of(child2));
836         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
837
838         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
839
840         assertEquals(APPEARED, aggregationResult.getRootNode().modificationType());
841     }
842
843     @Test
844     void testAppearedDelete() {
845         final var parentNode1 = normalizedNode("container");
846         final var childNode1 = normalizedNode("child1");
847
848         final var node1 = dataTreeCandidateNode(null, parentNode1, APPEARED);
849         final var child1 = dataTreeCandidateNode(null, childNode1, WRITE);
850         setChildNodes(node1, List.of(child1));
851         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
852
853         final var node2 = dataTreeCandidateNode(parentNode1, null, DELETE);
854         final var child2 = dataTreeCandidateNode(childNode1, null, DELETE);
855         setChildNodes(node2, List.of(child2));
856         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
857
858         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
859
860         assertEquals(UNMODIFIED, aggregationResult.getRootNode().modificationType());
861     }
862
863     @Test
864     void testAppearedWriteWithoutChanges() {
865         final var parentNode1 = normalizedNode("container");
866         final var parentNode2 = normalizedNode("value2");
867         final var childNode1 = normalizedNode("child1");
868         final var childNode2 = normalizedNode("child2");
869
870         final var node1 = dataTreeCandidateNode(null, parentNode1, APPEARED);
871         final var child1 = dataTreeCandidateNode(null, childNode1, WRITE);
872         setChildNodes(node1, List.of(child1));
873         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
874
875         final var node2 = dataTreeCandidateNode(parentNode1, parentNode2, WRITE);
876         final var child2 = dataTreeCandidateNode(childNode1, childNode2, WRITE);
877         setChildNodes(node2, List.of(child2));
878         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
879
880         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
881
882         assertEquals(WRITE, aggregationResult.getRootNode().modificationType());
883     }
884
885     @Test
886     void testAppearedSubtreeModified() {
887         final var parentNode1 = normalizedNode("container");
888         final var childNode1 = normalizedNode("child1");
889         final var childNode2 = normalizedNode("child2");
890
891         final var node1 = dataTreeCandidateNode(null, parentNode1, APPEARED);
892         final var child1 = dataTreeCandidateNode(null, childNode1, WRITE);
893         setChildNodes(node1, List.of(child1));
894         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
895
896         final var node2 = dataTreeCandidateNode(parentNode1, parentNode1, SUBTREE_MODIFIED);
897         final var child2 = dataTreeCandidateNode(childNode1, childNode2, WRITE);
898         setChildNodes(node2, List.of(child2));
899         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
900
901         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
902
903         assertEquals(APPEARED, aggregationResult.getRootNode().modificationType());
904     }
905
906     @Test
907     void testAppearedAppeared() {
908         final var parentNode1 = normalizedNode("container");
909         final var childNode1 = normalizedNode("child1");
910
911         final var node1 = dataTreeCandidateNode(null, parentNode1, APPEARED);
912         final var child1 = dataTreeCandidateNode(null, childNode1, WRITE);
913         setChildNodes(node1, List.of(child1));
914         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
915
916         final var node2 = dataTreeCandidateNode(null, parentNode1, APPEARED);
917         final var child2 = dataTreeCandidateNode(null, childNode1, WRITE);
918         setChildNodes(node2, List.of(child2));
919         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
920
921         assertThrows(IllegalArgumentException.class,
922             () -> DataTreeCandidates.aggregate(List.of(candidate1, candidate2)));
923     }
924
925     @Test
926     void testAppearedDisappeared() {
927         final var parentNode1 = normalizedNode("container");
928         final var childNode1 = normalizedNode("child1");
929
930         final var node1 = dataTreeCandidateNode(null, parentNode1, APPEARED);
931         final var child1 = dataTreeCandidateNode(null, childNode1, WRITE);
932         setChildNodes(node1, List.of(child1));
933         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
934
935         final var node2 = dataTreeCandidateNode(parentNode1, null, DISAPPEARED);
936         final var child2 = dataTreeCandidateNode(childNode1, null, DELETE);
937         setChildNodes(node2, List.of(child2));
938         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
939
940         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
941
942         assertEquals(UNMODIFIED, aggregationResult.getRootNode().modificationType());
943     }
944
945     @Test
946     void testDisappearedUnmodified() {
947         final var parentNode1 = normalizedNode("container");
948         final var childNode1 = normalizedNode("child1");
949
950         final var node1 = dataTreeCandidateNode(parentNode1, null, DISAPPEARED);
951         final var child1 = dataTreeCandidateNode(childNode1, null, DELETE);
952         setChildNodes(node1, List.of(child1));
953         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
954
955         final var node2 = dataTreeCandidateNode(null, null, UNMODIFIED);
956         final var child2 = dataTreeCandidateNode(null, null, UNMODIFIED);
957         setChildNodes(node2, List.of(child2));
958         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
959
960         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
961
962         assertEquals(DISAPPEARED, aggregationResult.getRootNode().modificationType());
963     }
964
965     @Test
966     void testDisappearedDelete() {
967         final var parentNode1 = normalizedNode("container");
968         final var childNode1 = normalizedNode("child1");
969
970         final var node1 = dataTreeCandidateNode(parentNode1, null, DISAPPEARED);
971         final var child1 = dataTreeCandidateNode(childNode1, null, DELETE);
972         setChildNodes(node1, List.of(child1));
973         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
974
975         final var node2 = dataTreeCandidateNode(null, null, DELETE);
976         final var child2 = dataTreeCandidateNode(null, null, DELETE);
977         setChildNodes(node2, List.of(child2));
978         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
979
980         assertThrows(IllegalArgumentException.class,
981             () -> DataTreeCandidates.aggregate(List.of(candidate1, candidate2)));
982     }
983
984     @Test
985     void testDisappearedWrite() {
986         final var parentNode1 = normalizedNode("container1");
987         final var parentNode2 = normalizedNode("container2");
988         final var childNode1 = normalizedNode("child1");
989         final var childNode2 = normalizedNode("child2");
990
991         final var node1 = dataTreeCandidateNode(parentNode1, null, DISAPPEARED);
992         final var child1 = dataTreeCandidateNode(childNode1, null, DELETE);
993         setChildNodes(node1, List.of(child1));
994         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
995
996         final var node2 = dataTreeCandidateNode(null, parentNode2, WRITE);
997         final var child2 = dataTreeCandidateNode(null, childNode2, WRITE);
998         setChildNodes(node2, List.of(child2));
999         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
1000
1001         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
1002
1003         assertEquals(WRITE, aggregationResult.getRootNode().modificationType());
1004     }
1005
1006     @Test
1007     void testDisappearedSubtreeModified() {
1008         final var parentNode1 = normalizedNode("container");
1009         final var childNode1 = normalizedNode("child1");
1010         final var childNode2 = normalizedNode("child2");
1011
1012         final var node1 = dataTreeCandidateNode(parentNode1, null, DISAPPEARED);
1013         final var child1 = dataTreeCandidateNode(childNode1, null, DELETE);
1014         setChildNodes(node1, List.of(child1));
1015         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
1016
1017         final var node2 = dataTreeCandidateNode(null, null, SUBTREE_MODIFIED);
1018         final var child2 = dataTreeCandidateNode(null, childNode2, WRITE);
1019         setChildNodes(node2, List.of(child2));
1020         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
1021
1022         assertThrows(IllegalArgumentException.class,
1023             () -> DataTreeCandidates.aggregate(List.of(candidate1, candidate2)));
1024     }
1025
1026     @Test
1027     void testDisappearedAppeared() {
1028         final var parentNode1 = normalizedNode("container");
1029         final var parentNode2 = normalizedNode("container");
1030         final var childNode1 = normalizedNode("child1");
1031         final var childNode2 = normalizedNode("child2");
1032
1033         final var node1 = dataTreeCandidateNode(parentNode1, null, DISAPPEARED);
1034         final var child1 = dataTreeCandidateNode(childNode1, null, DELETE);
1035         setChildNodes(node1, List.of(child1));
1036         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
1037
1038         final var node2 = dataTreeCandidateNode(null, parentNode2, APPEARED);
1039         final var child2 = dataTreeCandidateNode(null, childNode2, WRITE);
1040         setChildNodes(node2, List.of(child2));
1041         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
1042
1043         final var aggregationResult = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
1044
1045         assertEquals(SUBTREE_MODIFIED, aggregationResult.getRootNode().modificationType());
1046     }
1047
1048     @Test
1049     void testDisappearedDisappear() {
1050         final var parentNode1 = normalizedNode("container");
1051         final var childNode1 = normalizedNode("child1");
1052
1053         final var node1 = dataTreeCandidateNode(parentNode1, null, DISAPPEARED);
1054         final var child1 = dataTreeCandidateNode(childNode1, null, DELETE);
1055         setChildNodes(node1, List.of(child1));
1056         final var candidate1 = new DefaultDataTreeCandidate(ROOT_PATH, node1);
1057
1058         final var node2 = dataTreeCandidateNode(null, null, DISAPPEARED);
1059         final var child2 = dataTreeCandidateNode(null, null, DELETE);
1060         setChildNodes(node2, List.of(child2));
1061         final var candidate2 = new DefaultDataTreeCandidate(ROOT_PATH, node2);
1062
1063         assertThrows(IllegalArgumentException.class,
1064             () -> DataTreeCandidates.aggregate(List.of(candidate1, candidate2)));
1065     }
1066
1067     private static LeafNode<String> normalizedNode(final String value) {
1068         final var node = mock(LeafNode.class);
1069         doReturn(value).when(node).body();
1070         return node;
1071     }
1072
1073     private static TerminalDataTreeCandidateNode dataTreeCandidateNode(final NormalizedNode before,
1074                                                                        final NormalizedNode after,
1075                                                                        final ModificationType modification) {
1076         final var dataTreeCandidateNode = mock(TerminalDataTreeCandidateNode.class);
1077         doReturn(null).when(dataTreeCandidateNode).name();
1078         doReturn(before).when(dataTreeCandidateNode).dataBefore();
1079         doReturn(after).when(dataTreeCandidateNode).dataAfter();
1080         doReturn(modification).when(dataTreeCandidateNode).modificationType();
1081         return dataTreeCandidateNode;
1082     }
1083
1084     private static void setChildNodes(final TerminalDataTreeCandidateNode parentNode,
1085                                       final List<DataTreeCandidateNode> childNodes) {
1086         doReturn(null).when(parentNode).name();
1087         childNodes.forEach(child -> doReturn(CHILD_ID).when(child).name());
1088         doReturn(childNodes).when(parentNode).childNodes();
1089     }
1090 }