View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.commons.compress.archivers;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertNull;
24  import static org.junit.jupiter.api.Assumptions.assumeTrue;
25  
26  import java.io.File;
27  import java.io.IOException;
28  import java.io.InputStream;
29  import java.nio.file.Files;
30  import java.nio.file.attribute.BasicFileAttributes;
31  import java.security.NoSuchAlgorithmException;
32  
33  import javax.crypto.Cipher;
34  
35  import org.apache.commons.compress.AbstractTest;
36  import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
37  import org.apache.commons.compress.archivers.sevenz.SevenZFile;
38  import org.apache.commons.compress.archivers.sevenz.SevenZMethod;
39  import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;
40  import org.apache.commons.compress.utils.TimeUtilsTest;
41  import org.junit.jupiter.api.BeforeEach;
42  import org.junit.jupiter.api.Test;
43  
44  class SevenZTest extends AbstractTest {
45  
46      private static void assumeStrongCryptoIsAvailable() throws NoSuchAlgorithmException {
47          assumeTrue(Cipher.getMaxAllowedKeyLength("AES/ECB/PKCS5Padding") >= 256, "test requires strong crypto");
48      }
49  
50      private File output;
51  
52      private final File file1;
53      private final File file2;
54  
55      SevenZTest() throws IOException {
56          file1 = getFile("test1.xml");
57          file2 = getFile("test2.xml");
58      }
59  
60      private void copy(final File src, final SevenZOutputFile dst) throws IOException {
61          try (InputStream fis = Files.newInputStream(src.toPath())) {
62              final byte[] buffer = new byte[8 * 1024];
63              int bytesRead;
64              while ((bytesRead = fis.read(buffer)) >= 0) {
65                  dst.write(buffer, 0, bytesRead);
66              }
67          }
68      }
69  
70      private void createArchive(final SevenZMethod method) throws Exception {
71          try (SevenZOutputFile outArchive = new SevenZOutputFile(output)) {
72              outArchive.setContentCompression(method);
73              SevenZArchiveEntry entry;
74  
75              entry = outArchive.createArchiveEntry(file1, file1.getName());
76              outArchive.putArchiveEntry(entry);
77              copy(file1, outArchive);
78              outArchive.closeArchiveEntry();
79  
80              entry = outArchive.createArchiveEntry(file2, file2.getName());
81              outArchive.putArchiveEntry(entry);
82              copy(file2, outArchive);
83              outArchive.closeArchiveEntry();
84          }
85      }
86  
87      private void multiByteReadConsistentlyReturnsMinusOneAtEof(final SevenZFile archive) throws Exception {
88          final byte[] buf = new byte[2];
89          assertNotNull(archive.getNextEntry());
90          assertNotNull(archive.getNextEntry());
91          readFully(archive);
92          assertEquals(-1, archive.read(buf));
93          assertEquals(-1, archive.read(buf));
94      }
95  
96      private void multiByteReadConsistentlyReturnsMinusOneAtEof(final SevenZMethod method) throws Exception {
97          createArchive(method);
98          try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
99              multiByteReadConsistentlyReturnsMinusOneAtEof(archive);
100         }
101     }
102 
103     private void readFully(final SevenZFile archive) throws IOException {
104         final byte[] buf = new byte[1024];
105         int x = 0;
106         while (0 <= (x = archive.read(buf))) {
107             // do nothing
108         }
109     }
110 
111     @BeforeEach
112     public void setUp() throws Exception {
113         output = newTempFile("bla.7z");
114     }
115 
116     private void singleByteReadConsistentlyReturnsMinusOneAtEof(final SevenZFile archive) throws Exception {
117         assertNotNull(archive.getNextEntry());
118         assertNotNull(archive.getNextEntry());
119         readFully(archive);
120         assertEquals(-1, archive.read());
121         assertEquals(-1, archive.read());
122     }
123 
124     private void singleByteReadConsistentlyReturnsMinusOneAtEof(final SevenZMethod method) throws Exception {
125         createArchive(method);
126         try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
127             singleByteReadConsistentlyReturnsMinusOneAtEof(archive);
128         }
129     }
130 
131     @Test
132     void testMultiByteReadConsistentlyReturnsMinusOneAtEofUsingAES() throws Exception {
133         assumeStrongCryptoIsAvailable();
134         try (SevenZFile archive = new SevenZFile(getFile("bla.encrypted.7z"), "foo".toCharArray())) {
135             multiByteReadConsistentlyReturnsMinusOneAtEof(archive);
136         }
137     }
138 
139     @Test
140     void testMultiByteReadConsistentlyReturnsMinusOneAtEofUsingBZIP2() throws Exception {
141         multiByteReadConsistentlyReturnsMinusOneAtEof(SevenZMethod.BZIP2);
142     }
143 
144     @Test
145     void testMultiByteReadConsistentlyReturnsMinusOneAtEofUsingDeflate() throws Exception {
146         multiByteReadConsistentlyReturnsMinusOneAtEof(SevenZMethod.DEFLATE);
147     }
148 
149     @Test
150     void testMultiByteReadConsistentlyReturnsMinusOneAtEofUsingLZMA() throws Exception {
151         multiByteReadConsistentlyReturnsMinusOneAtEof(SevenZMethod.LZMA);
152     }
153 
154     @Test
155     void testMultiByteReadConsistentlyReturnsMinusOneAtEofUsingLZMA2() throws Exception {
156         multiByteReadConsistentlyReturnsMinusOneAtEof(SevenZMethod.LZMA2);
157     }
158 
159     private void testSevenZArchiveCreation(final SevenZMethod method) throws Exception {
160         createArchive(method);
161         try (SevenZFile archive = SevenZFile.builder().setFile(output).get()) {
162             SevenZArchiveEntry entry;
163 
164             entry = archive.getNextEntry();
165             assertNotNull(entry);
166             assertEquals(file1.getName(), entry.getName());
167             BasicFileAttributes attributes = Files.readAttributes(file1.toPath(), BasicFileAttributes.class);
168             assertEquals(TimeUtilsTest.truncateToHundredNanos(attributes.lastModifiedTime()), entry.getLastModifiedTime());
169             assertEquals(TimeUtilsTest.truncateToHundredNanos(attributes.creationTime()), entry.getCreationTime());
170             assertNotNull(entry.getAccessTime());
171 
172             entry = archive.getNextEntry();
173             assertNotNull(entry);
174             assertEquals(file2.getName(), entry.getName());
175             attributes = Files.readAttributes(file2.toPath(), BasicFileAttributes.class);
176             assertEquals(TimeUtilsTest.truncateToHundredNanos(attributes.lastModifiedTime()), entry.getLastModifiedTime());
177             assertEquals(TimeUtilsTest.truncateToHundredNanos(attributes.creationTime()), entry.getCreationTime());
178             assertNotNull(entry.getAccessTime());
179 
180             assertNull(archive.getNextEntry());
181         }
182     }
183 
184     @Test
185     void testSevenZArchiveCreationUsingBZIP2() throws Exception {
186         testSevenZArchiveCreation(SevenZMethod.BZIP2);
187     }
188 
189     @Test
190     void testSevenZArchiveCreationUsingCopy() throws Exception {
191         testSevenZArchiveCreation(SevenZMethod.COPY);
192     }
193 
194     @Test
195     void testSevenZArchiveCreationUsingDeflate() throws Exception {
196         testSevenZArchiveCreation(SevenZMethod.DEFLATE);
197     }
198 
199     @Test
200     void testSevenZArchiveCreationUsingLZMA() throws Exception {
201         testSevenZArchiveCreation(SevenZMethod.LZMA);
202     }
203 
204     @Test
205     void testSevenZArchiveCreationUsingLZMA2() throws Exception {
206         testSevenZArchiveCreation(SevenZMethod.LZMA2);
207     }
208 
209     @Test
210     void testSingleByteReadConsistentlyReturnsMinusOneAtEofUsingAES() throws Exception {
211         assumeStrongCryptoIsAvailable();
212         try (SevenZFile archive = new SevenZFile(getFile("bla.encrypted.7z"), "foo".toCharArray())) {
213             singleByteReadConsistentlyReturnsMinusOneAtEof(archive);
214         }
215     }
216 
217     @Test
218     void testSingleByteReadConsistentlyReturnsMinusOneAtEofUsingBZIP2() throws Exception {
219         singleByteReadConsistentlyReturnsMinusOneAtEof(SevenZMethod.BZIP2);
220     }
221 
222     @Test
223     void testSingleByteReadConsistentlyReturnsMinusOneAtEofUsingCopy() throws Exception {
224         singleByteReadConsistentlyReturnsMinusOneAtEof(SevenZMethod.COPY);
225     }
226 
227     @Test
228     void testSingleByteReadConsistentlyReturnsMinusOneAtEofUsingDeflate() throws Exception {
229         singleByteReadConsistentlyReturnsMinusOneAtEof(SevenZMethod.DEFLATE);
230     }
231 
232     @Test
233     void testSingleByteReadConsistentlyReturnsMinusOneAtEofUsingLZMA() throws Exception {
234         singleByteReadConsistentlyReturnsMinusOneAtEof(SevenZMethod.LZMA);
235     }
236 
237     @Test
238     void testSingleByteReadConsistentlyReturnsMinusOneAtEofUsingLZMA2() throws Exception {
239         singleByteReadConsistentlyReturnsMinusOneAtEof(SevenZMethod.LZMA2);
240     }
241 }