1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.bcel.classfile;
18
19 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import static org.junit.jupiter.api.Assertions.assertTrue;
21
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.net.URL;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.stream.Stream;
31
32 import org.apache.bcel.Const;
33 import org.apache.commons.lang3.stream.Streams;
34 import org.junit.jupiter.params.ParameterizedTest;
35 import org.junit.jupiter.params.provider.MethodSource;
36
37
38
39
40 public final class ConstantPoolModuleAccessTestCase {
41
42 static Stream<URL> testJREModules() throws IOException {
43 return Streams.of(ConstantPoolModuleAccessTestCase.class.getClassLoader().getResources("module-info.class"));
44 }
45
46 @ParameterizedTest
47 @MethodSource
48 public void testJREModules(final URL url) throws Exception {
49 try (InputStream inputStream = url.openStream()) {
50 final ClassParser classParser = new ClassParser(inputStream, "module-info.class");
51 final JavaClass javaClass = classParser.parse();
52 final ConstantPool constantPool = javaClass.getConstantPool();
53 final EmptyVisitor visitor = new EmptyVisitor() {
54 @Override
55 public void visitModule(final Module obj) {
56 final String urlPath = url.getPath();
57 if (urlPath.contains("/commons-")) {
58 assertEquals(4096, obj.getModuleFlags(), url.toString());
59 } else {
60 assertEquals(0, obj.getModuleFlags(), url.toString());
61 }
62 final String[] usedClassNames = obj.getUsedClassNames(constantPool, true);
63 if (urlPath.contains("junit-jupiter-engine")) {
64 assertEquals(1, usedClassNames.length);
65 assertEquals("org.junit.jupiter.api.extension.Extension", usedClassNames[0]);
66 } else if (urlPath.contains("junit-platform-launcher")) {
67 final List<String> expected = new ArrayList<>();
68 expected.add("org.junit.platform.engine.TestEngine");
69 expected.add("org.junit.platform.launcher.LauncherDiscoveryListener");
70 expected.add("org.junit.platform.launcher.LauncherInterceptor");
71 expected.add("org.junit.platform.launcher.LauncherSessionListener");
72 expected.add("org.junit.platform.launcher.PostDiscoveryFilter");
73 expected.add("org.junit.platform.launcher.TestExecutionListener");
74 assertEquals(expected, Arrays.asList(usedClassNames));
75 } else if (urlPath.contains("junit-platform-engine")) {
76 final List<String> expected = new ArrayList<>();
77 expected.add("org.junit.platform.engine.discovery.DiscoverySelectorIdentifierParser");
78 assertEquals(expected, Arrays.asList(usedClassNames));
79 } else if (urlPath.contains("/java.rmi/module-info.class")) {
80 final List<String> expected = new ArrayList<>();
81 expected.add("java.rmi.server.RMIClassLoaderSpi");
82 assertEquals(expected, Arrays.asList(usedClassNames));
83 } else if (urlPath.contains("/java.xml/module-info.class")) {
84 final List<String> expected = new ArrayList<>();
85 expected.add("javax.xml.datatype.DatatypeFactory");
86 expected.add("javax.xml.parsers.DocumentBuilderFactory");
87 expected.add("javax.xml.parsers.SAXParserFactory");
88 expected.add("javax.xml.stream.XMLEventFactory");
89 expected.add("javax.xml.stream.XMLInputFactory");
90 expected.add("javax.xml.stream.XMLOutputFactory");
91 expected.add("javax.xml.transform.TransformerFactory");
92 expected.add("javax.xml.validation.SchemaFactory");
93 expected.add("javax.xml.xpath.XPathFactory");
94 expected.add("org.xml.sax.XMLReader");
95 assertEquals(expected, Arrays.asList(usedClassNames));
96 } else if (urlPath.contains("/java.datatransfer/module-info.class")) {
97 final List<String> expected = new ArrayList<>();
98 expected.add("sun.datatransfer.DesktopDatatransferService");
99 assertEquals(expected, Arrays.asList(usedClassNames));
100 } else if (urlPath.contains("/java.desktop/module-info.class")) {
101 final List<String> expected = new ArrayList<>();
102 expected.add("java.awt.im.spi.InputMethodDescriptor");
103 expected.add("javax.accessibility.AccessibilityProvider");
104 expected.add("javax.imageio.spi.ImageInputStreamSpi");
105 expected.add("javax.imageio.spi.ImageOutputStreamSpi");
106 expected.add("javax.imageio.spi.ImageReaderSpi");
107 expected.add("javax.imageio.spi.ImageTranscoderSpi");
108 expected.add("javax.imageio.spi.ImageWriterSpi");
109 expected.add("javax.print.PrintServiceLookup");
110 expected.add("javax.print.StreamPrintServiceFactory");
111 expected.add("javax.sound.midi.spi.MidiDeviceProvider");
112 expected.add("javax.sound.midi.spi.MidiFileReader");
113 expected.add("javax.sound.midi.spi.MidiFileWriter");
114 expected.add("javax.sound.midi.spi.SoundbankReader");
115 expected.add("javax.sound.sampled.spi.AudioFileReader");
116 expected.add("javax.sound.sampled.spi.AudioFileWriter");
117 expected.add("javax.sound.sampled.spi.FormatConversionProvider");
118 expected.add("javax.sound.sampled.spi.MixerProvider");
119 expected.add("sun.swing.InteropProvider");
120 assertEquals(expected, Arrays.asList(usedClassNames));
121 } else if (urlPath.contains("/java.naming/module-info.class")) {
122 final List<String> expected = new ArrayList<>();
123 expected.add("javax.naming.ldap.StartTlsResponse");
124 expected.add("javax.naming.spi.InitialContextFactory");
125 if (javaClass.getMajor() > Const.MAJOR_11) {
126 expected.add("javax.naming.ldap.spi.LdapDnsProvider");
127 }
128 assertEquals(expected, Arrays.asList(usedClassNames));
129 } else if (urlPath.contains("/java.prefs/module-info.class")) {
130 final List<String> expected = new ArrayList<>();
131 expected.add("java.util.prefs.PreferencesFactory");
132 assertEquals(expected, Arrays.asList(usedClassNames));
133 } else if (urlPath.contains("/java.base/module-info.class")) {
134 final List<String> expected = new ArrayList<>();
135 expected.add("java.lang.System$LoggerFinder");
136 expected.add("java.net.ContentHandlerFactory");
137 if (javaClass.getMajor() > Const.MAJOR_17) {
138 expected.add("java.net.spi.InetAddressResolverProvider");
139 }
140 expected.add("java.net.spi.URLStreamHandlerProvider");
141 expected.add("java.nio.channels.spi.AsynchronousChannelProvider");
142 expected.add("java.nio.channels.spi.SelectorProvider");
143 expected.add("java.nio.charset.spi.CharsetProvider");
144 expected.add("java.nio.file.spi.FileSystemProvider");
145 expected.add("java.nio.file.spi.FileTypeDetector");
146 expected.add("java.security.Provider");
147 expected.add("java.text.spi.BreakIteratorProvider");
148 expected.add("java.text.spi.CollatorProvider");
149 expected.add("java.text.spi.DateFormatProvider");
150 expected.add("java.text.spi.DateFormatSymbolsProvider");
151 expected.add("java.text.spi.DecimalFormatSymbolsProvider");
152 expected.add("java.text.spi.NumberFormatProvider");
153 expected.add("java.time.chrono.AbstractChronology");
154 expected.add("java.time.chrono.Chronology");
155 expected.add("java.time.zone.ZoneRulesProvider");
156 if (javaClass.getMajor() > Const.MAJOR_11) {
157 expected.add("java.util.random.RandomGenerator");
158 }
159 expected.add("java.util.spi.CalendarDataProvider");
160 expected.add("java.util.spi.CalendarNameProvider");
161 expected.add("java.util.spi.CurrencyNameProvider");
162 expected.add("java.util.spi.LocaleNameProvider");
163 expected.add("java.util.spi.ResourceBundleControlProvider");
164 expected.add("java.util.spi.ResourceBundleProvider");
165 expected.add("java.util.spi.TimeZoneNameProvider");
166 expected.add("java.util.spi.ToolProvider");
167 expected.add("javax.security.auth.spi.LoginModule");
168 if (javaClass.getMajor() > Const.MAJOR_17) {
169 expected.add("jdk.internal.io.JdkConsoleProvider");
170 }
171 expected.add("jdk.internal.logger.DefaultLoggerFinder");
172 expected.add("sun.text.spi.JavaTimeDateTimePatternProvider");
173 expected.add("sun.util.locale.provider.LocaleDataMetaInfo");
174 expected.add("sun.util.resources.LocaleData$CommonResourceBundleProvider");
175 expected.add("sun.util.resources.LocaleData$SupplementaryResourceBundleProvider");
176 expected.add("sun.util.spi.CalendarProvider");
177 assertEquals(expected, Arrays.asList(usedClassNames));
178 } else if (urlPath.contains("/jdk.management.agent/module-info.class") && javaClass.getMajor() < Const.MAJOR_21) {
179 final List<String> expected = new ArrayList<>();
180 expected.add("jdk.internal.agent.spi.AgentProvider");
181 assertEquals(expected, Arrays.asList(usedClassNames));
182 } else if (urlPath.contains("/java.management/module-info.class")) {
183 final List<String> expected = new ArrayList<>();
184 expected.add("javax.management.remote.JMXConnectorProvider");
185 expected.add("javax.management.remote.JMXConnectorServerProvider");
186 expected.add("sun.management.spi.PlatformMBeanProvider");
187 assertEquals(expected, Arrays.asList(usedClassNames));
188 } else if (urlPath.contains("/java.sql/module-info.class")) {
189 final List<String> expected = new ArrayList<>();
190 expected.add("java.sql.Driver");
191 assertEquals(expected, Arrays.asList(usedClassNames));
192 } else if (urlPath.contains("/jdk.httpserver/module-info.class")) {
193 final List<String> expected = new ArrayList<>();
194 expected.add("com.sun.net.httpserver.spi.HttpServerProvider");
195 assertEquals(expected, Arrays.asList(usedClassNames));
196 } else if (urlPath.contains("/java.sql.rowset/module-info.class")) {
197 final List<String> expected = new ArrayList<>();
198 expected.add("javax.sql.rowset.RowSetFactory");
199 assertEquals(expected, Arrays.asList(usedClassNames));
200 } else if (urlPath.contains("/java.compiler/module-info.class")) {
201 final List<String> expected = new ArrayList<>();
202 expected.add("javax.tools.DocumentationTool");
203 expected.add("javax.tools.JavaCompiler");
204 assertEquals(expected, Arrays.asList(usedClassNames));
205 } else if (urlPath.contains("/java.scripting/module-info.class")) {
206 final List<String> expected = new ArrayList<>();
207 expected.add("javax.script.ScriptEngineFactory");
208 assertEquals(expected, Arrays.asList(usedClassNames));
209 } else if (urlPath.contains("/jdk.dynalink/module-info.class")) {
210 final List<String> expected = new ArrayList<>();
211 expected.add("jdk.dynalink.linker.GuardingDynamicLinkerExporter");
212 assertEquals(expected, Arrays.asList(usedClassNames));
213 } else if (urlPath.contains("/jdk.jdi/module-info.class")) {
214 final List<String> expected = new ArrayList<>();
215 expected.add("com.sun.jdi.connect.Connector");
216 expected.add("com.sun.jdi.connect.spi.TransportService");
217 assertEquals(expected, Arrays.asList(usedClassNames));
218 } else if (urlPath.contains("/jdk.compiler/module-info.class")) {
219 final List<String> expected = new ArrayList<>();
220 expected.add("javax.annotation.processing.Processor");
221 expected.add("com.sun.source.util.Plugin");
222 if (javaClass.getMajor() > Const.MAJOR_11) {
223 expected.add("com.sun.tools.doclint.DocLint");
224 }
225 expected.add("com.sun.tools.javac.platform.PlatformProvider");
226 assertEquals(expected, Arrays.asList(usedClassNames));
227 } else if (urlPath.contains("/jdk.jconsole/module-info.class")) {
228 final List<String> expected = new ArrayList<>();
229 expected.add("com.sun.tools.jconsole.JConsolePlugin");
230 assertEquals(expected, Arrays.asList(usedClassNames));
231 } else if (urlPath.contains("/jdk.attach/module-info.class")) {
232 final List<String> expected = new ArrayList<>();
233 expected.add("com.sun.tools.attach.spi.AttachProvider");
234 assertEquals(expected, Arrays.asList(usedClassNames));
235 } else if (urlPath.contains("/jdk.jshell/module-info.class")) {
236 final List<String> expected = new ArrayList<>();
237 expected.add("jdk.jshell.spi.ExecutionControlProvider");
238 expected.add("jdk.internal.editor.spi.BuildInEditorProvider");
239 assertEquals(expected, Arrays.asList(usedClassNames));
240 } else if (urlPath.contains("/jdk.internal.le/module-info.class")) {
241 final List<String> expected = new ArrayList<>();
242 assertEquals(expected, Arrays.asList(usedClassNames));
243 } else if (urlPath.contains("/jdk.jlink/module-info.class")) {
244 final List<String> expected = new ArrayList<>();
245 expected.add("jdk.tools.jlink.plugin.Plugin");
246 assertEquals(expected, Arrays.asList(usedClassNames));
247 } else if (urlPath.contains("/jdk.internal.jvmstat/module-info.class")) {
248 final List<String> expected = new ArrayList<>();
249 expected.add("sun.jvmstat.monitor.MonitoredHostService");
250 assertEquals(expected, Arrays.asList(usedClassNames));
251 } else if (urlPath.contains("/jdk.jpackage/module-info.class")) {
252 final List<String> expected = new ArrayList<>();
253 expected.add("jdk.jpackage.internal.Bundler");
254 expected.add("jdk.jpackage.internal.Bundlers");
255 assertEquals(expected, Arrays.asList(usedClassNames));
256 } else if (urlPath.contains("/jdk.naming.ldap/module-info.class")) {
257 final List<String> expected = new ArrayList<>();
258 expected.add("com.sun.jndi.ldap.spi.LdapDnsProvider");
259 assertEquals(expected, Arrays.asList(usedClassNames));
260 } else if (urlPath.contains("/jdk.jsobject/module-info.class") && javaClass.getMajor() == Const.MAJOR_11) {
261 final List<String> expected = new ArrayList<>();
262 expected.add("jdk.internal.netscape.javascript.spi.JSObjectProvider");
263 assertEquals(expected, Arrays.asList(usedClassNames));
264 } else if (urlPath.contains("/org/assertj/assertj-core/")) {
265 final List<String> expected = new ArrayList<>();
266 expected.add("org.assertj.core.configuration.Configuration");
267 expected.add("org.assertj.core.presentation.Representation");
268 assertEquals(expected, Arrays.asList(usedClassNames));
269 } else {
270 assertEquals(0, usedClassNames.length, "Found " + Arrays.toString(usedClassNames) + " in " + urlPath);
271 }
272 super.visitModule(obj);
273 }
274
275 @Override
276 public void visitModuleExports(final ModuleExports obj) {
277 assertEquals(0, obj.getExportsFlags(), url.toString());
278 final String packageName = obj.getPackageName(constantPool);
279 final String[] toModuleNames = obj.getToModuleNames(constantPool);
280 if (url.getPath().contains("junit-platform-commons")) {
281 final List<String> expected = new ArrayList<>();
282 expected.add("org.junit.jupiter.api");
283 expected.add("org.junit.jupiter.engine");
284 expected.add("org.junit.jupiter.migrationsupport");
285 expected.add("org.junit.jupiter.params");
286 expected.add("org.junit.platform.console");
287 expected.add("org.junit.platform.engine");
288 expected.add("org.junit.platform.launcher");
289 expected.add("org.junit.platform.reporting");
290 expected.add("org.junit.platform.runner");
291 expected.add("org.junit.platform.suite.api");
292 switch (packageName) {
293 case "org.junit.platform.commons.util":
294 expected.add("org.junit.platform.suite.commons");
295 expected.add("org.junit.platform.suite.engine");
296 expected.add("org.junit.platform.testkit");
297 expected.add("org.junit.vintage.engine");
298 assertEquals(expected, Arrays.asList(toModuleNames));
299 break;
300 case "org.junit.platform.commons.logging":
301 expected.add("org.junit.platform.suite.engine");
302 expected.add("org.junit.platform.testkit");
303 expected.add("org.junit.vintage.engine");
304 assertEquals(expected, Arrays.asList(toModuleNames));
305 break;
306 default:
307 assertEquals(0, toModuleNames.length);
308 break;
309 }
310 }
311 super.visitModuleExports(obj);
312 }
313
314 @Override
315 public void visitModuleOpens(final ModuleOpens obj) {
316 assertEquals(0, obj.getOpensFlags(), url.toString());
317 final String packageName = obj.getPackageName(constantPool);
318 final String[] toModuleNames = obj.getToModuleNames(constantPool);
319 final String urlPath = url.getPath();
320 if (urlPath.contains("junit-jupiter-engine")) {
321 assertEquals("org.junit.jupiter.engine.extension", packageName);
322 assertEquals(1, toModuleNames.length);
323 assertEquals("org.junit.platform.commons", toModuleNames[0]);
324 } else if (urlPath.contains("junit-jupiter-api")) {
325 assertEquals("org.junit.jupiter.api.condition", packageName);
326 assertEquals(1, toModuleNames.length);
327 assertEquals("org.junit.platform.commons", toModuleNames[0]);
328 }
329 super.visitModuleOpens(obj);
330 }
331
332 @Override
333 public void visitModuleProvides(final ModuleProvides obj) {
334 final String interfaceName = obj.getInterfaceName(constantPool);
335 final String[] implementationClassNames = obj.getImplementationClassNames(constantPool, true);
336 final String urlPath = url.getPath();
337 if (urlPath.contains("junit-jupiter-engine")) {
338 assertEquals("org.junit.platform.engine.TestEngine", interfaceName);
339 assertEquals(1, implementationClassNames.length);
340 assertEquals("org.junit.jupiter.engine.JupiterTestEngine", implementationClassNames[0]);
341 } else if (urlPath.contains("junit-platform-launcher")) {
342 assertEquals("org.junit.platform.launcher.TestExecutionListener", interfaceName);
343 assertEquals(1, implementationClassNames.length);
344 assertEquals("org.junit.platform.launcher.listeners.UniqueIdTrackingListener", implementationClassNames[0]);
345 }
346 super.visitModuleProvides(obj);
347 }
348
349 @Override
350 public void visitModuleRequires(final ModuleRequires obj) {
351 if (url.getPath().contains("junit-jupiter-engine")) {
352 final String moduleName = obj.getModuleName(constantPool);
353 final Map<String, Integer> expected = new HashMap<>();
354 expected.put("java.base", 32768);
355 expected.put("org.apiguardian.api", 64);
356 expected.put("org.junit.jupiter.api", 0);
357 expected.put("org.junit.platform.commons", 0);
358 expected.put("org.junit.platform.engine", 0);
359 expected.put("org.opentest4j", 0);
360 assertTrue(expected.containsKey(moduleName));
361 assertEquals(expected.get(moduleName), obj.getRequiresFlags(), moduleName);
362 }
363 super.visitModuleRequires(obj);
364 }
365 };
366 javaClass.accept(new DescendingVisitor(javaClass, visitor));
367 }
368 }
369 }