View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2026 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ///////////////////////////////////////////////////////////////////////////////////////////////
19  
20  package com.puppycrawl.tools.checkstyle.xpath;
21  
22  import static com.google.common.truth.Truth.assertWithMessage;
23  import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.getExpectedThrowable;
24  import static com.puppycrawl.tools.checkstyle.utils.XpathUtil.getXpathItems;
25  
26  import java.io.File;
27  import java.util.List;
28  
29  import org.junit.jupiter.api.BeforeEach;
30  import org.junit.jupiter.api.Test;
31  
32  import com.puppycrawl.tools.checkstyle.AbstractPathTestSupport;
33  import com.puppycrawl.tools.checkstyle.DetailAstImpl;
34  import com.puppycrawl.tools.checkstyle.JavaParser;
35  import com.puppycrawl.tools.checkstyle.api.DetailAST;
36  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
37  import net.sf.saxon.om.AxisInfo;
38  import net.sf.saxon.om.NodeInfo;
39  import net.sf.saxon.tree.iter.AxisIterator;
40  import net.sf.saxon.tree.iter.EmptyIterator;
41  
42  public class RootNodeTest extends AbstractPathTestSupport {
43  
44      private static RootNode rootNode;
45  
46      @Override
47      public String getPackageLocation() {
48          return "com/puppycrawl/tools/checkstyle/xpath/xpathmapper";
49      }
50  
51      @BeforeEach
52      public void init() throws Exception {
53          final File file = new File(getPath("InputXpathMapperAst.java"));
54          final DetailAST rootAst = JavaParser.parseFile(file, JavaParser.Options.WITHOUT_COMMENTS);
55          rootNode = new RootNode(rootAst);
56      }
57  
58      @Test
59      public void testCompareOrder() {
60          final UnsupportedOperationException exc =
61                  getExpectedThrowable(UnsupportedOperationException.class, () -> {
62                      rootNode.compareOrder(null);
63                  });
64          assertWithMessage("Invalid exception message")
65              .that(exc.getMessage())
66              .isEqualTo("Operation is not supported");
67      }
68  
69      @Test
70      public void testXpath() throws Exception {
71          final String xpath = "/";
72          final List<NodeInfo> nodes = getXpathItems(xpath, rootNode);
73          assertWithMessage("Invalid number of nodes")
74              .that(nodes)
75              .hasSize(1);
76          final NodeInfo firstNode = nodes.getFirst();
77          assertWithMessage("Should return true, because selected node is RootNode")
78                  .that(firstNode)
79                  .isInstanceOf(RootNode.class);
80          assertWithMessage("Result node should have same reference as expected")
81              .that(rootNode)
82              .isEqualTo(firstNode);
83      }
84  
85      @Test
86      public void testGetDepth() {
87          assertWithMessage("Root node depth should be 0")
88                  .that(rootNode.getDepth())
89                  .isEqualTo(0);
90      }
91  
92      @Test
93      public void testGetTokenType() {
94          assertWithMessage("Invalid token type")
95              .that(rootNode.getTokenType())
96              .isEqualTo(TokenTypes.COMPILATION_UNIT);
97      }
98  
99      @Test
100     public void testGetLineNumber() {
101         assertWithMessage("Invalid line number")
102             .that(rootNode.getLineNumber())
103             .isEqualTo(1);
104     }
105 
106     @Test
107     public void testGetColumnNumber() {
108         assertWithMessage("Invalid column number")
109             .that(rootNode.getColumnNumber())
110             .isEqualTo(0);
111     }
112 
113     /*
114      * This test exists to cover pitest mutation.
115      * It is impossible to create RootNode that does not have column as 0.
116      * Test exists until https://github.com/checkstyle/checkstyle/issues/4997
117      */
118     @Test
119     public void testNonRealGetColumnNumber() {
120         final DetailAstImpl nonRealNode = new DetailAstImpl();
121         nonRealNode.setType(TokenTypes.PACKAGE_DEF);
122         nonRealNode.setLineNo(555);
123         nonRealNode.setColumnNo(888);
124 
125         final RootNode nonRealRootNode = new RootNode(nonRealNode);
126         assertWithMessage("Invalid column number")
127             .that(nonRealRootNode.getColumnNumber())
128             .isEqualTo(888);
129     }
130 
131     @Test
132     public void testGetLocalPart() {
133         assertWithMessage("Invalid local part")
134             .that(rootNode.getLocalPart())
135             .isEqualTo("ROOT");
136     }
137 
138     @Test
139     public void testIterate() {
140         try (AxisIterator following = rootNode.iterateAxis(AxisInfo.FOLLOWING)) {
141             assertWithMessage("Result iterator does not match expected")
142                 .that(following)
143                 .isEqualTo(EmptyIterator.ofNodes());
144         }
145         try (AxisIterator followingSibling = rootNode.iterateAxis(AxisInfo.FOLLOWING_SIBLING)) {
146             assertWithMessage("Result iterator does not match expected")
147                 .that(followingSibling)
148                 .isEqualTo(EmptyIterator.ofNodes());
149         }
150         try (AxisIterator preceding = rootNode.iterateAxis(AxisInfo.PRECEDING)) {
151             assertWithMessage("Result iterator does not match expected")
152                 .that(preceding)
153                 .isEqualTo(EmptyIterator.ofNodes());
154         }
155         try (AxisIterator precedingSibling = rootNode.iterateAxis(AxisInfo.PRECEDING_SIBLING)) {
156             assertWithMessage("Result iterator does not match expected")
157                 .that(precedingSibling)
158                 .isEqualTo(EmptyIterator.ofNodes());
159         }
160         try (AxisIterator parent = rootNode.iterateAxis(AxisInfo.PARENT)) {
161             assertWithMessage("Result iterator does not match expected")
162                 .that(parent)
163                 .isEqualTo(EmptyIterator.ofNodes());
164         }
165         try (AxisIterator parentNull = rootNode.iterateAxis(AxisInfo.PARENT, null)) {
166             assertWithMessage("Result iterator does not match expected")
167                 .that(parentNull)
168                 .isEqualTo(EmptyIterator.ofNodes());
169         }
170     }
171 
172     @Test
173     public void testRootWithNullDetailAst() {
174         final RootNode emptyRootNode = new RootNode(null);
175         assertWithMessage("Empty node should not have children")
176                 .that(emptyRootNode.hasChildNodes())
177                 .isFalse();
178 
179         try (AxisIterator iterator = emptyRootNode.iterateAxis(AxisInfo.DESCENDANT)) {
180             assertWithMessage("Result iterator does not match expected")
181                 .that(iterator)
182                 .isEqualTo(EmptyIterator.ofNodes());
183         }
184         try (AxisIterator iterator = emptyRootNode.iterateAxis(AxisInfo.CHILD)) {
185             assertWithMessage("Result iterator does not match expected")
186                 .that(iterator)
187                 .isEqualTo(EmptyIterator.ofNodes());
188         }
189     }
190 
191     @Test
192     public void testGetStringValue() {
193         final UnsupportedOperationException exc =
194                 getExpectedThrowable(UnsupportedOperationException.class, rootNode::getStringValue);
195         assertWithMessage("Invalid exception message")
196             .that(exc.getMessage())
197             .isEqualTo("Operation is not supported");
198     }
199 
200     @Test
201     public void testGetAttributeValue() {
202         final UnsupportedOperationException exc =
203                 getExpectedThrowable(UnsupportedOperationException.class, () -> {
204                     rootNode.getAttributeValue("", "");
205                 });
206         assertWithMessage("Invalid exception message")
207             .that(exc.getMessage())
208             .isEqualTo("Operation is not supported");
209     }
210 
211     @Test
212     public void testGetDeclaredNamespaces() {
213         final UnsupportedOperationException exc =
214                 getExpectedThrowable(UnsupportedOperationException.class, () -> {
215                     rootNode.getDeclaredNamespaces(null);
216                 });
217         assertWithMessage("Invalid exception message")
218             .that(exc.getMessage())
219             .isEqualTo("Operation is not supported");
220     }
221 
222     @Test
223     public void testIsId() {
224         final UnsupportedOperationException exc =
225                 getExpectedThrowable(UnsupportedOperationException.class, rootNode::isId);
226         assertWithMessage("Invalid exception message")
227             .that(exc.getMessage())
228             .isEqualTo("Operation is not supported");
229     }
230 
231     @Test
232     public void testIsIdref() {
233         final UnsupportedOperationException exc =
234                 getExpectedThrowable(UnsupportedOperationException.class, rootNode::isIdref);
235         assertWithMessage("Invalid exception message")
236             .that(exc.getMessage())
237             .isEqualTo("Operation is not supported");
238     }
239 
240     @Test
241     public void testIsNilled() {
242         final UnsupportedOperationException exc =
243                 getExpectedThrowable(UnsupportedOperationException.class, rootNode::isNilled);
244         assertWithMessage("Invalid exception message")
245             .that(exc.getMessage())
246             .isEqualTo("Operation is not supported");
247     }
248 
249     @Test
250     public void testIsStreamed() {
251         final UnsupportedOperationException exc =
252                 getExpectedThrowable(UnsupportedOperationException.class, rootNode::isStreamed);
253         assertWithMessage("Invalid exception message")
254             .that(exc.getMessage())
255             .isEqualTo("Operation is not supported");
256     }
257 
258     @Test
259     public void testGetConfiguration() {
260         final UnsupportedOperationException exc =
261                 getExpectedThrowable(UnsupportedOperationException.class,
262                         rootNode::getConfiguration);
263         assertWithMessage("Invalid exception message")
264             .that(exc.getMessage())
265             .isEqualTo("Operation is not supported");
266     }
267 
268     @Test
269     public void testSetSystemId() {
270         final UnsupportedOperationException exc =
271                 getExpectedThrowable(UnsupportedOperationException.class, () -> {
272                     rootNode.setSystemId("1");
273                 });
274         assertWithMessage("Invalid exception message")
275             .that(exc.getMessage())
276             .isEqualTo("Operation is not supported");
277     }
278 
279     @Test
280     public void testGetSystemId() {
281         final UnsupportedOperationException exc =
282                 getExpectedThrowable(UnsupportedOperationException.class, rootNode::getSystemId);
283         assertWithMessage("Invalid exception message")
284             .that(exc.getMessage())
285             .isEqualTo("Operation is not supported");
286     }
287 
288     @Test
289     public void testGetPublicId() {
290         final UnsupportedOperationException exc =
291                 getExpectedThrowable(UnsupportedOperationException.class, rootNode::getPublicId);
292         assertWithMessage("Invalid exception message")
293             .that(exc.getMessage())
294             .isEqualTo("Operation is not supported");
295     }
296 
297     @Test
298     public void testBaseUri() {
299         final UnsupportedOperationException exc =
300                 getExpectedThrowable(UnsupportedOperationException.class, rootNode::getBaseURI);
301         assertWithMessage("Invalid exception message")
302             .that(exc.getMessage())
303             .isEqualTo("Operation is not supported");
304     }
305 
306     @Test
307     public void testSaveLocation() {
308         final UnsupportedOperationException exc =
309                 getExpectedThrowable(UnsupportedOperationException.class, rootNode::saveLocation);
310         assertWithMessage("Invalid exception message")
311             .that(exc.getMessage())
312             .isEqualTo("Operation is not supported");
313     }
314 
315     @Test
316     public void testGetStringValueCs() {
317         final UnsupportedOperationException exc =
318                 getExpectedThrowable(UnsupportedOperationException.class,
319                         rootNode::getUnicodeStringValue);
320         assertWithMessage("Invalid exception message")
321             .that(exc.getMessage())
322             .isEqualTo("Operation is not supported");
323     }
324 
325     @Test
326     public void testFingerprint() {
327         final UnsupportedOperationException exc =
328                 getExpectedThrowable(UnsupportedOperationException.class, rootNode::getFingerprint);
329         assertWithMessage("Invalid exception message")
330             .that(exc.getMessage())
331             .isEqualTo("Operation is not supported");
332     }
333 
334     @Test
335     public void testGetDisplayName() {
336         final UnsupportedOperationException exc =
337                 getExpectedThrowable(UnsupportedOperationException.class, rootNode::getDisplayName);
338         assertWithMessage("Invalid exception message")
339             .that(exc.getMessage())
340             .isEqualTo("Operation is not supported");
341     }
342 
343     @Test
344     public void testGetPrefix() {
345         final UnsupportedOperationException exc =
346                 getExpectedThrowable(UnsupportedOperationException.class, rootNode::getPrefix);
347         assertWithMessage("Invalid exception message")
348             .that(exc.getMessage())
349             .isEqualTo("Operation is not supported");
350     }
351 
352     @Test
353     public void testGetSchemaType() {
354         final UnsupportedOperationException exc =
355                 getExpectedThrowable(UnsupportedOperationException.class, rootNode::getSchemaType);
356         assertWithMessage("Invalid exception message")
357             .that(exc.getMessage())
358             .isEqualTo("Operation is not supported");
359     }
360 
361     @Test
362     public void testAtomize() {
363         final UnsupportedOperationException exc =
364                 getExpectedThrowable(UnsupportedOperationException.class, rootNode::atomize);
365         assertWithMessage("Invalid exception message")
366             .that(exc.getMessage())
367             .isEqualTo("Operation is not supported");
368     }
369 
370     @Test
371     public void testGenerateId() {
372         final UnsupportedOperationException exc =
373                 getExpectedThrowable(UnsupportedOperationException.class, () -> {
374                     rootNode.generateId(null);
375                 });
376         assertWithMessage("Invalid exception message")
377             .that(exc.getMessage())
378             .isEqualTo("Operation is not supported");
379     }
380 
381     @Test
382     public void testCopy() {
383         final UnsupportedOperationException exc =
384                 getExpectedThrowable(UnsupportedOperationException.class, () -> {
385                     rootNode.copy(null, -1, null);
386                 });
387         assertWithMessage("Invalid exception message")
388             .that(exc.getMessage())
389             .isEqualTo("Operation is not supported");
390     }
391 
392     @Test
393     public void testGetAllNamespaces() {
394         final UnsupportedOperationException exc =
395                 getExpectedThrowable(UnsupportedOperationException.class,
396                         rootNode::getAllNamespaces);
397         assertWithMessage("Invalid exception message")
398             .that(exc.getMessage())
399             .isEqualTo("Operation is not supported");
400     }
401 
402     @Test
403     public void testSameNodeInfo() {
404         assertWithMessage("Should return true, because object is being compared to itself")
405                 .that(rootNode.isSameNodeInfo(rootNode))
406                 .isTrue();
407         assertWithMessage("Should return false, because object does not equal null")
408                 .that(rootNode.isSameNodeInfo(null))
409                 .isFalse();
410     }
411 }