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",
336                         Checker.class, className);
337         assertWithMessage("Checker should not be null when creating module from name")
338             .that(checker)
339             .isNotNull();
340     }
341 
342     @Test
343     public void testCreateCheckByBruteForce() throws Exception {
344         final String checkName = "AnnotationLocation";
345         final PackageObjectFactory packageObjectFactory = new PackageObjectFactory(
346             new HashSet<>(Arrays.asList(BASE_PACKAGE, BASE_PACKAGE + ".checks.annotation")),
347             Thread.currentThread().getContextClassLoader(), TRY_IN_ALL_REGISTERED_PACKAGES);
348         final AnnotationLocationCheck check = TestUtil.invokeMethod(
349                 packageObjectFactory, "createModuleByTryInEachPackage",
350                 AnnotationLocationCheck.class, checkName);
351         assertWithMessage("Check should not be null when creating module from name")
352             .that(check)
353             .isNotNull();
354     }
355 
356     @Test
357     public void testCreateCheckWithPartialPackageNameByBruteForce() throws Exception {
358         final String checkName = "checks.annotation.AnnotationLocation";
359         final PackageObjectFactory packageObjectFactory = new PackageObjectFactory(
360             new HashSet<>(Collections.singletonList(BASE_PACKAGE)),
361             Thread.currentThread().getContextClassLoader(), TRY_IN_ALL_REGISTERED_PACKAGES);
362         final AnnotationLocationCheck check = (AnnotationLocationCheck) packageObjectFactory
363                 .createModule(checkName);
364         assertWithMessage("Check should not be null when creating module from name")
365             .that(check)
366             .isNotNull();
367     }
368 
369     @Test
370     public void testJoinPackageNamesWithClassName() throws Exception {
371         final Set<String> packages = Collections.singleton("test");
372         final String className = "SomeClass";
373         final String actual = TestUtil.invokeStaticMethod(
374                 PackageObjectFactory.class, "joinPackageNamesWithClassName", String.class,
375                 className, packages);
376         assertWithMessage("Invalid class name")
377             .that(actual)
378             .isEqualTo("test." + className);
379     }
380 
381     @Test
382     public void testNameToFullModuleNameMap() throws Exception {
383         final Set<Class<?>> classes = CheckUtil.getCheckstyleModules();
384         final Class<PackageObjectFactory> packageObjectFactoryClass = PackageObjectFactory.class;
385         final Collection<String> canonicalNames =
386                 TestUtil.getInternalStaticStateMap(
387                         packageObjectFactoryClass, "NAME_TO_FULL_MODULE_NAME").values();
388 
389         final Optional<Class<?>> optional1 = classes.stream()
390                 .filter(clazz -> {
391                     return !canonicalNames.contains(clazz.getCanonicalName())
392                             && !Definitions.INTERNAL_MODULES.contains(clazz.getName());
393                 }).findFirst();
394         assertWithMessage("Invalid canonical name: %s", optional1)
395                 .that(optional1.isPresent())
396                 .isFalse();
397         final Optional<String> optional2 = canonicalNames.stream().filter(canonicalName -> {
398             return classes.stream().map(Class::getCanonicalName)
399                     .noneMatch(clssCanonicalName -> clssCanonicalName.equals(canonicalName));
400         }).findFirst();
401         assertWithMessage("Invalid class: %s", optional2)
402                 .that(optional2.isPresent())
403                 .isFalse();
404     }
405 
406     @Test
407     public void testConstructorFailure() {
408         try {
409             factory.createModule(FailConstructorFileSet.class.getName());
410             assertWithMessage("Exception is expected").fail();
411         }
412         catch (CheckstyleException exc) {
413             assertWithMessage("Invalid exception message")
414                 .that(exc.getMessage())
415                 .isEqualTo("Unable to instantiate com.puppycrawl.tools.checkstyle."
416                     + "PackageObjectFactoryTest$FailConstructorFileSet");
417             assertWithMessage("Invalid exception cause class")
418                 .that(exc.getCause().getClass().getSimpleName())
419                 .isEqualTo("IllegalAccessException");
420         }
421     }
422 
423     @Test
424     public void testGetShortFromFullModuleNames() {
425         final String fullName =
426                 "com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheck";
427 
428         assertWithMessage("Invalid simple check name")
429             .that(PackageObjectFactory.getShortFromFullModuleNames(fullName))
430             .isEqualTo("DefaultComesLastCheck");
431     }
432 
433     @Test
434     public void testGetShortFromFullModuleNamesThirdParty() {
435         final String fullName =
436                 "java.util.stream.Collectors";
437 
438         assertWithMessage("Invalid simple check name")
439             .that(PackageObjectFactory.getShortFromFullModuleNames(fullName))
440             .isEqualTo(fullName);
441     }
442 
443     /**
444      * This method is for testing the case of an exception caught inside
445      * {@code PackageObjectFactory.generateThirdPartyNameToFullModuleName}, a private method used
446      * to initialize private field {@code PackageObjectFactory.thirdPartyNameToFullModuleNames}.
447      * Since the method and the field both are private, the {@link TestUtil} is required to ensure
448      * that the field is changed. Also, the expected exception should be thrown from the static
449      * method {@link ModuleReflectionUtil#isCheckstyleModule}, so {@link Mockito#mockStatic}
450      * is required to mock this exception.
451      *
452      * @throws Exception when the code tested throws an exception
453      */
454     @Test
455     public void testGenerateThirdPartyNameToFullModuleNameWithException() throws Exception {
456         final String name = "String";
457         final String packageName = "java.lang";
458         final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
459         final Set<String> packages = Collections.singleton(packageName);
460         final PackageObjectFactory objectFactory = new PackageObjectFactory(packages, classLoader,
461                 TRY_IN_ALL_REGISTERED_PACKAGES);
462 
463         try (MockedStatic<ModuleReflectionUtil> utilities =
464                      mockStatic(ModuleReflectionUtil.class)) {
465             utilities.when(() -> ModuleReflectionUtil.getCheckstyleModules(packages, classLoader))
466                     .thenThrow(new IOException("mock exception"));
467 
468             final String internalFieldName = "thirdPartyNameToFullModuleNames";
469             final Map<String, String> nullMap =
470                     TestUtil.getInternalStateMap(objectFactory, internalFieldName);
471             assertWithMessage("Expected uninitialized field")
472                     .that(nullMap)
473                     .isNull();
474 
475             final Object instance = objectFactory.createModule(name);
476             assertWithMessage("Expected empty string")
477                     .that(instance)
478                     .isEqualTo("");
479 
480             final Map<String, String> emptyMap =
481                     TestUtil.getInternalStateMap(objectFactory, internalFieldName);
482             assertWithMessage("Expected empty map")
483                     .that(emptyMap)
484                     .isEmpty();
485         }
486     }
487 
488     @Test
489     public void testCreateObjectWithNameContainingPackageSeparator() throws Exception {
490         final ClassLoader classLoader = ClassLoader.getSystemClassLoader();
491         final Set<String> packages = Collections.singleton(BASE_PACKAGE);
492         final PackageObjectFactory objectFactory =
493             new PackageObjectFactory(packages, classLoader, TRY_IN_ALL_REGISTERED_PACKAGES);
494 
495         final Object object = objectFactory.createModule(MockClass.class.getName());
496         assertWithMessage("Object should be an instance of MockClass")
497             .that(object)
498             .isInstanceOf(MockClass.class);
499     }
500 
501     /**
502      * This test case is designed to verify the behavior of the PackageObjectFactory's
503      * createModule method when it is provided with a fully qualified class name
504      * (containing a package separator).
505      * It ensures that ModuleReflectionUtil.getCheckstyleModules is not executed in this case.
506      */
507     @Test
508     public void testCreateObjectWithNameContainingPackageSeparatorWithoutSearch() throws Exception {
509         final ClassLoader classLoader = ClassLoader.getSystemClassLoader();
510         final Set<String> packages = Collections.singleton(BASE_PACKAGE);
511         final PackageObjectFactory objectFactory =
512             new PackageObjectFactory(packages, classLoader, TRY_IN_ALL_REGISTERED_PACKAGES);
513 
514         try (MockedStatic<ModuleReflectionUtil> utilities =
515                      mockStatic(ModuleReflectionUtil.class)) {
516             utilities.when(() -> ModuleReflectionUtil.getCheckstyleModules(packages, classLoader))
517                     .thenThrow(new IllegalStateException("creation of objects by fully qualified"
518                             + " class names should not result in search of modules in classpath"));
519 
520             final String fullyQualifiedName = MockClass.class.getName();
521             assertWithMessage("class name is not in expected format")
522                     .that(fullyQualifiedName).contains(".");
523             final Object object = objectFactory.createModule(fullyQualifiedName);
524             assertWithMessage("Object should be an instance of MockClass")
525                     .that(object)
526                     .isInstanceOf(MockClass.class);
527         }
528     }
529 
530     @Test
531     public void testCreateModuleWithTryInAllRegisteredPackages() {
532         final ClassLoader classLoader = ClassLoader.getSystemClassLoader();
533         final Set<String> packages = Collections.singleton(BASE_PACKAGE);
534         final PackageObjectFactory objectFactory =
535             new PackageObjectFactory(packages, classLoader, SEARCH_REGISTERED_PACKAGES);
536         final CheckstyleException ex =
537                 TestUtil.getExpectedThrowable(CheckstyleException.class, () -> {
538                     objectFactory.createModule("PackageObjectFactoryTest$MockClass");
539                 });
540 
541         assertWithMessage("Invalid exception message")
542             .that(ex.getMessage())
543             .startsWith(
544                 "Unable to instantiate 'PackageObjectFactoryTest$MockClass' class, it is also "
545                     + "not possible to instantiate it as "
546                     + "com.puppycrawl.tools.checkstyle.PackageObjectFactoryTest$MockClass, "
547                     + "PackageObjectFactoryTest$MockClassCheck, "
548                     + "com.puppycrawl.tools.checkstyle.PackageObjectFactoryTest$MockClassCheck"
549             );
550 
551     }
552 
553     @Test
554     public void testExceptionMessage() {
555         final String barPackage = BASE_PACKAGE + ".internal.testmodules.packageobjectfactory.bar";
556         final String fooPackage = BASE_PACKAGE + ".internal.testmodules.packageobjectfactory.foo";
557         final String zooPackage = BASE_PACKAGE + ".internal.testmodules.packageobjectfactory.zoo";
558         final String abcPackage = BASE_PACKAGE + ".internal.testmodules.packageobjectfactory.abc";
559         final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
560         final PackageObjectFactory objectFactory = new PackageObjectFactory(
561                 new HashSet<>(Arrays.asList(abcPackage, barPackage,
562                         fooPackage, zooPackage)), classLoader);
563         final String name = "FooCheck";
564         try {
565             objectFactory.createModule(name);
566             assertWithMessage("Exception is expected").fail();
567         }
568         catch (CheckstyleException exc) {
569             final String optionalNames = abcPackage + PACKAGE_SEPARATOR + name
570                     + STRING_SEPARATOR + barPackage + PACKAGE_SEPARATOR + name
571                     + STRING_SEPARATOR + fooPackage + PACKAGE_SEPARATOR + name
572                     + STRING_SEPARATOR + zooPackage + PACKAGE_SEPARATOR + name;
573             final LocalizedMessage exceptionMessage = new LocalizedMessage(
574                     Definitions.CHECKSTYLE_BUNDLE, getClass(),
575                     AMBIGUOUS_MODULE_NAME_EXCEPTION_MESSAGE, name, optionalNames);
576             assertWithMessage("Invalid exception message")
577                 .that(exc.getMessage())
578                 .isEqualTo(exceptionMessage.getMessage());
579         }
580     }
581 
582     private static final class FailConstructorFileSet extends AbstractFileSetCheck {
583 
584         private FailConstructorFileSet() {
585             throw new IllegalArgumentException("Test");
586         }
587 
588         @Override
589         protected void processFiltered(File file, FileText fileText) {
590             // not used
591         }
592 
593     }
594 
595     public static class MockClass {
596         // Mock class for testing purposes.
597     }
598 }