Skip to content

Commit 69db628

Browse files
committed
= Fix and refactor tests
- Removes huge amount of code duplication == Renames AbstractTestParent to AbstractTest Fix and refactor the file, removing code duplication and providing new methods for test classes. == Fix and refactor TagTest == Fix and refactor InterfaceTest == Fix and refactor Methods Tests - Split tests for each Method file inside the simpledata package into different test classes - Create AbstractMethodTest class to provide utility methods to remove the huge amount of code duplication == Renames files Method1.java, Method2.java and Method3.java to MethodsA, MethodsB and MethodsC Since files such as Method1 has methods named method1, method2 and so on, while file Method2 has methods with the same names, that was causing confusion. Signed-off-by: Manoel Campos <manoelcampos@gmail.com>
1 parent 452d491 commit 69db628

19 files changed

+1122
-1230
lines changed

src/main/java/com/github/markusbernhardt/xmldoclet/XmlDoclet.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public final class XmlDoclet implements Doclet {
3333
/**
3434
* The parsed object model. Used in unit tests.
3535
*/
36-
private Root root;
36+
private static Root root;
3737

3838
/**
3939
* The Options instance to parse command line strings, that defines the supported XMLDoclet {@link #options}.
@@ -263,4 +263,8 @@ public CommandLine parseCommandLine(final String[][] optionsMatrix) {
263263
return CommandLine.builder().build();
264264
}
265265
}
266+
267+
public static Root getRoot() {
268+
return root;
269+
}
266270
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package com.github.markusbernhardt.xmldoclet;
2+
3+
import com.github.markusbernhardt.xmldoclet.xjc.Method;
4+
import com.github.markusbernhardt.xmldoclet.xjc.MethodParameter;
5+
import com.github.markusbernhardt.xmldoclet.xjc.TypeInfo;
6+
7+
import java.util.List;
8+
9+
import static org.junit.Assert.*;
10+
11+
/**
12+
* Base class for implementing tests for methods.
13+
*/
14+
abstract class AbstractMethodsTest extends AbstractTest {
15+
protected final List<Method> testMethods;
16+
17+
public AbstractMethodsTest(final String sourceFileName) {
18+
final var javadocElemenets = newJavaDocElements(sourceFileName);
19+
this.testMethods = javadocElemenets.classNode().getMethod();
20+
}
21+
22+
/**
23+
* Short way of finding methodNodes. It's meant to only be used for methodNodes that do not
24+
* share the same name in the same class. In fact, this class will junit assert that there is
25+
* only 1 methodNode matching this name in the supplied <code>list</code>
26+
* methodParameterNodeeter.
27+
*
28+
* @param methodNodeName the shortname of the methodNode
29+
* @return The matching methodNode
30+
*/
31+
protected Method findByMethodName(final String methodNodeName) {
32+
for (final Method methodNode : testMethods) {
33+
if (methodNode.getName().equals(methodNodeName)) {
34+
return methodNode;
35+
}
36+
}
37+
38+
fail();
39+
return null;
40+
}
41+
42+
protected static void checkParamType(final TypeInfo methodParamType, final String fullQualifiedParamType) {
43+
assertEquals(methodParamType.getQualified(), fullQualifiedParamType);
44+
}
45+
46+
protected Method assertMethodSignature(
47+
final String methodName, final int paramCount, final String paramTypeList) {
48+
final Method methodNode = findByMethodName(methodName);
49+
assertEquals(methodNode.getParameter().size(), paramCount);
50+
assertEquals(methodNode.getSignature(), paramTypeList);
51+
return methodNode;
52+
}
53+
54+
/**
55+
* Asserts that the first parameter of the given method has the provided full qualified name
56+
* @param method method to check
57+
* @param fullQualifiedParamType full qualified name of the first parameter
58+
* @return the method's first parameter
59+
*/
60+
protected MethodParameter assertParamTypes(final Method method, final String fullQualifiedParamType) {
61+
assertParamTypes(method, new String[] {fullQualifiedParamType});
62+
return method.getParameter().getFirst();
63+
}
64+
65+
/**
66+
* Asserts that the parameters of the given method have the provided full qualified names
67+
* @param method method to check
68+
* @param fullQualifiedParamTypes full qualified names of the method's parameters
69+
*/
70+
protected void assertParamTypes(final Method method, final String... fullQualifiedParamTypes) {
71+
for (int i = 0; i < fullQualifiedParamTypes.length; i++) {
72+
final String paramType = fullQualifiedParamTypes[i];
73+
final var methodParameter = method.getParameter().get(i);
74+
assertEquals(methodParameter.getType().getQualified(), paramType);
75+
}
76+
}
77+
78+
protected static void paramHasNoGenericsNoDimensionNoWildcard(final TypeInfo paramTypeInfo) {
79+
paramHasNoDimensionNoWildcard(paramTypeInfo, 0);
80+
}
81+
82+
/**
83+
* Asserts that a method parameter has no dimension, no wildcard and a given number of
84+
* generic types (types between &lt; and &gt;).
85+
* @param paramTypeInfo type information for a method parameter
86+
* @param paramGenericTypes number of generic types expected for the parameter type
87+
*/
88+
protected static void paramHasNoDimensionNoWildcard(final TypeInfo paramTypeInfo, final int paramGenericTypes) {
89+
assertNull(paramTypeInfo.getDimension());
90+
assertNull(paramTypeInfo.getWildcard());
91+
assertEquals(paramTypeInfo.getGeneric().size(), paramGenericTypes);
92+
}
93+
}
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
package com.github.markusbernhardt.xmldoclet;
2+
3+
import com.github.markusbernhardt.xmldoclet.xjc.Class;
4+
import com.github.markusbernhardt.xmldoclet.xjc.Package;
5+
import com.github.markusbernhardt.xmldoclet.xjc.Root;
6+
import org.junit.Test;
7+
8+
import java.io.File;
9+
import java.io.PrintWriter;
10+
import java.nio.charset.Charset;
11+
import java.util.ArrayList;
12+
import java.util.Arrays;
13+
import java.util.List;
14+
import java.util.logging.Level;
15+
import java.util.logging.Logger;
16+
import java.util.spi.ToolProvider;
17+
18+
import static java.util.Arrays.stream;
19+
20+
/**
21+
* Base class for all tests.
22+
*
23+
* @author markus
24+
*/
25+
abstract class AbstractTest {
26+
private final static Logger LOGGER = Logger.getLogger(AbstractTest.class.getName());
27+
28+
protected static final String[] TEST_DIR = { "./src/test/java/" };
29+
protected static final String SIMPLE_DATA_PACKAGE = "com.github.markusbernhardt.xmldoclet.simpledata";
30+
protected static final String SIMPLE_DATA_DIR = TEST_DIR[0] + SIMPLE_DATA_PACKAGE.replaceAll("\\.", "/");
31+
32+
protected static final String[] ARGS = { "-dryrun" };
33+
protected static final String[] SUB_PACKAGES = { "com" };
34+
35+
/**
36+
* Gets the first {@link Package} and {@link Class} from a JavaDoc {@link Root} element.
37+
* @param sourceFileName Name of a source files inside the {@link #SIMPLE_DATA_DIR} to test.
38+
*/
39+
public JavaDocElements newJavaDocElements(final String ...sourceFileName) {
40+
final var sourceFiles = stream(sourceFileName).map(this::getFilePathFromSimpleDataDir).toArray(String[]::new);
41+
final var rootNode = executeJavadoc(null, null, null, sourceFiles, null, ARGS);
42+
43+
final var packageNode = rootNode.getPackage().getFirst();
44+
final var classNode = packageNode.getClazz().getFirst();
45+
return new JavaDocElements(rootNode, packageNode, classNode);
46+
}
47+
48+
/**
49+
* Rigourous Parser :-)
50+
*/
51+
@Test
52+
public void testSampledoc() {
53+
executeJavadoc(".", TEST_DIR, null, null, SUB_PACKAGES, ARGS);
54+
}
55+
56+
/**
57+
* Processes the source code using javadoc.
58+
*
59+
* @param extendedClassPath Any classpath information required to help along javadoc. Javadoc
60+
* will actually compile the source code you specify; so if there are any jars or classes
61+
* that are referenced by the source code to process, then including those compiled items
62+
* in the classpath will give you more complete data in the resulting XML.
63+
* @param sourcePaths Usually sourcePaths is specified in conjunction with either/both packages &
64+
* subpackages. The sourcepaths value should be the path of the source files right before
65+
* the standard package-based folder layout of projects begins. For example, if you have
66+
* code that exists in package foo.bar, and your code is physically in /MyFolder/foo/bar/,
67+
* then the sourcePaths would be /MyFolder
68+
* @param packages Use if you want to detail specific packages to process (contrast with
69+
* subpackages, which is probably the easiest/most brute force way of using xml-doclet).
70+
* If you have within your code two packages, foo.bar and bar.foo, but only wanted
71+
* foo.bar processed, then specify just 'foo.bar' for this argument.
72+
* @param sourceFiles You can specify source files individually. This usually is used instead of
73+
* sourcePaths/subPackages/packages. If you use this parameter, specify the full path of
74+
* any java file you want processed.
75+
* @param subPackages You can specify 'subPackages', which simply gives one an easy way to
76+
* specify the root package, and have javadoc recursively look through everything under
77+
* that package. So for instance, if you had foo.bar, foo.bar.bar, and bar.foo,
78+
* specifying 'foo' will process foo.bar and foo.bar.bar packages, but not bar.foo
79+
* (unless you specify 'bar' as a subpackage, too)
80+
* @param additionalArguments Additional Arguments.
81+
* @return XStream compatible data structure
82+
*/
83+
public Root executeJavadoc(
84+
final String extendedClassPath, final String[] sourcePaths, final String[] packages,
85+
final String[] sourceFiles, final String[] subPackages, final String[] additionalArguments) {
86+
try {
87+
88+
final var errorWriter = new PrintWriter(System.err, true, Charset.defaultCharset());
89+
final var infoWriter = new PrintWriter(System.out, true, Charset.defaultCharset());
90+
91+
// aggregate arguments and packages
92+
final var argumentList = new ArrayList<String>();
93+
94+
// by setting this to 'private', nothing is omitted in the parsing
95+
argumentList.add("-private");
96+
97+
final String classPath = getClassPath(extendedClassPath);
98+
argumentList.add("-classpath");
99+
argumentList.add(classPath);
100+
101+
if (sourcePaths != null) {
102+
final String concatedSourcePaths = join(File.pathSeparator, sourcePaths);
103+
if (!concatedSourcePaths.isEmpty()) {
104+
argumentList.add("-sourcepath");
105+
argumentList.add(concatedSourcePaths);
106+
}
107+
}
108+
109+
if (subPackages != null) {
110+
final String concatedSubPackages = join(";", subPackages);
111+
if (!concatedSubPackages.isEmpty()) {
112+
argumentList.add("-subpackages");
113+
argumentList.add(concatedSubPackages);
114+
}
115+
}
116+
117+
if (packages != null) {
118+
argumentList.addAll(Arrays.asList(packages));
119+
}
120+
121+
if (sourceFiles != null) {
122+
argumentList.addAll(Arrays.asList(sourceFiles));
123+
}
124+
125+
if (additionalArguments != null) {
126+
argumentList.addAll(Arrays.asList(additionalArguments));
127+
}
128+
129+
LOGGER.info("Executing doclet with arguments: " + join(" ", argumentList));
130+
131+
final var javadoc = ToolProvider.findFirst("javadoc").orElseThrow();
132+
final String[] arguments = argumentList.toArray(new String[] {});
133+
javadoc.run(infoWriter, errorWriter, arguments);
134+
135+
LOGGER.info("done with doclet processing");
136+
} catch (Exception e) {
137+
LOGGER.log(Level.SEVERE, "doclet exception", e);
138+
} catch (Error e) {
139+
LOGGER.log(Level.SEVERE, "doclet error", e);
140+
}
141+
142+
return XmlDoclet.getRoot();
143+
}
144+
145+
private static String getClassPath(final String extendedClassPath) {
146+
final String classPath = System.getProperty("java.class.path", ".");
147+
return extendedClassPath == null ? classPath : classPath + File.pathSeparator + extendedClassPath;
148+
149+
}
150+
151+
/**
152+
* Helper method to concat strings.
153+
*
154+
* @param glue the separator.
155+
* @param strings the strings to concat.
156+
* @return concatenated string
157+
*/
158+
public static String join(final String glue, final String[] strings) {
159+
return join(glue, Arrays.asList(strings));
160+
}
161+
162+
/**
163+
* Helper method to concat strings.
164+
*
165+
* @param glue the separator.
166+
* @param strings the strings to concat.
167+
* @return concatenated string
168+
*/
169+
public static String join(final String glue, final List<String> strings) {
170+
if (strings == null) {
171+
return null;
172+
}
173+
174+
return String.join(glue, strings);
175+
}
176+
177+
178+
/**
179+
* {@return the path (separated by /) to a source file in the {@link #SIMPLE_DATA_DIR}}
180+
* @param sourceFileName the name of the file to get its full path from the {@link #SIMPLE_DATA_DIR}
181+
*/
182+
protected String getFilePathFromSimpleDataDir(final String sourceFileName) {
183+
return join("/", List.of(SIMPLE_DATA_DIR, sourceFileName));
184+
}
185+
186+
/**
187+
* {@return the full qualified name of a class, interface, record, enum or even some other element inside
188+
* those ones (separated by .) in the {@link #SIMPLE_DATA_PACKAGE}}
189+
* Those internal elements can be something such as fields, methods, constructors, etc.
190+
* @param elementName the name of the element (class, interface, record, method, etc.) to get its
191+
* full qualified name from the {@link #SIMPLE_DATA_PACKAGE}
192+
*/
193+
protected static String getElementPathFromSimpleDataPackage(final String elementName) {
194+
return join(".", List.of(SIMPLE_DATA_PACKAGE, elementName));
195+
}
196+
197+
}

0 commit comments

Comments
 (0)