1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.documentsui.archives;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.junit.Assert.fail;
22 import static org.mockito.Mockito.mock;
23 import static org.mockito.Mockito.when;
24 
25 import android.os.ParcelFileDescriptor;
26 
27 import androidx.annotation.NonNull;
28 import androidx.annotation.Nullable;
29 import androidx.test.runner.AndroidJUnit4;
30 
31 import org.apache.commons.compress.archivers.ArchiveEntry;
32 import org.apache.commons.compress.archivers.ArchiveException;
33 import org.apache.commons.compress.compressors.CompressorException;
34 import org.junit.Rule;
35 import org.junit.Test;
36 import org.junit.runner.RunWith;
37 
38 import java.io.FileInputStream;
39 import java.io.IOException;
40 import java.io.InputStream;
41 import java.util.ArrayList;
42 import java.util.Date;
43 import java.util.Enumeration;
44 import java.util.List;
45 import java.util.Locale;
46 
47 @RunWith(AndroidJUnit4.class)
48 public class ArchiveHandleTest {
49     @Rule
50     public ArchiveFileTestRule mArchiveFileTestRule = new ArchiveFileTestRule();
51 
52 
prepareArchiveHandle(String archivePath, String suffix, String mimeType)53     private ArchiveHandle prepareArchiveHandle(String archivePath, String suffix,
54             String mimeType) throws IOException, CompressorException, ArchiveException {
55         ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule
56                 .openAssetFile(archivePath, suffix);
57 
58         return ArchiveHandle.create(parcelFileDescriptor, mimeType);
59     }
60 
getFileInArchive(Enumeration<ArchiveEntry> enumeration, String pathInArchive)61     private static ArchiveEntry getFileInArchive(Enumeration<ArchiveEntry> enumeration,
62             String pathInArchive) {
63         while (enumeration.hasMoreElements()) {
64             ArchiveEntry entry = enumeration.nextElement();
65             if (entry.getName().equals(pathInArchive)) {
66                 return entry;
67             }
68         }
69         return null;
70     }
71 
72 
73     private static class ArchiveEntryRecord implements ArchiveEntry {
74         private final String mName;
75         private final long mSize;
76         private final boolean mIsDirectory;
77 
ArchiveEntryRecord(ArchiveEntry archiveEntry)78         private ArchiveEntryRecord(ArchiveEntry archiveEntry) {
79             this(archiveEntry.getName(), archiveEntry.getSize(), archiveEntry.isDirectory());
80         }
81 
ArchiveEntryRecord(String name, long size, boolean isDirectory)82         private ArchiveEntryRecord(String name, long size, boolean isDirectory) {
83             mName = name;
84             mSize = size;
85             mIsDirectory = isDirectory;
86         }
87 
88         @Override
equals(@ullable Object obj)89         public boolean equals(@Nullable Object obj) {
90             if (obj == null) {
91                 return false;
92             }
93 
94             if (obj instanceof ArchiveEntryRecord) {
95                 ArchiveEntryRecord recordB = (ArchiveEntryRecord) obj;
96                 return mName.equals(recordB.mName)
97                         && mSize == recordB.mSize
98                         && mIsDirectory == recordB.mIsDirectory;
99             }
100 
101             return false;
102         }
103 
104         @Override
getName()105         public String getName() {
106             return mName;
107         }
108 
109         @Override
getSize()110         public long getSize() {
111             return mSize;
112         }
113 
114         @Override
isDirectory()115         public boolean isDirectory() {
116             return mIsDirectory;
117         }
118 
119         @Override
getLastModifiedDate()120         public Date getLastModifiedDate() {
121             return null;
122         }
123 
124         @NonNull
125         @Override
toString()126         public String toString() {
127             return String.format(Locale.ENGLISH, "name: %s, size: %d, isDirectory: %b",
128                     mName, mSize, mIsDirectory);
129         }
130     }
131 
transformToIterable(Enumeration<ArchiveEntry> enumeration)132     private static List<ArchiveEntry> transformToIterable(Enumeration<ArchiveEntry> enumeration) {
133         List list = new ArrayList<ArchiveEntry>();
134         while (enumeration.hasMoreElements()) {
135             list.add(new ArchiveEntryRecord(enumeration.nextElement()));
136         }
137         return list;
138     }
139 
140     private static final List<ArchiveEntryRecord> sExpectEntries = List.of(
141             new ArchiveEntryRecord("hello/hello.txt", 48, false),
142             new ArchiveEntryRecord("hello/inside_folder/hello_insside.txt", 14, false),
143             new ArchiveEntryRecord("hello/hello2.txt", 48, false));
144 
145 
146     @Test
buildArchiveHandle_withoutFileDescriptor_shouldBeIllegal()147     public void buildArchiveHandle_withoutFileDescriptor_shouldBeIllegal() throws Exception {
148         try {
149             ArchiveHandle.create(null,
150                     "application/x-7z-compressed");
151             fail("It should not be here!");
152         } catch (NullPointerException e) {
153             /* do nothing */
154         }
155     }
156 
157     @Test
buildArchiveHandle_withWrongMimeType_shouldBeIllegal()158     public void buildArchiveHandle_withWrongMimeType_shouldBeIllegal() throws Exception {
159         ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule
160                 .openAssetFile("archives/7z/hello.7z", ".7z");
161 
162         try {
163             ArchiveHandle.create(parcelFileDescriptor, null);
164             fail("It should not be here!");
165         } catch (IllegalArgumentException e) {
166             /* do nothing */
167         }
168     }
169 
170     @Test
buildArchiveHandle_sevenZFile_shouldNotNull()171     public void buildArchiveHandle_sevenZFile_shouldNotNull() throws Exception {
172         ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z",
173                 ".7z", "application/x-7z-compressed");
174 
175         assertThat(archiveHandle).isNotNull();
176     }
177 
178     @Test
buildArchiveHandle_zipFile_shouldNotNull()179     public void buildArchiveHandle_zipFile_shouldNotNull() throws Exception {
180         ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip",
181                 ".zip", "application/zip");
182 
183         assertThat(archiveHandle).isNotNull();
184     }
185 
186     @Test
buildArchiveHandle_zipWithWrongMimeType_shouldBeNull()187     public void buildArchiveHandle_zipWithWrongMimeType_shouldBeNull() throws Exception {
188         try {
189             prepareArchiveHandle("archives/zip/hello.zip",
190                     ".zip", "application/xxxzip");
191             fail("It should not be here!");
192         } catch (UnsupportedOperationException e) {
193             /* do nothing */
194         }
195     }
196 
197     @Test
buildArchiveHandle_tarFile_shouldNotNull()198     public void buildArchiveHandle_tarFile_shouldNotNull() throws Exception {
199         ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar/hello.tar",
200                 ".tar", "application/x-gtar");
201 
202         assertThat(archiveHandle).isNotNull();
203     }
204 
205     @Test
buildArchiveHandle_tgzFile_shouldNotNull()206     public void buildArchiveHandle_tgzFile_shouldNotNull() throws Exception {
207         ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar_gz/hello.tgz",
208                 ".tgz", "application/x-compressed-tar");
209 
210         assertThat(archiveHandle).isNotNull();
211     }
212 
213     @Test
buildArchiveHandle_tarGzFile_shouldNotNull()214     public void buildArchiveHandle_tarGzFile_shouldNotNull() throws Exception {
215         ArchiveHandle archiveHandle =
216                 prepareArchiveHandle("archives/tar_gz/hello_tar_gz", ".tar.gz",
217                         "application/x-compressed-tar");
218 
219         assertThat(archiveHandle).isNotNull();
220     }
221 
222     @Test
buildArchiveHandle_tarBzipFile_shouldNotNull()223     public void buildArchiveHandle_tarBzipFile_shouldNotNull() throws Exception {
224         ArchiveHandle archiveHandle =
225                 prepareArchiveHandle("archives/tar_bz2/hello.tar.bz2",
226                         ".tar.bz2", "application/x-bzip-compressed-tar");
227 
228         assertThat(archiveHandle).isNotNull();
229     }
230 
231     @Test
buildArchiveHandle_tarXzFile_shouldNotNull()232     public void buildArchiveHandle_tarXzFile_shouldNotNull() throws Exception {
233         ArchiveHandle archiveHandle =
234                 prepareArchiveHandle("archives/xz/hello.tar.xz", ".tar.xz",
235                         "application/x-xz-compressed-tar");
236 
237         assertThat(archiveHandle).isNotNull();
238     }
239 
240     @Test
buildArchiveHandle_tarBrFile_shouldNotNull()241     public void buildArchiveHandle_tarBrFile_shouldNotNull() throws Exception {
242         ArchiveHandle archiveHandle =
243                 prepareArchiveHandle("archives/brotli/hello.tar.br", ".tar.br",
244                 "application/x-brotli-compressed-tar");
245 
246         assertThat(archiveHandle).isNotNull();
247     }
248 
249     @Test
getMimeType_sevenZFile_shouldBeSevenZ()250     public void getMimeType_sevenZFile_shouldBeSevenZ()
251             throws CompressorException, ArchiveException, IOException {
252         ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z",
253                 ".7z", "application/x-7z-compressed");
254 
255         assertThat(archiveHandle.getMimeType()).isEqualTo("application/x-7z-compressed");
256     }
257 
258     @Test
getMimeType_tarBrotli_shouldBeBrotliCompressedTar()259     public void getMimeType_tarBrotli_shouldBeBrotliCompressedTar()
260             throws CompressorException, ArchiveException, IOException {
261         ArchiveHandle archiveHandle =
262                 prepareArchiveHandle("archives/brotli/hello.tar.br", ".tar.br",
263                         "application/x-brotli-compressed-tar");
264 
265         assertThat(archiveHandle.getMimeType())
266                 .isEqualTo("application/x-brotli-compressed-tar");
267     }
268 
269     @Test
getMimeType_tarXz_shouldBeXzCompressedTar()270     public void getMimeType_tarXz_shouldBeXzCompressedTar()
271             throws CompressorException, ArchiveException, IOException {
272         ArchiveHandle archiveHandle =
273                 prepareArchiveHandle("archives/xz/hello.tar.xz", ".tar.xz",
274                         "application/x-xz-compressed-tar");
275 
276         assertThat(archiveHandle.getMimeType())
277                 .isEqualTo("application/x-xz-compressed-tar");
278     }
279 
280     @Test
getMimeType_tarGz_shouldBeCompressedTar()281     public void getMimeType_tarGz_shouldBeCompressedTar()
282             throws CompressorException, ArchiveException, IOException {
283         ArchiveHandle archiveHandle =
284                 prepareArchiveHandle("archives/tar_gz/hello_tar_gz", ".tar.gz",
285                         "application/x-compressed-tar");
286 
287         assertThat(archiveHandle.getMimeType())
288                 .isEqualTo("application/x-compressed-tar");
289     }
290 
291     @Test
getCommonArchive_tarBrFile_shouldBeCommonArchiveInputHandle()292     public void getCommonArchive_tarBrFile_shouldBeCommonArchiveInputHandle() throws Exception {
293         ArchiveHandle archiveHandle =
294                 prepareArchiveHandle("archives/brotli/hello.tar.br", ".tar.br",
295                         "application/x-brotli-compressed-tar");
296 
297         assertThat(archiveHandle.toString()).contains("CommonArchiveInputHandle");
298     }
299 
300     @Test
getCommonArchive_sevenZFile_shouldBeSevenZFileHandle()301     public void getCommonArchive_sevenZFile_shouldBeSevenZFileHandle() throws Exception {
302         ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z",
303                 ".7z", "application/x-7z-compressed");
304 
305         assertThat(archiveHandle.toString()).contains("SevenZFileHandle");
306     }
307 
308 
309     @Test
getCommonArchive_zipFile_shouldBeZipFileHandle()310     public void getCommonArchive_zipFile_shouldBeZipFileHandle() throws Exception {
311         ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip",
312                 ".zip", "application/zip");
313 
314         assertThat(archiveHandle.toString()).contains("ZipFileHandle");
315     }
316 
317     @Test
close_zipFile_shouldBeSuccess()318     public void close_zipFile_shouldBeSuccess() throws Exception {
319         ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip",
320                 ".zip", "application/zip");
321 
322         archiveHandle.close();
323     }
324 
325     @Test
close_sevenZFile_shouldBeSuccess()326     public void close_sevenZFile_shouldBeSuccess() throws Exception {
327         ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z",
328                 ".7z", "application/x-7z-compressed");
329 
330         archiveHandle.close();
331     }
332 
333     @Test
closeInputStream_zipFile_shouldBeSuccess()334     public void closeInputStream_zipFile_shouldBeSuccess() throws Exception {
335         ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip",
336                 ".zip", "application/zip");
337 
338         InputStream inputStream = archiveHandle.getInputStream(
339                 getFileInArchive(archiveHandle.getEntries(),
340                         "hello/inside_folder/hello_insside.txt"));
341 
342         assertThat(inputStream).isNotNull();
343 
344         inputStream.close();
345     }
346 
347     @Test
close_zipFile_shouldNotOpen()348     public void close_zipFile_shouldNotOpen() throws Exception {
349         ParcelFileDescriptor parcelFileDescriptor =  mArchiveFileTestRule
350                 .openAssetFile("archives/zip/hello.zip", ".zip");
351 
352         ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor,
353                 "application/zip");
354 
355         archiveHandle.close();
356 
357         FileInputStream fileInputStream =
358                 new FileInputStream(parcelFileDescriptor.getFileDescriptor());
359         assertThat(fileInputStream).isNotNull();
360     }
361 
362     @Test
getInputStream_zipFile_shouldHaveTheSameContent()363     public void getInputStream_zipFile_shouldHaveTheSameContent() throws Exception {
364         ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule
365                 .openAssetFile("archives/zip/hello.zip", ".zip");
366 
367         String expectedContent = mArchiveFileTestRule.getAssetText(
368                 "archives/original/hello/inside_folder/hello_insside.txt");
369 
370         ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor,
371                 "application/zip");
372 
373         InputStream inputStream = archiveHandle.getInputStream(
374                 getFileInArchive(archiveHandle.getEntries(),
375                         "hello/inside_folder/hello_insside.txt"));
376 
377         assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream))
378                 .isEqualTo(expectedContent);
379     }
380 
381     @Test
getInputStream_zipFileNotExistEntry_shouldFail()382     public void getInputStream_zipFileNotExistEntry_shouldFail() throws Exception {
383         ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip",
384                 ".zip", "application/zip");
385 
386         ArchiveEntry archiveEntry = mock(ArchiveEntry.class);
387         when(archiveEntry.getName()).thenReturn("/not_exist_entry");
388 
389         try {
390             archiveHandle.getInputStream(archiveEntry);
391             fail("It should not be here.");
392         } catch (ClassCastException e) {
393             /* do nothing */
394         }
395     }
396 
397     @Test
getInputStream_directoryEntry_shouldFail()398     public void getInputStream_directoryEntry_shouldFail() throws Exception {
399         ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip",
400                 ".zip", "application/zip");
401 
402         ArchiveEntry archiveEntry = mock(ArchiveEntry.class);
403         when(archiveEntry.isDirectory()).thenReturn(true);
404 
405         try {
406             archiveHandle.getInputStream(archiveEntry);
407             fail("It should not be here.");
408         } catch (IllegalArgumentException e) {
409             /* expected, do nothing */
410         }
411     }
412 
413     @Test
getInputStream_negativeSizeEntry_shouldFail()414     public void getInputStream_negativeSizeEntry_shouldFail() throws Exception {
415         ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip",
416                 ".zip", "application/zip");
417 
418         ArchiveEntry archiveEntry = mock(ArchiveEntry.class);
419         when(archiveEntry.isDirectory()).thenReturn(false);
420         when(archiveEntry.getSize()).thenReturn(-1L);
421 
422         try {
423             archiveHandle.getInputStream(archiveEntry);
424             fail("It should not be here.");
425         } catch (IllegalArgumentException e) {
426             /* expected, do nothing */
427         }
428     }
429 
430     @Test
getInputStream_emptyStringEntry_shouldFail()431     public void getInputStream_emptyStringEntry_shouldFail() throws Exception {
432         ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip",
433                 ".zip", "application/zip");
434 
435         ArchiveEntry archiveEntry = mock(ArchiveEntry.class);
436         when(archiveEntry.isDirectory()).thenReturn(false);
437         when(archiveEntry.getSize()).thenReturn(14L);
438         when(archiveEntry.getName()).thenReturn("");
439 
440         try {
441             archiveHandle.getInputStream(archiveEntry);
442             fail("It should not be here.");
443         } catch (IllegalArgumentException e) {
444             /* expected, do nothing */
445         }
446     }
447 
448     @Test
getInputStream_sevenZFile_shouldHaveTheSameContent()449     public void getInputStream_sevenZFile_shouldHaveTheSameContent() throws Exception {
450         ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule
451                 .openAssetFile("archives/7z/hello.7z", ".7z");
452 
453         String expectedContent = mArchiveFileTestRule.getAssetText(
454                 "archives/original/hello/inside_folder/hello_insside.txt");
455 
456         ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor,
457                 "application/x-7z-compressed");
458 
459         InputStream inputStream = archiveHandle.getInputStream(
460                 getFileInArchive(archiveHandle.getEntries(),
461                         "hello/inside_folder/hello_insside.txt"));
462 
463         assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream))
464                 .isEqualTo(expectedContent);
465     }
466 
467     @Test
getInputStream_tarGzFile_shouldHaveTheSameContent()468     public void getInputStream_tarGzFile_shouldHaveTheSameContent() throws Exception {
469         ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule
470                 .openAssetFile("archives/tar_gz/hello.tgz", ".tar.gz");
471 
472         String expectedContent = mArchiveFileTestRule.getAssetText(
473                 "archives/original/hello/inside_folder/hello_insside.txt");
474 
475         ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor,
476                 "application/x-compressed-tar");
477 
478         InputStream inputStream = archiveHandle.getInputStream(
479                 getFileInArchive(archiveHandle.getEntries(),
480                         "hello/inside_folder/hello_insside.txt"));
481 
482         assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream))
483                 .isEqualTo(expectedContent);
484     }
485 
486     @Test
getInputStream_tarGzFileNullEntry_getNullInputStream()487     public void getInputStream_tarGzFileNullEntry_getNullInputStream() throws Exception {
488         ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule
489                 .openAssetFile("archives/tar_gz/hello.tgz", ".tar.gz");
490 
491         String expectedContent = mArchiveFileTestRule.getAssetText(
492                 "archives/original/hello/inside_folder/hello_insside.txt");
493 
494         ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor,
495                 "application/x-compressed-tar");
496 
497         try {
498             archiveHandle.getInputStream(null);
499             fail("It should not here");
500         } catch (IllegalArgumentException | ArchiveException | CompressorException e) {
501             /* expected, do nothing */
502         }
503     }
504 
505 
506     @Test
getInputStream_tarGzFileInvalidEntry_getNullInputStream()507     public void getInputStream_tarGzFileInvalidEntry_getNullInputStream() throws Exception {
508         ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule
509                 .openAssetFile("archives/tar_gz/hello.tgz", ".tar.gz");
510 
511         String expectedContent = mArchiveFileTestRule.getAssetText(
512                 "archives/original/hello/inside_folder/hello_insside.txt");
513 
514         ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor,
515                 "application/x-compressed-tar");
516 
517         ArchiveEntry archiveEntry = mock(ArchiveEntry.class);
518         when(archiveEntry.getName()).thenReturn("");
519         try {
520             archiveHandle.getInputStream(archiveEntry);
521             fail("It should not here");
522         } catch (IllegalArgumentException | ArchiveException | CompressorException e) {
523             /* expected, do nothing */
524         }
525     }
526 
527     @Test
getInputStream_tarBrotliFile_shouldHaveTheSameContent()528     public void getInputStream_tarBrotliFile_shouldHaveTheSameContent() throws Exception {
529         ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule
530                 .openAssetFile("archives/brotli/hello.tar.br", ".tar.br");
531 
532         String expectedContent = mArchiveFileTestRule.getAssetText(
533                 "archives/original/hello/inside_folder/hello_insside.txt");
534 
535         ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor,
536                 "application/x-brotli-compressed-tar");
537 
538         InputStream inputStream = archiveHandle.getInputStream(
539                 getFileInArchive(archiveHandle.getEntries(),
540                         "hello/inside_folder/hello_insside.txt"));
541 
542         assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream))
543                 .isEqualTo(expectedContent);
544     }
545 
546     @Test
getEntries_zipFile_shouldTheSameWithList()547     public void getEntries_zipFile_shouldTheSameWithList() throws Exception {
548         ArchiveHandle archiveHandle =
549                 prepareArchiveHandle("archives/zip/hello.zip", ".zip",
550                         "application/zip");
551 
552         assertThat(transformToIterable(archiveHandle.getEntries()))
553                 .containsAtLeastElementsIn(sExpectEntries);
554     }
555 
556     @Test
getEntries_tarFile_shouldTheSameWithList()557     public void getEntries_tarFile_shouldTheSameWithList() throws Exception {
558         ArchiveHandle archiveHandle =
559                 prepareArchiveHandle("archives/tar/hello.tar", ".tar",
560                 "application/x-gtar");
561 
562         assertThat(transformToIterable(archiveHandle.getEntries()))
563                 .containsAtLeastElementsIn(sExpectEntries);
564     }
565 
566     @Test
getEntries_tgzFile_shouldTheSameWithList()567     public void getEntries_tgzFile_shouldTheSameWithList() throws Exception {
568         ArchiveHandle archiveHandle =
569                 prepareArchiveHandle("archives/tar_gz/hello.tgz", ".tgz",
570                         "application/x-compressed-tar");
571 
572         assertThat(transformToIterable(archiveHandle.getEntries()))
573                 .containsAtLeastElementsIn(sExpectEntries);
574     }
575 
576     @Test
getEntries_tarBzFile_shouldTheSameWithList()577     public void getEntries_tarBzFile_shouldTheSameWithList() throws Exception {
578         ArchiveHandle archiveHandle =
579                 prepareArchiveHandle("archives/tar_bz2/hello.tar.bz2", ".tar.bz2",
580                         "application/x-bzip-compressed-tar");
581 
582         assertThat(transformToIterable(archiveHandle.getEntries()))
583                 .containsAtLeastElementsIn(sExpectEntries);
584     }
585 
586     @Test
getEntries_tarBrotliFile_shouldTheSameWithList()587     public void getEntries_tarBrotliFile_shouldTheSameWithList() throws Exception {
588         ArchiveHandle archiveHandle =
589                 prepareArchiveHandle("archives/brotli/hello.tar.br", ".tar.br",
590                         "application/x-brotli-compressed-tar");
591 
592         assertThat(transformToIterable(archiveHandle.getEntries()))
593                 .containsAtLeastElementsIn(sExpectEntries);
594     }
595 
596     @Test
getEntries_tarXzFile_shouldTheSameWithList()597     public void getEntries_tarXzFile_shouldTheSameWithList() throws Exception {
598         ArchiveHandle archiveHandle =
599                 prepareArchiveHandle("archives/xz/hello.tar.xz", ".tar.xz",
600                         "application/x-xz-compressed-tar");
601 
602         assertThat(transformToIterable(archiveHandle.getEntries()))
603                 .containsAtLeastElementsIn(sExpectEntries);
604     }
605 }
606