Path: blob/master/test/jdk/tools/jar/multiRelease/Basic.java
41149 views
/*1* Copyright (c) 2016, 2019, 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# @bug 8186087 8196748 821280726* @library /test/lib27* @modules java.base/jdk.internal.misc28* jdk.compiler29* jdk.jartool30* @build jdk.test.lib.util.FileUtils31* jdk.test.lib.Utils32* jdk.test.lib.Asserts33* jdk.test.lib.JDKToolFinder34* jdk.test.lib.JDKToolLauncher35* jdk.test.lib.Platform36* jdk.test.lib.process.*37* MRTestBase38* @run testng Basic39*/4041import jdk.test.lib.util.FileUtils;42import org.testng.annotations.*;4344import java.io.File;45import java.nio.file.Files;46import java.nio.file.Path;47import java.nio.file.Paths;48import java.util.List;49import java.util.Map;50import java.util.jar.JarFile;51import java.util.zip.ZipFile;5253import static org.testng.Assert.*;5455public class Basic extends MRTestBase {5657@Test58// create a regular, non-multi-release jar59public void test00() throws Throwable {60String jarfile = "test.jar";6162compile("test01"); //use same data as test016364Path classes = Paths.get("classes");65jarTool("cf", jarfile, "-C", classes.resolve("base").toString(), ".")66.shouldHaveExitValue(SUCCESS);6768checkMultiRelease(jarfile, false);6970Map<String, String[]> names = Map.of(71"version/Main.class",72new String[]{"base", "version", "Main.class"},7374"version/Version.class",75new String[]{"base", "version", "Version.class"}76);7778compare(jarfile, names);7980FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));81FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));82}8384@Test85// create a multi-release jar86public void test01() throws Throwable {87String jarfile = "test.jar";8889compile("test01");9091Path classes = Paths.get("classes");92jarTool("cf", jarfile, "-C", classes.resolve("base").toString(), ".",93"--release", "9", "-C", classes.resolve("v9").toString(), ".",94"--release", "10", "-C", classes.resolve("v10").toString(), ".")95.shouldHaveExitValue(SUCCESS);9697checkMultiRelease(jarfile, true);9899Map<String, String[]> names = Map.of(100"version/Main.class",101new String[]{"base", "version", "Main.class"},102103"version/Version.class",104new String[]{"base", "version", "Version.class"},105106"META-INF/versions/9/version/Version.class",107new String[]{"v9", "version", "Version.class"},108109"META-INF/versions/10/version/Version.class",110new String[]{"v10", "version", "Version.class"}111);112113compare(jarfile, names);114115FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));116FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));117}118119@Test120public void versionFormat() throws Throwable {121String jarfile = "test.jar";122123compile("test01");124125Path classes = Paths.get("classes");126127// valid128for (String release : List.of("10000", "09", "00010", "10")) {129jarTool("cf", jarfile, "-C", classes.resolve("base").toString(), ".",130"--release", release, "-C", classes.resolve("v10").toString(), ".")131.shouldHaveExitValue(SUCCESS)132.shouldBeEmptyIgnoreVMWarnings();133}134// invalid135for (String release : List.of("9.0", "8", "v9",136"9v", "0", "-10")) {137jarTool("cf", jarfile, "-C", classes.resolve("base").toString(), ".",138"--release", release, "-C", classes.resolve("v10").toString(), ".")139.shouldNotHaveExitValue(SUCCESS)140.shouldContain("release " + release + " not valid");141}142FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));143FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));144}145146@Test147// update a regular jar to a multi-release jar148public void test02() throws Throwable {149String jarfile = "test.jar";150151compile("test01"); //use same data as test01152153Path classes = Paths.get("classes");154jarTool("cf", jarfile, "-C", classes.resolve("base").toString(), ".")155.shouldHaveExitValue(SUCCESS);156157checkMultiRelease(jarfile, false);158159jarTool("uf", jarfile,160"--release", "9", "-C", classes.resolve("v9").toString(), ".")161.shouldHaveExitValue(SUCCESS);162163checkMultiRelease(jarfile, true);164165Map<String, String[]> names = Map.of(166"version/Main.class",167new String[]{"base", "version", "Main.class"},168169"version/Version.class",170new String[]{"base", "version", "Version.class"},171172"META-INF/versions/9/version/Version.class",173new String[]{"v9", "version", "Version.class"}174);175176compare(jarfile, names);177178FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));179FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));180}181182@Test183// replace a base entry and a versioned entry184public void test03() throws Throwable {185String jarfile = "test.jar";186187compile("test01"); //use same data as test01188189Path classes = Paths.get("classes");190jarTool("cf", jarfile, "-C", classes.resolve("base").toString(), ".",191"--release", "9", "-C", classes.resolve("v9").toString(), ".")192.shouldHaveExitValue(SUCCESS);193194checkMultiRelease(jarfile, true);195196Map<String, String[]> names = Map.of(197"version/Main.class",198new String[]{"base", "version", "Main.class"},199200"version/Version.class",201new String[]{"base", "version", "Version.class"},202203"META-INF/versions/9/version/Version.class",204new String[]{"v9", "version", "Version.class"}205);206207compare(jarfile, names);208209// write the v9 version/Version.class entry in base and the v10210// version/Version.class entry in versions/9 section211jarTool("uf", jarfile, "-C", classes.resolve("v9").toString(), "version",212"--release", "9", "-C", classes.resolve("v10").toString(), ".")213.shouldHaveExitValue(SUCCESS);214215checkMultiRelease(jarfile, true);216217names = Map.of(218"version/Main.class",219new String[]{"base", "version", "Main.class"},220221"version/Version.class",222new String[]{"v9", "version", "Version.class"},223224"META-INF/versions/9/version/Version.class",225new String[]{"v10", "version", "Version.class"}226);227228compare(jarfile, names);229230FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));231FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));232}233234/*235* The following tests exercise the jar validator236*/237238@Test239// META-INF/versions/9 class has different api than base class240public void test04() throws Throwable {241String jarfile = "test.jar";242243compile("test01"); //use same data as test01244245Path classes = Paths.get("classes");246247// replace the v9 class248Path source = Paths.get(src, "data", "test04", "v9", "version");249javac(classes.resolve("v9"), source.resolve("Version.java"));250251jarTool("cf", jarfile, "-C", classes.resolve("base").toString(), ".",252"--release", "9", "-C", classes.resolve("v9").toString(), ".")253.shouldNotHaveExitValue(SUCCESS)254.shouldContain("different api from earlier");255256FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));257FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));258}259260@Test261// META-INF/versions/9 contains an extra public class262public void test05() throws Throwable {263String jarfile = "test.jar";264265compile("test01"); //use same data as test01266267Path classes = Paths.get("classes");268269// add the new v9 class270Path source = Paths.get(src, "data", "test05", "v9", "version");271javac(classes.resolve("v9"), source.resolve("Extra.java"));272273jarTool("cf", jarfile, "-C", classes.resolve("base").toString(), ".",274"--release", "9", "-C", classes.resolve("v9").toString(), ".")275.shouldNotHaveExitValue(SUCCESS)276.shouldContain("contains a new public class");277278FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));279FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));280}281282@Test283// META-INF/versions/9 contains an extra package private class -- this is okay284public void test06() throws Throwable {285String jarfile = "test.jar";286287compile("test01"); //use same data as test01288289Path classes = Paths.get("classes");290291// add the new v9 class292Path source = Paths.get(src, "data", "test06", "v9", "version");293javac(classes.resolve("v9"), source.resolve("Extra.java"));294295jarTool("cf", jarfile, "-C", classes.resolve("base").toString(), ".",296"--release", "9", "-C", classes.resolve("v9").toString(), ".")297.shouldHaveExitValue(SUCCESS);298299FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));300FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));301}302303@Test304// META-INF/versions/9 contains an identical class to base entry class305// this is okay but produces warning306public void test07() throws Throwable {307String jarfile = "test.jar";308309compile("test01"); //use same data as test01310311Path classes = Paths.get("classes");312313// add the new v9 class314Path source = Paths.get(src, "data", "test01", "base", "version");315javac(classes.resolve("v9"), source.resolve("Version.java"));316317jarTool("cf", jarfile, "-C", classes.resolve("base").toString(), ".",318"--release", "9", "-C", classes.resolve("v9").toString(), ".")319.shouldHaveExitValue(SUCCESS)320.shouldContain("contains a class that")321.shouldContain("is identical");322323FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));324FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));325}326327@Test328// META-INF/versions/9 contains an identical class to previous version entry class329// this is okay but produces warning330public void identicalClassToPreviousVersion() throws Throwable {331String jarfile = "test.jar";332333compile("test01"); //use same data as test01334335Path classes = Paths.get("classes");336337jarTool("cf", jarfile, "-C", classes.resolve("base").toString(), ".",338"--release", "9", "-C", classes.resolve("v9").toString(), ".")339.shouldHaveExitValue(SUCCESS)340.shouldBeEmptyIgnoreVMWarnings();341jarTool("uf", jarfile,342"--release", "10", "-C", classes.resolve("v9").toString(), ".")343.shouldHaveExitValue(SUCCESS)344.shouldContain("contains a class that")345.shouldContain("is identical");346347FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));348FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));349}350351@Test352// a class with an internal name different from the external name353public void test09() throws Throwable {354String jarfile = "test.jar";355356compile("test01"); //use same data as test01357358Path classes = Paths.get("classes");359360Path base = classes.resolve("base").resolve("version");361362Files.copy(base.resolve("Main.class"), base.resolve("Foo.class"));363364jarTool("cf", jarfile, "-C", classes.resolve("base").toString(), ".",365"--release", "9", "-C", classes.resolve("v9").toString(), ".")366.shouldNotHaveExitValue(SUCCESS)367.shouldContain("names do not match");368369FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));370FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));371}372373@Test374// assure that basic nested classes are acceptable375public void test10() throws Throwable {376String jarfile = "test.jar";377378compile("test01"); //use same data as test01379380Path classes = Paths.get("classes");381382// add a base class with a nested class383Path source = Paths.get(src, "data", "test10", "base", "version");384javac(classes.resolve("base"), source.resolve("Nested.java"));385386// add a versioned class with a nested class387source = Paths.get(src, "data", "test10", "v9", "version");388javac(classes.resolve("v9"), source.resolve("Nested.java"));389390jarTool("cf", jarfile, "-C", classes.resolve("base").toString(), ".",391"--release", "9", "-C", classes.resolve("v9").toString(), ".")392.shouldHaveExitValue(SUCCESS);393394FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));395FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));396}397398@Test399// a base entry contains a nested class that doesn't have a matching top level class400public void test11() throws Throwable {401String jarfile = "test.jar";402403compile("test01"); //use same data as test01404405Path classes = Paths.get("classes");406407// add a base class with a nested class408Path source = Paths.get(src, "data", "test10", "base", "version");409javac(classes.resolve("base"), source.resolve("Nested.java"));410411// remove the top level class, thus isolating the nested class412Files.delete(classes.resolve("base").resolve("version").resolve("Nested.class"));413414// add a versioned class with a nested class415source = Paths.get(src, "data", "test10", "v9", "version");416javac(classes.resolve("v9"), source.resolve("Nested.java"));417418List<String> output = jarTool("cf", jarfile,419"-C", classes.resolve("base").toString(), ".",420"--release", "9", "-C", classes.resolve("v9").toString(), ".")421.shouldNotHaveExitValue(SUCCESS)422.asLinesWithoutVMWarnings();423424/* "META-INF/versions/9/version/Nested$nested.class" is really NOT isolated425assertTrue(output.size() == 4);426assertTrue(output.size() == 3);427assertTrue(output.get(0).contains("an isolated nested class"),428output.get(0));429assertTrue(output.get(1).contains("contains a new public class"),430output.get(1));431assertTrue(output.get(2).contains("an isolated nested class"),432output.get(2));433assertTrue(output.get(3).contains("invalid multi-release jar file"),434output.get(3));435assertTrue(output.get(2).contains("invalid multi-release jar file"),436output.get(2));437*/438439assertTrue(output.size() == 3);440assertTrue(output.get(0).contains("an isolated nested class"),441output.get(0));442assertTrue(output.get(1).contains("contains a new public class"),443output.get(1));444assertTrue(output.get(2).contains("invalid multi-release jar file"),445output.get(2));446447FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));448FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));449}450451@Test452// a versioned entry contains a nested class that doesn't have a matching top level class453public void test12() throws Throwable {454String jarfile = "test.jar";455456compile("test01"); //use same data as test01457458Path classes = Paths.get("classes");459460// add a base class with a nested class461Path source = Paths.get(src, "data", "test10", "base", "version");462javac(classes.resolve("base"), source.resolve("Nested.java"));463464// add a versioned class with a nested class465source = Paths.get(src, "data", "test10", "v9", "version");466javac(classes.resolve("v9"), source.resolve("Nested.java"));467468// remove the top level class, thus isolating the nested class469Files.delete(classes.resolve("v9").resolve("version").resolve("Nested.class"));470471jarTool("cf", jarfile, "-C", classes.resolve("base").toString(), ".",472"--release", "9", "-C", classes.resolve("v9").toString(), ".")473.shouldNotHaveExitValue(SUCCESS)474.shouldContain("an isolated nested class");475476FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));477FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));478}479480@Test481// assure the nested-nested classes are acceptable482public void test13() throws Throwable {483String jarfile = "test.jar";484485compile("test01"); //use same data as test01486487Path classes = Paths.get("classes");488489// add a base class with a nested and nested-nested class490Path source = Paths.get(src, "data", "test13", "base", "version");491javac(classes.resolve("base"), source.resolve("Nested.java"));492493// add a versioned class with a nested and nested-nested class494source = Paths.get(src, "data", "test13", "v10", "version");495javac(classes.resolve("v10"), source.resolve("Nested.java"));496497jarTool("cf", jarfile, "-C", classes.resolve("base").toString(), ".",498"--release", "10", "-C", classes.resolve("v10").toString(), ".")499.shouldHaveExitValue(SUCCESS);500501FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));502FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));503}504505@Test506public void testCustomManifest() throws Throwable {507String jarfile = "test.jar";508509compile("test01");510511Path classes = Paths.get("classes");512Path manifest = Paths.get("Manifest.txt");513514// create515Files.write(manifest, "Class-Path: MyUtils.jar\n".getBytes());516517jarTool("cfm", jarfile, manifest.toString(),518"-C", classes.resolve("base").toString(), ".",519"--release", "10", "-C", classes.resolve("v10").toString(), ".")520.shouldHaveExitValue(SUCCESS)521.shouldBeEmptyIgnoreVMWarnings();522523try (JarFile jf = new JarFile(new File(jarfile), true,524ZipFile.OPEN_READ, JarFile.runtimeVersion())) {525assertTrue(jf.isMultiRelease(), "Not multi-release jar");526assertEquals(jf.getManifest()527.getMainAttributes()528.getValue("Class-Path"),529"MyUtils.jar");530}531532// update533Files.write(manifest, "Multi-release: false\n".getBytes());534535jar("ufm", jarfile, manifest.toString(),536"-C", classes.resolve("base").toString(), ".",537"--release", "9", "-C", classes.resolve("v10").toString(), ".")538.shouldHaveExitValue(SUCCESS)539.shouldContain("WARNING: Duplicate name in Manifest: Multi-release.");540541try (JarFile jf = new JarFile(new File(jarfile), true,542ZipFile.OPEN_READ, JarFile.runtimeVersion())) {543assertTrue(jf.isMultiRelease(), "Not multi-release jar");544assertEquals(jf.getManifest()545.getMainAttributes()546.getValue("Class-Path"),547"MyUtils.jar");548}549550FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));551FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));552}553}554555556