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