Path: blob/master/test/jdk/tools/jmod/JmodNegativeTest.java
41144 views
/*1* Copyright (c) 2015, 2020, 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 jdk.compiler27* jdk.jlink28* @build jdk.test.lib.compiler.CompilerUtils29* jdk.test.lib.util.FileUtils30* jdk.test.lib.Platform31* @run testng JmodNegativeTest32* @summary Negative tests for jmod33*/3435import java.io.*;36import java.nio.file.Files;37import java.nio.file.Path;38import java.nio.file.Paths;39import java.util.Arrays;40import java.util.List;41import java.util.function.Consumer;42import java.util.function.Supplier;43import java.util.spi.ToolProvider;44import java.util.zip.ZipOutputStream;45import jdk.test.lib.util.FileUtils;46import jdk.test.lib.compiler.CompilerUtils;47import org.testng.annotations.BeforeTest;48import org.testng.annotations.DataProvider;49import org.testng.annotations.Test;5051import static java.io.File.pathSeparator;52import static java.nio.charset.StandardCharsets.UTF_8;53import static org.testng.Assert.assertTrue;5455public class JmodNegativeTest {5657static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod")58.orElseThrow(() ->59new RuntimeException("jmod tool not found")60);6162static final String TEST_SRC = System.getProperty("test.src", ".");63static final Path SRC_DIR = Paths.get(TEST_SRC, "src");64static final Path EXPLODED_DIR = Paths.get("build");65static final Path MODS_DIR = Paths.get("jmods");6667@BeforeTest68public void buildExplodedModules() throws IOException {69if (Files.exists(EXPLODED_DIR))70FileUtils.deleteFileTreeWithRetry(EXPLODED_DIR);7172for (String name : new String[] { "foo"/*, "bar", "baz"*/ } ) {73Path dir = EXPLODED_DIR.resolve(name);74assertTrue(compileModule(name, dir.resolve("classes")));75}7677if (Files.exists(MODS_DIR))78FileUtils.deleteFileTreeWithRetry(MODS_DIR);79Files.createDirectories(MODS_DIR);80}8182@Test83public void testNoArgs() {84jmod()85.assertFailure()86.resultChecker(r ->87assertContains(r.output, "Error: one of create, extract, list, describe, or hash must be specified")88);89}9091@Test92public void testBadAction() {93jmod("badAction")94.assertFailure()95.resultChecker(r ->96assertContains(r.output, "Error: mode must be one of create, extract, list, describe, or hash")97);9899jmod("--badOption")100.assertFailure()101.resultChecker(r ->102assertContains(r.output, "Error: badOption is not a recognized option")103);104}105106@Test107public void testTooManyArgs() throws IOException {108Path jmod = MODS_DIR.resolve("doesNotExist.jmod");109FileUtils.deleteFileIfExistsWithRetry(jmod);110111jmod("create",112jmod.toString(),113"AAA")114.assertFailure()115.resultChecker(r ->116assertContains(r.output, "Error: unknown option(s): [AAA]")117);118}119120@Test121public void testCreateNoArgs() {122jmod("create")123.assertFailure()124.resultChecker(r ->125assertContains(r.output, "Error: jmod-file must be specified")126);127}128129@Test130public void testListNoArgs() {131jmod("list")132.assertFailure()133.resultChecker(r ->134assertContains(r.output, "Error: jmod-file must be specified")135);136}137138@Test139public void testListFileDoesNotExist() throws IOException {140Path jmod = MODS_DIR.resolve("doesNotExist.jmod");141FileUtils.deleteFileIfExistsWithRetry(jmod);142143jmod("list",144jmod.toString())145.assertFailure()146.resultChecker(r ->147assertContains(r.output, "Error: no jmod file found: "148+ jmod.toString())149);150}151152@Test153public void testListJmodIsDir() throws IOException {154Path jmod = MODS_DIR.resolve("testListJmodIsDir.jmod");155if (Files.notExists(jmod))156Files.createDirectory(jmod);157158jmod("list",159jmod.toString())160.assertFailure()161.resultChecker(r ->162assertContains(r.output, "Error: error opening jmod file")163);164}165166@Test167public void testlistJmodMalformed() throws IOException {168Path jmod = MODS_DIR.resolve("testlistJmodMalformed.jmod");169if (Files.notExists(jmod))170Files.createFile(jmod);171172jmod("list",173jmod.toString())174.assertFailure()175.resultChecker(r ->176assertContains(r.output, "Error: error opening jmod file")177);178}179180@Test181public void testHashModulesModulePathNotSpecified() {182jmod("create",183"--hash-modules", "anyPattern.*",184"output.jmod")185.assertFailure()186.resultChecker(r ->187assertContains(r.output, "Error: --module-path must be "188+"specified when hashing modules")189);190}191192@Test193public void testCreateJmodAlreadyExists() throws IOException {194Path jmod = MODS_DIR.resolve("testCreateJmodAlreadyExists.jmod");195if (Files.notExists(jmod))196Files.createFile(jmod);197198jmod("create",199"--class-path", Paths.get(".").toString(), // anything that exists200jmod.toString())201.assertFailure()202.resultChecker(r ->203assertContains(r.output, "Error: file already exists: " + jmod.toString())204);205}206207@Test208public void testCreateJmodIsDir() throws IOException {209Path jmod = MODS_DIR.resolve("testCreateJmodAlreadyExists");210if (Files.notExists(jmod))211Files.createDirectory(jmod);212213jmod("create",214"--class-path", Paths.get(".").toString(), // anything that exists215jmod.toString())216.assertFailure()217.resultChecker(r ->218assertContains(r.output, "Error: file already exists: " + jmod.toString())219);220}221222@Test223public void testInvalidModuleVersion() throws IOException {224Path jmod = MODS_DIR.resolve("testEmptyModuleVersion.jmod");225FileUtils.deleteFileIfExistsWithRetry(jmod);226String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();227228for (String version : new String[] { "", "NOT_A_VALID_VERSION" }) {229jmod("create",230"--class-path", cp,231"--module-version", version,232jmod.toString())233.assertFailure()234.resultChecker(r ->235assertContains(r.output, "Error: invalid module version")236);237}238}239240@Test241public void testEmptyFileInClasspath() throws IOException {242Path jmod = MODS_DIR.resolve("testEmptyFileInClasspath.jmod");243FileUtils.deleteFileIfExistsWithRetry(jmod);244Path jar = MODS_DIR.resolve("NotARealJar_Empty.jar");245FileUtils.deleteFileIfExistsWithRetry(jar);246Files.createFile(jar);247248jmod("create",249"--class-path", jar.toString(),250jmod.toString())251.assertFailure()252.resultChecker(r ->253assertContains(r.output, "Error: module-info.class not found")254);255}256257@Test258public void testEmptyJarInClasspath() throws IOException {259Path jmod = MODS_DIR.resolve("testEmptyJarInClasspath.jmod");260FileUtils.deleteFileIfExistsWithRetry(jmod);261Path jar = MODS_DIR.resolve("empty.jar");262FileUtils.deleteFileIfExistsWithRetry(jar);263try (FileOutputStream fos = new FileOutputStream(jar.toFile());264ZipOutputStream zos = new ZipOutputStream(fos)) {265// empty266}267268jmod("create",269"--class-path", jar.toString(),270jmod.toString())271.assertFailure()272.resultChecker(r ->273assertContains(r.output, "Error: module-info.class not found")274);275}276277@Test278public void testModuleInfoNotFound() throws IOException {279Path jmod = MODS_DIR.resolve("output.jmod");280FileUtils.deleteFileIfExistsWithRetry(jmod);281Path jar = MODS_DIR.resolve("empty");282FileUtils.deleteFileIfExistsWithRetry(jar);283Files.createDirectory(jar);284285jmod("create",286"--class-path", jar.toString(),287jmod.toString())288.assertFailure()289.resultChecker(r ->290assertContains(r.output, "Error: module-info.class not found")291);292}293294@Test295public void testModuleInfoIsDir() throws IOException {296Path jmod = MODS_DIR.resolve("output.jmod");297FileUtils.deleteFileIfExistsWithRetry(jmod);298Path cp = MODS_DIR.resolve("module-info.class");299FileUtils.deleteFileIfExistsWithRetry(cp);300Files.createDirectory(cp);301Files.createFile(cp.resolve("nada.txt"));302303jmod("create",304"--class-path", cp.toString(),305jmod.toString())306.assertFailure()307.resultChecker(r ->308assertContains(r.output, "Error: module-info.class not found")309);310}311312@Test313public void testNoModuleHash() throws IOException {314Path jmod = MODS_DIR.resolve("output.jmod");315FileUtils.deleteFileIfExistsWithRetry(jmod);316Path emptyDir = Paths.get("empty");317if (Files.exists(emptyDir))318FileUtils.deleteFileTreeWithRetry(emptyDir);319Files.createDirectory(emptyDir);320String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();321322jmod("create",323"--class-path", cp,324"--hash-modules", ".*",325"--module-path", emptyDir.toString(),326jmod.toString())327.resultChecker(r ->328assertContains(r.output, "No hashes recorded: " +329"no module specified for hashing depends on foo")330);331}332333@Test334public void testEmptyFileInModulePath() throws IOException {335Path jmod = MODS_DIR.resolve("output.jmod");336FileUtils.deleteFileIfExistsWithRetry(jmod);337Path empty = MODS_DIR.resolve("emptyFile.jmod");338FileUtils.deleteFileIfExistsWithRetry(empty);339Files.createFile(empty);340try {341String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();342343jmod("create",344"--class-path", cp,345"--hash-modules", ".*",346"--module-path", MODS_DIR.toString(),347jmod.toString())348.assertFailure();349} finally {350FileUtils.deleteFileWithRetry(empty);351}352}353354@Test355public void testFileInModulePath() throws IOException {356Path jmod = MODS_DIR.resolve("output.jmod");357FileUtils.deleteFileIfExistsWithRetry(jmod);358Path file = MODS_DIR.resolve("testFileInModulePath.txt");359FileUtils.deleteFileIfExistsWithRetry(file);360Files.createFile(file);361362jmod("create",363"--hash-modules", ".*",364"--module-path", file.toString(),365jmod.toString())366.assertFailure()367.resultChecker(r ->368assertContains(r.output, "Error: path must be a directory")369);370}371372@DataProvider(name = "pathDoesNotExist")373public Object[][] pathDoesNotExist() throws IOException {374Path jmod = MODS_DIR.resolve("output.jmod");375FileUtils.deleteFileIfExistsWithRetry(jmod);376FileUtils.deleteFileIfExistsWithRetry(Paths.get("doesNotExist"));377378List<Supplier<JmodResult>> tasks = Arrays.asList(379() -> jmod("create",380"--hash-modules", "anyPattern",381"--module-path", "doesNotExist",382"output.jmod"),383() -> jmod("create",384"--class-path", "doesNotExist",385"output.jmod"),386() -> jmod("create",387"--class-path", "doesNotExist.jar",388"output.jmod"),389() -> jmod("create",390"--cmds", "doesNotExist",391"output.jmod"),392() -> jmod("create",393"--config", "doesNotExist",394"output.jmod"),395() -> jmod("create",396"--libs", "doesNotExist",397"output.jmod") );398399String errMsg = "Error: path not found: doesNotExist";400return tasks.stream().map(t -> new Object[] {t, errMsg} )401.toArray(Object[][]::new);402}403404@Test(dataProvider = "pathDoesNotExist")405public void testPathDoesNotExist(Supplier<JmodResult> supplier,406String errMsg)407{408supplier.get()409.assertFailure()410.resultChecker(r -> {411assertContains(r.output, errMsg);412});413}414415@DataProvider(name = "partOfPathDoesNotExist")416public Object[][] partOfPathDoesNotExist() throws IOException {417Path jmod = MODS_DIR.resolve("output.jmod");418FileUtils.deleteFileIfExistsWithRetry(jmod);419FileUtils.deleteFileIfExistsWithRetry(Paths.get("doesNotExist"));420421Path emptyDir = Paths.get("empty");422if (Files.exists(emptyDir))423FileUtils.deleteFileTreeWithRetry(emptyDir);424Files.createDirectory(emptyDir);425426List<Supplier<JmodResult>> tasks = Arrays.asList(427() -> jmod("create",428"--hash-modules", "anyPattern",429"--module-path","empty" + pathSeparator + "doesNotExist",430"output.jmod"),431() -> jmod("create",432"--class-path", "empty" + pathSeparator + "doesNotExist",433"output.jmod"),434() -> jmod("create",435"--class-path", "empty" + pathSeparator + "doesNotExist.jar",436"output.jmod"),437() -> jmod("create",438"--cmds", "empty" + pathSeparator + "doesNotExist",439"output.jmod"),440() -> jmod("create",441"--config", "empty" + pathSeparator + "doesNotExist",442"output.jmod"),443() -> jmod("create",444"--libs", "empty" + pathSeparator + "doesNotExist",445"output.jmod") );446447String errMsg = "Error: path not found: doesNotExist";448return tasks.stream().map(t -> new Object[] {t, errMsg} )449.toArray(Object[][]::new);450}451452@Test(dataProvider = "partOfPathDoesNotExist")453public void testPartOfPathNotExist(Supplier<JmodResult> supplier,454String errMsg)455{456supplier.get()457.assertFailure()458.resultChecker(r -> {459assertContains(r.output, errMsg);460});461}462463@DataProvider(name = "pathIsFile")464public Object[][] pathIsFile() throws IOException {465Path jmod = MODS_DIR.resolve("output.jmod");466FileUtils.deleteFileIfExistsWithRetry(jmod);467Path aFile = Paths.get("aFile.txt");468if (Files.exists(aFile) && !Files.isRegularFile(aFile))469throw new InternalError("Unexpected file:" + aFile);470else471Files.createFile(aFile);472473List<Supplier<JmodResult>> tasks = Arrays.asList(474() -> jmod("create",475"--class-path", "aFile.txt",476"output.jmod"),477() -> jmod("create",478"--module-path", "aFile.txt",479"output.jmod"),480() -> jmod("create",481"--cmds", "aFile.txt",482"output.jmod"),483() -> jmod("create",484"--config", "aFile.txt",485"output.jmod"),486() -> jmod("create",487"--libs", "aFile.txt",488"output.jmod") );489490String errMsg = "Error: path must be a directory: aFile.txt";491Object[][] a = tasks.stream().map(t -> new Object[] {t, errMsg} )492.toArray(Object[][]::new);493a[0][1] = "invalid class path entry: aFile.txt"; // class path err msg494return a;495}496497@Test(dataProvider = "pathIsFile")498public void testPathIsFile(Supplier<JmodResult> supplier,499String errMsg)500{501supplier.get()502.assertFailure()503.resultChecker(r -> {504assertContains(r.output, errMsg);505});506}507508@Test509public void testNoMatchingHashModule() throws IOException {510Path lib = Paths.get("hashes");511Files.createDirectories(lib);512// create jmod file with no module depending on it513Path jmod = lib.resolve("foo.jmod");514jmod("create",515"--class-path", EXPLODED_DIR.resolve("foo").resolve("classes").toString(),516jmod.toString());517518// jmod hash command should report no module found to record hashes519jmod("hash",520"--module-path", lib.toString(),521"--hash-modules", ".*",522jmod.toString())523.resultChecker(r ->524assertContains(r.output, "No hashes recorded: " +525"no module matching \".*\" found to record hashes")526);527jmod("hash",528"--module-path", lib.toString(),529"--hash-modules", "foo")530.resultChecker(r ->531assertContains(r.output, "No hashes recorded: " +532"no module matching \"foo\" found to record hashes")533);534}535536// ---537538static boolean compileModule(String name, Path dest) throws IOException {539return CompilerUtils.compile(SRC_DIR.resolve(name), dest);540}541542static void assertContains(String output, String subString) {543if (output.contains(subString))544assertTrue(true);545else546assertTrue(false,"Expected to find [" + subString + "], in output ["547+ output + "]");548}549550static JmodResult jmod(String... args) {551ByteArrayOutputStream baos = new ByteArrayOutputStream();552PrintStream ps = new PrintStream(baos);553System.out.println("jmod " + Arrays.asList(args));554int ec = JMOD_TOOL.run(ps, ps, args);555return new JmodResult(ec, new String(baos.toByteArray(), UTF_8));556}557558static class JmodResult {559final int exitCode;560final String output;561562JmodResult(int exitValue, String output) {563this.exitCode = exitValue;564this.output = output;565}566JmodResult assertFailure() { assertTrue(exitCode != 0, output); return this; }567JmodResult resultChecker(Consumer<JmodResult> r) { r.accept(this); return this; }568}569}570571572