View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2024 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ///////////////////////////////////////////////////////////////////////////////////////////////
19  
20  package com.puppycrawl.tools.checkstyle;
21  
22  import static com.google.common.truth.Truth.assertWithMessage;
23  import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.AMBIGUOUS_MODULE_NAME_EXCEPTION_MESSAGE;
24  import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.BASE_PACKAGE;
25  import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.CHECK_SUFFIX;
26  import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.ModuleLoadOption.SEARCH_REGISTERED_PACKAGES;
27  import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.ModuleLoadOption.TRY_IN_ALL_REGISTERED_PACKAGES;
28  import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.NULL_LOADER_MESSAGE;
29  import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.NULL_PACKAGE_MESSAGE;
30  import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.PACKAGE_SEPARATOR;
31  import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.STRING_SEPARATOR;
32  import static com.puppycrawl.tools.checkstyle.PackageObjectFactory.UNABLE_TO_INSTANTIATE_EXCEPTION_MESSAGE;
33  import static org.junit.jupiter.api.Assertions.assertThrows;
34  import static org.mockito.Mockito.mockStatic;
35  
36  import java.io.File;
37  import java.io.IOException;
38  import java.lang.reflect.Field;
39  import java.lang.reflect.Method;
40  import java.util.Arrays;
41  import java.util.Collection;
42  import java.util.Collections;
43  import java.util.HashSet;
44  import java.util.LinkedHashSet;
45  import java.util.Map;
46  import java.util.Optional;
47  import java.util.Set;
48  
49  import org.junit.jupiter.api.Test;
50  import org.mockito.MockedStatic;
51  import org.mockito.Mockito;
52  
53  import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
54  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
55  import com.puppycrawl.tools.checkstyle.api.FileText;
56  import com.puppycrawl.tools.checkstyle.api.Violation;
57  import com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationLocationCheck;
58  import com.puppycrawl.tools.checkstyle.internal.utils.CheckUtil;
59  import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
60  import com.puppycrawl.tools.checkstyle.utils.ModuleReflectionUtil;
61  
62  /**
63   * Enter a description of class PackageObjectFactoryTest.java.
64   *
65   */
66  public class PackageObjectFactoryTest {
67  
68      private final PackageObjectFactory factory = new PackageObjectFactory(
69              BASE_PACKAGE, Thread.currentThread().getContextClassLoader());
70  
71      @Test
72      public void testCtorNullLoaderException1() {
73          try {
74              final Object test = new PackageObjectFactory(new HashSet<>(), null);
75              assertWithMessage("Exception is expected but got " + test).fail();
76          }
77          catch (IllegalArgumentException ex) {
78              assertWithMessage("Invalid exception message")
79                  .that(ex.getMessage())
80                  .isEqualTo(NULL_LOADER_MESSAGE);
81          }
82      }
83  
84      @Test
85      public void testCtorNullLoaderException2() {
86          try {
87              final Object test = new PackageObjectFactory("test", null);
88              assertWithMessage("Exception is expected but got " + test).fail();
89          }
90          catch (IllegalArgumentException ex) {
91              assertWithMessage("Invalid exception message")
92                  .that(ex.getMessage())
93                  .isEqualTo(NULL_LOADER_MESSAGE);
94          }
95      }
96  
97      @Test
98      public void testCtorNullPackageException1() {
99          final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
100         try {
101             final Object test = new PackageObjectFactory(Collections.singleton(null), classLoader);
102             assertWithMessage("Exception is expected but got " + test).fail();
103         }
104         catch (IllegalArgumentException ex) {
105             assertWithMessage("Invalid exception message")
106                 .that(ex.getMessage())
107                 .isEqualTo(NULL_PACKAGE_MESSAGE);
108         }
109     }
110 
111     @Test
112     public void testCtorNullPackageException2() {
113         final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
114         try {
115             final Object test = new PackageObjectFactory((String) null, classLoader);
116             assertWithMessage("Exception is expected but got " + test).fail();
117         }
118         catch (IllegalArgumentException ex) {
119             assertWithMessage("Invalid exception message")
120                 .that(ex.getMessage())
121                 .isEqualTo(NULL_PACKAGE_MESSAGE);
122         }
123     }
124 
125     @Test
126     public void testCtorNullPackageException3() {
127         final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
128         try {
129             final Object test = new PackageObjectFactory(Collections.singleton(null), classLoader,
130                     TRY_IN_ALL_REGISTERED_PACKAGES);
131             assertWithMessage("Exception is expected but got " + test).fail();
132         }
133         catch (IllegalArgumentException ex) {
134             assertWithMessage("Invalid exception message")
135                 .that(ex.getMessage())
136                 .isEqualTo(NULL_PACKAGE_MESSAGE);
137         }
138     }
139 
140     @Test
141     public void testMakeObjectFromName()
142             throws CheckstyleException {
143         final Checker checker =
144             (Checker) factory.createModule(
145                         "com.puppycrawl.tools.checkstyle.Checker");
146         assertWithMessage("Checker should not be null when creating module from name")
147             .that(checker)
148             .isNotNull();
149     }
150 
151     @Test
152     public void testMakeCheckFromName() {
153         final String name = "com.puppycrawl.tools.checkstyle.checks.naming.ConstantName";
154         try {
155             factory.createModule(name);
156             assertWithMessage("Exception is expected").fail();
157         }
158         catch (CheckstyleException ex) {
159             final LocalizedMessage exceptionMessage = new LocalizedMessage(
160                     Definitions.CHECKSTYLE_BUNDLE, factory.getClass(),
161                     UNABLE_TO_INSTANTIATE_EXCEPTION_MESSAGE, name, null);
162             assertWithMessage("Invalid exception message")
163                 .that(ex.getMessage())
164                 .isEqualTo(exceptionMessage.getMessage());
165         }
166     }
167 
168     @Test
169     public void testCreateModuleWithNonExistName() {
170         final String[] names = {"NonExistClassOne", "NonExistClassTwo", };
171         for (String name : names) {
172             try {
173                 factory.createModule(name);
174                 assertWithMessage("Exception is expected").fail();
175             }
176             catch (CheckstyleException ex) {
177                 final String attemptedNames = BASE_PACKAGE + PACKAGE_SEPARATOR + name
178                     + STRING_SEPARATOR + name + CHECK_SUFFIX + STRING_SEPARATOR
179                     + BASE_PACKAGE + PACKAGE_SEPARATOR + name + CHECK_SUFFIX;
180                 final LocalizedMessage exceptionMessage = new LocalizedMessage(
181                     Definitions.CHECKSTYLE_BUNDLE, factory.getClass(),
182                     UNABLE_TO_INSTANTIATE_EXCEPTION_MESSAGE, name, attemptedNames);
183                 assertWithMessage("Invalid exception message")
184                     .that(ex.getMessage())
185                     .isEqualTo(exceptionMessage.getMessage());
186             }
187         }
188     }
189 
190     @Test
191     public void testCreateObjectFromMap() throws Exception {
192         final String moduleName = "Foo";
193         final String name = moduleName + CHECK_SUFFIX;
194         final String packageName = BASE_PACKAGE + ".packageobjectfactory.bar";
195         final String fullName = packageName + PACKAGE_SEPARATOR + name;
196         final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
197         final PackageObjectFactory objectFactory =
198                 new PackageObjectFactory(packageName, classLoader);
199         final Object instance1 = objectFactory.createModule(name);
200         assertWithMessage("Invalid canonical name")
201             .that(instance1.getClass().getCanonicalName())
202             .isEqualTo(fullName);
203         final Object instance2 = objectFactory.createModule(moduleName);
204         assertWithMessage("Invalid canonical name")
205             .that(instance2.getClass().getCanonicalName())
206             .isEqualTo(fullName);
207     }
208 
209     @Test
210     public void testCreateStandardModuleObjectFromMap() throws Exception {
211         final String moduleName = "TreeWalker";
212         final String packageName = BASE_PACKAGE + ".packageobjectfactory.bar";
213         final String fullName = BASE_PACKAGE + PACKAGE_SEPARATOR + moduleName;
214         final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
215         final PackageObjectFactory objectFactory =
216                 new PackageObjectFactory(packageName, classLoader);
217         final Object instance = objectFactory.createModule(moduleName);
218         assertWithMessage("Invalid canonical name")
219             .that(instance.getClass().getCanonicalName())
220             .isEqualTo(fullName);
221     }
222 
223     @Test
224     public void testCreateStandardCheckModuleObjectFromMap() throws Exception {
225         final String moduleName = "TypeName";
226         final String packageName = BASE_PACKAGE + ".packageobjectfactory.bar";
227         final String fullName = BASE_PACKAGE + PACKAGE_SEPARATOR + "checks" + PACKAGE_SEPARATOR
228             + "naming" + PACKAGE_SEPARATOR + moduleName + CHECK_SUFFIX;
229         final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
230         final PackageObjectFactory objectFactory =
231                 new PackageObjectFactory(packageName, classLoader);
232         final Object instance = objectFactory.createModule(moduleName);
233         assertWithMessage("Invalid canonical name")
234             .that(instance.getClass().getCanonicalName())
235             .isEqualTo(fullName);
236     }
237 
238     @Test
239     public void testCreateObjectFromFullModuleNamesWithAmbiguousException() {
240         final String barPackage = BASE_PACKAGE + ".packageobjectfactory.bar";
241         final String fooPackage = BASE_PACKAGE + ".packageobjectfactory.foo";
242         final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
243         final PackageObjectFactory objectFactory = new PackageObjectFactory(
244                 new LinkedHashSet<>(Arrays.asList(barPackage, fooPackage)), classLoader);
245         final String name = "FooCheck";
246         try {
247             objectFactory.createModule(name);
248             assertWithMessage("Exception is expected").fail();
249         }
250         catch (CheckstyleException ex) {
251             final String optionalNames = barPackage + PACKAGE_SEPARATOR + name
252                     + STRING_SEPARATOR + fooPackage + PACKAGE_SEPARATOR + name;
253             final LocalizedMessage exceptionMessage = new LocalizedMessage(
254                     Definitions.CHECKSTYLE_BUNDLE, getClass(),
255                     AMBIGUOUS_MODULE_NAME_EXCEPTION_MESSAGE, name, optionalNames);
256             assertWithMessage("Invalid exception message")
257                 .that(ex.getMessage())
258                 .isEqualTo(exceptionMessage.getMessage());
259         }
260     }
261 
262     @Test
263     public void testCreateObjectFromFullModuleNamesWithCantInstantiateException() {
264         final String package1 = BASE_PACKAGE + ".wrong1";
265         final String package2 = BASE_PACKAGE + ".wrong2";
266         final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
267         final PackageObjectFactory objectFactory = new PackageObjectFactory(
268                 new LinkedHashSet<>(Arrays.asList(package1, package2)), classLoader);
269         final String name = "FooCheck";
270         final String checkName = name + CHECK_SUFFIX;
271         try {
272             objectFactory.createModule(name);
273             assertWithMessage("Exception is expected").fail();
274         }
275         catch (CheckstyleException ex) {
276             final String attemptedNames = package1 + PACKAGE_SEPARATOR + name + STRING_SEPARATOR
277                     + package2 + PACKAGE_SEPARATOR + name + STRING_SEPARATOR
278                     + checkName + STRING_SEPARATOR
279                     + package1 + PACKAGE_SEPARATOR + checkName + STRING_SEPARATOR
280                     + package2 + PACKAGE_SEPARATOR + checkName;
281             final LocalizedMessage exceptionMessage = new LocalizedMessage(
282                     Definitions.CHECKSTYLE_BUNDLE, getClass(),
283                     UNABLE_TO_INSTANTIATE_EXCEPTION_MESSAGE, name, attemptedNames);
284             assertWithMessage("Invalid exception message")
285                 .that(ex.getMessage())
286                 .isEqualTo(exceptionMessage.getMessage());
287         }
288     }
289 
290     @Test
291     public void testCreateObjectFromFullModuleNamesWithExceptionByBruteForce() {
292         final String package1 = BASE_PACKAGE + ".wrong1";
293         final String package2 = BASE_PACKAGE + ".wrong2";
294         final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
295         final PackageObjectFactory objectFactory = new PackageObjectFactory(
296                 new LinkedHashSet<>(Arrays.asList(package1, package2)), classLoader,
297                 TRY_IN_ALL_REGISTERED_PACKAGES);
298         final String name = "FooCheck";
299         final String checkName = name + CHECK_SUFFIX;
300         try {
301             objectFactory.createModule(name);
302             assertWithMessage("Exception is expected").fail();
303         }
304         catch (CheckstyleException ex) {
305             final String attemptedNames = package1 + PACKAGE_SEPARATOR + name + STRING_SEPARATOR
306                     + package2 + PACKAGE_SEPARATOR + name + STRING_SEPARATOR
307                     + checkName + STRING_SEPARATOR
308                     + package1 + PACKAGE_SEPARATOR + checkName + STRING_SEPARATOR
309                     + package2 + PACKAGE_SEPARATOR + checkName;
310             final Violation exceptionMessage = new Violation(1,
311                     Definitions.CHECKSTYLE_BUNDLE, UNABLE_TO_INSTANTIATE_EXCEPTION_MESSAGE,
312                     new String[] {name, attemptedNames}, null, getClass(), null);
313             assertWithMessage("Invalid exception message")
314                 .that(ex.getMessage())
315                 .isEqualTo(exceptionMessage.getViolation());
316         }
317     }
318 
319     @Test
320     public void testCreateObjectByBruteForce() throws Exception {
321         final String className = "Checker";
322         final Method createModuleByBruteForce = PackageObjectFactory.class.getDeclaredMethod(
323                 "createModuleByTryInEachPackage", String.class);
324         createModuleByBruteForce.setAccessible(true);
325         final Checker checker = (Checker) createModuleByBruteForce.invoke(factory, className);
326         assertWithMessage("Checker should not be null when creating module from name")
327             .that(checker)
328             .isNotNull();
329     }
330 
331     @Test
332     public void testCreateCheckByBruteForce() throws Exception {
333         final String checkName = "AnnotationLocation";
334         final Method createModuleByBruteForce = PackageObjectFactory.class.getDeclaredMethod(
335                 "createModuleByTryInEachPackage", String.class);
336         final PackageObjectFactory packageObjectFactory = new PackageObjectFactory(
337             new HashSet<>(Arrays.asList(BASE_PACKAGE, BASE_PACKAGE + ".checks.annotation")),
338             Thread.currentThread().getContextClassLoader(), TRY_IN_ALL_REGISTERED_PACKAGES);
339         createModuleByBruteForce.setAccessible(true);
340         final AnnotationLocationCheck check = (AnnotationLocationCheck) createModuleByBruteForce
341                 .invoke(packageObjectFactory, checkName);
342         assertWithMessage("Check should not be null when creating module from name")
343             .that(check)
344             .isNotNull();
345     }
346 
347     @Test
348     public void testCreateCheckWithPartialPackageNameByBruteForce() throws Exception {
349         final String checkName = "checks.annotation.AnnotationLocation";
350         final PackageObjectFactory packageObjectFactory = new PackageObjectFactory(
351             new HashSet<>(Collections.singletonList(BASE_PACKAGE)),
352             Thread.currentThread().getContextClassLoader(), TRY_IN_ALL_REGISTERED_PACKAGES);
353         final AnnotationLocationCheck check = (AnnotationLocationCheck) packageObjectFactory
354                 .createModule(checkName);
355         assertWithMessage("Check should not be null when creating module from name")
356             .that(check)
357             .isNotNull();
358     }
359 
360     @Test
361     public void testJoinPackageNamesWithClassName() throws Exception {
362         final Class<PackageObjectFactory> clazz = PackageObjectFactory.class;
363         final Method method =
364             clazz.getDeclaredMethod("joinPackageNamesWithClassName", String.class, Set.class);
365         method.setAccessible(true);
366         final Set<String> packages = Collections.singleton("test");
367         final String className = "SomeClass";
368         final String actual =
369             String.valueOf(method.invoke(PackageObjectFactory.class, className, packages));
370         assertWithMessage("Invalid class name")
371             .that(actual)
372             .isEqualTo("test." + className);
373     }
374 
375     @Test
376     @SuppressWarnings("unchecked")
377     public void testNameToFullModuleNameMap() throws Exception {
378         final Set<Class<?>> classes = CheckUtil.getCheckstyleModules();
379         final Class<PackageObjectFactory> packageObjectFactoryClass = PackageObjectFactory.class;
380         final Field field = packageObjectFactoryClass.getDeclaredField("NAME_TO_FULL_MODULE_NAME");
381         field.setAccessible(true);
382         final Collection<String> canonicalNames = ((Map<String, String>) field.get(null)).values();
383 
384         final Optional<Class<?>> optional1 = classes.stream()
385                 .filter(clazz -> {
386                     return !canonicalNames.contains(clazz.getCanonicalName())
387                             && !Definitions.INTERNAL_MODULES.contains(clazz.getName());
388                 }).findFirst();
389         assertWithMessage("Invalid canonical name: %s", optional1)
390                 .that(optional1.isPresent())
391                 .isFalse();
392         final Optional<String> optional2 = canonicalNames.stream().filter(canonicalName -> {
393             return classes.stream().map(Class::getCanonicalName)
394                     .noneMatch(clssCanonicalName -> clssCanonicalName.equals(canonicalName));
395         }).findFirst();
396         assertWithMessage("Invalid class: %s", optional2)
397                 .that(optional2.isPresent())
398                 .isFalse();
399     }
400 
401     @Test
402     public void testConstructorFailure() {
403         try {
404             factory.createModule(FailConstructorFileSet.class.getName());
405             assertWithMessage("Exception is expected").fail();
406         }
407         catch (CheckstyleException ex) {
408             assertWithMessage("Invalid exception message")
409                 .that(ex.getMessage())
410                 .isEqualTo("Unable to instantiate com.puppycrawl.tools.checkstyle."
411                     + "PackageObjectFactoryTest$FailConstructorFileSet");
412             assertWithMessage("Invalid exception cause class")
413                 .that(ex.getCause().getClass().getSimpleName())
414                 .isEqualTo("IllegalAccessException");
415         }
416     }
417 
418     @Test
419     public void testGetShortFromFullModuleNames() {
420         final String fullName =
421                 "com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheck";
422 
423         assertWithMessage("Invalid simple check name")
424             .that(PackageObjectFactory.getShortFromFullModuleNames(fullName))
425             .isEqualTo("DefaultComesLastCheck");
426     }
427 
428     @Test
429     public void testGetShortFromFullModuleNamesThirdParty() {
430         final String fullName =
431                 "java.util.stream.Collectors";
432 
433         assertWithMessage("Invalid simple check name")
434             .that(PackageObjectFactory.getShortFromFullModuleNames(fullName))
435             .isEqualTo(fullName);
436     }
437 
438     /**
439      * This method is for testing the case of an exception caught inside
440      * {@code PackageObjectFactory.generateThirdPartyNameToFullModuleName}, a private method used
441      * to initialize private field {@code PackageObjectFactory.thirdPartyNameToFullModuleNames}.
442      * Since the method and the field both are private, the {@link TestUtil} is required to ensure
443      * that the field is changed. Also, the expected exception should be thrown from the static
444      * method {@link ModuleReflectionUtil#isCheckstyleModule}, so {@link Mockito#mockStatic}
445      * is required to mock this exception.
446      *
447      * @throws Exception when the code tested throws an exception
448      */
449     @Test
450     public void testGenerateThirdPartyNameToFullModuleNameWithException() throws Exception {
451         final String name = "String";
452         final String packageName = "java.lang";
453         final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
454         final Set<String> packages = Collections.singleton(packageName);
455         final PackageObjectFactory objectFactory = new PackageObjectFactory(packages, classLoader,
456                 TRY_IN_ALL_REGISTERED_PACKAGES);
457 
458         try (MockedStatic<ModuleReflectionUtil> utilities =
459                      mockStatic(ModuleReflectionUtil.class)) {
460             utilities.when(() -> ModuleReflectionUtil.getCheckstyleModules(packages, classLoader))
461                     .thenThrow(new IOException("mock exception"));
462 
463             final String internalFieldName = "thirdPartyNameToFullModuleNames";
464             final Map<String, String> nullMap = TestUtil.getInternalState(objectFactory,
465                     internalFieldName);
466             assertWithMessage("Expected uninitialized field")
467                     .that(nullMap)
468                     .isNull();
469 
470             final Object instance = objectFactory.createModule(name);
471             assertWithMessage("Expected empty string")
472                     .that(instance)
473                     .isEqualTo("");
474 
475             final Map<String, String> emptyMap = TestUtil.getInternalState(objectFactory,
476                     internalFieldName);
477             assertWithMessage("Expected empty map")
478                     .that(emptyMap)
479                     .isEmpty();
480         }
481     }
482 
483     @Test
484     public void testCreateObjectWithNameContainingPackageSeparator() throws Exception {
485         final ClassLoader classLoader = ClassLoader.getSystemClassLoader();
486         final Set<String> packages = Collections.singleton(BASE_PACKAGE);
487         final PackageObjectFactory objectFactory =
488             new PackageObjectFactory(packages, classLoader, TRY_IN_ALL_REGISTERED_PACKAGES);
489 
490         final Object object = objectFactory.createModule(MockClass.class.getName());
491         assertWithMessage("Object should be an instance of MockClass")
492             .that(object)
493             .isInstanceOf(MockClass.class);
494     }
495 
496     /**
497      * This test case is designed to verify the behavior of the PackageObjectFactory's
498      * createModule method when it is provided with a fully qualified class name
499      * (containing a package separator).
500      * It ensures that ModuleReflectionUtil.getCheckstyleModules is not executed in this case.
501      */
502     @Test
503     public void testCreateObjectWithNameContainingPackageSeparatorWithoutSearch() throws Exception {
504         final ClassLoader classLoader = ClassLoader.getSystemClassLoader();
505         final Set<String> packages = Collections.singleton(BASE_PACKAGE);
506         final PackageObjectFactory objectFactory =
507             new PackageObjectFactory(packages, classLoader, TRY_IN_ALL_REGISTERED_PACKAGES);
508 
509         try (MockedStatic<ModuleReflectionUtil> utilities =
510                      mockStatic(ModuleReflectionUtil.class)) {
511             utilities.when(() -> ModuleReflectionUtil.getCheckstyleModules(packages, classLoader))
512                     .thenThrow(new IllegalStateException("creation of objects by fully qualified"
513                             + " class names should not result in search of modules in classpath"));
514 
515             final String fullyQualifiedName = MockClass.class.getName();
516             assertWithMessage("class name is not in expected format")
517                     .that(fullyQualifiedName).contains(".");
518             final Object object = objectFactory.createModule(fullyQualifiedName);
519             assertWithMessage("Object should be an instance of MockClass")
520                     .that(object)
521                     .isInstanceOf(MockClass.class);
522         }
523     }
524 
525     @Test
526     public void testCreateModuleWithTryInAllRegisteredPackages() {
527         final ClassLoader classLoader = ClassLoader.getSystemClassLoader();
528         final Set<String> packages = Collections.singleton(BASE_PACKAGE);
529         final PackageObjectFactory objectFactory =
530             new PackageObjectFactory(packages, classLoader, SEARCH_REGISTERED_PACKAGES);
531         final CheckstyleException ex = assertThrows(CheckstyleException.class, () -> {
532             objectFactory.createModule("PackageObjectFactoryTest$MockClass");
533         });
534 
535         assertWithMessage("Invalid exception message")
536             .that(ex.getMessage())
537             .startsWith(
538                 "Unable to instantiate 'PackageObjectFactoryTest$MockClass' class, it is also "
539                     + "not possible to instantiate it as "
540                     + "com.puppycrawl.tools.checkstyle.PackageObjectFactoryTest$MockClass, "
541                     + "PackageObjectFactoryTest$MockClassCheck, "
542                     + "com.puppycrawl.tools.checkstyle.PackageObjectFactoryTest$MockClassCheck"
543             );
544 
545     }
546 
547     @Test
548     public void testExceptionMessage() {
549         final String barPackage = BASE_PACKAGE + ".packageobjectfactory.bar";
550         final String fooPackage = BASE_PACKAGE + ".packageobjectfactory.foo";
551         final String zooPackage = BASE_PACKAGE + ".packageobjectfactory.zoo";
552         final String abcPackage = BASE_PACKAGE + ".packageobjectfactory.abc";
553         final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
554         final PackageObjectFactory objectFactory = new PackageObjectFactory(
555                 new HashSet<>(Arrays.asList(abcPackage, barPackage,
556                         fooPackage, zooPackage)), classLoader);
557         final String name = "FooCheck";
558         try {
559             objectFactory.createModule(name);
560             assertWithMessage("Exception is expected").fail();
561         }
562         catch (CheckstyleException ex) {
563             final String optionalNames = abcPackage + PACKAGE_SEPARATOR + name
564                     + STRING_SEPARATOR + barPackage + PACKAGE_SEPARATOR + name
565                     + STRING_SEPARATOR + fooPackage + PACKAGE_SEPARATOR + name
566                     + STRING_SEPARATOR + zooPackage + PACKAGE_SEPARATOR + name;
567             final LocalizedMessage exceptionMessage = new LocalizedMessage(
568                     Definitions.CHECKSTYLE_BUNDLE, getClass(),
569                     AMBIGUOUS_MODULE_NAME_EXCEPTION_MESSAGE, name, optionalNames);
570             assertWithMessage("Invalid exception message")
571                 .that(ex.getMessage())
572                 .isEqualTo(exceptionMessage.getMessage());
573         }
574     }
575 
576     private static final class FailConstructorFileSet extends AbstractFileSetCheck {
577 
578         private FailConstructorFileSet() {
579             throw new IllegalArgumentException("Test");
580         }
581 
582         @Override
583         protected void processFiltered(File file, FileText fileText) {
584             // not used
585         }
586 
587     }
588 
589     public static class MockClass {
590         // Mock class for testing purposes.
591     }
592 }