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