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