1/* 2 * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/* 25 * @test 26 * @bug 8165944 27 * @summary test several jar tool input file scenarios with variations on -C 28 * options with/without a --release option. Some input files are 29 * duplicates that sometimes cause exceptions and other times do not, 30 * demonstrating identical behavior to JDK 8 jar tool. 31 * @library /test/lib 32 * @modules jdk.jartool 33 * @build jdk.test.lib.Platform 34 * jdk.test.lib.util.FileUtils 35 * @run testng InputFilesTest 36 */ 37 38import org.testng.Assert; 39import org.testng.annotations.AfterMethod; 40import org.testng.annotations.BeforeMethod; 41import org.testng.annotations.Test; 42 43import java.io.ByteArrayOutputStream; 44import java.io.IOException; 45import java.io.PrintStream; 46import java.io.UncheckedIOException; 47import java.nio.file.Files; 48import java.nio.file.Path; 49import java.nio.file.Paths; 50import java.util.Arrays; 51import java.util.spi.ToolProvider; 52import java.util.stream.Stream; 53import java.util.zip.ZipException; 54 55import jdk.test.lib.util.FileUtils; 56 57public class InputFilesTest { 58 private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") 59 .orElseThrow(() -> 60 new RuntimeException("jar tool not found") 61 ); 62 63 private final String nl = System.lineSeparator(); 64 private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 65 private final PrintStream out = new PrintStream(baos); 66 private Runnable onCompletion; 67 68 @BeforeMethod 69 public void reset() { 70 onCompletion = null; 71 } 72 73 @AfterMethod 74 public void run() { 75 if (onCompletion != null) { 76 onCompletion.run(); 77 } 78 } 79 80 @Test 81 public void test1() throws IOException { 82 mkdir("test1 test2"); 83 touch("test1/testfile1 test2/testfile2"); 84 jar("cf test.jar -C test1 . -C test2 ."); 85 jar("tf test.jar"); 86 println(); 87 String output = "META-INF/" + nl + 88 "META-INF/MANIFEST.MF" + nl + 89 "testfile1" + nl + 90 "testfile2" + nl; 91 rm("test.jar test1 test2"); 92 Assert.assertEquals(baos.toByteArray(), output.getBytes()); 93 } 94 95 @Test 96 public void test2() throws IOException { 97 mkdir("test1 test2 test3 test4"); 98 touch("test1/testfile1 test2/testfile2 test3/testfile3 test4/testfile4"); 99 jar("cf test.jar -C test1 . -C test2 . --release 9 -C test3 . -C test4 ."); 100 jar("tf test.jar"); 101 println(); 102 String output = "META-INF/" + nl + 103 "META-INF/MANIFEST.MF" + nl + 104 "testfile1" + nl + 105 "testfile2" + nl + 106 "META-INF/versions/9/" + nl + 107 "META-INF/versions/9/testfile3" + nl + 108 "META-INF/versions/9/testfile4" + nl; 109 rm("test.jar test1 test2 test3 test4"); 110 Assert.assertEquals(baos.toByteArray(), output.getBytes()); 111 } 112 113 @Test 114 public void test3() throws IOException { 115 touch("test"); 116 jar("cf test.jar test test"); 117 jar("tf test.jar"); 118 println(); 119 String output = "META-INF/" + nl + 120 "META-INF/MANIFEST.MF" + nl + 121 "test" + nl; 122 rm("test.jar test"); 123 Assert.assertEquals(baos.toByteArray(), output.getBytes()); 124 } 125 126 @Test 127 public void test4() throws IOException { 128 mkdir("a"); 129 touch("a/test"); 130 jar("cf test.jar -C a test -C a test"); 131 jar("tf test.jar"); 132 println(); 133 String output = "META-INF/" + nl + 134 "META-INF/MANIFEST.MF" + nl + 135 "test" + nl; 136 rm("test.jar a"); 137 Assert.assertEquals(baos.toByteArray(), output.getBytes()); 138 } 139 140 @Test(expectedExceptions = {ZipException.class}) 141 public void test5() throws IOException { 142 mkdir("a"); 143 touch("test a/test"); 144 onCompletion = () -> rm("test a"); 145 jar("cf test.jar -C a test test"); 146 } 147 148 @Test(expectedExceptions = {ZipException.class}) 149 public void test6() throws IOException { 150 mkdir("test1 test2"); 151 touch("test1/a test2/a"); 152 onCompletion = () -> rm("test1 test2"); 153 jar("cf test.jar --release 9 -C test1 a -C test2 a"); 154 } 155 156 private Stream<Path> mkpath(String... args) { 157 return Arrays.stream(args).map(d -> Paths.get(".", d.split("/"))); 158 } 159 160 private void mkdir(String cmdline) { 161 System.out.println("mkdir -p " + cmdline); 162 mkpath(cmdline.split(" +")).forEach(p -> { 163 try { 164 Files.createDirectories(p); 165 } catch (IOException x) { 166 throw new UncheckedIOException(x); 167 } 168 }); 169 } 170 171 private void touch(String cmdline) { 172 System.out.println("touch " + cmdline); 173 mkpath(cmdline.split(" +")).forEach(p -> { 174 try { 175 Files.createFile(p); 176 } catch (IOException x) { 177 throw new UncheckedIOException(x); 178 } 179 }); 180 } 181 182 private void rm(String cmdline) { 183 System.out.println("rm -rf " + cmdline); 184 mkpath(cmdline.split(" +")).forEach(p -> { 185 try { 186 if (Files.isDirectory(p)) { 187 FileUtils.deleteFileTreeWithRetry(p); 188 } else { 189 FileUtils.deleteFileIfExistsWithRetry(p); 190 } 191 } catch (IOException x) { 192 throw new UncheckedIOException(x); 193 } 194 }); 195 } 196 197 private void jar(String cmdline) throws IOException { 198 System.out.println("jar " + cmdline); 199 baos.reset(); 200 201 // the run method catches IOExceptions, we need to expose them 202 ByteArrayOutputStream baes = new ByteArrayOutputStream(); 203 PrintStream err = new PrintStream(baes); 204 PrintStream saveErr = System.err; 205 System.setErr(err); 206 int rc = JAR_TOOL.run(out, err, cmdline.split(" +")); 207 System.setErr(saveErr); 208 if (rc != 0) { 209 String s = baes.toString(); 210 if (s.startsWith("java.util.zip.ZipException: duplicate entry: ")) { 211 throw new ZipException(s); 212 } 213 throw new IOException(s); 214 } 215 } 216 217 private void println() throws IOException { 218 System.out.println(new String(baos.toByteArray())); 219 } 220} 221