1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.configuration2.tree;
18
19 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import static org.junit.jupiter.api.Assertions.assertFalse;
21 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
22 import static org.junit.jupiter.api.Assertions.assertNotNull;
23 import static org.junit.jupiter.api.Assertions.assertNotSame;
24 import static org.junit.jupiter.api.Assertions.assertNull;
25 import static org.junit.jupiter.api.Assertions.assertSame;
26 import static org.junit.jupiter.api.Assertions.assertThrows;
27 import static org.junit.jupiter.api.Assertions.assertTrue;
28 import static org.mockito.ArgumentMatchers.any;
29 import static org.mockito.ArgumentMatchers.eq;
30 import static org.mockito.Mockito.when;
31
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.Collection;
35 import java.util.Collections;
36 import java.util.HashMap;
37 import java.util.HashSet;
38 import java.util.Iterator;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Set;
42
43 import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
44 import org.junit.jupiter.api.BeforeAll;
45 import org.junit.jupiter.api.BeforeEach;
46 import org.junit.jupiter.api.Test;
47
48
49
50
51 public class TestInMemoryNodeModelTrackedNodes {
52
53 private static final String NEW_FIELD = "newTableField";
54
55
56 private static final String TEST_KEY = "someTestKey";
57
58
59 private static final String SELECTOR_KEY = "tables.table(1)";
60
61
62 private static ImmutableNode root;
63
64
65 private static NodeSelector selector;
66
67
68
69
70
71
72
73 private static void checkedForChangedField(final ImmutableNode nodeFields, final int idx) {
74 assertEquals(NodeStructureHelper.fieldsLength(1), nodeFields.getChildren().size());
75 int childIndex = 0;
76 for (final ImmutableNode field : nodeFields) {
77 final String expName = childIndex == idx ? NEW_FIELD : NodeStructureHelper.field(1, childIndex);
78 checkFieldNode(field, expName);
79 childIndex++;
80 }
81 }
82
83
84
85
86
87
88
89 private static void checkFieldNode(final ImmutableNode nodeField, final String name) {
90 assertEquals("field", nodeField.getNodeName());
91 assertEquals(1, nodeField.getChildren().size());
92 final ImmutableNode nodeName = nodeField.getChildren().get(0);
93 assertEquals("name", nodeName.getNodeName());
94 assertEquals(name, nodeName.getValue());
95 }
96
97
98
99
100
101
102 private static void checkForAddedField(final ImmutableNode nodeFields) {
103 assertEquals(NodeStructureHelper.fieldsLength(1) + 1, nodeFields.getChildren().size());
104 final ImmutableNode nodeField = nodeFields.getChildren().get(NodeStructureHelper.fieldsLength(1));
105 checkFieldNode(nodeField, NEW_FIELD);
106 }
107
108
109
110
111
112
113
114 private static void checkForRemovedField(final ImmutableNode nodeFields, final int idx) {
115 assertEquals(NodeStructureHelper.fieldsLength(1) - 1, nodeFields.getChildren().size());
116 final Set<String> expectedNames = new HashSet<>();
117 final Set<String> actualNames = new HashSet<>();
118 for (int i = 0; i < NodeStructureHelper.fieldsLength(1); i++) {
119 if (idx != i) {
120 expectedNames.add(NodeStructureHelper.field(1, i));
121 }
122 }
123 for (final ImmutableNode field : nodeFields) {
124 final ImmutableNode nodeName = field.getChildren().get(0);
125 actualNames.add(String.valueOf(nodeName.getValue()));
126 }
127 assertEquals(expectedNames, actualNames);
128 }
129
130
131
132
133
134
135 private static NodeKeyResolver<ImmutableNode> createResolver() {
136 final NodeKeyResolver<ImmutableNode> resolver = NodeStructureHelper.createResolverMock();
137 NodeStructureHelper.prepareResolveKeyForQueries(resolver);
138 return resolver;
139 }
140
141
142
143
144
145
146
147 private static void prepareResolverForUpdateKeys(final NodeKeyResolver<ImmutableNode> resolver) {
148 when(resolver.resolveUpdateKey(any(), any(), any(), any())).thenAnswer(invocation -> {
149 final ImmutableNode root = invocation.getArgument(0, ImmutableNode.class);
150 final String key = invocation.getArgument(1, String.class);
151 final TreeData handler = invocation.getArgument(3, TreeData.class);
152 final List<QueryResult<ImmutableNode>> results = DefaultExpressionEngine.INSTANCE.query(root, key, handler);
153 assertEquals(1, results.size());
154 return new NodeUpdateData<>(Collections.singletonMap(results.get(0), invocation.getArgument(2)), null, null, null);
155 });
156 }
157
158 @BeforeAll
159 public static void setUpBeforeClass() throws Exception {
160 root = new ImmutableNode.Builder(1).addChild(NodeStructureHelper.ROOT_TABLES_TREE).create();
161 selector = new NodeSelector(SELECTOR_KEY);
162 }
163
164
165 private InMemoryNodeModel model;
166
167
168
169
170 private void checkReplaceTrackedNode() {
171 final ImmutableNode newNode = new ImmutableNode.Builder().name("newNode").create();
172 model.replaceTrackedNode(selector, newNode);
173 assertSame(newNode, model.getTrackedNode(selector));
174 assertTrue(model.isTrackedNodeDetached(selector));
175 }
176
177
178
179
180
181
182 private void checkTrackChildNodesNoResult(final List<ImmutableNode> queryResult) {
183 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
184 when(resolver.resolveNodeKey(root, TEST_KEY, model.getNodeHandler())).thenReturn(queryResult);
185
186 final TreeData oldData = model.getTreeData();
187
188 assertTrue(model.trackChildNodes(TEST_KEY, resolver).isEmpty());
189 assertSame(oldData, model.getTreeData());
190 }
191
192
193
194
195
196
197 private void checkTrackChildNodeWithCreationInvalidKey(final List<ImmutableNode> queryResult) {
198 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
199 when(resolver.resolveNodeKey(model.getRootNode(), TEST_KEY, model.getNodeHandler())).thenReturn(queryResult);
200
201 assertThrows(ConfigurationRuntimeException.class, () -> model.trackChildNodeWithCreation(TEST_KEY, "someChild", resolver));
202 }
203
204
205
206
207
208
209
210
211 private void prepareNodeKey(final NodeKeyResolver<ImmutableNode> resolver, final ImmutableNode node, final String key) {
212 final Map<ImmutableNode, String> cache = new HashMap<>();
213 when(resolver.nodeKey(node, cache, model.getNodeHandler())).thenReturn(key);
214 }
215
216
217
218
219
220
221 private ImmutableNode fieldsNodeFromModel() {
222 return NodeStructureHelper.nodeForKey(model, "tables/table(1)/fields");
223 }
224
225
226
227
228
229
230 private ImmutableNode fieldsNodeFromTrackedNode() {
231 return NodeStructureHelper.nodeForKey(model.getTrackedNode(selector), "fields");
232 }
233
234
235
236
237
238
239 private void initDetachedNode(final NodeKeyResolver<ImmutableNode> resolver) {
240 model.trackNode(selector, resolver);
241 model.clearTree("tables.table(0)", resolver);
242 }
243
244 @BeforeEach
245 public void setUp() throws Exception {
246 model = new InMemoryNodeModel(root);
247 }
248
249
250
251
252 @Test
253 public void testAddNodesOnDetachedNode() {
254 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
255 NodeStructureHelper.prepareResolveAddKeys(resolver);
256 model.trackNode(selector, resolver);
257 initDetachedNode(resolver);
258 final ImmutableNode rootNode = model.getRootNode();
259 model.addNodes("fields", selector, Collections.singleton(NodeStructureHelper.createFieldNode(NEW_FIELD)), resolver);
260 assertSame(rootNode, model.getRootNode());
261 checkForAddedField(fieldsNodeFromTrackedNode());
262 }
263
264
265
266
267 @Test
268 public void testAddNodesOnTrackedNode() {
269 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
270 NodeStructureHelper.prepareResolveAddKeys(resolver);
271 model.trackNode(selector, resolver);
272 model.addNodes("fields", selector, Collections.singleton(NodeStructureHelper.createFieldNode(NEW_FIELD)), resolver);
273 checkForAddedField(fieldsNodeFromModel());
274 checkForAddedField(fieldsNodeFromTrackedNode());
275 }
276
277
278
279
280 @Test
281 public void testAddPropertyOnDetachedNode() {
282 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
283 NodeStructureHelper.prepareResolveAddKeys(resolver);
284 model.trackNode(selector, resolver);
285 initDetachedNode(resolver);
286 final ImmutableNode rootNode = model.getRootNode();
287 model.addProperty("fields.field(-1).name", selector, Collections.singleton(NEW_FIELD), resolver);
288 assertSame(rootNode, model.getRootNode());
289 checkForAddedField(fieldsNodeFromTrackedNode());
290 }
291
292
293
294
295 @Test
296 public void testAddPropertyOnTrackedNode() {
297 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
298 NodeStructureHelper.prepareResolveAddKeys(resolver);
299 model.trackNode(selector, resolver);
300 model.addProperty("fields.field(-1).name", selector, Collections.singleton(NEW_FIELD), resolver);
301 checkForAddedField(fieldsNodeFromModel());
302 checkForAddedField(fieldsNodeFromTrackedNode());
303 }
304
305
306
307
308 @Test
309 public void testClearPropertyOnDetachedNode() {
310 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
311 initDetachedNode(resolver);
312 final ImmutableNode rootNode = model.getRootNode();
313 model.clearProperty("fields.field(0).name", selector, resolver);
314 assertSame(rootNode, model.getRootNode());
315 final ImmutableNode nodeFields = fieldsNodeFromTrackedNode();
316 checkForRemovedField(nodeFields, 0);
317 }
318
319
320
321
322 @Test
323 public void testClearPropertyOnTrackedNode() {
324 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
325 model.trackNode(selector, resolver);
326 model.clearProperty("fields.field(0).name", selector, resolver);
327 final ImmutableNode nodeFields = fieldsNodeFromModel();
328 checkForRemovedField(nodeFields, 0);
329 }
330
331
332
333
334 @Test
335 public void testClearTreeOnDetachedNode() {
336 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
337 initDetachedNode(resolver);
338 final ImmutableNode rootNode = model.getRootNode();
339 model.clearTree("fields.field(1)", selector, resolver);
340 assertSame(rootNode, model.getRootNode());
341 final ImmutableNode nodeFields = fieldsNodeFromTrackedNode();
342 checkForRemovedField(nodeFields, 1);
343 }
344
345
346
347
348 @Test
349 public void testClearTreeOnTrackedNode() {
350 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
351 model.trackNode(selector, resolver);
352 model.clearTree("fields.field(1)", selector, resolver);
353 final ImmutableNode nodeFields = fieldsNodeFromModel();
354 checkForRemovedField(nodeFields, 1);
355 }
356
357
358
359
360 @Test
361 public void testGetTrackedNodeAfterClear() {
362 final ImmutableNode node = NodeStructureHelper.nodeForKey(model, "tables/table(1)");
363 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
364 model.trackNode(selector, resolver);
365 model.clear(resolver);
366 assertSame(node, model.getTrackedNode(selector));
367 }
368
369
370
371
372 @Test
373 public void testGetTrackedNodeAfterSetRootNode() {
374 final ImmutableNode node = NodeStructureHelper.nodeForKey(model, "tables/table(1)");
375 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
376 model.trackNode(selector, resolver);
377 model.setRootNode(root);
378 assertSame(node, model.getTrackedNode(selector));
379 }
380
381
382
383
384 @Test
385 public void testGetTrackedNodeAfterUpdate() {
386 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
387 model.trackNode(selector, resolver);
388 model.clearProperty("tables.table(1).fields.field(1).name", resolver);
389 final ImmutableNode node = model.getTrackedNode(selector);
390 assertEquals(NodeStructureHelper.table(1), node.getChildren().get(0).getValue());
391 }
392
393
394
395
396 @Test
397 public void testGetTrackedNodeAfterUpdateNoLongerExisting() {
398 final ImmutableNode node = NodeStructureHelper.nodeForKey(model, "tables/table(1)");
399 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
400 initDetachedNode(resolver);
401 assertSame(node, model.getTrackedNode(selector));
402 }
403
404
405
406
407 @Test
408 public void testGetTrackedNodeExisting() {
409 final ImmutableNode node = NodeStructureHelper.nodeForKey(model, "tables/table(1)");
410 model.trackNode(selector, createResolver());
411 assertSame(node, model.getTrackedNode(selector));
412 }
413
414
415
416
417 @Test
418 public void testGetTrackedNodeHandlerActive() {
419 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
420 model.trackNode(selector, resolver);
421 final NodeHandler<ImmutableNode> handler = model.getTrackedNodeHandler(selector);
422 final TrackedNodeHandler tnh = assertInstanceOf(TrackedNodeHandler.class, handler);
423 assertSame(model.getTrackedNode(selector), handler.getRootNode());
424 assertSame(model.getTreeData(), tnh.getParentHandler());
425 }
426
427
428
429
430 @Test
431 public void testGetTrackedNodeHandlerDetached() {
432 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
433 model.trackNode(selector, resolver);
434 initDetachedNode(resolver);
435 final NodeHandler<ImmutableNode> handler = model.getTrackedNodeHandler(selector);
436 assertSame(model.getTrackedNode(selector), handler.getRootNode());
437 assertInstanceOf(TreeData.class, handler);
438 assertNotSame(model.getNodeHandler(), handler);
439 }
440
441
442
443
444 @Test
445 public void testGetTrackedNodeNonExisting() {
446 assertThrows(ConfigurationRuntimeException.class, () -> model.getTrackedNode(selector));
447 }
448
449
450
451
452 @Test
453 public void testIsDetachedAfterClear() {
454 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
455 model.trackNode(selector, resolver);
456 model.clear(resolver);
457 assertTrue(model.isTrackedNodeDetached(selector));
458 }
459
460
461
462
463 @Test
464 public void testIsDetachedAfterSetRoot() {
465 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
466 model.trackNode(selector, resolver);
467 model.clearProperty("tables.table(1).fields.field(1).name", resolver);
468 model.setRootNode(root);
469 assertTrue(model.isTrackedNodeDetached(selector));
470 }
471
472
473
474
475 @Test
476 public void testIsDetachedFalseAfterUpdate() {
477 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
478 model.trackNode(selector, resolver);
479 model.clearProperty("tables.table(1).fields.field(1).name", resolver);
480 assertFalse(model.isTrackedNodeDetached(selector));
481 }
482
483
484
485
486 @Test
487 public void testIsDetachedFalseNoUpdates() {
488 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
489 model.trackNode(selector, resolver);
490 assertFalse(model.isTrackedNodeDetached(selector));
491 }
492
493
494
495
496 @Test
497 public void testIsDetachedTrue() {
498 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
499 initDetachedNode(resolver);
500 assertTrue(model.isTrackedNodeDetached(selector));
501 }
502
503
504
505
506 @Test
507 public void testReplaceTrackedNodeForActiveTrackedNode() {
508 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
509 model.trackNode(selector, resolver);
510 checkReplaceTrackedNode();
511 }
512
513
514
515
516 @Test
517 public void testReplaceTrackedNodeForDetachedNode() {
518 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
519 model.trackNode(selector, resolver);
520 initDetachedNode(resolver);
521 checkReplaceTrackedNode();
522 }
523
524
525
526
527 @Test
528 public void testReplaceTrackedNodeNull() {
529 model.trackNode(selector, createResolver());
530 assertThrows(IllegalArgumentException.class, () -> model.replaceTrackedNode(selector, null));
531 }
532
533
534
535
536 @Test
537 public void testSelectAndTrackNodes() {
538 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
539 final String nodeKey1 = "tables/table(0)";
540 final String nodeKey2 = "tables/table(1)";
541 final ImmutableNode node1 = NodeStructureHelper.nodeForKey(root, nodeKey1);
542 final ImmutableNode node2 = NodeStructureHelper.nodeForKey(root, nodeKey2);
543
544 when(resolver.resolveNodeKey(root, TEST_KEY, model.getNodeHandler())).thenReturn(Arrays.asList(node1, node2));
545 prepareNodeKey(resolver, node1, nodeKey1);
546 prepareNodeKey(resolver, node2, nodeKey2);
547
548 final Collection<NodeSelector> selectors = model.selectAndTrackNodes(TEST_KEY, resolver);
549 final Iterator<NodeSelector> it = selectors.iterator();
550 NodeSelector sel = it.next();
551 assertEquals(new NodeSelector(nodeKey1), sel);
552 assertSame(node1, model.getTrackedNode(sel));
553 sel = it.next();
554 assertEquals(new NodeSelector(nodeKey2), sel);
555 assertSame(node2, model.getTrackedNode(sel));
556 assertFalse(it.hasNext());
557 }
558
559
560
561
562 @Test
563 public void testSelectAndTrackNodesNodeAlreadyTracked() {
564 NodeKeyResolver<ImmutableNode> resolver = createResolver();
565 model.trackNode(selector, resolver);
566 resolver = createResolver();
567 final ImmutableNode node = model.getTrackedNode(selector);
568
569 when(resolver.resolveNodeKey(root, TEST_KEY, model.getNodeHandler())).thenReturn(Collections.singletonList(node));
570 prepareNodeKey(resolver, node, SELECTOR_KEY);
571
572 final Collection<NodeSelector> selectors = model.selectAndTrackNodes(TEST_KEY, resolver);
573 assertEquals(1, selectors.size());
574 assertEquals(selector, selectors.iterator().next());
575 model.untrackNode(selector);
576 assertSame(node, model.getTrackedNode(selector));
577 }
578
579
580
581
582 @Test
583 public void testSelectAndTrackNodesNoSelection() {
584 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
585
586 when(resolver.resolveNodeKey(root, TEST_KEY, model.getNodeHandler())).thenReturn(Collections.<ImmutableNode>emptyList());
587
588 assertTrue(model.selectAndTrackNodes(TEST_KEY, resolver).isEmpty());
589 }
590
591
592
593
594 @Test
595 public void testSetPropertyOnDetachedNode() {
596 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
597 prepareResolverForUpdateKeys(resolver);
598 model.trackNode(selector, resolver);
599 initDetachedNode(resolver);
600 final ImmutableNode rootNode = model.getRootNode();
601 model.setProperty("fields.field(0).name", selector, NEW_FIELD, resolver);
602 assertSame(rootNode, model.getRootNode());
603 checkedForChangedField(fieldsNodeFromTrackedNode(), 0);
604 }
605
606
607
608
609 @Test
610 public void testSetPropertyOnTrackedNode() {
611 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
612 prepareResolverForUpdateKeys(resolver);
613 model.trackNode(selector, resolver);
614 model.setProperty("fields.field(0).name", selector, NEW_FIELD, resolver);
615 checkedForChangedField(fieldsNodeFromModel(), 0);
616 checkedForChangedField(fieldsNodeFromTrackedNode(), 0);
617 }
618
619
620
621
622 @Test
623 public void testTrackChildNodes() {
624 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
625 final ImmutableNode node = NodeStructureHelper.nodeForKey(root, "tables");
626 final String[] keys = new String[node.getChildren().size()];
627
628 for (int i = 0; i < keys.length; i++) {
629 final ImmutableNode child = node.getChildren().get(i);
630 keys[i] = String.format("%s.%s(%d)", node.getNodeName(), child.getNodeName(), i);
631 prepareNodeKey(resolver, child, keys[i]);
632 }
633 when(resolver.resolveNodeKey(root, TEST_KEY, model.getNodeHandler())).thenReturn(Collections.singletonList(node));
634
635 final Collection<NodeSelector> selectors = model.trackChildNodes(TEST_KEY, resolver);
636 assertEquals(node.getChildren().size(), selectors.size());
637 int idx = 0;
638 for (final NodeSelector sel : selectors) {
639 assertEquals(new NodeSelector(keys[idx]), sel);
640 assertEquals(node.getChildren().get(idx), model.getTrackedNode(sel), "Wrong tracked node for " + sel);
641 idx++;
642 }
643 }
644
645
646
647
648 @Test
649 public void testTrackChildNodesMultipleResults() {
650 checkTrackChildNodesNoResult(
651 Arrays.asList(NodeStructureHelper.nodeForKey(root, "tables/table(0)"), NodeStructureHelper.nodeForKey(root, "tables/table(1)")));
652 }
653
654
655
656
657 @Test
658 public void testTrackChildNodesNodeWithNoChildren() {
659 checkTrackChildNodesNoResult(Collections.singletonList(NodeStructureHelper.nodeForKey(root, "tables/table(0)/name")));
660 }
661
662
663
664
665 @Test
666 public void testTrackChildNodesNoResults() {
667 checkTrackChildNodesNoResult(Collections.<ImmutableNode>emptyList());
668 }
669
670
671
672
673 @Test
674 public void testTrackChildNodeWithCreationExisting() {
675 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
676 final String childName = "name";
677 final String parentKey = "tables/table(0)";
678 final String childKey = parentKey + "/" + childName;
679 final ImmutableNode node = NodeStructureHelper.nodeForKey(model, parentKey);
680 final ImmutableNode child = NodeStructureHelper.nodeForKey(node, childName);
681
682 when(resolver.resolveNodeKey(root, TEST_KEY, model.getNodeHandler())).thenReturn(Collections.singletonList(node));
683 prepareNodeKey(resolver, child, childKey);
684
685 final NodeSelector childSelector = model.trackChildNodeWithCreation(TEST_KEY, childName, resolver);
686 assertEquals(new NodeSelector(childKey), childSelector);
687 assertSame(child, model.getTrackedNode(childSelector));
688 }
689
690
691
692
693 @Test
694 public void testTrackChildNodeWithCreationMultipleResults() {
695 final List<ImmutableNode> nodes = Arrays.asList(NodeStructureHelper.nodeForKey(root, "tables/table(0)"),
696 NodeStructureHelper.nodeForKey(root, "tables/table(1)"));
697 checkTrackChildNodeWithCreationInvalidKey(nodes);
698 }
699
700
701
702
703 @Test
704 public void testTrackChildNodeWithCreationNonExisting() {
705 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
706 final String childName = "space";
707 final String parentKey = "tables/table(0)";
708 final String childKey = parentKey + "/" + childName;
709 final ImmutableNode node = NodeStructureHelper.nodeForKey(model, parentKey);
710
711 when(resolver.resolveNodeKey(root, TEST_KEY, model.getNodeHandler())).thenReturn(Collections.singletonList(node));
712 when(resolver.nodeKey(any(), eq(new HashMap<>()), any())).thenReturn(childKey);
713
714 final NodeSelector childSelector = model.trackChildNodeWithCreation(TEST_KEY, childName, resolver);
715 assertEquals(new NodeSelector(childKey), childSelector);
716 final ImmutableNode child = model.getTrackedNode(childSelector);
717 assertEquals(childName, child.getNodeName());
718 assertNull(child.getValue());
719 final ImmutableNode parent = model.getNodeHandler().getParent(child);
720 assertEquals("table", parent.getNodeName());
721 assertEquals(child, NodeStructureHelper.nodeForKey(model, childKey));
722 }
723
724
725
726
727 @Test
728 public void testTrackChildNodeWithCreationNoResults() {
729 checkTrackChildNodeWithCreationInvalidKey(new ArrayList<>());
730 }
731
732
733
734
735
736 @Test
737 public void testTrackedNodeClearedInOperation() {
738 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
739 model.trackNode(selector, resolver);
740 model.clearTree(null, selector, resolver);
741 assertTrue(model.isTrackedNodeDetached(selector));
742 final ImmutableNode node = model.getTrackedNode(selector);
743 assertEquals("table", node.getNodeName());
744 assertFalse(model.getNodeHandler().isDefined(node));
745 }
746
747
748
749
750 @Test
751 public void testTrackNodeKeyMultipleResults() {
752 final NodeSelector nodeSelector = new NodeSelector("tables.table.fields.field.name");
753 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
754 assertThrows(ConfigurationRuntimeException.class, () -> model.trackNode(nodeSelector, resolver));
755 }
756
757
758
759
760 @Test
761 public void testTrackNodeKeyNoResults() {
762 final NodeSelector nodeSelector = new NodeSelector("tables.unknown");
763 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
764 assertThrows(ConfigurationRuntimeException.class, () -> model.trackNode(nodeSelector, resolver));
765 }
766
767
768
769
770 @Test
771 public void testTrackNodeMultipleTimes() {
772 final NodeKeyResolver<ImmutableNode> resolver = createResolver();
773 model.trackNode(selector, resolver);
774 model.trackNode(selector, resolver);
775 model.untrackNode(selector);
776 assertNotNull(model.getTrackedNode(selector));
777 }
778
779
780
781
782 @Test
783 public void testUntrackNode() {
784 model.trackNode(selector, createResolver());
785 model.untrackNode(selector);
786 assertThrows(ConfigurationRuntimeException.class, () -> model.getTrackedNode(selector));
787 }
788
789
790
791
792 @Test
793 public void testUntrackNodeNonExisting() {
794 assertThrows(ConfigurationRuntimeException.class, () -> model.untrackNode(selector));
795 }
796 }