1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.compress.archivers.sevenz;
18
19 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertFalse;
22 import static org.junit.jupiter.api.Assertions.assertNotEquals;
23 import static org.junit.jupiter.api.Assertions.assertNotNull;
24 import static org.junit.jupiter.api.Assertions.assertThrows;
25 import static org.junit.jupiter.api.Assertions.assertTrue;
26
27 import java.io.ByteArrayInputStream;
28 import java.io.File;
29 import java.io.IOException;
30 import java.nio.file.Files;
31 import java.nio.file.Paths;
32 import java.nio.file.attribute.FileTime;
33 import java.time.Instant;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.Calendar;
37 import java.util.Collections;
38 import java.util.Date;
39 import java.util.Iterator;
40
41 import org.apache.commons.compress.AbstractTest;
42 import org.apache.commons.compress.PasswordRequiredException;
43 import org.apache.commons.compress.utils.ByteUtils;
44 import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
45 import org.apache.commons.compress.utils.TimeUtils;
46 import org.junit.jupiter.api.Test;
47 import org.tukaani.xz.LZMA2Options;
48
49 public class SevenZOutputFileTest extends AbstractTest {
50
51 private static final boolean XZ_BCJ_IS_BUGGY;
52
53 static {
54 final String version = org.tukaani.xz.XZ.class.getPackage().getImplementationVersion();
55
56 XZ_BCJ_IS_BUGGY = version != null && version.equals("1.4");
57 if (XZ_BCJ_IS_BUGGY) {
58 System.out.println("XZ version is " + version + " - skipping BCJ tests");
59 }
60 }
61
62 private static void assertContentMethodsEquals(final Iterable<? extends SevenZMethodConfiguration> expected,
63 final Iterable<? extends SevenZMethodConfiguration> actual) {
64 assertNotNull(actual);
65 final Iterator<? extends SevenZMethodConfiguration> actualIter = actual.iterator();
66 for (final SevenZMethodConfiguration expConfig : expected) {
67 assertTrue(actualIter.hasNext());
68 final SevenZMethodConfiguration actConfig = actualIter.next();
69 assertEquals(expConfig.getMethod(), actConfig.getMethod());
70 }
71 assertFalse(actualIter.hasNext());
72 }
73
74 private void addDir(final SevenZOutputFile archive) throws Exception {
75 final SevenZArchiveEntry entry = archive.createArchiveEntry(getTempDirFile(), "foo/");
76 archive.putArchiveEntry(entry);
77 archive.closeArchiveEntry();
78 }
79
80 private void addFile(final SevenZOutputFile archive, final int index, final boolean nonEmpty) throws Exception {
81 addFile(archive, index, nonEmpty, null);
82 }
83
84 private void addFile(final SevenZOutputFile archive, final int index, final boolean nonEmpty, final Iterable<SevenZMethodConfiguration> methods)
85 throws Exception {
86 addFile(archive, index, nonEmpty ? 1 : 0, methods);
87 }
88
89 private void addFile(final SevenZOutputFile archive, final int index, final int size, final Iterable<SevenZMethodConfiguration> methods) throws Exception {
90 final SevenZArchiveEntry entry = new SevenZArchiveEntry();
91 entry.setName("foo/" + index + ".txt");
92 entry.setContentMethods(methods);
93 archive.putArchiveEntry(entry);
94 archive.write(generateFileData(size));
95 archive.closeArchiveEntry();
96 }
97
98 private void createAndReadBack(final File output, final Iterable<SevenZMethodConfiguration> methods) throws Exception {
99 try (SevenZOutputFile outArchive = new SevenZOutputFile(output)) {
100 outArchive.setContentMethods(methods);
101 addFile(outArchive, 0, true);
102 }
103
104 try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
105 assertEquals(Boolean.TRUE, verifyFile(archive, 0, methods));
106 }
107 }
108
109 private void createAndReadBack(final SeekableInMemoryByteChannel output, final Iterable<SevenZMethodConfiguration> methods) throws Exception {
110 try (SevenZOutputFile outArchive = new SevenZOutputFile(output)) {
111 outArchive.setContentMethods(methods);
112 addFile(outArchive, 0, true);
113 }
114 try (SevenZFile archive = SevenZFile.builder().setByteArray(output.array()).setDefaultName("in memory").get()) {
115 assertEquals(Boolean.TRUE, verifyFile(archive, 0, methods));
116 }
117 }
118
119 private byte[] generateFileData(final int size) {
120 final byte[] data = new byte[size];
121 for (int i = 0; i < size; i++) {
122 data[i] = (byte) ('A' + i % 26);
123 }
124 return data;
125 }
126
127 private FileTime getHundredNanosFileTime() {
128 final Instant now = Instant.now();
129
130
131 final FileTime fileTime = FileTime.from(Instant.ofEpochSecond(now.getEpochSecond(), now.getNano() + 999900));
132
133
134 return TimeUtils.truncateToHundredNanos(fileTime);
135 }
136
137 @Test
138 public void testArchiveWithMixedMethods() throws Exception {
139 final File output = newTempFile("mixed-methods.7z");
140 try (SevenZOutputFile outArchive = new SevenZOutputFile(output)) {
141 addFile(outArchive, 0, true);
142 addFile(outArchive, 1, true, Arrays.asList(new SevenZMethodConfiguration(SevenZMethod.BZIP2)));
143 }
144
145 try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
146 assertEquals(Boolean.TRUE, verifyFile(archive, 0, Arrays.asList(new SevenZMethodConfiguration(SevenZMethod.LZMA2))));
147 assertEquals(Boolean.TRUE, verifyFile(archive, 1, Arrays.asList(new SevenZMethodConfiguration(SevenZMethod.BZIP2))));
148 }
149 }
150
151 @Test
152 public void testBCJARMRoundtrip() throws Exception {
153 if (XZ_BCJ_IS_BUGGY) {
154 return;
155 }
156 testFilterRoundTrip(new SevenZMethodConfiguration(SevenZMethod.BCJ_ARM_FILTER));
157 }
158
159 @Test
160 public void testBCJARMThumbRoundtrip() throws Exception {
161 if (XZ_BCJ_IS_BUGGY) {
162 return;
163 }
164 testFilterRoundTrip(new SevenZMethodConfiguration(SevenZMethod.BCJ_ARM_THUMB_FILTER));
165 }
166
167 @Test
168 public void testBCJIA64Roundtrip() throws Exception {
169 if (XZ_BCJ_IS_BUGGY) {
170 return;
171 }
172 testFilterRoundTrip(new SevenZMethodConfiguration(SevenZMethod.BCJ_IA64_FILTER));
173 }
174
175 @Test
176 public void testBCJPPCRoundtrip() throws Exception {
177 if (XZ_BCJ_IS_BUGGY) {
178 return;
179 }
180 testFilterRoundTrip(new SevenZMethodConfiguration(SevenZMethod.BCJ_PPC_FILTER));
181 }
182
183 @Test
184 public void testBCJSparcRoundtrip() throws Exception {
185 if (XZ_BCJ_IS_BUGGY) {
186 return;
187 }
188 testFilterRoundTrip(new SevenZMethodConfiguration(SevenZMethod.BCJ_SPARC_FILTER));
189 }
190
191 @Test
192 public void testBCJX86Roundtrip() throws Exception {
193 if (XZ_BCJ_IS_BUGGY) {
194 return;
195 }
196 testFilterRoundTrip(new SevenZMethodConfiguration(SevenZMethod.BCJ_X86_FILTER));
197 }
198
199 @Test
200 public void testBzip2Roundtrip() throws Exception {
201 testRoundTrip(SevenZMethod.BZIP2);
202 }
203
204 @Test
205 public void testBzip2WithConfiguration() throws Exception {
206 final File output = newTempFile("bzip2-options.7z");
207
208 createAndReadBack(output, Collections.singletonList(new SevenZMethodConfiguration(SevenZMethod.BZIP2, 4)));
209 }
210
211 @Test
212 public void testCantFinishTwice() throws IOException {
213 final File output = newTempFile("finish.7z");
214 try (SevenZOutputFile outArchive = new SevenZOutputFile(output)) {
215 outArchive.finish();
216 final IOException ex = assertThrows(IOException.class, outArchive::finish, "shouldn't be able to call finish twice");
217 assertEquals("This archive has already been finished", ex.getMessage());
218 }
219 }
220
221 private void testCompress252(final int numberOfFiles, final int numberOfNonEmptyFiles) throws Exception {
222 final int nonEmptyModulus = numberOfNonEmptyFiles != 0 ? numberOfFiles / numberOfNonEmptyFiles : numberOfFiles + 1;
223 int nonEmptyFilesAdded = 0;
224 final File output = newTempFile("COMPRESS252-" + numberOfFiles + "-" + numberOfNonEmptyFiles + ".7z");
225 try (SevenZOutputFile archive = new SevenZOutputFile(output)) {
226 addDir(archive);
227 for (int i = 0; i < numberOfFiles; i++) {
228 addFile(archive, i, (i + 1) % nonEmptyModulus == 0 && nonEmptyFilesAdded++ < numberOfNonEmptyFiles);
229 }
230 }
231 verifyCompress252(output, numberOfFiles, numberOfNonEmptyFiles);
232 }
233
234 @Test
235 public void testCopyRoundtrip() throws Exception {
236 testRoundTrip(SevenZMethod.COPY);
237 }
238
239 @Test
240 public void testDeflateRoundtrip() throws Exception {
241 testRoundTrip(SevenZMethod.DEFLATE);
242 }
243
244 @Test
245 public void testDeflateWithConfiguration() throws Exception {
246 final File output = newTempFile("deflate-options.7z");
247
248 createAndReadBack(output, Collections.singletonList(new SevenZMethodConfiguration(SevenZMethod.DEFLATE, 1)));
249 }
250
251 @Test
252 public void testDeltaRoundtrip() throws Exception {
253 testFilterRoundTrip(new SevenZMethodConfiguration(SevenZMethod.DELTA_FILTER));
254 }
255
256 @Test
257 public void testDirectoriesAndEmptyFiles() throws Exception {
258 final File output = newTempFile("empties.7z");
259
260 final FileTime accessTime = getHundredNanosFileTime();
261 final Date accessDate = new Date(accessTime.toMillis());
262 final Calendar cal = Calendar.getInstance();
263 cal.add(Calendar.HOUR, -1);
264 final Date creationDate = cal.getTime();
265
266 try (SevenZOutputFile outArchive = new SevenZOutputFile(output)) {
267 SevenZArchiveEntry entry = outArchive.createArchiveEntry(getTempDirFile(), "foo/");
268 outArchive.putArchiveEntry(entry);
269 outArchive.closeArchiveEntry();
270
271 entry = new SevenZArchiveEntry();
272 entry.setName("foo/bar");
273 entry.setCreationDate(creationDate);
274 entry.setAccessTime(accessTime);
275 outArchive.putArchiveEntry(entry);
276 outArchive.write(ByteUtils.EMPTY_BYTE_ARRAY);
277 outArchive.closeArchiveEntry();
278
279 entry = new SevenZArchiveEntry();
280 entry.setName("foo/bar/boo0");
281 entry.setCreationDate(creationDate);
282 entry.setAccessTime(accessTime);
283 outArchive.putArchiveEntry(entry);
284 outArchive.write(new ByteArrayInputStream(ByteUtils.EMPTY_BYTE_ARRAY));
285 outArchive.closeArchiveEntry();
286
287 entry = new SevenZArchiveEntry();
288 entry.setName("foo/bar/boo1");
289 entry.setCreationDate(creationDate);
290 entry.setAccessTime(accessTime);
291 outArchive.putArchiveEntry(entry);
292 outArchive.write(new ByteArrayInputStream(new byte[] { 'a' }));
293 outArchive.closeArchiveEntry();
294
295 entry = new SevenZArchiveEntry();
296 entry.setName("foo/bar/boo10000");
297 entry.setCreationDate(creationDate);
298 entry.setAccessTime(accessTime);
299 outArchive.putArchiveEntry(entry);
300 outArchive.write(new ByteArrayInputStream(new byte[10000]));
301 outArchive.closeArchiveEntry();
302
303 entry = new SevenZArchiveEntry();
304 entry.setName("foo/bar/test.txt");
305 entry.setCreationDate(creationDate);
306 entry.setAccessTime(accessTime);
307 outArchive.putArchiveEntry(entry);
308 outArchive.write(Paths.get("src/test/resources/test.txt"));
309 outArchive.closeArchiveEntry();
310
311 entry = new SevenZArchiveEntry();
312 entry.setName("xyzzy");
313 outArchive.putArchiveEntry(entry);
314 outArchive.write(0);
315 outArchive.closeArchiveEntry();
316
317 entry = outArchive.createArchiveEntry(getTempDirFile(), "baz/");
318 entry.setAntiItem(true);
319 outArchive.putArchiveEntry(entry);
320 outArchive.closeArchiveEntry();
321
322 entry = outArchive.createArchiveEntry(getTempDirFile().toPath(), "baz2/");
323 entry.setAntiItem(true);
324 outArchive.putArchiveEntry(entry);
325 outArchive.closeArchiveEntry();
326
327 entry = new SevenZArchiveEntry();
328 entry.setName("dada");
329 entry.setHasWindowsAttributes(true);
330 entry.setWindowsAttributes(17);
331 outArchive.putArchiveEntry(entry);
332 outArchive.write(5);
333 outArchive.write(42);
334 outArchive.closeArchiveEntry();
335
336 outArchive.finish();
337 }
338
339 try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
340 SevenZArchiveEntry entry = archive.getNextEntry();
341 assert entry != null;
342 assertEquals("foo/", entry.getName());
343 assertTrue(entry.isDirectory());
344 assertFalse(entry.isAntiItem());
345
346 entry = archive.getNextEntry();
347 assert entry != null;
348 assertEquals("foo/bar", entry.getName());
349 assertFalse(entry.isDirectory());
350 assertFalse(entry.isAntiItem());
351 assertEquals(0, entry.getSize());
352 assertFalse(entry.getHasLastModifiedDate());
353 assertEquals(accessTime, entry.getAccessTime());
354 assertEquals(accessDate, entry.getAccessDate());
355 assertEquals(creationDate, entry.getCreationDate());
356
357 entry = archive.getNextEntry();
358 assert entry != null;
359 assertEquals("foo/bar/boo0", entry.getName());
360 assertFalse(entry.isDirectory());
361 assertFalse(entry.isAntiItem());
362 assertEquals(0, entry.getSize());
363 assertFalse(entry.getHasLastModifiedDate());
364 assertEquals(accessTime, entry.getAccessTime());
365 assertEquals(accessDate, entry.getAccessDate());
366 assertEquals(creationDate, entry.getCreationDate());
367
368 entry = archive.getNextEntry();
369 assert entry != null;
370 assertEquals("foo/bar/boo1", entry.getName());
371 assertFalse(entry.isDirectory());
372 assertFalse(entry.isAntiItem());
373 assertEquals(1, entry.getSize());
374 assertFalse(entry.getHasLastModifiedDate());
375 assertEquals(accessTime, entry.getAccessTime());
376 assertEquals(accessDate, entry.getAccessDate());
377 assertEquals(creationDate, entry.getCreationDate());
378
379 entry = archive.getNextEntry();
380 assert entry != null;
381 assertEquals("foo/bar/boo10000", entry.getName());
382 assertFalse(entry.isDirectory());
383 assertFalse(entry.isAntiItem());
384 assertEquals(10000, entry.getSize());
385 assertFalse(entry.getHasLastModifiedDate());
386 assertEquals(accessTime, entry.getAccessTime());
387 assertEquals(accessDate, entry.getAccessDate());
388 assertEquals(creationDate, entry.getCreationDate());
389
390 entry = archive.getNextEntry();
391 assert entry != null;
392 assertEquals("foo/bar/test.txt", entry.getName());
393 assertFalse(entry.isDirectory());
394 assertFalse(entry.isAntiItem());
395 assertEquals(Files.size(Paths.get("src/test/resources/test.txt")), entry.getSize());
396 assertFalse(entry.getHasLastModifiedDate());
397 assertEquals(accessTime, entry.getAccessTime());
398 assertEquals(accessDate, entry.getAccessDate());
399 assertEquals(creationDate, entry.getCreationDate());
400
401 entry = archive.getNextEntry();
402 assert entry != null;
403 assertEquals("xyzzy", entry.getName());
404 assertEquals(1, entry.getSize());
405 assertFalse(entry.getHasAccessDate());
406 assertFalse(entry.getHasCreationDate());
407 assertEquals(0, archive.read());
408
409 entry = archive.getNextEntry();
410 assert entry != null;
411 assertEquals("baz/", entry.getName());
412 assertTrue(entry.isDirectory());
413 assertTrue(entry.isAntiItem());
414
415 entry = archive.getNextEntry();
416 assert entry != null;
417 assertEquals("baz2/", entry.getName());
418 assertTrue(entry.isDirectory());
419 assertTrue(entry.isAntiItem());
420
421 entry = archive.getNextEntry();
422 assert entry != null;
423 assertEquals("dada", entry.getName());
424 assertEquals(2, entry.getSize());
425 final byte[] content = new byte[2];
426 assertEquals(2, archive.read(content));
427 assertEquals(5, content[0]);
428 assertEquals(42, content[1]);
429 assertEquals(17, entry.getWindowsAttributes());
430
431 assert archive.getNextEntry() == null;
432 }
433
434 }
435
436 @Test
437 public void testDirectoriesOnly() throws Exception {
438 final File output = newTempFile("dirs.7z");
439 try (SevenZOutputFile outArchive = new SevenZOutputFile(output)) {
440 final SevenZArchiveEntry entry = new SevenZArchiveEntry();
441 entry.setName("foo/");
442 entry.setDirectory(true);
443 outArchive.putArchiveEntry(entry);
444 outArchive.closeArchiveEntry();
445 }
446
447 try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
448 final SevenZArchiveEntry entry = archive.getNextEntry();
449 assert entry != null;
450 assertEquals("foo/", entry.getName());
451 assertTrue(entry.isDirectory());
452 assertFalse(entry.isAntiItem());
453
454 assert archive.getNextEntry() == null;
455 }
456
457 }
458
459 @Test
460 public void testEightEmptyFiles() throws Exception {
461 testCompress252(8, 0);
462 }
463
464 @Test
465 public void testEightFilesSomeNotEmpty() throws Exception {
466 testCompress252(8, 2);
467 }
468
469
470
471
472
473
474
475
476
477 @Test
478 public void testEncrypt() throws Exception {
479 final File output = newTempFile("encrypted.7z");
480 try (SevenZOutputFile outArchive = new SevenZOutputFile(output, "foo".toCharArray())) {
481 addFile(outArchive, 0, 1, null);
482 addFile(outArchive, 1, 16, null);
483 addFile(outArchive, 2, 32, null);
484 addFile(outArchive, 3, 33, null);
485 addFile(outArchive, 4, 10000, null);
486 }
487
488
489 try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
490 assertThrows(
491 PasswordRequiredException.class, () -> verifyFile(archive, 0), "A password should be needed");
492 }
493
494 try (SevenZFile archive = SevenZFile.builder().setFile(output).setPassword("foo").get()) {
495 assertEquals(Boolean.TRUE, verifyFile(archive, 0, 1, null));
496 assertEquals(Boolean.TRUE, verifyFile(archive, 1, 16, null));
497 assertEquals(Boolean.TRUE, verifyFile(archive, 2, 32, null));
498 assertEquals(Boolean.TRUE, verifyFile(archive, 3, 33, null));
499 assertEquals(Boolean.TRUE, verifyFile(archive, 4, 10000, null));
500 }
501 }
502
503 private void testFilterRoundTrip(final SevenZMethodConfiguration method) throws Exception {
504 final File output = newTempFile(method.getMethod() + "-roundtrip.7z");
505 final ArrayList<SevenZMethodConfiguration> methods = new ArrayList<>();
506 methods.add(method);
507 methods.add(new SevenZMethodConfiguration(SevenZMethod.LZMA2));
508 createAndReadBack(output, methods);
509 }
510
511 @Test
512 public void testLzma2Roundtrip() throws Exception {
513 testRoundTrip(SevenZMethod.LZMA2);
514 }
515
516 @Test
517 public void testLzma2WithIntConfiguration() throws Exception {
518 final File output = newTempFile("lzma2-options.7z");
519
520 createAndReadBack(output, Collections.singletonList(new SevenZMethodConfiguration(SevenZMethod.LZMA2, 1 << 20)));
521 }
522
523 @Test
524 public void testLzma2WithOptionsConfiguration() throws Exception {
525 final File output = newTempFile("lzma2-options2.7z");
526 final LZMA2Options opts = new LZMA2Options(1);
527 createAndReadBack(output, Collections.singletonList(new SevenZMethodConfiguration(SevenZMethod.LZMA2, opts)));
528 }
529
530 @Test
531 public void testLzmaWithIntConfiguration() throws Exception {
532 final File output = newTempFile("lzma-options.7z");
533
534 createAndReadBack(output, Collections.singletonList(new SevenZMethodConfiguration(SevenZMethod.LZMA, 1 << 20)));
535 }
536
537 @Test
538 public void testLzmaWithOptionsConfiguration() throws Exception {
539 final File output = newTempFile("lzma-options2.7z");
540 final LZMA2Options opts = new LZMA2Options(1);
541 createAndReadBack(output, Collections.singletonList(new SevenZMethodConfiguration(SevenZMethod.LZMA, opts)));
542 }
543
544 @Test
545 public void testNineEmptyFiles() throws Exception {
546 testCompress252(9, 0);
547 }
548
549 @Test
550 public void testNineFilesSomeNotEmpty() throws Exception {
551 testCompress252(9, 2);
552 }
553
554 private void testRoundTrip(final SevenZMethod method) throws Exception {
555 final File output = newTempFile(method + "-roundtrip.7z");
556 final ArrayList<SevenZMethodConfiguration> methods = new ArrayList<>();
557 methods.add(new SevenZMethodConfiguration(method));
558 createAndReadBack(output, methods);
559 }
560
561 @Test
562 public void testSevenEmptyFiles() throws Exception {
563 testCompress252(7, 0);
564 }
565
566 @Test
567 public void testSevenFilesSomeNotEmpty() throws Exception {
568 testCompress252(7, 2);
569 }
570
571 @Test
572 public void testSixEmptyFiles() throws Exception {
573 testCompress252(6, 0);
574 }
575
576 @Test
577 public void testSixFilesSomeNotEmpty() throws Exception {
578 testCompress252(6, 2);
579 }
580
581 @Test
582 public void testStackOfContentCompressions() throws Exception {
583 final File output = newTempFile("multiple-methods.7z");
584 final ArrayList<SevenZMethodConfiguration> methods = new ArrayList<>();
585 methods.add(new SevenZMethodConfiguration(SevenZMethod.LZMA2));
586 methods.add(new SevenZMethodConfiguration(SevenZMethod.COPY));
587 methods.add(new SevenZMethodConfiguration(SevenZMethod.DEFLATE));
588 methods.add(new SevenZMethodConfiguration(SevenZMethod.BZIP2));
589 createAndReadBack(output, methods);
590 }
591
592 @Test
593 public void testStackOfContentCompressionsInMemory() throws Exception {
594 final ArrayList<SevenZMethodConfiguration> methods = new ArrayList<>();
595 methods.add(new SevenZMethodConfiguration(SevenZMethod.LZMA2));
596 methods.add(new SevenZMethodConfiguration(SevenZMethod.COPY));
597 methods.add(new SevenZMethodConfiguration(SevenZMethod.DEFLATE));
598 methods.add(new SevenZMethodConfiguration(SevenZMethod.BZIP2));
599 try (SeekableInMemoryByteChannel channel = new SeekableInMemoryByteChannel()) {
600 createAndReadBack(channel, methods);
601 }
602 }
603
604 @Test
605 public void testTwentyNineEmptyFiles() throws Exception {
606 testCompress252(29, 0);
607 }
608
609 @Test
610 public void testTwentyNineFilesSomeNotEmpty() throws Exception {
611 testCompress252(29, 7);
612 }
613
614 private void verifyCompress252(final File output, final int numberOfFiles, final int numberOfNonEmptyFiles) throws Exception {
615 int filesFound = 0;
616 int nonEmptyFilesFound = 0;
617 try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
618 verifyDir(archive);
619 Boolean b = verifyFile(archive, filesFound++);
620 while (b != null) {
621 if (Boolean.TRUE.equals(b)) {
622 nonEmptyFilesFound++;
623 }
624 b = verifyFile(archive, filesFound++);
625 }
626 }
627 assertEquals(numberOfFiles + 1, filesFound);
628 assertEquals(numberOfNonEmptyFiles, nonEmptyFilesFound);
629 }
630
631 private void verifyDir(final SevenZFile archive) throws Exception {
632 final SevenZArchiveEntry entry = archive.getNextEntry();
633 assertNotNull(entry);
634 assertEquals("foo/", entry.getName());
635 assertTrue(entry.isDirectory());
636 }
637
638 private Boolean verifyFile(final SevenZFile archive, final int index) throws Exception {
639 return verifyFile(archive, index, null);
640 }
641
642 private Boolean verifyFile(final SevenZFile archive, final int index, final int size, final Iterable<SevenZMethodConfiguration> methods) throws Exception {
643 final SevenZArchiveEntry entry = archive.getNextEntry();
644 if (entry == null) {
645 return null;
646 }
647 assertEquals("foo/" + index + ".txt", entry.getName());
648 assertFalse(entry.isDirectory());
649 if (entry.getSize() == 0) {
650 return Boolean.FALSE;
651 }
652 assertEquals(size, entry.getSize());
653
654 final byte[] actual = new byte[size];
655 int count = 0;
656 while (count < size) {
657 final int read = archive.read(actual, count, actual.length - count);
658 assertNotEquals(-1, read, "EOF reached before reading all expected data");
659 count += read;
660 }
661 assertArrayEquals(generateFileData(size), actual);
662 assertEquals(-1, archive.read());
663 if (methods != null) {
664 assertContentMethodsEquals(methods, entry.getContentMethods());
665 }
666 return Boolean.TRUE;
667 }
668
669 private Boolean verifyFile(final SevenZFile archive, final int index, final Iterable<SevenZMethodConfiguration> methods) throws Exception {
670 return verifyFile(archive, index, 1, methods);
671 }
672 }