blob: 13ff802cc5125d4aedd37b18fd11e527648dc2f6 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
// 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;
import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.AMBIGUOUS_MODULE_NAME_EXCEPTION_MESSAGE;
import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.BASE_PACKAGE;
import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.CHECK_SUFFIX;
import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.ModuleLoadOption.TRY_IN_ALL_REGISTERED_PACKAGES;
import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.NULL_LOADER_MESSAGE;
import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.NULL_PACKAGE_MESSAGE;
import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.PACKAGE_SEPARATOR;
import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.STRING_SEPARATOR;
import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.UNABLE_TO_INSTANTIATE_EXCEPTION_MESSAGE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.FileText;
import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
import com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationLocationCheck;
import com.puppycrawl.tools.checkstyle.internal.utils.CheckUtil;
/**
* Enter a description of class PackageObjectFactoryTest.java.
*
* @author Rick Giles
*/
public class PackageObjectFactoryTest {
private final PackageObjectFactory factory = new PackageObjectFactory(
BASE_PACKAGE, Thread.currentThread().getContextClassLoader());
@Test
public void testCtorNullLoaderException1() {
try {
final Object test = new PackageObjectFactory(new HashSet<>(), null);
fail("Exception is expected but got " + test);
}
catch (IllegalArgumentException ex) {
assertEquals("Invalid exception message", NULL_LOADER_MESSAGE, ex.getMessage());
}
}
@Test
public void testCtorNullLoaderException2() {
try {
final Object test = new PackageObjectFactory("test", null);
fail("Exception is expected but got " + test);
}
catch (IllegalArgumentException ex) {
assertEquals("Invalid exception message", NULL_LOADER_MESSAGE, ex.getMessage());
}
}
@Test
public void testCtorNullPackageException1() {
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
try {
final Object test = new PackageObjectFactory(Collections.singleton(null), classLoader);
fail("Exception is expected but got " + test);
}
catch (IllegalArgumentException ex) {
assertEquals("Invalid exception message", NULL_PACKAGE_MESSAGE, ex.getMessage());
}
}
@Test
public void testCtorNullPackageException2() {
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
try {
final Object test = new PackageObjectFactory((String) null, classLoader);
fail("Exception is expected but got " + test);
}
catch (IllegalArgumentException ex) {
assertEquals("Invalid exception message", NULL_PACKAGE_MESSAGE, ex.getMessage());
}
}
@Test
public void testCtorNullPackageException3() {
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
try {
final Object test = new PackageObjectFactory(Collections.singleton(null), classLoader,
TRY_IN_ALL_REGISTERED_PACKAGES);
fail("Exception is expected but got " + test);
}
catch (IllegalArgumentException ex) {
assertEquals("Invalid exception message", NULL_PACKAGE_MESSAGE, ex.getMessage());
}
}
@Test
public void testMakeObjectFromName()
throws CheckstyleException {
final Checker checker =
(Checker) factory.createModule(
"com.puppycrawl.tools.checkstyle.Checker");
assertNotNull("Checker should not be null when creating module from name", checker);
}
@Test
public void testMakeCheckFromName() {
final String name = "com.puppycrawl.tools.checkstyle.checks.naming.ConstantName";
try {
factory.createModule(name);
fail("Exception is expected");
}
catch (CheckstyleException ex) {
final LocalizedMessage exceptionMessage = new LocalizedMessage(0,
Definitions.CHECKSTYLE_BUNDLE, UNABLE_TO_INSTANTIATE_EXCEPTION_MESSAGE,
new String[] {name, null}, null, factory.getClass(), null);
assertEquals("Invalid exception message",
exceptionMessage.getMessage(), ex.getMessage());
}
}
@Test
public void testCreateModuleWithNonExistName() {
testCreateModuleWithNonExistName("NonExistClassOne");
testCreateModuleWithNonExistName("NonExistClassTwo");
}
private void testCreateModuleWithNonExistName(String name) {
try {
factory.createModule(name);
fail("Exception is expected");
}
catch (CheckstyleException ex) {
final String attemptedNames = BASE_PACKAGE + PACKAGE_SEPARATOR + name + STRING_SEPARATOR
+ name + CHECK_SUFFIX + STRING_SEPARATOR
+ BASE_PACKAGE + PACKAGE_SEPARATOR + name + CHECK_SUFFIX;
final LocalizedMessage exceptionMessage = new LocalizedMessage(0,
Definitions.CHECKSTYLE_BUNDLE, UNABLE_TO_INSTANTIATE_EXCEPTION_MESSAGE,
new String[] {name, attemptedNames}, null, factory.getClass(), null);
assertEquals("Invalid exception message",
exceptionMessage.getMessage(), ex.getMessage());
}
}
@Test
public void testCreateObjectFromMap() throws Exception {
final String moduleName = "Foo";
final String name = moduleName + CHECK_SUFFIX;
final String packageName = BASE_PACKAGE + ".packageobjectfactory.bar";
final String fullName = packageName + PACKAGE_SEPARATOR + name;
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
final PackageObjectFactory objectFactory =
new PackageObjectFactory(packageName, classLoader);
final Object instance1 = objectFactory.createModule(name);
assertEquals("Invalid canonical name", fullName, instance1.getClass().getCanonicalName());
final Object instance2 = objectFactory.createModule(moduleName);
assertEquals("Invalid canonical name", fullName, instance2.getClass().getCanonicalName());
}
@Test
public void testCreateObjectFromFullModuleNamesWithAmbiguousException() {
final String barPackage = BASE_PACKAGE + ".packageobjectfactory.bar";
final String fooPackage = BASE_PACKAGE + ".packageobjectfactory.foo";
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
final PackageObjectFactory objectFactory = new PackageObjectFactory(
new LinkedHashSet<>(Arrays.asList(barPackage, fooPackage)), classLoader);
final String name = "FooCheck";
try {
objectFactory.createModule(name);
fail("Exception is expected");
}
catch (CheckstyleException ex) {
final String optionalNames = barPackage + PACKAGE_SEPARATOR + name
+ STRING_SEPARATOR + fooPackage + PACKAGE_SEPARATOR + name;
final LocalizedMessage exceptionMessage = new LocalizedMessage(0,
Definitions.CHECKSTYLE_BUNDLE, AMBIGUOUS_MODULE_NAME_EXCEPTION_MESSAGE,
new String[] {name, optionalNames}, null, getClass(), null);
assertEquals("Invalid exception message",
exceptionMessage.getMessage(), ex.getMessage());
}
}
@Test
public void testCreateObjectFromFullModuleNamesWithCantInstantiateException() {
final String package1 = BASE_PACKAGE + ".wrong1";
final String package2 = BASE_PACKAGE + ".wrong2";
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
final PackageObjectFactory objectFactory = new PackageObjectFactory(
new LinkedHashSet<>(Arrays.asList(package1, package2)), classLoader);
final String name = "FooCheck";
final String checkName = name + CHECK_SUFFIX;
try {
objectFactory.createModule(name);
fail("Exception is expected");
}
catch (CheckstyleException ex) {
final String attemptedNames = package1 + PACKAGE_SEPARATOR + name + STRING_SEPARATOR
+ package2 + PACKAGE_SEPARATOR + name + STRING_SEPARATOR
+ checkName + STRING_SEPARATOR
+ package1 + PACKAGE_SEPARATOR + checkName + STRING_SEPARATOR
+ package2 + PACKAGE_SEPARATOR + checkName;
final LocalizedMessage exceptionMessage = new LocalizedMessage(0,
Definitions.CHECKSTYLE_BUNDLE, UNABLE_TO_INSTANTIATE_EXCEPTION_MESSAGE,
new String[] {name, attemptedNames}, null, getClass(), null);
assertEquals("Invalid exception message",
exceptionMessage.getMessage(), ex.getMessage());
}
}
@Test
public void testCreateObjectFromFullModuleNamesWithExceptionByBruteForce() {
final String package1 = BASE_PACKAGE + ".wrong1";
final String package2 = BASE_PACKAGE + ".wrong2";
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
final PackageObjectFactory objectFactory = new PackageObjectFactory(
new LinkedHashSet<>(Arrays.asList(package1, package2)), classLoader,
TRY_IN_ALL_REGISTERED_PACKAGES);
final String name = "FooCheck";
final String checkName = name + CHECK_SUFFIX;
try {
objectFactory.createModule(name);
fail("Exception is expected");
}
catch (CheckstyleException ex) {
final String attemptedNames = package1 + PACKAGE_SEPARATOR + name + STRING_SEPARATOR
+ package2 + PACKAGE_SEPARATOR + name + STRING_SEPARATOR
+ checkName + STRING_SEPARATOR
+ package1 + PACKAGE_SEPARATOR + checkName + STRING_SEPARATOR
+ package2 + PACKAGE_SEPARATOR + checkName;
final LocalizedMessage exceptionMessage = new LocalizedMessage(0,
Definitions.CHECKSTYLE_BUNDLE, UNABLE_TO_INSTANTIATE_EXCEPTION_MESSAGE,
new String[] {name, attemptedNames}, null, getClass(), null);
assertEquals("Invalid exception message",
exceptionMessage.getMessage(), ex.getMessage());
}
}
@Test
public void testCreateObjectByBruteForce() throws Exception {
final String className = "Checker";
final Method createModuleByBruteForce = PackageObjectFactory.class.getDeclaredMethod(
"createModuleByTryInEachPackage", String.class);
createModuleByBruteForce.setAccessible(true);
final Checker checker = (Checker) createModuleByBruteForce.invoke(factory, className);
assertNotNull("Checker should not be null when creating module from name", checker);
}
@Test
public void testCreateCheckByBruteForce() throws Exception {
final String checkName = "AnnotationLocation";
final Method createModuleByBruteForce = PackageObjectFactory.class.getDeclaredMethod(
"createModuleByTryInEachPackage", String.class);
final PackageObjectFactory packageObjectFactory = new PackageObjectFactory(
new HashSet<>(Arrays.asList(BASE_PACKAGE, BASE_PACKAGE + ".checks.annotation")),
Thread.currentThread().getContextClassLoader(), TRY_IN_ALL_REGISTERED_PACKAGES);
createModuleByBruteForce.setAccessible(true);
final AnnotationLocationCheck check = (AnnotationLocationCheck) createModuleByBruteForce
.invoke(packageObjectFactory, checkName);
assertNotNull("Check should not be null when creating module from name", check);
}
@Test
public void testCreateCheckWithPartialPackageNameByBruteForce() throws Exception {
final String checkName = "checks.annotation.AnnotationLocation";
final PackageObjectFactory packageObjectFactory = new PackageObjectFactory(
new HashSet<>(Collections.singletonList(BASE_PACKAGE)),
Thread.currentThread().getContextClassLoader(), TRY_IN_ALL_REGISTERED_PACKAGES);
final AnnotationLocationCheck check = (AnnotationLocationCheck) packageObjectFactory
.createModule(checkName);
assertNotNull("Check should not be null when creating module from name", check);
}
@Test
@SuppressWarnings("unchecked")
public void testGenerateThirdPartyNameToFullModuleNameWithException() throws Exception {
final URLClassLoader classLoader = mock(URLClassLoader.class);
when(classLoader.getURLs()).thenThrow(IOException.class);
final Method method = factory.getClass().getDeclaredMethod(
"generateThirdPartyNameToFullModuleName", ClassLoader.class);
method.setAccessible(true);
final int size = ((Map<String, String>) method.invoke(factory, classLoader)).size();
assertEquals("Invalid map size", 0, size);
}
@Test
public void testJoinPackageNamesWithClassName() throws Exception {
final Class<PackageObjectFactory> clazz = PackageObjectFactory.class;
final Method method =
clazz.getDeclaredMethod("joinPackageNamesWithClassName", String.class, Set.class);
method.setAccessible(true);
final Set<String> packages = Collections.singleton("test");
final String className = "SomeClass";
final String actual =
String.valueOf(method.invoke(PackageObjectFactory.class, className, packages));
assertEquals("Invalid class name", "test." + className, actual);
}
@Test
@SuppressWarnings("unchecked")
public void testNameToFullModuleNameMap() throws Exception {
final Set<Class<?>> classes = CheckUtil.getCheckstyleModules();
final Class<PackageObjectFactory> packageObjectFactoryClass = PackageObjectFactory.class;
final Field field = packageObjectFactoryClass.getDeclaredField("NAME_TO_FULL_MODULE_NAME");
field.setAccessible(true);
final Collection<String> canonicalNames = ((Map<String, String>) field.get(null)).values();
assertFalse("Invalid canonical name", classes.stream()
.anyMatch(clazz -> !canonicalNames.contains(clazz.getCanonicalName())));
}
@Test
public void testConstructorFailure() {
try {
factory.createModule(FailConstructorFileSet.class.getName());
fail("Exception is expected");
}
catch (CheckstyleException ex) {
assertEquals("Invalid exception message",
"Unable to instantiate com.puppycrawl.tools.checkstyle."
+ "PackageObjectFactoryTest$FailConstructorFileSet", ex.getMessage());
assertEquals("Invalid exception cause class",
"IllegalArgumentException", ex.getCause().getCause().getClass()
.getSimpleName());
}
}
private static final class FailConstructorFileSet extends AbstractFileSetCheck {
private FailConstructorFileSet() {
throw new IllegalArgumentException("Test");
}
@Override
protected void processFiltered(File file, FileText fileText) {
// not used
}
}
}