1 7 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 ; 30 import java.io.File ; 31 import java.io.FileNotFoundException ; 32 import java.io.FileOutputStream ; 33 import java.io.IOException ; 34 import java.io.InputStream ; 35 import java.io.OutputStream ; 36 import java.io.RandomAccessFile ; 37 import java.io.UnsupportedEncodingException ; 38 import java.lang.reflect.Array ; 39 import java.security.SecureRandom ; 40 import java.util.ArrayList ; 41 import java.util.Collections ; 42 import java.util.Enumeration ; 43 import java.util.HashSet ; 44 import java.util.Iterator ; 45 import java.util.List ; 46 import java.util.Random ; 47 import java.util.Set ; 48 import java.util.logging.Logger ; 49 50 import junit.framework.*; 51 52 57 public abstract class ZipTestBase extends TestCase { 58 59 private static final Logger logger 60 = Logger.getLogger(ZipTestBase.class.getName()); 61 62 63 protected static final Random rnd = new SecureRandom (); 64 65 66 protected byte[] data; 67 68 69 private File zip; 70 71 public ZipTestBase(String testName) { 72 super(testName); 73 } 74 75 81 protected void setUp() throws Exception { 82 if (data == null) 83 throw new IllegalStateException ("'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 { 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 out) 99 throws IOException { 100 return new ZipOutputStream(out); 101 } 102 103 protected ZipOutputStream createZipOutputStream( 104 OutputStream out, String encoding) 105 throws IOException , UnsupportedEncodingException { 106 return new ZipOutputStream(out, encoding); 107 } 108 109 protected ZipFile createZipFile(String name) 110 throws IOException { 111 return new ZipFile(name); 112 } 113 114 protected ZipFile createZipFile( 115 String name, String encoding) 116 throws IOException , UnsupportedEncodingException { 117 return new ZipFile(name, encoding); 118 } 119 120 protected ZipFile createZipFile(File file) 121 throws IOException { 122 return new ZipFile(file); 123 } 124 125 protected ZipFile createZipFile( 126 File file, String encoding) 127 throws IOException , UnsupportedEncodingException { 128 return new ZipFile(file, encoding); 129 } 130 131 protected ZipFile createZipFile(ReadOnlyFile file) 132 throws IOException { 133 return new ZipFile(file); 134 } 135 136 protected ZipFile createZipFile( 137 ReadOnlyFile file, String encoding) 138 throws IOException , UnsupportedEncodingException { 139 return new ZipFile(file, encoding); 140 } 141 142 public void testConstructors() throws Exception { 143 logger.fine("testConstructors"); 144 145 { 146 final OutputStream os = new FileOutputStream (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 npe) { 158 } 160 try { 161 createZipOutputStream(new ByteArrayOutputStream (), null); 162 fail("Use of null arguments should throw a NullPointerException!"); 163 } 164 catch (NullPointerException npe) { 165 } 167 try { 168 createZipOutputStream(null, "UTF-8"); 169 fail("Use of null arguments should throw a NullPointerException!"); 170 } 171 catch (NullPointerException npe) { 172 } 174 try { 175 createZipOutputStream(new ByteArrayOutputStream (), "unknown"); 176 fail("Use of unknown encoding should throw an UnsupportedEncodingException!"); 177 } 178 catch (UnsupportedEncodingException uee) { 179 } 181 182 try { 183 createZipFile((String ) null); 184 fail("Use of null arguments should throw a NullPointerException!"); 185 } 186 catch (NullPointerException npe) { 187 } 189 try { 190 createZipFile((String ) null, null); 191 fail("Use of null arguments should throw a NullPointerException!"); 192 } 193 catch (NullPointerException npe) { 194 } 196 try { 197 createZipFile((String ) null, "UTF-8"); 198 fail("Use of null arguments should throw a NullPointerException!"); 199 } 200 catch (NullPointerException npe) { 201 } 203 try { 204 createZipFile(zip.getName(), null); 205 fail("Use of null arguments should throw a NullPointerException!"); 206 } 207 catch (NullPointerException npe) { 208 } 210 211 try { 212 createZipFile((File) null); 213 fail("Use of null arguments should throw a NullPointerException!"); 214 } 215 catch (NullPointerException npe) { 216 } 218 try { 219 createZipFile((File) null, null); 220 fail("Use of null arguments should throw a NullPointerException!"); 221 } 222 catch (NullPointerException npe) { 223 } 225 try { 226 createZipFile((File) null, "UTF-8"); 227 fail("Use of null arguments should throw a NullPointerException!"); 228 } 229 catch (NullPointerException npe) { 230 } 232 try { 233 createZipFile(zip, null); 234 fail("Use of null arguments should throw a NullPointerException!"); 235 } 236 catch (NullPointerException npe) { 237 } 239 240 try { 241 createZipFile((ReadOnlyFile) null); 242 fail("Use of null arguments should throw a NullPointerException!"); 243 } 244 catch (NullPointerException npe) { 245 } 247 try { 248 createZipFile((ReadOnlyFile) null, null); 249 fail("Use of null arguments should throw a NullPointerException!"); 250 } 251 catch (NullPointerException npe) { 252 } 254 try { 255 createZipFile((ReadOnlyFile) null, "UTF-8"); 256 fail("Use of null arguments should throw a NullPointerException!"); 257 } 258 catch (NullPointerException npe) { 259 } 261 try { 262 createZipFile(rof, null); 263 fail("Use of null arguments should throw a NullPointerException!"); 264 } 265 catch (NullPointerException npe) { 266 } 268 269 try { 270 createZipFile(zip, "unknown"); 271 fail("Use of unknown encoding should throw an UnsupportedEncodingException!"); 272 } 273 catch (UnsupportedEncodingException uee) { 274 } 276 277 try { 278 createZipFile(zip.getName()); 279 fail("This is not a valid ZIP file!"); 280 } 281 catch (IOException ze) { 282 } 284 try { 285 createZipFile(zip); 286 fail("This is not a valid ZIP file!"); 287 } 288 catch (IOException ze) { 289 } 291 try { 292 createZipFile(rof); 293 fail("This is not a valid ZIP file!"); 294 } 295 catch (IOException ze) { 296 } 298 try { 299 createZipFile(zip, "UTF-8"); 300 fail("This is not a valid ZIP file!"); 301 } 302 catch (IOException ze) { 303 } 305 try { 306 createZipFile(rof, "UTF-8"); 307 fail("This is not a valid ZIP file!"); 308 } 309 catch (IOException ze) { 310 } 312 313 rof.close(); 314 assertTrue(zip.delete()); 315 } 316 317 public void testPreambleOfEmptyZipFile() throws IOException { 318 logger.fine("testPreambleOfEmptyZipFile"); 319 320 createZipOutputStream(new FileOutputStream (zip)).close(); 322 323 final ZipFile zipIn = createZipFile(zip); 325 try { 326 assertEquals(0, zipIn.getPreambleLength()); 327 final InputStream 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 { 340 logger.fine("testWriteAndReadSingleBytes"); 341 342 final ZipOutputStream zipOut 343 = createZipOutputStream(new FileOutputStream (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 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 { 363 logger.fine("testMultithreading"); 364 365 testMultithreading(20, 40); 366 } 367 368 376 private void testMultithreading(final int nEntries, final int nThreads) 377 throws Exception { 378 createTestZipFile(nEntries); 379 380 final ZipFile zipIn = createZipFile(zip); 381 382 class CheckAllEntriesThread extends Thread { 384 Throwable failure; 385 386 public void run() { 387 try { 388 final List entries = Collections.list(zipIn.entries()); 390 assert entries.size() == nEntries; 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 final byte[] buf = new byte[4096]; 400 for (final Iterator it = entries.iterator(); it.hasNext();) { 401 final ZipEntry entry = (ZipEntry) it.next(); 402 final InputStream 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 t) { 423 failure = t; 424 } 425 } 426 } 427 428 try { 429 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 for (int i = 0; i < nThreads; ) { 439 final CheckAllEntriesThread thread = threads[i]; 440 try { 441 thread.join(); 442 } catch (InterruptedException ignored) { 443 continue; 444 } 445 if (thread.failure != null) 446 throw new Exception (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 461 private void createTestZipFile(final int nEntries) throws IOException { 462 final HashSet set = new HashSet (); 463 464 ZipOutputStream zipOut 465 = createZipOutputStream(new FileOutputStream (zip)); 466 try { 467 for (int i = 0; i < nEntries; i++) { 468 String 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; 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 for (final Enumeration 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 { 496 logger.finer("goodGetCheckedInputStream"); 497 498 final String name = "entry"; 500 final ZipOutputStream zipOut 501 = createZipOutputStream(new FileOutputStream (zip)); 502 zipOut.putNextEntry(new ZipEntry(name)); 503 zipOut.write(data); 504 zipOut.close(); 505 506 final ZipFile zipIn = createZipFile(zip); 507 508 InputStream in = zipIn.getCheckedInputStream(name); 510 in.close(); 511 512 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 ; in.close(); 521 522 zipIn.close(); 523 } 524 525 public void testBadGetCheckedInputStream() throws IOException { 526 logger.finer("badGetCheckedInputStream"); 527 528 final String name = "entry"; 530 final ZipOutputStream zipOut 531 = new ZipOutputStream(new FileOutputStream (zip)); zipOut.putNextEntry(new ZipEntry(name)); 533 zipOut.write(data); 534 zipOut.close(); 535 536 final RandomAccessFile raf = new RandomAccessFile (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); 549 InputStream in = zipIn.getCheckedInputStream(name); 551 try { 552 in.close(); 553 fail("Expected CRC32Exception!"); 554 } catch (CRC32Exception expected) { 555 } 556 557 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 ; try { 566 in.close(); 567 fail("Expected CRC32Exception!"); 568 } catch (CRC32Exception expected) { 569 } 570 571 zipIn.close(); 572 } 573 } 574 | Popular Tags |