KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > de > schlichtherle > util > zip > ZipTestBase


1 /*
2  * ZipTestBase.java
3  * JUnit based test
4  *
5  * Created on 11. September 2005, 13:43
6  */

7 /*
8  * Copyright 2005 Schlichtherle IT Services
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  */

22
23 package de.schlichtherle.util.zip;
24
25 import de.schlichtherle.io.rof.ReadOnlyFile;
26 import de.schlichtherle.io.rof.SimpleReadOnlyFile;
27 import de.schlichtherle.util.Arrays;
28
29 import java.io.ByteArrayOutputStream JavaDoc;
30 import java.io.File JavaDoc;
31 import java.io.FileNotFoundException JavaDoc;
32 import java.io.FileOutputStream JavaDoc;
33 import java.io.IOException JavaDoc;
34 import java.io.InputStream JavaDoc;
35 import java.io.OutputStream JavaDoc;
36 import java.io.RandomAccessFile JavaDoc;
37 import java.io.UnsupportedEncodingException JavaDoc;
38 import java.lang.reflect.Array JavaDoc;
39 import java.security.SecureRandom JavaDoc;
40 import java.util.ArrayList JavaDoc;
41 import java.util.Collections JavaDoc;
42 import java.util.Enumeration JavaDoc;
43 import java.util.HashSet JavaDoc;
44 import java.util.Iterator JavaDoc;
45 import java.util.List JavaDoc;
46 import java.util.Random JavaDoc;
47 import java.util.Set JavaDoc;
48 import java.util.logging.Logger JavaDoc;
49
50 import junit.framework.*;
51
52 /**
53  * Tests compression of data.
54  *
55  * @author Christian Schlichtherle
56  */

