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