1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle.utils;
21
22 import static com.google.common.truth.Truth.assertWithMessage;
23 import static com.puppycrawl.tools.checkstyle.AbstractPathTestSupport.addEndOfLine;
24 import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.getExpectedThrowable;
25 import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.isUtilsClassHasPrivateConstructor;
26 import static com.puppycrawl.tools.checkstyle.utils.XpathUtil.getTextAttributeValue;
27
28 import java.io.File;
29 import java.io.IOException;
30 import java.nio.charset.StandardCharsets;
31 import java.nio.file.Files;
32 import java.util.List;
33 import java.util.UUID;
34
35 import org.junit.jupiter.api.Test;
36 import org.junit.jupiter.api.io.TempDir;
37
38 import com.puppycrawl.tools.checkstyle.DetailAstImpl;
39 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
40 import com.puppycrawl.tools.checkstyle.api.DetailAST;
41 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
42 import com.puppycrawl.tools.checkstyle.xpath.AbstractNode;
43 import com.puppycrawl.tools.checkstyle.xpath.RootNode;
44
45 public class XpathUtilTest {
46
47 @TempDir
48 public File tempFolder;
49
50 @Test
51 public void testIsProperUtilsClass() throws ReflectiveOperationException {
52 assertWithMessage("Constructor is not private")
53 .that(isUtilsClassHasPrivateConstructor(XpathUtil.class))
54 .isTrue();
55 }
56
57 @Test
58 public void testSupportsTextAttribute() {
59 assertWithMessage("Should return true for supported token types")
60 .that(XpathUtil.supportsTextAttribute(createDetailAST(TokenTypes.IDENT)))
61 .isTrue();
62 assertWithMessage("Should return true for supported token types")
63 .that(XpathUtil.supportsTextAttribute(createDetailAST(TokenTypes.NUM_INT)))
64 .isTrue();
65 assertWithMessage("Should return true for supported token types")
66 .that(XpathUtil.supportsTextAttribute(createDetailAST(TokenTypes.STRING_LITERAL)))
67 .isTrue();
68 assertWithMessage("Should return true for supported token types")
69 .that(XpathUtil.supportsTextAttribute(createDetailAST(TokenTypes.CHAR_LITERAL)))
70 .isTrue();
71 assertWithMessage("Should return true for supported token types")
72 .that(XpathUtil.supportsTextAttribute(createDetailAST(TokenTypes.NUM_DOUBLE)))
73 .isTrue();
74 assertWithMessage("Should return false for unsupported token types")
75 .that(XpathUtil.supportsTextAttribute(createDetailAST(TokenTypes.VARIABLE_DEF)))
76 .isFalse();
77 assertWithMessage("Should return false for unsupported token types")
78 .that(XpathUtil.supportsTextAttribute(createDetailAST(TokenTypes.OBJBLOCK)))
79 .isFalse();
80 assertWithMessage("Should return true for supported token types")
81 .that(XpathUtil.supportsTextAttribute(createDetailAST(TokenTypes.LITERAL_CHAR)))
82 .isFalse();
83 }
84
85 @Test
86 public void testGetValue() {
87 assertWithMessage("Returned value differs from expected")
88 .that(getTextAttributeValue(
89 createDetailAST(TokenTypes.STRING_LITERAL, "\"HELLO WORLD\"")))
90 .isEqualTo("HELLO WORLD");
91 assertWithMessage("Returned value differs from expected")
92 .that(getTextAttributeValue(createDetailAST(TokenTypes.NUM_INT, "123")))
93 .isEqualTo("123");
94 assertWithMessage("Returned value differs from expected")
95 .that(getTextAttributeValue(createDetailAST(TokenTypes.IDENT, "HELLO WORLD")))
96 .isEqualTo("HELLO WORLD");
97 assertWithMessage("Returned value differs from expected")
98 .that(getTextAttributeValue(createDetailAST(TokenTypes.STRING_LITERAL, "HELLO WORLD")))
99 .isNotEqualTo("HELLO WORLD");
100 }
101
102 @Test
103 public void testPrintXpathNotComment() throws Exception {
104 final String fileContent = "class Test { public void method() {int a = 5;}}";
105 final String uniqueFileName = "junit_" + UUID.randomUUID() + ".java";
106 final File file = new File(tempFolder, uniqueFileName);
107 Files.writeString(file.toPath(), fileContent, StandardCharsets.UTF_8);
108 final String expected = addEndOfLine(
109 "COMPILATION_UNIT -> COMPILATION_UNIT [1:1]",
110 "`--CLASS_DEF -> CLASS_DEF [1:1]",
111 " `--OBJBLOCK -> OBJBLOCK [1:12]",
112 " |--METHOD_DEF -> METHOD_DEF [1:14]",
113 " | `--SLIST -> { [1:35]",
114 " | |--VARIABLE_DEF -> VARIABLE_DEF [1:36]",
115 " | | |--IDENT -> a [1:40]");
116 final String result = XpathUtil.printXpathBranch(
117 "//CLASS_DEF//METHOD_DEF//VARIABLE_DEF//IDENT", file);
118 assertWithMessage("Branch string is different")
119 .that(result)
120 .isEqualTo(expected);
121 }
122
123 @Test
124 public void testPrintXpathComment() throws Exception {
125 final String fileContent = "class Test { /* comment */ }";
126 final String uniqueFileName = "junit_" + UUID.randomUUID() + ".java";
127 final File file = new File(tempFolder, uniqueFileName);
128 Files.writeString(file.toPath(), fileContent, StandardCharsets.UTF_8);
129 final String expected = addEndOfLine(
130 "COMPILATION_UNIT -> COMPILATION_UNIT [1:1]",
131 "`--CLASS_DEF -> CLASS_DEF [1:1]",
132 " `--OBJBLOCK -> OBJBLOCK [1:12]",
133 " |--BLOCK_COMMENT_BEGIN -> /* [1:14]");
134 final String result = XpathUtil.printXpathBranch(
135 "//CLASS_DEF//BLOCK_COMMENT_BEGIN", file);
136 assertWithMessage("Branch string is different")
137 .that(result)
138 .isEqualTo(expected);
139 }
140
141 @Test
142 public void testPrintXpathTwo() throws Exception {
143 final String fileContent = "class Test { public void method() {int a = 5; int b = 5;}}";
144 final String uniqueFileName = "junit_" + UUID.randomUUID() + ".java";
145 final File file = new File(tempFolder, uniqueFileName);
146 Files.writeString(file.toPath(), fileContent, StandardCharsets.UTF_8);
147 final String expected = addEndOfLine(
148 "COMPILATION_UNIT -> COMPILATION_UNIT [1:1]",
149 "`--CLASS_DEF -> CLASS_DEF [1:1]",
150 " `--OBJBLOCK -> OBJBLOCK [1:12]",
151 " |--METHOD_DEF -> METHOD_DEF [1:14]",
152 " | `--SLIST -> { [1:35]",
153 " | |--VARIABLE_DEF -> VARIABLE_DEF [1:36]",
154 " | | |--IDENT -> a [1:40]",
155 "---------",
156 "COMPILATION_UNIT -> COMPILATION_UNIT [1:1]",
157 "`--CLASS_DEF -> CLASS_DEF [1:1]",
158 " `--OBJBLOCK -> OBJBLOCK [1:12]",
159 " |--METHOD_DEF -> METHOD_DEF [1:14]",
160 " | `--SLIST -> { [1:35]",
161 " | |--VARIABLE_DEF -> VARIABLE_DEF [1:47]",
162 " | | |--IDENT -> b [1:51]");
163 final String result = XpathUtil.printXpathBranch(
164 "//CLASS_DEF//METHOD_DEF//VARIABLE_DEF//IDENT", file);
165 assertWithMessage("Branch string is different")
166 .that(result)
167 .isEqualTo(expected);
168 }
169
170 @Test
171 public void testInvalidXpath() throws IOException {
172 final String fileContent = "class Test { public void method() {int a = 5; int b = 5;}}";
173 final String uniqueFileName = "junit_" + UUID.randomUUID() + ".java";
174 final File file = new File(tempFolder, uniqueFileName);
175 Files.writeString(file.toPath(), fileContent, StandardCharsets.UTF_8);
176 final String invalidXpath = "\\//CLASS_DEF"
177 + "//METHOD_DEF//VARIABLE_DEF//IDENT";
178 final CheckstyleException exc = getExpectedThrowable(CheckstyleException.class, () -> {
179 XpathUtil.printXpathBranch(invalidXpath, file);
180 });
181
182 final String expectedMessage =
183 "Error during evaluation for xpath: " + invalidXpath
184 + ", file: " + file.getCanonicalPath();
185 assertWithMessage("Exception message is different")
186 .that(exc.getMessage())
187 .isEqualTo(expectedMessage);
188 }
189
190 @Test
191 public void testCreateChildren() {
192 final DetailAstImpl rootAst = new DetailAstImpl();
193 final DetailAstImpl elementAst = new DetailAstImpl();
194 rootAst.addChild(elementAst);
195 final RootNode rootNode = new RootNode(rootAst);
196 final List<AbstractNode> children =
197 XpathUtil.createChildren(rootNode, rootNode, elementAst);
198
199 assertWithMessage("Expected one child node")
200 .that(children)
201 .hasSize(1);
202 assertWithMessage("Node depth should be 1")
203 .that(children.getFirst().getDepth())
204 .isEqualTo(1);
205 }
206
207 private static DetailAST createDetailAST(int type) {
208 final DetailAstImpl detailAST = new DetailAstImpl();
209 detailAST.setType(type);
210 return detailAST;
211 }
212
213 private static DetailAST createDetailAST(int type, String text) {
214 final DetailAstImpl detailAST = new DetailAstImpl();
215 detailAST.setType(type);
216 detailAST.setText(text);
217 return detailAST;
218 }
219 }