57 public abstract class ZipTestBase extends TestCase {
58
59     private static final Logger JavaDoc logger
60             = Logger.getLogger(ZipTestBase.class.getName());
61
62     /** May be used by some tests or sub classes. */
63     protected static final Random JavaDoc rnd = new SecureRandom JavaDoc();
64
65     /** The data to get compressed. */
66     protected byte[] data;
67
68     /** The temporary file to use as a ZIP file. */
69     private File zip;
70     
71     public ZipTestBase(String JavaDoc testName) {
72         super(testName);
73     }
74
75     /**
76      * A subclass must override this method to create the {@link #data}
77      * to be zipped.
78      * It must also finally call this superclass implementation to create
79      * the temporary file to be used as a ZIP file.
80      */

81     protected void setUp() throws Exception JavaDoc {
82         if (data == null)
83             throw new IllegalStateException JavaDoc("'data' hasn't been initialized!");
84
85         zip = File.createTempFile("tmp", ".zip", null);
86         assertTrue(zip.delete());
87     }
88
89     protected void tearDown() throws Exception JavaDoc {
90         final boolean deleted = zip.delete();
91         if (!deleted && zip.exists())
92             logger.warning(zip + " (could not delete)");
93         zip = null;
94
95         data = null;
96     }
97
98     protected ZipOutputStream createZipOutputStream(OutputStream JavaDoc out)
99     throws IOException JavaDoc {
100         return new ZipOutputStream(out);
101     }
102
103     protected ZipOutputStream createZipOutputStream(
104             OutputStream JavaDoc out, String JavaDoc encoding)
105     throws IOException JavaDoc, UnsupportedEncodingException JavaDoc {
106         return new ZipOutputStream(out, encoding);
107     }
108
109     protected ZipFile createZipFile(String JavaDoc name)
110     throws IOException JavaDoc {
111         return new ZipFile(name);
112     }
113
114     protected ZipFile createZipFile(
115             String JavaDoc name, String JavaDoc encoding)
116     throws IOException JavaDoc, UnsupportedEncodingException JavaDoc {
117         return new ZipFile(name, encoding);
118     }
119
120     protected ZipFile createZipFile(File file)
121     throws IOException JavaDoc {
122         return new ZipFile(file);
123     }
124
125     protected ZipFile createZipFile(
126             File file, String JavaDoc encoding)
127     throws IOException JavaDoc, UnsupportedEncodingException JavaDoc {
128         return new ZipFile(file, encoding);
129     }
130
131     protected ZipFile createZipFile(ReadOnlyFile file)
132     throws IOException JavaDoc {
133         return new ZipFile(file);
134     }
135
136     protected ZipFile createZipFile(
137             ReadOnlyFile file, String JavaDoc encoding)
138     throws IOException JavaDoc, UnsupportedEncodingException JavaDoc {
139         return new ZipFile(file, encoding);
140     }
141
142     public void testConstructors() throws Exception JavaDoc {
143         logger.fine("testConstructors");
144
145         {
146             final OutputStream JavaDoc os = new FileOutputStream JavaDoc(zip);
147             os.write(data);
148             os.close();
149         }
150
151         final ReadOnlyFile rof = new SimpleReadOnlyFile(zip);
152
153         try {
154             createZipOutputStream(null, null);
155             fail("Use of null arguments should throw a NullPointerException!");
156         }
157         catch (NullPointerException JavaDoc npe) {
158             // This is the expected result!
159
}
160         try {
161             createZipOutputStream(new ByteArrayOutputStream JavaDoc(), null);
162             fail("Use of null arguments should throw a NullPointerException!");
163         }
164         catch (NullPointerException JavaDoc npe) {
165             // This is the expected result!
166
}
167         try {
168             createZipOutputStream(null, "UTF-8");
169             fail("Use of null arguments should throw a NullPointerException!");
170         }
171         catch (NullPointerException JavaDoc npe) {
172             // This is the expected result!
173
}
174         try {
175             createZipOutputStream(new ByteArrayOutputStream JavaDoc(), "unknown");
176             fail("Use of unknown encoding should throw an UnsupportedEncodingException!");
177         }
178         catch (UnsupportedEncodingException JavaDoc uee) {
179             // This is the expected result!
180
}
181
182         try {
183             createZipFile((String JavaDoc) null);
184             fail("Use of null arguments should throw a NullPointerException!");
185         }
186         catch (NullPointerException JavaDoc npe) {
187             // This is the expected result!
188
}
189         try {
190             createZipFile((String JavaDoc) null, null);
191             fail("Use of null arguments should throw a NullPointerException!");
192         }
193         catch (NullPointerException JavaDoc npe) {
194             // This is the expected result!
195
}
196         try {
197             createZipFile((String JavaDoc) null, "UTF-8");
198             fail("Use of null arguments should throw a NullPointerException!");
199         }
200         catch (NullPointerException JavaDoc npe) {
201             // This is the expected result!
202
}
203         try {
204             createZipFile(zip.getName(), null);
205             fail("Use of null arguments should throw a NullPointerException!");
206         }
207         catch (NullPointerException JavaDoc npe) {
208             // This is the expected result!
209
}
210
211         try {
212             createZipFile((File) null);
213             fail("Use of null arguments should throw a NullPointerException!");
214         }
215         catch (NullPointerException JavaDoc npe) {
216             // This is the expected result!
217
}
218         try {
219             createZipFile((File) null, null);
220             fail("Use of null arguments should throw a NullPointerException!");
221         }
222         catch (NullPointerException JavaDoc npe) {
223             // This is the expected result!
224
}
225         try {
226             createZipFile((File) null, "UTF-8");
227             fail("Use of null arguments should throw a NullPointerException!");
228         }
229         catch (NullPointerException JavaDoc npe) {
230             // This is the expected result!
231
}
232         try {
233             createZipFile(zip, null);
234             fail("Use of null arguments should throw a NullPointerException!");
235         }
236         catch (NullPointerException JavaDoc npe) {
237             // This is the expected result!
238
}
239
240         try {
241             createZipFile((ReadOnlyFile) null);
242             fail("Use of null arguments should throw a NullPointerException!");
243         }
244         catch (NullPointerException JavaDoc npe) {
245             // This is the expected result!
246
}
247         try {
248             createZipFile((ReadOnlyFile) null, null);
249             fail("Use of null arguments should throw a NullPointerException!");
250         }
251         catch (NullPointerException JavaDoc npe) {
252             // This is the expected result!
253
}
254         try {
255             createZipFile((ReadOnlyFile) null, "UTF-8");
256             fail("Use of null arguments should throw a NullPointerException!");
257         }
258         catch (NullPointerException JavaDoc npe) {
259             // This is the expected result!
260
}
261         try {
262             createZipFile(rof, null);
263             fail("Use of null arguments should throw a NullPointerException!");
264         }
265         catch (NullPointerException JavaDoc npe) {
266             // This is the expected result!
267
}
268
269         try {
270             createZipFile(zip, "unknown");
271             fail("Use of unknown encoding should throw an UnsupportedEncodingException!");
272         }
273         catch (UnsupportedEncodingException JavaDoc uee) {
274             // This is the expected result!
275
}
276
277         try {
278             createZipFile(zip.getName());
279             fail("This is not a valid ZIP file!");
280         }
281         catch (IOException JavaDoc ze) {
282             // This is the expected result!
283
}
284         try {
285             createZipFile(zip);
286             fail("This is not a valid ZIP file!");
287         }
288         catch (IOException JavaDoc ze) {
289             // This is the expected result!
290
}
291         try {
292             createZipFile(rof);
293             fail("This is not a valid ZIP file!");
294         }
295         catch (IOException JavaDoc ze) {
296             // This is the expected result!
297
}
298         try {
299             createZipFile(zip, "UTF-8");
300             fail("This is not a valid ZIP file!");
301         }
302         catch (IOException JavaDoc ze) {
303             // This is the expected result!
304
}
305         try {
306             createZipFile(rof, "UTF-8");
307             fail("This is not a valid ZIP file!");
308         }
309         catch (IOException JavaDoc ze) {
310             // This is the expected result!
311
}
312
313         rof.close();
314         assertTrue(zip.delete());
315     }
316
317     public void testPreambleOfEmptyZipFile() throws IOException JavaDoc {
318         logger.fine("testPreambleOfEmptyZipFile");
319
320         // Create empty ZIP file.
321
createZipOutputStream(new FileOutputStream JavaDoc(zip)).close();
322
323         // Assert that the empty ZIP file has no preamble.
324
final ZipFile zipIn = createZipFile(zip);
325         try {
326             assertEquals(0, zipIn.getPreambleLength());
327             final InputStream JavaDoc in = zipIn.getPreambleInputStream();
328             try {
329                 assertEquals(-1, in.read());
330             } finally {
331                 in.close();
332             }
333         } finally {
334             zipIn.close();
335         }
336         
337     }
338     
339     public void testWriteAndReadSingleBytes() throws IOException JavaDoc {
340         logger.fine("testWriteAndReadSingleBytes");
341
342         final ZipOutputStream zipOut
343                 = createZipOutputStream(new FileOutputStream JavaDoc(zip));
344         zipOut.putNextEntry(new ZipEntry("file"));
345         for (int i = 0; i < data.length; i++) {
346             zipOut.write(data[i]);
347         }
348         zipOut.close();
349         logger.finer("Compressed one file with the data to " + zip.length() + " bytes ZIP file length.");
350
351         final ZipFile zipIn = createZipFile(zip);
352         InputStream JavaDoc in = zipIn.getInputStream("file");
353         for (int i = 0, c; (c = in.read()) != -1; i++) {
354             assertEquals(data[i] & 0xFF, c);
355         }
356         in.close();
357         zipIn.close();
358         logger.finer("Successfully decompressed the data in the file.");
359     }
360
361     public void testMultithreading()
362     throws Exception JavaDoc {
363         logger.fine("testMultithreading");
364
365         testMultithreading(20, 40);
366     }
367
368     /**
369      * Creates a test ZIP file with the given number of entries and then
370      * creates the given number of threads where each of them read all these
371      * entries.
372      *
373      * @param nEntries The number of ZIP file entries to be created.
374      * @param nThreads The number of threads to be created.
375      */

376     private void testMultithreading(final int nEntries, final int nThreads)
377     throws Exception JavaDoc {
378         createTestZipFile(nEntries);
379
380         final ZipFile zipIn = createZipFile(zip);
381
382         // Define thread class to check all entries.
383
class CheckAllEntriesThread extends Thread JavaDoc {
384             Throwable JavaDoc failure;
385
386             public void run() {
387                 try {
388                     // Retrieve list of entries and randomize its order.
389
final List JavaDoc entries = Collections.list(zipIn.entries());
390                     assert entries.size() == nEntries; // this would be a programming error in the test - not the testlet!
391
for (int i = 0; i < nEntries; i++) {
392                         final int j = rnd.nextInt(nEntries);
393                         final ZipEntry temp = (ZipEntry) entries.get(i);
394                         entries.set(i, entries.get(j));
395                         entries.set(j, temp);
396                     }
397
398                     // Now read in the entries in the randomized order.
399
final byte[] buf = new byte[4096];
400                     for (final Iterator JavaDoc it = entries.iterator(); it.hasNext();) {
401                         final ZipEntry entry = (ZipEntry) it.next();
402                         // Read full entry and check the contents.
403
final InputStream JavaDoc in = zipIn.getInputStream(entry);
404                         try {
405                             int off = 0;
406                             int read;
407                             do {
408                                 read = in.read(buf);
409                                 if (read < 0)
410                                     break;
411                                 assertTrue(read > 0);
412                                 assertTrue(Arrays.equals(data, off, buf, 0, read));
413                                 off += read;
414                             } while (true);
415                             assertEquals(-1, read);
416                             assertEquals(off, data.length);
417                             assertEquals(0, in.read(new byte[0]));
418                         } finally {
419                             in.close();
420                         }
421                     }
422                 } catch (Throwable JavaDoc t) {
423                     failure = t;
424                 }
425             }
426         }
427
428         try {
429             // Create and start all threads.
430
final CheckAllEntriesThread[] threads = new CheckAllEntriesThread[nThreads];
431             for (int i = 0; i < nThreads; i++) {
432                 final CheckAllEntriesThread thread = new CheckAllEntriesThread();
433                 thread.start();
434                 threads[i] = thread;
435             }
436
437             // Wait for all threads until done.
438
for (int i = 0; i < nThreads; ) {
439                 final CheckAllEntriesThread thread = threads[i];
440                 try {
441                     thread.join();
442                 } catch (InterruptedException JavaDoc ignored) {
443                     continue;
444                 }
445                 if (thread.failure != null)
446                     throw new Exception JavaDoc(thread.failure);
447                 i++;
448             }
449         } finally {
450             zipIn.close();
451         }
452
453         logger.finer(nThreads + " threads have successfully decompressed the data in all archive entries.");
454     }
455
456     /**
457      * Creates test ZIP file with <code>nEntries</code> and returns the
458      * entry names in a set.
459      * The field <code>zip</code> is used to determine the ZIP file.
460      */

461     private void createTestZipFile(final int nEntries) throws IOException JavaDoc {
462         final HashSet JavaDoc set = new HashSet JavaDoc();
463
464         ZipOutputStream zipOut
465                 = createZipOutputStream(new FileOutputStream JavaDoc(zip));
466         try {
467             for (int i = 0; i < nEntries; i++) {
468                 String JavaDoc name = i + ".txt";
469                 zipOut.putNextEntry(new ZipEntry(name));
470                 zipOut.write(data);
471                 assertTrue(set.add(name));
472             }
473         } finally {
474             zipOut.close();
475         }
476         zipOut = null; // allow GC
477
logger.finer("Compressed "
478                 + nEntries + " archive entries with the data to "
479                 + zip.length() + " bytes ZIP file length.");
480
481         ZipFile zipIn = createZipFile(zip);
482         try {
483             // Check that zipIn correctly enumerates all entries.
484
for (final Enumeration JavaDoc e = zipIn.entries(); e.hasMoreElements(); ) {
485                 final ZipEntry entry = (ZipEntry) e.nextElement();
486                 assertEquals(data.length, entry.getSize());
487                 assertTrue(set.remove(entry.getName()));
488             }
489             assertTrue(set.isEmpty());
490         } finally {
491             zipIn.close();
492         }
493     }
494
495     public void testGoodGetCheckedInputStream() throws IOException JavaDoc {
496         logger.finer("goodGetCheckedInputStream");
497
498         // Create test ZIP file.
499
final String JavaDoc name = "entry";
500         final ZipOutputStream zipOut
501                 = createZipOutputStream(new FileOutputStream JavaDoc(zip));
502         zipOut.putNextEntry(new ZipEntry(name));
503         zipOut.write(data);
504         zipOut.close();
505
506         final ZipFile zipIn = createZipFile(zip);
507
508         // Open checked input stream and close immediately.
509
InputStream JavaDoc in = zipIn.getCheckedInputStream(name);
510         in.close();
511
512         // Open checked input stream and read fully, using multiple methods.
513
in = zipIn.getCheckedInputStream(name);
514         final int n = data.length / 4;
515         in.skip(n);
516         in.read(new byte[n]);
517         in.read(new byte[n], 0, n);
518         while (in.read() != -1)
519             ; // read until EOF
520
in.close();
521
522         zipIn.close();
523     }
524
525     public void testBadGetCheckedInputStream() throws IOException JavaDoc {
526         logger.finer("badGetCheckedInputStream");
527
528         // Create test ZIP file.
529
final String JavaDoc name = "entry";
530         final ZipOutputStream zipOut
531                 = new ZipOutputStream(new FileOutputStream JavaDoc(zip)); // NOT createZipOutputStream(...) !
532
zipOut.putNextEntry(new ZipEntry(name));
533         zipOut.write(data);
534         zipOut.close();
535
536         // Modify ZIP file to contain an incorrect CRC32 value in the
537
// Central File Header.
538
// TODO: This is a hack which works with a plain ZIP file only
539
// (not an RAES encrypted ZIP file) and may easily break if the
540
// ZipOutputStream class changes its implementation!
541
final RandomAccessFile JavaDoc raf = new RandomAccessFile JavaDoc(zip, "rw");
542         raf.seek(raf.length() - 57);
543         final byte octet = (byte) 0xFF;
544         raf.write(new byte[] { octet, octet, octet, octet});
545         raf.close();
546
547         final ZipFile zipIn = new ZipFile(zip); // NOT createZipFile(...) !
548

549         // Open checked input stream and close immediately.
550
InputStream JavaDoc in = zipIn.getCheckedInputStream(name);
551         try {
552             in.close();
553             fail("Expected CRC32Exception!");
554         } catch (CRC32Exception expected) {
555         }
556
557         // Open checked input stream and read fully, using multiple methods.
558
in = zipIn.getCheckedInputStream(name);
559         final int n = data.length / 4;
560         in.skip(n);
561         in.read(new byte[n]);
562         in.read(new byte[n], 0, n);
563         while (in.read() != -1)
564             ; // read until EOF
565
try {
566             in.close();
567             fail("Expected CRC32Exception!");
568         } catch (CRC32Exception expected) {
569         }
570
571         zipIn.close();
572     }
573 }
574
Popular Tags