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