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