1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.javadoc;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.StringReader;
24 import java.lang.reflect.Method;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Properties;
29
30 import com.thoughtworks.qdox.JavaProjectBuilder;
31 import com.thoughtworks.qdox.model.DocletTag;
32 import com.thoughtworks.qdox.model.JavaClass;
33 import com.thoughtworks.qdox.model.JavaMethod;
34 import org.apache.maven.execution.MavenSession;
35 import org.apache.maven.plugin.logging.Log;
36 import org.apache.maven.plugin.testing.AbstractMojoTestCase;
37 import org.apache.maven.plugin.testing.stubs.MavenProjectStub;
38 import org.apache.maven.plugins.javadoc.AbstractFixJavadocMojo.JavaEntityTags;
39 import org.apache.maven.shared.invoker.MavenInvocationException;
40 import org.codehaus.plexus.util.FileUtils;
41 import org.codehaus.plexus.util.StringUtils;
42 import org.eclipse.aether.DefaultRepositorySystemSession;
43 import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory;
44 import org.eclipse.aether.repository.LocalRepository;
45
46 import static org.apache.commons.lang3.reflect.MethodUtils.invokeMethod;
47
48
49
50
51 public class FixJavadocMojoTest extends AbstractMojoTestCase {
52
53 private static final String EOL = System.getProperty("line.separator");
54
55
56 private static boolean TEST_REPO_CREATED = false;
57
58
59 @Override
60 protected void setUp() throws Exception {
61 super.setUp();
62
63 createTestRepo();
64 }
65
66
67
68
69
70
71 private void createTestRepo() throws Exception {
72 if (TEST_REPO_CREATED) {
73 return;
74 }
75
76 File localRepo = new File(getBasedir(), "target/local-repo/");
77 localRepo.mkdirs();
78
79
80
81
82
83 File sourceDir = new File(getBasedir(), "src/test/resources/unit/fix-test/repo/");
84 assertTrue(sourceDir.exists());
85 FileUtils.copyDirectoryStructure(sourceDir, localRepo);
86
87
88 List<String> files = FileUtils.getFileAndDirectoryNames(
89 localRepo, FileUtils.getDefaultExcludesAsString(), null, true, true, true, true);
90 for (String filename : files) {
91 File file = new File(filename);
92
93 if (file.isDirectory()) {
94 FileUtils.deleteDirectory(file);
95 } else {
96 file.delete();
97 }
98 }
99
100 TEST_REPO_CREATED = true;
101 }
102
103
104
105
106 public void testFix() throws Exception {
107 File testPomBasedir = new File(getBasedir(), "target/test/unit/fix-test");
108
109 executeMojoAndTest(testPomBasedir, new String[] {
110 "ClassWithJavadoc.java",
111 "ClassWithNoJavadoc.java",
112 "InterfaceWithJavadoc.java",
113 "InterfaceWithNoJavadoc.java"
114 });
115 }
116
117
118
119
120
121
122
123
124 public void testAutodetectIndentation() throws Exception {
125 Method method = AbstractFixJavadocMojo.class.getDeclaredMethod("autodetectIndentation", String.class);
126 method.setAccessible(true);
127
128 String s = null;
129 assertEquals("", (String) method.invoke(null, s));
130
131 s = "no indentation";
132 assertEquals("", (String) method.invoke(null, s));
133
134 s = "no indentation with right spaces ";
135 assertEquals("", (String) method.invoke(null, s));
136
137 s = " indentation";
138 assertEquals(" ", (String) method.invoke(null, s));
139
140 s = " indentation with right spaces ";
141 assertEquals(" ", (String) method.invoke(null, s));
142
143 s = "\ttab indentation";
144 assertEquals("\t", (String) method.invoke(null, s));
145
146 s = " \n indentation with right spaces ";
147 assertEquals(" \n ", (String) method.invoke(null, s));
148 }
149
150
151
152
153 public void testTrimLeft() throws Exception {
154 Method method = AbstractFixJavadocMojo.class.getDeclaredMethod("trimLeft", String.class);
155 method.setAccessible(true);
156
157 assertEquals("", (String) method.invoke(null, (String) null));
158 assertEquals("", (String) method.invoke(null, " "));
159 assertEquals("", (String) method.invoke(null, " \t "));
160 assertEquals("a", (String) method.invoke(null, "a"));
161 assertEquals("a", (String) method.invoke(null, " a"));
162 assertEquals("a", (String) method.invoke(null, "\ta"));
163 assertEquals("a ", (String) method.invoke(null, " a "));
164 assertEquals("a\t", (String) method.invoke(null, "\ta\t"));
165 }
166
167
168
169
170 public void testTrimRight() throws Exception {
171 Method method = AbstractFixJavadocMojo.class.getDeclaredMethod("trimRight", String.class);
172 method.setAccessible(true);
173
174 assertEquals("", (String) method.invoke(null, (String) null));
175 assertEquals("", (String) method.invoke(null, " "));
176 assertEquals("", (String) method.invoke(null, " \t "));
177 assertEquals("a", (String) method.invoke(null, "a"));
178 assertEquals("a", (String) method.invoke(null, "a "));
179 assertEquals("a", (String) method.invoke(null, "a\t"));
180 assertEquals(" a", (String) method.invoke(null, " a "));
181 assertEquals("\ta", (String) method.invoke(null, "\ta\t"));
182 }
183
184
185
186
187 public void testHasInheritedTag() throws Exception {
188 Method method = AbstractFixJavadocMojo.class.getDeclaredMethod("hasInheritedTag", String.class);
189 method.setAccessible(true);
190
191 String content = "/** {@inheritDoc} */";
192 Boolean has = (Boolean) method.invoke(null, content);
193 assertEquals(Boolean.TRUE, has);
194
195 content = "/**{@inheritDoc}*/";
196 has = (Boolean) method.invoke(null, content);
197 assertEquals(Boolean.TRUE, has);
198
199 content = "/**{@inheritDoc } */";
200 has = (Boolean) method.invoke(null, content);
201 assertEquals(Boolean.TRUE, has);
202
203 content = "/** {@inheritDoc } */";
204 has = (Boolean) method.invoke(null, content);
205 assertEquals(Boolean.TRUE, has);
206
207 content = "/** */";
208 has = (Boolean) method.invoke(null, content);
209 assertEquals(Boolean.FALSE, has);
210
211 content = "/**{ @inheritDoc }*/";
212 has = (Boolean) method.invoke(null, content);
213 assertEquals(Boolean.FALSE, has);
214
215 content = "/**{@ inheritDoc}*/";
216 has = (Boolean) method.invoke(null, content);
217 assertEquals(Boolean.FALSE, has);
218 }
219
220
221
222
223 public void testJavadocComment() throws Throwable {
224 String content = "/**" + EOL + " * Dummy Class."
225 + EOL + " */"
226 + EOL + "public class DummyClass"
227 + EOL + "{"
228 + EOL + " /**"
229 + EOL + " *"
230 + EOL + " * Dummy"
231 + EOL + " *"
232 + EOL + " * Method."
233 + EOL + " *"
234 + EOL + " * @param args not"
235 + EOL + " *"
236 + EOL + " * null"
237 + EOL + " * @param i non negative"
238 + EOL + " * @param object could"
239 + EOL + " * be"
240 + EOL + " * null"
241 + EOL + " * @return a"
242 + EOL + " * String"
243 + EOL + " *"
244 + EOL + " * @throws Exception if"
245 + EOL + " * any"
246 + EOL + " *"
247 + EOL + " */"
248 + EOL + " public static String dummyMethod( String[] args, int i, Object object )"
249 + EOL + " throws Exception"
250 + EOL + " {"
251 + EOL + " return null;"
252 + EOL + " }"
253 + EOL + "}";
254
255 JavaProjectBuilder builder = new JavaProjectBuilder();
256 builder.setEncoding("UTF-8");
257 builder.addSource(new StringReader(content));
258
259 JavaClass clazz = builder.addSource(new StringReader(content)).getClassByName("DummyClass");
260
261 JavaMethod javaMethod = clazz.getMethods().get(0);
262
263 String javadoc = AbstractFixJavadocMojo.extractOriginalJavadoc(content, javaMethod);
264 assertEquals(
265 " /**" + EOL + " *"
266 + EOL + " * Dummy"
267 + EOL + " *"
268 + EOL + " * Method."
269 + EOL + " *"
270 + EOL + " * @param args not"
271 + EOL + " *"
272 + EOL + " * null"
273 + EOL + " * @param i non negative"
274 + EOL + " * @param object could"
275 + EOL + " * be"
276 + EOL + " * null"
277 + EOL + " * @return a"
278 + EOL + " * String"
279 + EOL + " *"
280 + EOL + " * @throws Exception if"
281 + EOL + " * any"
282 + EOL + " *"
283 + EOL + " */",
284 javadoc);
285
286 String javadocContent = AbstractFixJavadocMojo.extractOriginalJavadocContent(content, javaMethod);
287 assertEquals(
288 " *" + EOL + " * Dummy"
289 + EOL + " *"
290 + EOL + " * Method."
291 + EOL + " *"
292 + EOL + " * @param args not"
293 + EOL + " *"
294 + EOL + " * null"
295 + EOL + " * @param i non negative"
296 + EOL + " * @param object could"
297 + EOL + " * be"
298 + EOL + " * null"
299 + EOL + " * @return a"
300 + EOL + " * String"
301 + EOL + " *"
302 + EOL + " * @throws Exception if"
303 + EOL + " * any"
304 + EOL + " *",
305 javadocContent);
306
307 Method method = AbstractFixJavadocMojo.class.getDeclaredMethod("removeLastEmptyJavadocLines", String.class);
308 method.setAccessible(true);
309
310 String withoutEmptyJavadocLines = (String) method.invoke(null, javadocContent);
311 assertTrue(withoutEmptyJavadocLines.endsWith("any"));
312
313 String methodJavadoc = AbstractFixJavadocMojo.getJavadocComment(content, javaMethod);
314 assertEquals(
315 " *" + EOL + " * Dummy" + EOL + " *" + EOL + " * Method." + EOL + " *",
316 methodJavadoc);
317 withoutEmptyJavadocLines = (String) method.invoke(null, methodJavadoc);
318 assertTrue(withoutEmptyJavadocLines.endsWith("Method."));
319
320 assertEquals(5, javaMethod.getTags().size());
321
322 AbstractFixJavadocMojo mojoInstance = new FixJavadocMojo();
323 setVariableValueToObject(mojoInstance, "fixTagsSplitted", new String[] {"all"});
324
325 DocletTag tag = javaMethod.getTags().get(0);
326 String tagJavadoc = mojoInstance.getJavadocComment(content, javaMethod, tag);
327 assertEquals(" * @param args not" + EOL + " *" + EOL + " * null", tagJavadoc);
328 withoutEmptyJavadocLines = (String) method.invoke(null, tagJavadoc);
329 assertTrue(withoutEmptyJavadocLines.endsWith("null"));
330
331 tag = javaMethod.getTags().get(1);
332 tagJavadoc = mojoInstance.getJavadocComment(content, javaMethod, tag);
333 assertEquals(" * @param i non negative", tagJavadoc);
334 withoutEmptyJavadocLines = (String) method.invoke(null, tagJavadoc);
335 assertTrue(withoutEmptyJavadocLines.endsWith("negative"));
336
337 tag = javaMethod.getTags().get(2);
338 tagJavadoc = mojoInstance.getJavadocComment(content, javaMethod, tag);
339 assertEquals(" * @param object could" + EOL + " * be" + EOL + " * null", tagJavadoc);
340 withoutEmptyJavadocLines = (String) method.invoke(null, tagJavadoc);
341 assertTrue(withoutEmptyJavadocLines.endsWith("null"));
342
343 tag = javaMethod.getTags().get(3);
344 tagJavadoc = mojoInstance.getJavadocComment(content, javaMethod, tag);
345 assertEquals(" * @return a" + EOL + " * String" + EOL + " *", tagJavadoc);
346 withoutEmptyJavadocLines = (String) method.invoke(null, tagJavadoc);
347 assertTrue(withoutEmptyJavadocLines.endsWith("String"));
348
349 tag = javaMethod.getTags().get(4);
350 tagJavadoc = mojoInstance.getJavadocComment(content, javaMethod, tag);
351 assertEquals(" * @throws Exception if" + EOL + " * any" + EOL + " *", tagJavadoc);
352 withoutEmptyJavadocLines = (String) method.invoke(null, tagJavadoc);
353 assertTrue(withoutEmptyJavadocLines.endsWith("any"));
354 }
355
356 public void testJavadocCommentJdk5() throws Exception {
357 String content = "/**" + EOL + " * Dummy Class."
358 + EOL + " */"
359 + EOL + "public class DummyClass"
360 + EOL + "{"
361 + EOL + " /**"
362 + EOL + " * Dummy method."
363 + EOL + " *"
364 + EOL + " * @param <K> The Key type for the method"
365 + EOL + " * @param <V> The Value type for the method"
366 + EOL + " * @param name The name."
367 + EOL + " * @return A map configured."
368 + EOL + " */"
369 + EOL + " public <K, V> java.util.Map<K, V> dummyMethod( String name )"
370 + EOL + " {"
371 + EOL + " return null;"
372 + EOL + " }"
373 + EOL + "}";
374
375 JavaProjectBuilder builder = new JavaProjectBuilder();
376 builder.setEncoding("UTF-8");
377 JavaClass clazz = builder.addSource(new StringReader(content)).getClassByName("DummyClass");
378
379 JavaMethod javaMethod = clazz.getMethods().get(0);
380
381 String methodJavadoc = AbstractFixJavadocMojo.getJavadocComment(content, javaMethod);
382 assertEquals(" * Dummy method." + EOL + " *", methodJavadoc);
383
384 assertEquals(4, javaMethod.getTags().size());
385
386 AbstractFixJavadocMojo mojoInstance = new FixJavadocMojo();
387 setVariableValueToObject(mojoInstance, "fixTagsSplitted", new String[] {"all"});
388
389 DocletTag tag = javaMethod.getTags().get(0);
390 String tagJavadoc = mojoInstance.getJavadocComment(content, javaMethod, tag);
391 assertEquals(" * @param <K> The Key type for the method", tagJavadoc);
392
393 tag = javaMethod.getTags().get(1);
394 tagJavadoc = mojoInstance.getJavadocComment(content, javaMethod, tag);
395 assertEquals(" * @param <V> The Value type for the method", tagJavadoc);
396
397 tag = javaMethod.getTags().get(2);
398 tagJavadoc = mojoInstance.getJavadocComment(content, javaMethod, tag);
399 assertEquals(" * @param name The name.", tagJavadoc);
400
401 tag = javaMethod.getTags().get(3);
402 tagJavadoc = mojoInstance.getJavadocComment(content, javaMethod, tag);
403 assertEquals(" * @return A map configured.", tagJavadoc);
404 }
405
406 public void testInitParameters() throws Throwable {
407 AbstractFixJavadocMojo mojoInstance = new FixJavadocMojo();
408 setVariableValueToObject(mojoInstance, "fixTags", "author, version, since, param, return, throws, link");
409 setVariableValueToObject(mojoInstance, "defaultSince", "1.0");
410 setVariableValueToObject(mojoInstance, "level", "protected");
411
412 invokeMethod(mojoInstance, true, "init");
413
414 String[] fixTags = (String[]) getVariableValueFromObject(mojoInstance, "fixTagsSplitted");
415
416 assertEquals("author", fixTags[0]);
417 assertEquals("version", fixTags[1]);
418 assertEquals("since", fixTags[2]);
419 assertEquals("param", fixTags[3]);
420 assertEquals("return", fixTags[4]);
421 assertEquals("throws", fixTags[5]);
422 assertEquals("link", fixTags[6]);
423 assertEquals(7, fixTags.length);
424
425 setVariableValueToObject(mojoInstance, "fixTags", "return, fake_value");
426 invokeMethod(mojoInstance, true, "init");
427 fixTags = (String[]) getVariableValueFromObject(mojoInstance, "fixTagsSplitted");
428
429 assertEquals("return", fixTags[0]);
430 assertEquals(1, fixTags.length);
431 }
432
433 public void testRemoveUnknownExceptions() throws Exception {
434 AbstractFixJavadocMojo mojoInstance = new FixJavadocMojo();
435 setVariableValueToObject(mojoInstance, "fixTagsSplitted", new String[] {"all"});
436 setVariableValueToObject(mojoInstance, "project", new MavenProjectStub());
437
438 String source = "package a.b.c;" + EOL
439 + "public class Clazz {" + EOL
440 + " /**" + EOL
441 + " * @throws java.lang.RuntimeException" + EOL
442 + " * @throws NumberFormatException" + EOL
443 + " * @throws java.lang.Exception" + EOL
444 + " * @throws com.foo.FatalException" + EOL
445 + " */" + EOL
446 + " public void method() {}" + EOL
447 + "}";
448
449 JavaProjectBuilder builder = new JavaProjectBuilder();
450 JavaMethod javaMethod = builder.addSource(new StringReader(source))
451 .getClassByName("Clazz")
452 .getMethods()
453 .get(0);
454
455 JavaEntityTags javaEntityTags = mojoInstance.parseJavadocTags(source, javaMethod, "", true);
456
457 StringBuilder sb = new StringBuilder();
458 mojoInstance.writeThrowsTag(
459 sb, javaMethod, javaEntityTags, Collections.singletonList("java.lang" + ".RuntimeException"));
460 assertEquals(" * @throws java.lang.RuntimeException", sb.toString());
461
462 sb = new StringBuilder();
463 mojoInstance.writeThrowsTag(sb, javaMethod, javaEntityTags, Collections.singletonList("NumberFormatException"));
464 assertEquals(" * @throws java.lang.NumberFormatException", sb.toString());
465
466 sb = new StringBuilder();
467 mojoInstance.writeThrowsTag(sb, javaMethod, javaEntityTags, Collections.singletonList("java.lang.Exception"));
468 assertEquals("", sb.toString());
469
470 setVariableValueToObject(mojoInstance, "removeUnknownThrows", true);
471 sb = new StringBuilder();
472 mojoInstance.writeThrowsTag(
473 sb, javaMethod, javaEntityTags, Collections.singletonList("com.foo.FatalException"));
474 assertEquals("", sb.toString());
475
476 setVariableValueToObject(mojoInstance, "removeUnknownThrows", false);
477 sb = new StringBuilder();
478 mojoInstance.writeThrowsTag(
479 sb, javaMethod, javaEntityTags, Collections.singletonList("com.foo.FatalException"));
480 assertEquals(" * @throws com.foo.FatalException if any.", sb.toString());
481 }
482
483
484
485
486
487
488
489
490
491
492 private void executeMojoAndTest(File testPomBasedir, String[] clazzToCompare) throws Exception {
493 prepareTestProjects(testPomBasedir.getName());
494
495 File testPom = new File(testPomBasedir, "pom.xml");
496 assertTrue(testPom.getAbsolutePath() + " should exist", testPom.exists());
497
498 FixJavadocMojo mojo = (FixJavadocMojo) lookupMojo("fix", testPom);
499 assertNotNull(mojo);
500
501 MavenSession session = newMavenSession(mojo.getProject());
502 ((DefaultRepositorySystemSession) session.getRepositorySession())
503 .setLocalRepositoryManager(new SimpleLocalRepositoryManagerFactory()
504 .newInstance(
505 session.getRepositorySession(), new LocalRepository(new File("target/local-repo"))));
506
507 File globalSettingsFile = new File(getBasedir(), "target/test-classes/unit/settings.xml");
508 session.getRequest().setGlobalSettingsFile(globalSettingsFile);
509 setVariableValueToObject(mojo, "session", session);
510
511
512 invokeCompileGoal(testPom, globalSettingsFile, mojo.getLog());
513 assertTrue(new File(testPomBasedir, "target/classes").exists());
514
515 mojo.execute();
516
517 File expectedDir = new File(testPomBasedir, "expected/src/main/java/fix/test");
518 assertTrue(expectedDir.exists());
519
520 File generatedDir = new File(testPomBasedir, "target/generated/fix/test");
521 assertTrue(generatedDir.exists());
522
523 for (String className : clazzToCompare) {
524 assertEquals(new File(expectedDir, className), new File(generatedDir, className));
525 }
526 }
527
528
529
530
531
532
533
534
535 private void invokeCompileGoal(File testPom, File globalSettingsFile, Log log) throws Exception {
536 List<String> goals = new ArrayList<>();
537 goals.add("clean");
538 goals.add("compile");
539 File invokerDir = new File(getBasedir(), "target/invoker");
540 invokerDir.mkdirs();
541 File invokerLogFile = FileUtils.createTempFile("FixJavadocMojoTest", ".txt", invokerDir);
542
543 Properties properties = new Properties();
544
545 JavadocUtil.invokeMaven(
546 log,
547 new File(getBasedir(), "target/local-repo"),
548 testPom,
549 goals,
550 properties,
551 invokerLogFile,
552 globalSettingsFile);
553 }
554
555
556
557
558
559
560
561
562
563
564 private static void assertEquals(File expected, File actual) throws Exception {
565 assertTrue(" Expected file DNE: " + expected, expected.exists());
566 String expectedContent = StringUtils.unifyLineSeparators(readFile(expected));
567
568 assertTrue(" Actual file DNE: " + actual, actual.exists());
569 String actualContent = StringUtils.unifyLineSeparators(readFile(actual));
570
571 assertEquals(
572 "Expected file: " + expected.getAbsolutePath() + ", actual file: " + actual.getAbsolutePath(),
573 expectedContent,
574 actualContent);
575 }
576
577
578
579
580
581 private static void prepareTestProjects(String testProjectDirName) throws Exception {
582 File testPomBasedir = new File(getBasedir(), "target/test/unit/" + testProjectDirName);
583
584
585 FileUtils.copyDirectoryStructure(
586 new File(getBasedir(), "src/test/resources/unit/" + testProjectDirName), testPomBasedir);
587 List<String> scmFiles = FileUtils.getDirectoryNames(testPomBasedir, "**/.svn", null, true);
588 for (String filename : scmFiles) {
589 File dir = new File(filename);
590
591 if (dir.isDirectory()) {
592 FileUtils.deleteDirectory(dir);
593 }
594 }
595 }
596
597
598
599
600
601
602 private static String readFile(File file) throws Exception {
603 String content = FileUtils.fileRead(file, "UTF-8");
604 return content;
605 }
606 }