1
2
3
4 package net.sourceforge.pmd;
5
6 import static org.junit.Assert.assertEquals;
7 import static org.junit.Assert.assertFalse;
8 import static org.junit.Assert.assertTrue;
9
10 import java.io.IOException;
11 import java.io.StringWriter;
12 import java.util.Iterator;
13 import java.util.Map;
14
15 import junit.framework.JUnit4TestAdapter;
16 import net.sourceforge.pmd.lang.Language;
17 import net.sourceforge.pmd.lang.LanguageVersion;
18 import net.sourceforge.pmd.lang.ecmascript.ast.ASTFunctionNode;
19 import net.sourceforge.pmd.lang.ecmascript.rule.AbstractEcmascriptRule;
20 import net.sourceforge.pmd.lang.ecmascript.rule.EcmascriptRuleViolationFactory;
21 import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
22 import net.sourceforge.pmd.lang.java.ast.DummyJavaNode;
23 import net.sourceforge.pmd.lang.java.ast.JavaNode;
24 import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
25 import net.sourceforge.pmd.lang.java.rule.JavaRuleViolation;
26 import net.sourceforge.pmd.lang.java.symboltable.SourceFileScope;
27 import net.sourceforge.pmd.lang.rule.MockRule;
28 import net.sourceforge.pmd.renderers.Renderer;
29 import net.sourceforge.pmd.renderers.XMLRenderer;
30 import net.sourceforge.pmd.stat.Metric;
31 import net.sourceforge.pmd.testframework.RuleTst;
32
33 import org.junit.Test;
34
35
36 public class ReportTest extends RuleTst implements ReportListener {
37
38 public static class FooRule extends AbstractJavaRule {
39 public Object visit(ASTClassOrInterfaceDeclaration c, Object ctx) {
40 if ("Foo".equals(c.getImage())) addViolation(ctx, c);
41 return ctx;
42 }
43
44 public String getMessage() {
45 return "blah";
46 }
47
48 public String getName() {
49 return "Foo";
50 }
51
52 public String getRuleSetName() {
53 return "RuleSet";
54 }
55
56 public String getDescription() {
57 return "desc";
58 }
59 }
60
61 private boolean violationSemaphore;
62 private boolean metricSemaphore;
63
64 public void ruleViolationAdded(RuleViolation ruleViolation) {
65 violationSemaphore = true;
66 }
67
68 public void metricAdded(Metric metric) {
69 metricSemaphore = true;
70 }
71
72 @Test
73 public void testBasic() throws Throwable {
74 Report r = new Report();
75 runTestFromString(TEST1, new FooRule(), r);
76 assertFalse(r.isEmpty());
77 }
78
79 @Test
80 public void testMetric0() {
81 Report r = new Report();
82 assertFalse("Default report shouldn't contain metrics", r.hasMetrics());
83 }
84
85 @Test
86 public void testMetric1() {
87 Report r = new Report();
88 assertFalse("Default report shouldn't contain metrics", r.hasMetrics());
89
90 r.addMetric(new Metric("m1", 0, 0.0, 1.0, 2.0, 3.0, 4.0));
91 assertTrue("Expected metrics weren't there", r.hasMetrics());
92
93 Iterator<Metric> ms = r.metrics();
94 assertTrue("Should have some metrics in there now", ms.hasNext());
95
96 Object o = ms.next();
97 assertTrue("Expected Metric, got " + o.getClass(), o instanceof Metric);
98
99 Metric m = (Metric) o;
100 assertEquals("metric name mismatch", "m1", m.getMetricName());
101 assertEquals("wrong low value", 1.0, m.getLowValue(), 0.05);
102 assertEquals("wrong high value", 2.0, m.getHighValue(), 0.05);
103 assertEquals("wrong avg value", 3.0, m.getAverage(), 0.05);
104 assertEquals("wrong std dev value", 4.0, m.getStandardDeviation(), 0.05);
105 }
106
107 @Test
108 public void testExclusionsInReportWithRuleViolationSuppressRegex() throws Throwable {
109 Report rpt = new Report();
110 Rule rule = new FooRule();
111 rule.setProperty(Rule.VIOLATION_SUPPRESS_REGEX_DESCRIPTOR, ".*blah.*");
112 runTestFromString(TEST1, rule, rpt);
113 assertTrue(rpt.isEmpty());
114 assertEquals(1, rpt.getSuppressedRuleViolations().size());
115 }
116
117 @Test
118 public void testExclusionsInReportWithRuleViolationSuppressXPath() throws Throwable {
119 Report rpt = new Report();
120 Rule rule = new FooRule();
121 rule.setProperty(Rule.VIOLATION_SUPPRESS_XPATH_DESCRIPTOR, ".[@Image = 'Foo']");
122 runTestFromString(TEST1, rule, rpt);
123 assertTrue(rpt.isEmpty());
124 assertEquals(1, rpt.getSuppressedRuleViolations().size());
125 }
126
127 @Test
128 public void testExclusionsInReportWithAnnotations() throws Throwable {
129 Report rpt = new Report();
130 runTestFromString(TEST2, new FooRule(), rpt, LanguageVersion.JAVA_15);
131 assertTrue(rpt.isEmpty());
132 assertEquals(1, rpt.getSuppressedRuleViolations().size());
133 }
134
135 @Test
136 public void testExclusionsInReportWithAnnotationsFullName() throws Throwable {
137 Report rpt = new Report();
138 runTestFromString(TEST2_FULL, new FooRule(), rpt, LanguageVersion.JAVA_15);
139 assertTrue(rpt.isEmpty());
140 assertEquals(1, rpt.getSuppressedRuleViolations().size());
141 }
142
143 @Test
144 public void testExclusionsInReportWithNOPMD() throws Throwable {
145 Report rpt = new Report();
146 runTestFromString(TEST3, new FooRule(), rpt);
147 assertTrue(rpt.isEmpty());
148 assertEquals(1, rpt.getSuppressedRuleViolations().size());
149 }
150
151 @Test
152 public void testExclusionsInReportWithNOPMDEcmascript() throws Exception {
153 Report rpt = new Report();
154 Rule rule = new AbstractEcmascriptRule() {
155 @Override
156 public Object visit(ASTFunctionNode node, Object data) {
157 EcmascriptRuleViolationFactory.INSTANCE.addViolation((RuleContext)data, this, node, "Test", null);
158 return super.visit(node, data);
159 }
160 };
161 String code = "function(x) // NOPMD test suppress\n"
162 + "{ x = 1; }";
163 runTestFromString(code, rule, rpt, Language.ECMASCRIPT.getDefaultVersion());
164 assertTrue(rpt.isEmpty());
165 assertEquals(1, rpt.getSuppressedRuleViolations().size());
166 }
167
168 private static final String TEST1 =
169 "public class Foo {}" + PMD.EOL;
170
171 private static final String TEST2 =
172 "@SuppressWarnings(\"PMD\")" + PMD.EOL +
173 "public class Foo {}";
174 private static final String TEST2_FULL =
175 "@java.lang.SuppressWarnings(\"PMD\")" + PMD.EOL +
176 "public class Foo {}";
177
178 private static final String TEST3 =
179 "public class Foo {} // NOPMD";
180
181
182 @Test
183 public void testSortedReport_File() throws IOException {
184 Report r = new Report();
185 RuleContext ctx = new RuleContext();
186 ctx.setSourceCodeFilename("foo");
187 JavaNode s = getNode(10, 5, ctx.getSourceCodeFilename());
188 Rule rule1 = new MockRule("name", "desc", "msg", "rulesetname");
189 r.addRuleViolation(new JavaRuleViolation(rule1, ctx, s, rule1.getMessage()));
190 ctx.setSourceCodeFilename("bar");
191 JavaNode s1 = getNode(10, 5, ctx.getSourceCodeFilename());
192 Rule rule2 = new MockRule("name", "desc", "msg", "rulesetname");
193 r.addRuleViolation(new JavaRuleViolation(rule2, ctx, s1, rule2.getMessage()));
194 Renderer rend = new XMLRenderer();
195 String result = render(rend, r);
196 assertTrue("sort order wrong", result.indexOf("bar") < result.indexOf("foo"));
197 }
198
199 @Test
200 public void testSortedReport_Line() throws IOException {
201 Report r = new Report();
202 RuleContext ctx = new RuleContext();
203 ctx.setSourceCodeFilename("foo1");
204 JavaNode s = getNode(10, 5, ctx.getSourceCodeFilename());
205 Rule rule1 = new MockRule("rule2", "rule2", "msg", "rulesetname");
206 r.addRuleViolation(new JavaRuleViolation(rule1, ctx, s, rule1.getMessage()));
207 ctx.setSourceCodeFilename("foo2");
208 JavaNode s1 = getNode(20, 5, ctx.getSourceCodeFilename());
209 Rule rule2 = new MockRule("rule1", "rule1", "msg", "rulesetname");
210 r.addRuleViolation(new JavaRuleViolation(rule2, ctx, s1, rule2.getMessage()));
211 Renderer rend = new XMLRenderer();
212 String result = render(rend, r);
213 assertTrue("sort order wrong", result.indexOf("rule2") < result.indexOf("rule1"));
214 }
215
216 @Test
217 public void testListener() {
218 Report rpt = new Report();
219 rpt.addListener(this);
220 violationSemaphore = false;
221 RuleContext ctx = new RuleContext();
222 ctx.setSourceCodeFilename("file");
223 JavaNode s = getNode(5, 5, ctx.getSourceCodeFilename());
224 Rule rule1 = new MockRule("name", "desc", "msg", "rulesetname");
225 rpt.addRuleViolation(new JavaRuleViolation(rule1, ctx, s, rule1.getMessage()));
226 assertTrue(violationSemaphore);
227
228 metricSemaphore = false;
229 rpt.addMetric(new Metric("test", 0, 0.0, 0.0, 0.0, 0.0, 0.0));
230
231 assertTrue("no metric", metricSemaphore);
232 }
233
234 @Test
235 public void testSummary() {
236 Report r = new Report();
237 RuleContext ctx = new RuleContext();
238 ctx.setSourceCodeFilename("foo1");
239 JavaNode s = getNode(5, 5, ctx.getSourceCodeFilename());
240 Rule rule = new MockRule("name", "desc", "msg", "rulesetname");
241 r.addRuleViolation(new JavaRuleViolation(rule, ctx, s, rule.getMessage()));
242 ctx.setSourceCodeFilename("foo2");
243 Rule mr = new MockRule("rule1", "rule1", "msg", "rulesetname");
244 JavaNode s1 = getNode(20, 5, ctx.getSourceCodeFilename());
245 JavaNode s2 = getNode(30, 5, ctx.getSourceCodeFilename());
246 r.addRuleViolation(new JavaRuleViolation(mr, ctx, s1, mr.getMessage()));
247 r.addRuleViolation(new JavaRuleViolation(mr, ctx, s2, mr.getMessage()));
248 Map<String, Integer> summary = r.getSummary();
249 assertEquals(summary.keySet().size(), 2);
250 assertTrue(summary.values().contains(Integer.valueOf(1)));
251 assertTrue(summary.values().contains(Integer.valueOf(2)));
252 }
253
254 @Test
255 public void testTreeIterator() {
256 Report r = new Report();
257 RuleContext ctx = new RuleContext();
258 Rule rule = new MockRule("name", "desc", "msg", "rulesetname");
259 JavaNode node1 = getNode(5, 5, ctx.getSourceCodeFilename(), true);
260 r.addRuleViolation(new JavaRuleViolation(rule, ctx, node1, rule.getMessage()));
261 JavaNode node2 = getNode(5, 6, ctx.getSourceCodeFilename(), true);
262 r.addRuleViolation(new JavaRuleViolation(rule, ctx, node2, rule.getMessage()));
263
264 Iterator<RuleViolation> violations = r.iterator();
265 int violationCount = 0;
266 while (violations.hasNext()) {
267 violations.next();
268 violationCount++;
269 }
270 assertEquals(2, violationCount);
271
272 Iterator<RuleViolation> treeIterator = r.treeIterator();
273 int treeCount = 0;
274 while (treeIterator.hasNext()) {
275 treeIterator.next();
276 treeCount++;
277 }
278 assertEquals(2, treeCount);
279 }
280
281 public static JavaNode getNode(int line, int column, String scopeName){
282 DummyJavaNode s = new DummyJavaNode(2);
283 DummyJavaNode parent = new DummyJavaNode(1);
284 parent.testingOnly__setBeginLine(line);
285 parent.testingOnly__setBeginColumn(column);
286 s.jjtSetParent(parent);
287 s.setScope(new SourceFileScope(scopeName));
288 s.testingOnly__setBeginLine(10);
289 s.testingOnly__setBeginColumn(5);
290 return s;
291 }
292
293 public static JavaNode getNode(int line, int column, String scopeName, boolean nextLine) {
294 DummyJavaNode s = (DummyJavaNode)getNode(line, column, scopeName);
295 if (nextLine) {
296 s.testingOnly__setBeginLine(line + 1);
297 s.testingOnly__setBeginColumn(column + 4);
298 }
299 return s;
300 }
301
302 public static String render(Renderer renderer, Report report) throws IOException {
303 StringWriter writer = new StringWriter();
304 renderer.setWriter(writer);
305 renderer.start();
306 renderer.renderFileReport(report);
307 renderer.end();
308 return writer.toString();
309 }
310
311 public static junit.framework.Test suite() {
312 return new JUnit4TestAdapter(ReportTest.class);
313 }
314
315 }