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  
20  package org.apache.commons.compress.utils;
21  
22  import static org.apache.commons.compress.AbstractTest.getFile;
23  import static org.apache.commons.compress.AbstractTest.getPath;
24  import static org.junit.jupiter.api.Assertions.assertEquals;
25  import static org.junit.jupiter.api.Assertions.assertInstanceOf;
26  import static org.junit.jupiter.api.Assertions.assertSame;
27  import static org.junit.jupiter.api.Assertions.assertThrows;
28  
29  import java.io.File;
30  import java.io.IOException;
31  import java.nio.channels.SeekableByteChannel;
32  import java.nio.file.Files;
33  import java.nio.file.Path;
34  import java.nio.file.StandardOpenOption;
35  import java.util.ArrayList;
36  import java.util.List;
37  import java.util.Random;
38  
39  import org.apache.commons.compress.archivers.zip.ZipSplitReadOnlySeekableByteChannel;
40  import org.junit.jupiter.api.Test;
41  
42  class ZipSplitReadOnlySeekableByteChannelTest {
43  
44      private List<SeekableByteChannel> getSplitZipChannels() throws IOException {
45          final List<SeekableByteChannel> channels = new ArrayList<>();
46          final File file1 = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.z01");
47          channels.add(Files.newByteChannel(file1.toPath(), StandardOpenOption.READ));
48  
49          final File file2 = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.z02");
50          channels.add(Files.newByteChannel(file2.toPath(), StandardOpenOption.READ));
51  
52          final File lastFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.zip");
53          channels.add(Files.newByteChannel(lastFile.toPath(), StandardOpenOption.READ));
54  
55          return channels;
56      }
57  
58      @Test
59      void testBuildFromLastSplitSegmentThrowsOnNotZipFile() throws IOException {
60          final File lastFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.z01");
61          assertThrows(IllegalArgumentException.class, () -> ZipSplitReadOnlySeekableByteChannel.buildFromLastSplitSegment(lastFile));
62      }
63  
64      @Test
65      void testChannelsPositionIsZeroAfterConstructor() throws IOException {
66          final List<SeekableByteChannel> channels = getSplitZipChannels();
67          try (ZipSplitReadOnlySeekableByteChannel c = new ZipSplitReadOnlySeekableByteChannel(channels)) {
68              for (final SeekableByteChannel channel : channels) {
69                  assertEquals(0, channel.position());
70              }
71          }
72      }
73  
74      @Test
75      void testConstructorThrowsOnNonSplitZipFiles() throws IOException {
76          final List<SeekableByteChannel> channels = new ArrayList<>();
77          final File file = getFile("COMPRESS-189.zip");
78          try (SeekableByteChannel byteChannel = Files.newByteChannel(file.toPath(), StandardOpenOption.READ)) {
79              channels.add(byteChannel);
80              assertThrows(IOException.class, () -> new ZipSplitReadOnlySeekableByteChannel(channels));
81          }
82      }
83  
84      @Test
85      void testConstructorThrowsOnNullArg() {
86          assertThrows(NullPointerException.class, () -> new ZipSplitReadOnlySeekableByteChannel(null));
87      }
88  
89      @Test
90      void testForFilesOfTwoParametersThrowsOnNullArg() {
91          assertThrows(NullPointerException.class, () -> ZipSplitReadOnlySeekableByteChannel.forFiles(null, null));
92      }
93  
94      @Test
95      void testForFilesReturnCorrectClass() throws IOException {
96          final File firstFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.z01");
97          final File secondFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.z02");
98          final File lastFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.z01");
99  
100         final ArrayList<File> list = new ArrayList<>();
101         list.add(firstFile);
102         list.add(secondFile);
103 
104         try (SeekableByteChannel channel = ZipSplitReadOnlySeekableByteChannel.forFiles(lastFile, list)) {
105             assertInstanceOf(ZipSplitReadOnlySeekableByteChannel.class, channel);
106         }
107 
108         try (SeekableByteChannel channel = ZipSplitReadOnlySeekableByteChannel.forFiles(firstFile, secondFile, lastFile)) {
109             assertInstanceOf(ZipSplitReadOnlySeekableByteChannel.class, channel);
110         }
111     }
112 
113     @Test
114     void testForFilesThrowsOnNullArg() {
115         assertThrows(NullPointerException.class, () -> ZipSplitReadOnlySeekableByteChannel.forFiles((File[]) null));
116     }
117 
118     @Test
119     void testForOrderedSeekableByteChannelsOfTwoParametersThrowsOnNullArg() {
120         assertThrows(NullPointerException.class, () -> ZipSplitReadOnlySeekableByteChannel.forOrderedSeekableByteChannels(null, null));
121     }
122 
123     @Test
124     void testForOrderedSeekableByteChannelsReturnCorrectClass() throws IOException {
125         final File file1 = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.z01");
126         final File file2 = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.z02");
127         final File lastFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.zip");
128 
129         try (SeekableByteChannel firstChannel = Files.newByteChannel(file1.toPath(), StandardOpenOption.READ);
130                 SeekableByteChannel secondChannel = Files.newByteChannel(file2.toPath(), StandardOpenOption.READ);
131                 SeekableByteChannel lastChannel = Files.newByteChannel(lastFile.toPath(), StandardOpenOption.READ)) {
132 
133             final List<SeekableByteChannel> channels = new ArrayList<>();
134             channels.add(firstChannel);
135             channels.add(secondChannel);
136 
137             @SuppressWarnings("resource") // try-with-resources closes
138             final SeekableByteChannel channel1 = ZipSplitReadOnlySeekableByteChannel.forOrderedSeekableByteChannels(lastChannel, channels);
139             assertInstanceOf(ZipSplitReadOnlySeekableByteChannel.class, channel1);
140 
141             @SuppressWarnings("resource") // try-with-resources closes
142             final SeekableByteChannel channel2 = ZipSplitReadOnlySeekableByteChannel.forOrderedSeekableByteChannels(firstChannel, secondChannel, lastChannel);
143             assertInstanceOf(ZipSplitReadOnlySeekableByteChannel.class, channel2);
144         }
145     }
146 
147     @Test
148     void testForOrderedSeekableByteChannelsReturnsIdentityForSingleElement() throws IOException {
149         try (SeekableByteChannel emptyChannel = new SeekableInMemoryByteChannel(ByteUtils.EMPTY_BYTE_ARRAY);
150                 SeekableByteChannel channel = ZipSplitReadOnlySeekableByteChannel.forOrderedSeekableByteChannels(emptyChannel)) {
151             assertSame(emptyChannel, channel);
152         }
153     }
154 
155     @Test
156     void testForOrderedSeekableByteChannelsThrowsOnNullArg() {
157         assertThrows(NullPointerException.class, () -> ZipSplitReadOnlySeekableByteChannel.forOrderedSeekableByteChannels((SeekableByteChannel[]) null));
158     }
159 
160     @Test
161     void testForPathsOfTwoParametersThrowsOnNullArg() {
162         assertThrows(NullPointerException.class, () -> ZipSplitReadOnlySeekableByteChannel.forPaths((Path) null, null));
163     }
164 
165     @Test
166     void testForPathsReturnCorrectClass() throws IOException {
167         final Path firstFile = getPath("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.z01");
168         final Path secondFile = getPath("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.z02");
169         final Path lastFile = getPath("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.zip");
170 
171         final ArrayList<Path> list = new ArrayList<>();
172         list.add(firstFile);
173         list.add(secondFile);
174 
175         try (SeekableByteChannel channel = ZipSplitReadOnlySeekableByteChannel.forPaths(lastFile, list)) {
176             assertInstanceOf(ZipSplitReadOnlySeekableByteChannel.class, channel);
177         }
178 
179         try (SeekableByteChannel channel = ZipSplitReadOnlySeekableByteChannel.forPaths(firstFile, secondFile, lastFile)) {
180             assertInstanceOf(ZipSplitReadOnlySeekableByteChannel.class, channel);
181         }
182     }
183 
184     @Test
185     void testForPathsThrowsOnNullArg() {
186         assertThrows(NullPointerException.class, () -> ZipSplitReadOnlySeekableByteChannel.forPaths((Path[]) null));
187     }
188 
189     @Test
190     void testPositionToSomeZipSplitSegment() throws IOException {
191         final File firstFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.z01");
192         final int firstFileSize = (int) firstFile.length();
193 
194         final File secondFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.z02");
195         final int secondFileSize = (int) secondFile.length();
196 
197         final File lastFile = getFile("COMPRESS-477/split_zip_created_by_zip/split_zip_created_by_zip.zip");
198         final int lastFileSize = (int) lastFile.length();
199 
200         final Random random = new Random();
201         final int randomDiskNumber = random.nextInt(3);
202         final int randomOffset = randomDiskNumber < 2 ? random.nextInt(firstFileSize) : random.nextInt(lastFileSize);
203 
204         try (ZipSplitReadOnlySeekableByteChannel channel = (ZipSplitReadOnlySeekableByteChannel) ZipSplitReadOnlySeekableByteChannel
205                 .buildFromLastSplitSegment(lastFile)) {
206             channel.position(randomDiskNumber, randomOffset);
207             long expectedPosition = randomOffset;
208 
209             expectedPosition += randomDiskNumber > 0 ? firstFileSize : 0;
210             expectedPosition += randomDiskNumber > 1 ? secondFileSize : 0;
211 
212             assertEquals(expectedPosition, channel.position());
213         }
214     }
215 }