////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2017 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
////////////////////////////////////////////////////////////////////////////////
package com.puppycrawl.tools.checkstyle.doclets;
import static com.puppycrawl.tools.checkstyle.internal.TestUtils.assertUtilsClassHasPrivateConstructor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import javax.tools.JavaFileObject;
import org.junit.Assert;
import org.junit.Test;
import com.sun.javadoc.RootDoc;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javadoc.JavadocTool;
import com.sun.tools.javadoc.Messager;
import com.sun.tools.javadoc.ModifierFilter;
public class TokenTypesDocletTest {
private static String getPath(String filename) {
return "src/test/resources/com/puppycrawl/tools/checkstyle/doclets/" + filename;
}
@Test
public void testIsProperUtilsClass() throws ReflectiveOperationException {
assertUtilsClassHasPrivateConstructor(TokenTypesDoclet.class);
}
@Test
public void testOptionLength() {
// optionLength returns 2 for option "-destfile"
assertEquals(2, TokenTypesDoclet.optionLength("-destfile"));
// optionLength returns 0 for options different from "-destfile"
assertEquals(0, TokenTypesDoclet.optionLength("-anyOtherOption"));
}
@Test
public void testCheckOptions() {
final Context context = new Context();
final TestMessager testMessager = new TestMessager(context);
//pass invalid options - empty array
final String[][] options = new String[3][1];
assertFalse(TokenTypesDoclet.checkOptions(options, testMessager));
//pass valid options - array with one "-destfile" option
options[0][0] = "-destfile";
assertTrue(TokenTypesDoclet.checkOptions(options, testMessager));
//pass invalid options - array with more than one "-destfile" option
options[1][0] = "-destfile";
assertFalse(TokenTypesDoclet.checkOptions(options, testMessager));
final String[] expected = {
"Usage: javadoc -destfile file -doclet TokenTypesDoclet ...",
"Only one -destfile option allowed.",
};
Assert.assertArrayEquals(expected, testMessager.messages.toArray());
}
@Test
public void testNotConstants() throws Exception {
// Token types must be public int constants, which means that they must have
// modifiers public, static, final and type int, because they are referenced statically in
// a lot of different places, must not be changed and an int value is used to encrypt
// a token type.
final ListBuffer<String[]> options = new ListBuffer<>();
options.add(new String[] {"-doclet", "TokenTypesDoclet"});
options.add(new String[] {"-destfile", "target/tokentypes.properties"});
final ListBuffer<String> names = new ListBuffer<>();
names.add(getPath("InputTokenTypesDocletNotConstants.java"));
final Context context = new Context();
new TestMessager(context);
final JavadocTool javadocTool = JavadocTool.make0(context);
final RootDoc rootDoc = getRootDoc(javadocTool, options, names);
assertTrue(TokenTypesDoclet.start(rootDoc));
}
@Test
public void testEmptyJavadoc() throws Exception {
final ListBuffer<String[]> options = new ListBuffer<>();
options.add(new String[] {"-destfile", "target/tokentypes.properties"});
final ListBuffer<String> names = new ListBuffer<>();
names.add(getPath("InputTokenTypesDocletEmptyJavadoc.java"));
final Context context = new Context();
new TestMessager(context);
final JavadocTool javadocTool = JavadocTool.make0(context);
final RootDoc rootDoc = getRootDoc(javadocTool, options, names);
try {
TokenTypesDoclet.start(rootDoc);
fail("IllegalArgumentException is expected");
}
catch (IllegalArgumentException expected) {
// Token types must have first sentence of Javadoc summary
// so that a brief description could be provided. Otherwise,
// an IllegalArgumentException is thrown.
}
}
@Test
public void testCorrect() throws Exception {
final ListBuffer<String[]> options = new ListBuffer<>();
options.add(new String[] {"-destfile", "target/tokentypes.properties"});
final ListBuffer<String> names = new ListBuffer<>();
names.add(getPath("InputTokenTypesDocletCorrect.java"));
final Context context = new Context();
new TestMessager(context);
final JavadocTool javadocTool = JavadocTool.make0(context);
final RootDoc rootDoc = getRootDoc(javadocTool, options, names);
assertTrue(TokenTypesDoclet.start(rootDoc));
}
private static RootDoc getRootDoc(JavadocTool javadocTool, ListBuffer<String[]> options,
ListBuffer<String> names) throws Exception {
final Method getRootDocImpl = getMethodGetRootDocImplByReflection();
final RootDoc rootDoc;
if (System.getProperty("java.version").startsWith("1.7.")) {
rootDoc = (RootDoc) getRootDocImpl.invoke(javadocTool, "", "UTF-8",
new ModifierFilter(ModifierFilter.ALL_ACCESS),
names.toList(),
options.toList(),
false,
new ListBuffer<String>().toList(),
new ListBuffer<String>().toList(),
false, false, false);
}
else {
rootDoc = (RootDoc) getRootDocImpl.invoke(javadocTool, "", "UTF-8",
new ModifierFilter(ModifierFilter.ALL_ACCESS),
names.toList(),
options.toList(),
new ListBuffer<JavaFileObject>().toList(),
false,
new ListBuffer<String>().toList(),
new ListBuffer<String>().toList(),
false, false, false);
}
return rootDoc;
}
private static Method getMethodGetRootDocImplByReflection() throws ClassNotFoundException {
Method result = null;
final Class<?> javadocToolClass = Class.forName("com.sun.tools.javadoc.JavadocTool");
final Method[] methods = javadocToolClass.getMethods();
for (Method method: methods) {
if ("getRootDocImpl".equals(method.getName())) {
result = method;
}
}
return result;
}
private static class TestMessager extends Messager {
private final List<String> messages = new ArrayList<>();
TestMessager(Context context) {
super(context, "");
}
@Override
public void printError(String message) {
messages.add(message);
}
@Override
public void printNotice(String message) { }
}
}