21 * questions. |
21 * questions. |
22 */ |
22 */ |
23 |
23 |
24 /* |
24 /* |
25 * @test |
25 * @test |
26 * @ignore |
|
27 * @bug 6836682 7025988 |
26 * @bug 6836682 7025988 |
28 * @summary JavacFileManager handles zip64 archives (64K+ entries and large file support) |
27 * @summary JavacFileManager handling of zip64 archives (Scenario A and B) |
29 * @compile -XDignore.symbol.file T6836682.java Utils.java |
28 * @compile -XDignore.symbol.file T6836682.java Utils.java |
30 * @run main T6836682 |
29 * @run main T6836682 |
31 */ |
30 */ |
|
31 /* |
|
32 * This test consists of two scenarios: |
|
33 * |
|
34 * Scenario A: create a jar with entries exceeding 64K, and see if the javac |
|
35 * can handle this large jar on the classpath. Generally this test completes |
|
36 * within a minute |
|
37 * |
|
38 * Scenario B: create a jar with a large enough file exceeding 4GB, and |
|
39 * similarly test javac. This test is known to be slow and problematic on |
|
40 * certain operating systems, thus this test can be selected by passing a |
|
41 * property through jtreg as follows: |
|
42 * -javaoptions=-DT6836682.testScenarioB=true. |
|
43 * Note this test will only run iff all the disk requirements are met at runtime. |
|
44 */ |
|
45 import java.io.BufferedInputStream; |
32 import java.io.BufferedOutputStream; |
46 import java.io.BufferedOutputStream; |
33 import java.io.File; |
47 import java.io.File; |
34 import java.io.FileInputStream; |
48 import java.io.FileInputStream; |
35 import java.io.FileOutputStream; |
49 import java.io.FileOutputStream; |
36 import java.io.IOException; |
50 import java.io.IOException; |
|
51 import java.io.OutputStream; |
37 import java.nio.file.Files; |
52 import java.nio.file.Files; |
38 import java.nio.file.Path; |
53 import java.nio.file.Path; |
39 import java.util.jar.JarOutputStream; |
54 import java.util.zip.CRC32; |
40 import java.util.zip.ZipEntry; |
55 import java.util.zip.ZipEntry; |
|
56 import java.util.zip.ZipOutputStream; |
41 |
57 |
42 public class T6836682 { |
58 public class T6836682 { |
43 |
59 |
44 private static final long GIGA = 1024 * 1024 * 1024; |
60 private static final long GIGA = 1024 * 1024 * 1024; |
45 |
61 private static final int BUFFER_LEN = Short.MAX_VALUE * 2; |
46 static void createLargeFile(File outFile, long minlength) throws IOException { |
62 |
47 FileOutputStream fos = null; |
63 static long getCount(long minlength) { |
48 BufferedOutputStream bos = null; |
64 return (minlength / BUFFER_LEN) + 1; |
49 byte[] buffer = new byte[Short.MAX_VALUE * 2]; |
65 } |
50 try { |
66 |
51 fos = new FileOutputStream(outFile); |
67 static long computeCRC(long minlength) { |
52 bos = new BufferedOutputStream(fos); |
68 CRC32 crc = new CRC32(); |
53 long count = minlength / ( Short.MAX_VALUE * 2) + 1; |
69 byte[] buffer = new byte[BUFFER_LEN]; |
54 for (long i = 0 ; i < count ; i++) { |
70 long count = getCount(minlength); |
55 bos.write(buffer); |
71 for (long i = 0; i < count; i++) { |
56 } |
72 crc.update(buffer); |
57 } finally { |
73 } |
58 Utils.close(bos); |
74 return crc.getValue(); |
59 Utils.close(fos); |
75 } |
60 } |
76 |
61 if (outFile.length() < minlength) { |
77 static long computeCRC(File inFile) throws IOException { |
62 throw new RuntimeException("could not create large file " + outFile.getAbsolutePath()); |
78 byte[] buffer = new byte[8192]; |
63 } |
79 CRC32 crc = new CRC32(); |
|
80 FileInputStream fis = null; |
|
81 BufferedInputStream bis = null; |
|
82 try { |
|
83 fis = new FileInputStream(inFile); |
|
84 bis = new BufferedInputStream(fis); |
|
85 int n = bis.read(buffer); |
|
86 while (n > 0) { |
|
87 crc.update(buffer, 0, n); |
|
88 n = bis.read(buffer); |
|
89 } |
|
90 } finally { |
|
91 Utils.close(bis); |
|
92 Utils.close(fis); |
|
93 } |
|
94 return crc.getValue(); |
|
95 } |
|
96 |
|
97 static void createLargeFile(OutputStream os, long minlength) throws IOException { |
|
98 byte[] buffer = new byte[BUFFER_LEN]; |
|
99 long count = getCount(minlength); |
|
100 for (long i = 0; i < count; i++) { |
|
101 os.write(buffer); |
|
102 } |
|
103 os.flush(); |
64 } |
104 } |
65 |
105 |
66 static void createJarWithLargeFile(File jarFile, File javaFile, |
106 static void createJarWithLargeFile(File jarFile, File javaFile, |
67 long minlength) throws IOException { |
107 long minlength) throws IOException { |
68 Utils.createClassFile(javaFile, null, true); |
108 Utils.createClassFile(javaFile, null, true); |
69 File largeFile = new File("large.data"); |
109 File classFile = new File(Utils.getClassFileName(javaFile)); |
70 createLargeFile(largeFile, minlength); |
110 ZipOutputStream zos = null; |
71 String[] jarArgs = { |
111 BufferedOutputStream bos = null; |
72 "0cvf", |
112 FileInputStream fis = null; |
73 jarFile.getAbsolutePath(), |
113 try { |
74 largeFile.getName(), |
114 zos = new ZipOutputStream(new FileOutputStream(jarFile)); |
75 Utils.getClassFileName(javaFile) |
115 zos.setLevel(ZipOutputStream.STORED); |
76 }; |
116 zos.setMethod(0); |
77 Utils.jarTool.run(jarArgs); |
117 bos = new BufferedOutputStream(zos); |
|
118 |
|
119 ZipEntry ze = new ZipEntry("large.data"); |
|
120 ze.setCompressedSize(getCount(minlength) * BUFFER_LEN); |
|
121 ze.setSize(getCount(minlength) * BUFFER_LEN); |
|
122 ze.setCrc(computeCRC(minlength)); |
|
123 ze.setMethod(ZipEntry.STORED); |
|
124 zos.putNextEntry(ze); |
|
125 createLargeFile(bos, minlength); |
|
126 |
|
127 ze = new ZipEntry(classFile.getName()); |
|
128 ze.setCompressedSize(classFile.length()); |
|
129 ze.setSize(classFile.length()); |
|
130 ze.setCrc(computeCRC(classFile)); |
|
131 ze.setMethod(ZipEntry.STORED); |
|
132 zos.putNextEntry(ze); |
|
133 fis = new FileInputStream(classFile); |
|
134 Utils.copyStream(fis, bos); |
|
135 bos.flush(); |
|
136 zos.closeEntry(); |
|
137 } finally { |
|
138 Utils.close(bos); |
|
139 Utils.close(zos); |
|
140 Utils.close(fis); |
|
141 } |
78 // deleted to prevent accidental linkage |
142 // deleted to prevent accidental linkage |
79 new File(Utils.getClassFileName(javaFile)).delete(); |
143 new File(Utils.getClassFileName(javaFile)).delete(); |
80 } |
144 } |
81 |
145 |
82 static void createLargeJar(File jarFile, File javaFile) throws IOException { |
146 static void createLargeJar(File jarFile, File javaFile) throws IOException { |
83 File classFile = new File(Utils.getClassFileName(javaFile)); |
147 File classFile = new File(Utils.getClassFileName(javaFile)); |
84 Utils.createClassFile(javaFile, null, true); |
148 Utils.createClassFile(javaFile, null, true); |
85 JarOutputStream jos = null; |
149 ZipOutputStream zos = null; |
86 FileInputStream fis = null; |
150 FileInputStream fis = null; |
87 try { |
151 final int MAX = Short.MAX_VALUE * 2 + 10; |
88 jos = new JarOutputStream(new FileOutputStream(jarFile)); |
152 ZipEntry ze = null; |
89 |
153 try { |
90 for (int i = 0; i < Short.MAX_VALUE * 2 + 10; i++) { |
154 zos = new ZipOutputStream(new FileOutputStream(jarFile)); |
91 jos.putNextEntry(new ZipEntry("X" + i + ".txt")); |
155 zos.setLevel(ZipOutputStream.STORED); |
92 } |
156 zos.setMethod(ZipOutputStream.STORED); |
93 jos.putNextEntry(new ZipEntry(classFile.getName())); |
157 for (int i = 0; i < MAX ; i++) { |
|
158 ze = new ZipEntry("X" + i + ".txt"); |
|
159 ze.setSize(0); |
|
160 ze.setCompressedSize(0); |
|
161 ze.setCrc(0); |
|
162 zos.putNextEntry(ze); |
|
163 } |
|
164 |
|
165 // add a class file |
|
166 ze = new ZipEntry(classFile.getName()); |
|
167 ze.setCompressedSize(classFile.length()); |
|
168 ze.setSize(classFile.length()); |
|
169 ze.setCrc(computeCRC(classFile)); |
|
170 zos.putNextEntry(ze); |
94 fis = new FileInputStream(classFile); |
171 fis = new FileInputStream(classFile); |
95 Utils.copyStream(fis, jos); |
172 Utils.copyStream(fis, zos); |
96 } finally { |
173 } finally { |
97 Utils.close(jos); |
174 Utils.close(zos); |
98 Utils.close(fis); |
175 Utils.close(fis); |
99 } |
|
100 // deleted to prevent accidental linkage |
176 // deleted to prevent accidental linkage |
101 new File(Utils.getClassFileName(javaFile)).delete(); |
177 new File(Utils.getClassFileName(javaFile)).delete(); |
102 } |
178 } |
|
179 } |
103 |
180 |
104 // a jar with entries exceeding 64k + a class file for the existential test |
181 // a jar with entries exceeding 64k + a class file for the existential test |
105 public static void testLargeJar(String... args) throws IOException { |
182 public static void testScenarioA(String... args) throws IOException { |
106 File largeJar = new File("large.jar"); |
183 File largeJar = new File("large.jar"); |
107 File javaFile = new File("Foo.java"); |
184 File javaFile = new File("Foo.java"); |
108 createLargeJar(largeJar, javaFile); |
185 createLargeJar(largeJar, javaFile); |
109 |
186 |
110 File testFile = new File("Bar.java"); |
187 File testFile = new File("Bar.java"); |
118 Utils.deleteFile(largeJar); |
195 Utils.deleteFile(largeJar); |
119 } |
196 } |
120 } |
197 } |
121 |
198 |
122 // a jar with an enormous file + a class file for the existential test |
199 // a jar with an enormous file + a class file for the existential test |
123 public static void testHugeJar(String... args) throws IOException { |
200 public static void testScenarioB(String... args) throws IOException { |
124 final File largeJar = new File("huge.jar"); |
201 final File largeJar = new File("huge.jar"); |
125 final File javaFile = new File("Foo.java"); |
202 final File javaFile = new File("Foo.java"); |
126 |
203 |
127 final Path path = largeJar.getAbsoluteFile().getParentFile().toPath(); |
204 final Path path = largeJar.getAbsoluteFile().getParentFile().toPath(); |
128 final long available = Files.getFileStore(path).getUsableSpace(); |
205 final long available = Files.getFileStore(path).getUsableSpace(); |
129 final long MAX_VALUE = 0xFFFF_FFFFL; |
206 final long MAX_VALUE = 0xFFFF_FFFFL; |
130 |
207 |
131 final long absolute = MAX_VALUE + 1L; |
208 final long absolute = MAX_VALUE + 1L; |
132 final long required = (long)(absolute * 1.1); // pad for sundries |
209 final long required = (long)(absolute * 1.1); // pad for sundries |
133 System.out.println("\tavailable: " + available / GIGA + " GB"); |
210 System.out.println("\tavailable: " + available / GIGA + " GB"); |
134 System.out.println("\required: " + required / GIGA + " GB"); |
211 System.out.println("\trequired: " + required / GIGA + " GB"); |
135 |
212 |
136 if (available > required) { |
213 if (available > required) { |
137 createJarWithLargeFile(largeJar, javaFile, absolute); |
214 createJarWithLargeFile(largeJar, javaFile, absolute); |
138 File testFile = new File("Bar.java"); |
215 File testFile = new File("Bar.java"); |
139 Utils.createJavaFile(testFile, javaFile); |
216 Utils.createJavaFile(testFile, javaFile); |