Path: blob/master/test/jdk/java/lang/module/MultiReleaseJarTest.java
41149 views
/*1* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/**24* @test25* @library /test/lib26* @modules java.base/jdk.internal.module27* @build MultiReleaseJarTest jdk.test.lib.util.JarUtils28* @run testng MultiReleaseJarTest29* @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarTest30* @summary Basic test of modular JARs as multi-release JARs31*/3233import java.io.File;34import java.io.InputStream;35import java.io.OutputStream;36import java.lang.module.ModuleDescriptor;37import java.lang.module.ModuleFinder;38import java.lang.module.ModuleReader;39import java.lang.module.ModuleReference;40import java.net.URI;41import java.net.URLConnection;42import java.nio.ByteBuffer;43import java.nio.file.Files;44import java.nio.file.Path;45import java.nio.file.Paths;46import java.util.ArrayList;47import java.util.HashMap;48import java.util.HashSet;49import java.util.List;50import java.util.Map;51import java.util.Optional;52import java.util.Set;53import java.util.jar.Attributes;54import java.util.jar.Manifest;5556import jdk.internal.module.ModuleInfoWriter;57import jdk.test.lib.util.JarUtils;5859import org.testng.annotations.Test;60import static org.testng.Assert.*;616263@Test64public class MultiReleaseJarTest {6566private static final String MODULE_INFO = "module-info.class";6768private static final int VERSION = Runtime.version().major();6970// are multi-release JARs enabled?71private static final boolean MULTI_RELEASE;72static {73String s = System.getProperty("jdk.util.jar.enableMultiRelease");74MULTI_RELEASE = (s == null || Boolean.parseBoolean(s));75}7677/**78* Basic test of a multi-release JAR.79*/80public void testBasic() throws Exception {81String name = "m1";8283ModuleDescriptor descriptor = ModuleDescriptor.newModule(name)84.requires("java.base")85.build();8687Path jar = new JarBuilder(name)88.moduleInfo("module-info.class", descriptor)89.resource("p/Main.class")90.resource("p/Helper.class")91.resource("META-INF/versions/" + VERSION + "/p/Helper.class")92.resource("META-INF/versions/" + VERSION + "/p/internal/Helper.class")93.build();9495// find the module96ModuleFinder finder = ModuleFinder.of(jar);97Optional<ModuleReference> omref = finder.find(name);98assertTrue((omref.isPresent()));99ModuleReference mref = omref.get();100101// check module packages102descriptor = mref.descriptor();103Set<String> packages = descriptor.packages();104assertTrue(packages.contains("p"));105if (MULTI_RELEASE) {106assertTrue(packages.size() == 2);107assertTrue(packages.contains("p.internal"));108} else {109assertTrue(packages.size() == 1);110}111}112113/**114* Test a multi-release JAR with a module-info.class in the versioned115* section of the JAR.116*/117public void testModuleInfoInVersionedSection() throws Exception {118String name = "m1";119120ModuleDescriptor descriptor1 = ModuleDescriptor.newModule(name)121.requires("java.base")122.build();123124// module descriptor for versioned section125ModuleDescriptor descriptor2 = ModuleDescriptor.newModule(name)126.requires("java.base")127.requires("jdk.unsupported")128.build();129130Path jar = new JarBuilder(name)131.moduleInfo(MODULE_INFO, descriptor1)132.resource("p/Main.class")133.resource("p/Helper.class")134.moduleInfo("META-INF/versions/" + VERSION + "/" + MODULE_INFO, descriptor2)135.resource("META-INF/versions/" + VERSION + "/p/Helper.class")136.resource("META-INF/versions/" + VERSION + "/p/internal/Helper.class")137.build();138139// find the module140ModuleFinder finder = ModuleFinder.of(jar);141Optional<ModuleReference> omref = finder.find(name);142assertTrue((omref.isPresent()));143ModuleReference mref = omref.get();144145// ensure that the right module-info.class is loaded146ModuleDescriptor descriptor = mref.descriptor();147assertEquals(descriptor.name(), name);148if (MULTI_RELEASE) {149assertEquals(descriptor.requires(), descriptor2.requires());150} else {151assertEquals(descriptor.requires(), descriptor1.requires());152}153}154155/**156* Test multi-release JAR as an automatic module.157*/158public void testAutomaticModule() throws Exception {159String name = "m";160161Path jar = new JarBuilder(name)162.resource("p/Main.class")163.resource("p/Helper.class")164.resource("META-INF/versions/" + VERSION + "/p/Helper.class")165.resource("META-INF/versions/" + VERSION + "/p/internal/Helper.class")166.build();167168// find the module169ModuleFinder finder = ModuleFinder.of(jar);170Optional<ModuleReference> omref = finder.find(name);171assertTrue((omref.isPresent()));172ModuleReference mref = omref.get();173174// check module packages175ModuleDescriptor descriptor = mref.descriptor();176Set<String> packages = descriptor.packages();177if (MULTI_RELEASE) {178assertTrue(packages.size() == 2);179assertTrue(packages.contains("p.internal"));180} else {181assertTrue(packages.size() == 1);182}183}184185/**186* Exercise ModuleReader on a multi-release JAR187*/188public void testModuleReader() throws Exception {189String name = "m1";190191ModuleDescriptor descriptor1 = ModuleDescriptor.newModule(name)192.requires("java.base")193.build();194195// module descriptor for versioned section196ModuleDescriptor descriptor2 = ModuleDescriptor.newModule(name)197.requires("java.base")198.requires("jdk.unsupported")199.build();200201Path jar = new JarBuilder(name)202.moduleInfo(MODULE_INFO, descriptor1)203.moduleInfo("META-INF/versions/" + VERSION + "/" + MODULE_INFO, descriptor2)204.build();205206// find the module207ModuleFinder finder = ModuleFinder.of(jar);208Optional<ModuleReference> omref = finder.find(name);209assertTrue((omref.isPresent()));210ModuleReference mref = omref.get();211212ModuleDescriptor expected;213if (MULTI_RELEASE) {214expected = descriptor2;215} else {216expected = descriptor1;217}218219// test ModuleReader by reading module-info.class resource220try (ModuleReader reader = mref.open()) {221222// open resource223Optional<InputStream> oin = reader.open(MODULE_INFO);224assertTrue(oin.isPresent());225try (InputStream in = oin.get()) {226checkRequires(ModuleDescriptor.read(in), expected);227}228229// read resource230Optional<ByteBuffer> obb = reader.read(MODULE_INFO);231assertTrue(obb.isPresent());232ByteBuffer bb = obb.get();233try {234checkRequires(ModuleDescriptor.read(bb), expected);235} finally {236reader.release(bb);237}238239// find resource240Optional<URI> ouri = reader.find(MODULE_INFO);241assertTrue(ouri.isPresent());242URI uri = ouri.get();243244String expectedTail = "!/";245if (MULTI_RELEASE)246expectedTail += "META-INF/versions/" + VERSION + "/";247expectedTail += MODULE_INFO;248assertTrue(uri.toString().endsWith(expectedTail));249250URLConnection uc = uri.toURL().openConnection();251uc.setUseCaches(false);252try (InputStream in = uc.getInputStream()) {253checkRequires(ModuleDescriptor.read(in), expected);254}255256}257}258259/**260* Check that two ModuleDescriptor have the same requires261*/262static void checkRequires(ModuleDescriptor md1, ModuleDescriptor md2) {263assertEquals(md1.requires(), md2.requires());264}265266/**267* A builder of multi-release JAR files.268*/269static class JarBuilder {270private String name;271private Set<String> resources = new HashSet<>();272private Map<String, ModuleDescriptor> descriptors = new HashMap<>();273274JarBuilder(String name) {275this.name = name;276}277278/**279* Adds a module-info.class to the JAR file.280*/281JarBuilder moduleInfo(String name, ModuleDescriptor descriptor) {282descriptors.put(name, descriptor);283return this;284}285286/**287* Adds a dummy resource to the JAR file.288*/289JarBuilder resource(String name) {290resources.add(name);291return this;292}293294/**295* Create the multi-release JAR, returning its file path.296*/297Path build() throws Exception {298Path dir = Files.createTempDirectory(Paths.get(""), "jar");299List<Path> files = new ArrayList<>();300301// write the module-info.class302for (Map.Entry<String, ModuleDescriptor> e : descriptors.entrySet()) {303String name = e.getKey();304ModuleDescriptor descriptor = e.getValue();305Path mi = Paths.get(name.replace('/', File.separatorChar));306Path parent = dir.resolve(mi).getParent();307if (parent != null)308Files.createDirectories(parent);309try (OutputStream out = Files.newOutputStream(dir.resolve(mi))) {310ModuleInfoWriter.write(descriptor, out);311}312files.add(mi);313}314315// write the dummy resources316for (String name : resources) {317Path file = Paths.get(name.replace('/', File.separatorChar));318// create dummy resource319Path parent = dir.resolve(file).getParent();320if (parent != null)321Files.createDirectories(parent);322Files.createFile(dir.resolve(file));323files.add(file);324}325326Manifest man = new Manifest();327Attributes attrs = man.getMainAttributes();328attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0");329attrs.put(Attributes.Name.MULTI_RELEASE, "true");330331Path jarfile = Paths.get(name + ".jar");332JarUtils.createJarFile(jarfile, man, dir, files.toArray(new Path[0]));333return jarfile;334}335}336}337338339