View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
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.assertNull;
21  import static org.junit.jupiter.api.Assertions.assertSame;
22  import static org.junit.jupiter.api.Assertions.assertTrue;
23  import static org.mockito.Mockito.when;
24  
25  import java.util.Collections;
26  import java.util.LinkedList;
27  import java.util.List;
28  
29  import org.apache.commons.configuration2.ConfigurationAssert;
30  import org.junit.jupiter.api.BeforeAll;
31  import org.junit.jupiter.api.Test;
32  
33  /**
34   * Test class for {@code NodeSelector}.
35   */
36  public class TestNodeSelector {
37      /** Constant for a test key. */
38      private static final String KEY = "tables.testKey";
39  
40      /** The root node for query operations. */
41      private static ImmutableNode root;
42  
43      /** A NodeKeyResolver implementation. */
44      private static NodeKeyResolver<ImmutableNode> resolver;
45  
46      /** The node handler object. */
47      private static NodeHandler<ImmutableNode> handler;
48  
49      /**
50       * Creates a {@code NodeKeyResolver} object to be used in the tests. This resolver object uses a
51       * {@code DefaultExpressionEngine} instance for resolving keys. Methods for obtaining add or update data objects are not
52       * implemented.
53       *
54       * @return the {@code NodeKeyResolver}
55       */
56      private static NodeKeyResolver<ImmutableNode> createResolver() {
57          final NodeKeyResolver<ImmutableNode> resolver = NodeStructureHelper.createResolverMock();
58          NodeStructureHelper.prepareResolveKeyForQueries(resolver);
59          return resolver;
60      }
61  
62      @BeforeAll
63      public static void setUpBeforeClass() throws Exception {
64          resolver = createResolver();
65          handler = new InMemoryNodeModel().getNodeHandler();
66          root = new ImmutableNode.Builder(1).addChild(NodeStructureHelper.ROOT_TABLES_TREE).create();
67      }
68  
69      /**
70       * Tests equals() if the expected result is false.
71       */
72      @Test
73      void testEqualsFalse() {
74          final NodeSelector selector = new NodeSelector(KEY);
75          NodeSelector sel2 = new NodeSelector("other" + KEY);
76          ConfigurationAssert.checkEquals(selector, sel2, false);
77          sel2 = new NodeSelector(KEY).subSelector(KEY);
78          ConfigurationAssert.checkEquals(selector, sel2, false);
79      }
80  
81      /**
82       * Tests equals() with other objects.
83       */
84      @Test
85      void testEqualsOtherObjects() {
86          final NodeSelector selector = new NodeSelector(KEY);
87          ConfigurationAssert.checkEquals(selector, null, false);
88          ConfigurationAssert.checkEquals(selector, this, false);
89      }
90  
91      /**
92       * Tests equals() if the expected result is true.
93       */
94      @Test
95      void testEqualsTrue() {
96          final NodeSelector selector = new NodeSelector(KEY);
97          ConfigurationAssert.checkEquals(selector, selector, true);
98          final NodeSelector sel2 = new NodeSelector(KEY);
99          ConfigurationAssert.checkEquals(selector, sel2, true);
100         final NodeSelector sub1 = selector.subSelector("k2");
101         final NodeSelector sub2 = sel2.subSelector("k2");
102         ConfigurationAssert.checkEquals(sub1, sub2, true);
103     }
104 
105     /**
106      * Tests whether attribute results are ignored when evaluating the key.
107      */
108     @Test
109     void testSelectIgnoreAttributeResults() {
110         final NodeKeyResolver<ImmutableNode> resolverMock = NodeStructureHelper.createResolverMock();
111         final List<QueryResult<ImmutableNode>> results = new LinkedList<>();
112         results.add(QueryResult.createAttributeResult(NodeStructureHelper.nodeForKey(root, "tables/table(0)"), "type"));
113         final ImmutableNode target = NodeStructureHelper.nodeForKey(root, "tables/table(1)");
114         results.add(QueryResult.createNodeResult(target));
115         results.add(QueryResult.createAttributeResult(NodeStructureHelper.nodeForKey(root, "tables/table(0)/fields/field(1)"), "type"));
116 
117         when(resolverMock.resolveKey(root, KEY, handler)).thenReturn(results);
118 
119         final NodeSelector selector = new NodeSelector(KEY);
120         assertSame(target, selector.select(root, resolverMock, handler));
121     }
122 
123     /**
124      * Tests a select operation with a key yielding multiple target nodes.
125      */
126     @Test
127     void testSelectMultipleTargets() {
128         final NodeSelector selector = new NodeSelector("tables.table.name");
129         assertNull(selector.select(root, resolver, handler));
130     }
131 
132     /**
133      * Tests a select operation if the key selects an attribute node.
134      */
135     @Test
136     void testSelectSingleAttributeKey() {
137         final NodeKeyResolver<ImmutableNode> resolverMock = NodeStructureHelper.createResolverMock();
138 
139         when(resolverMock.resolveKey(root, KEY, handler)).thenReturn(Collections.singletonList(QueryResult.createAttributeResult(root, KEY)));
140 
141         final NodeSelector selector = new NodeSelector(KEY);
142         assertNull(selector.select(root, resolverMock, handler));
143     }
144 
145     /**
146      * Tests a successful select operation for a single key.
147      */
148     @Test
149     void testSelectSingleKeySuccess() {
150         final NodeSelector selector = new NodeSelector("tables.table(0).name");
151         final ImmutableNode target = selector.select(root, resolver, handler);
152         assertEquals("name", target.getNodeName());
153         assertEquals(NodeStructureHelper.table(0), target.getValue());
154     }
155 
156     /**
157      * Tests a select operation with a sub key.
158      */
159     @Test
160     void testSelectSubKey() {
161         final NodeSelector selectorParent = new NodeSelector("tables.table(0)");
162         final NodeSelector selector = selectorParent.subSelector("fields.field(1).name");
163         final ImmutableNode target = selector.select(root, resolver, handler);
164         assertEquals(NodeStructureHelper.field(0, 1), target.getValue());
165     }
166 
167     /**
168      * Tests a select operation with a sub key which requires complex processing: The first kes produce multiple results;
169      * the final key reduces the result set to a single node.
170      */
171     @Test
172     void testSelectSubKeyComplexEvaluation() {
173         final NodeSelector first = new NodeSelector("tables.table");
174         final NodeSelector second = first.subSelector("fields");
175         final int fldIdx = NodeStructureHelper.fieldsLength(1) - 1;
176         final NodeSelector selector = second.subSelector("field(" + fldIdx + ").name");
177         final ImmutableNode target = selector.select(root, resolver, handler);
178         assertEquals(NodeStructureHelper.field(1, fldIdx), target.getValue());
179     }
180 
181     /**
182      * Tests a select operation with a sub key which produces multiple results.
183      */
184     @Test
185     void testSelectSubKeyMultipleResults() {
186         final NodeSelector selectorParent = new NodeSelector("tables.table");
187         final NodeSelector selector = selectorParent.subSelector("fields.field(1).name");
188         assertNull(selector.select(root, resolver, handler));
189     }
190 
191     /**
192      * Tests select() if a key is used which does not yield any results.
193      */
194     @Test
195     void testSelectSubKeyUnknown() {
196         final NodeSelector selectorParent = new NodeSelector("tables.unknown");
197         final NodeSelector selector = selectorParent.subSelector("fields.field(1).name");
198         assertNull(selector.select(root, resolver, handler));
199     }
200 
201     /**
202      * Tests the string representation.
203      */
204     @Test
205     void testToString() {
206         final String key2 = "anotherSelectionKey";
207         final NodeSelector selector = new NodeSelector(KEY).subSelector(key2);
208         final String s = selector.toString();
209         assertTrue(s.contains(KEY));
210         assertTrue(s.contains(key2));
211     }
212 }