1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.commons.compress.utils;
20
21 import static java.nio.charset.StandardCharsets.UTF_8;
22 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
23 import static org.junit.jupiter.api.Assertions.assertEquals;
24 import static org.junit.jupiter.api.Assertions.assertFalse;
25 import static org.junit.jupiter.api.Assertions.assertThrows;
26
27 import java.io.IOException;
28 import java.nio.ByteBuffer;
29 import java.nio.channels.ClosedChannelException;
30 import java.nio.channels.SeekableByteChannel;
31 import java.util.Arrays;
32
33 import org.junit.jupiter.api.Disabled;
34 import org.junit.jupiter.api.Test;
35
36 public class SeekableInMemoryByteChannelTest {
37
38 private final byte[] testData = "Some data".getBytes(UTF_8);
39
40
41
42
43 @Test
44 public void testCloseIsIdempotent() throws Exception {
45 try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) {
46 c.close();
47 assertFalse(c.isOpen());
48 c.close();
49 assertFalse(c.isOpen());
50 }
51 }
52
53
54
55
56
57 @Test
58 public void testReadingFromAPositionAfterEndReturnsEOF() throws Exception {
59 try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) {
60 c.position(2);
61 assertEquals(2, c.position());
62 final ByteBuffer readBuffer = ByteBuffer.allocate(5);
63 assertEquals(-1, c.read(readBuffer));
64 }
65 }
66
67 @Test
68 public void testShouldReadContentsProperly() throws IOException {
69
70 try (SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel(testData)) {
71 final ByteBuffer readBuffer = ByteBuffer.allocate(testData.length);
72
73 final int readCount = c.read(readBuffer);
74
75 assertEquals(testData.length, readCount);
76 assertArrayEquals(testData, readBuffer.array());
77 assertEquals(testData.length, c.position());
78 }
79 }
80
81 @Test
82 public void testShouldReadContentsWhenBiggerBufferSupplied() throws IOException {
83
84 try (SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel(testData)) {
85 final ByteBuffer readBuffer = ByteBuffer.allocate(testData.length + 1);
86
87 final int readCount = c.read(readBuffer);
88
89 assertEquals(testData.length, readCount);
90 assertArrayEquals(testData, Arrays.copyOf(readBuffer.array(), testData.length));
91 assertEquals(testData.length, c.position());
92 }
93 }
94
95 @Test
96 public void testShouldReadDataFromSetPosition() throws IOException {
97
98 try (SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel(testData)) {
99 final ByteBuffer readBuffer = ByteBuffer.allocate(4);
100
101 c.position(5L);
102 final int readCount = c.read(readBuffer);
103
104 assertEquals(4L, readCount);
105 assertEquals("data", new String(readBuffer.array(), UTF_8));
106 assertEquals(testData.length, c.position());
107 }
108 }
109
110 @Test
111 public void testShouldSetProperPosition() throws IOException {
112
113 try (SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel(testData)) {
114
115 final long posAtFour = c.position(4L).position();
116 final long posAtTheEnd = c.position(testData.length).position();
117 final long posPastTheEnd = c.position(testData.length + 1L).position();
118
119 assertEquals(4L, posAtFour);
120 assertEquals(c.size(), posAtTheEnd);
121 assertEquals(testData.length + 1L, posPastTheEnd);
122 }
123 }
124
125 @Test
126 public void testShouldSetProperPositionOnTruncate() throws IOException {
127
128 try (SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel(testData)) {
129
130 c.position(testData.length);
131 c.truncate(4L);
132
133 assertEquals(4L, c.position());
134 assertEquals(4L, c.size());
135 }
136 }
137
138 @Test
139 public void testShouldSignalEOFWhenPositionAtTheEnd() throws IOException {
140
141 try (SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel(testData)) {
142 final ByteBuffer readBuffer = ByteBuffer.allocate(testData.length);
143
144 c.position(testData.length + 1);
145 final int readCount = c.read(readBuffer);
146
147 assertEquals(0L, readBuffer.position());
148 assertEquals(-1, readCount);
149 assertEquals(-1, c.read(readBuffer));
150 }
151 }
152
153 @Test
154 public void testShouldThrowExceptionOnReadingClosedChannel() {
155
156 final SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel();
157
158 c.close();
159 assertThrows(ClosedChannelException.class, () -> c.read(ByteBuffer.allocate(1)));
160 }
161
162 @Test
163 public void testShouldThrowExceptionOnWritingToClosedChannel() {
164
165 final SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel();
166
167 c.close();
168 assertThrows(ClosedChannelException.class, () -> c.write(ByteBuffer.allocate(1)));
169 }
170
171 @Test
172 public void testShouldThrowExceptionWhenSettingIncorrectPosition() {
173
174 try (SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel()) {
175
176 assertThrows(IOException.class, () -> c.position(Integer.MAX_VALUE + 1L));
177 }
178 }
179
180 @Test
181 public void testShouldThrowExceptionWhenTruncatingToIncorrectSize() {
182
183 try (SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel()) {
184
185 assertThrows(IllegalArgumentException.class, () -> c.truncate(Integer.MAX_VALUE + 1L));
186 }
187 }
188
189 @Test
190 public void testShouldTruncateContentsProperly() {
191
192 try (SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel(testData)) {
193
194 c.truncate(4);
195
196 final byte[] bytes = Arrays.copyOf(c.array(), (int) c.size());
197 assertEquals("Some", new String(bytes, UTF_8));
198 }
199 }
200
201
202
203
204
205 @Test
206 public void testShouldWriteDataProperly() throws IOException {
207
208 try (SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel()) {
209 final ByteBuffer inData = ByteBuffer.wrap(testData);
210
211 final int writeCount = c.write(inData);
212
213 assertEquals(testData.length, writeCount);
214 assertArrayEquals(testData, Arrays.copyOf(c.array(), (int) c.size()));
215 assertEquals(testData.length, c.position());
216 }
217 }
218
219
220
221 @Test
222 public void testShouldWriteDataProperlyAfterPositionSet() throws IOException {
223
224 try (SeekableInMemoryByteChannel c = new SeekableInMemoryByteChannel(testData)) {
225 final ByteBuffer inData = ByteBuffer.wrap(testData);
226 final ByteBuffer expectedData = ByteBuffer.allocate(testData.length + 5).put(testData, 0, 5).put(testData);
227
228 c.position(5L);
229 final int writeCount = c.write(inData);
230
231
232 assertEquals(testData.length, writeCount);
233 assertArrayEquals(expectedData.array(), Arrays.copyOf(c.array(), (int) c.size()));
234 assertEquals(testData.length + 5, c.position());
235 }
236 }
237
238
239
240
241
242
243 @Test
244 public void testThrowsClosedChannelExceptionWhenPositionIsSetOnClosedChannel() throws Exception {
245 try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) {
246 c.close();
247 assertThrows(ClosedChannelException.class, () -> c.position(0));
248 }
249 }
250
251
252
253
254
255
256 @Test
257 public void testThrowsIllegalArgumentExceptionWhenTruncatingToANegativeSize() throws Exception {
258 try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) {
259 assertThrows(IllegalArgumentException.class, () -> c.truncate(-1));
260 }
261 }
262
263
264
265
266 @Test
267 public void testThrowsIOExceptionWhenPositionIsSetToANegativeValue() throws Exception {
268 try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) {
269 assertThrows(IOException.class, () -> c.position(-1));
270 }
271 }
272
273
274
275
276 @Test
277 public void testTruncateDoesntChangeSmallPosition() throws Exception {
278 try (SeekableByteChannel c = new SeekableInMemoryByteChannel(testData)) {
279 c.position(1);
280 c.truncate(testData.length - 1);
281 assertEquals(testData.length - 1, c.size());
282 assertEquals(1, c.position());
283 }
284 }
285
286
287
288
289 @Test
290 public void testTruncateMovesPositionWhenNewSizeIsBiggerThanSizeAndPositionIsEvenBigger() throws Exception {
291 try (SeekableByteChannel c = new SeekableInMemoryByteChannel(testData)) {
292 c.position(2 * testData.length);
293 c.truncate(testData.length + 1);
294 assertEquals(testData.length, c.size());
295 assertEquals(testData.length + 1, c.position());
296 }
297 }
298
299
300
301
302
303
304 @Test
305 public void testTruncateMovesPositionWhenNotResizingButPositionBiggerThanSize() throws Exception {
306 try (SeekableByteChannel c = new SeekableInMemoryByteChannel(testData)) {
307 c.position(2 * testData.length);
308 c.truncate(testData.length);
309 assertEquals(testData.length, c.size());
310 assertEquals(testData.length, c.position());
311 }
312 }
313
314
315
316
317 @Test
318 public void testTruncateMovesPositionWhenShrinkingBeyondPosition() throws Exception {
319 try (SeekableByteChannel c = new SeekableInMemoryByteChannel(testData)) {
320 c.position(4);
321 c.truncate(3);
322 assertEquals(3, c.size());
323 assertEquals(3, c.position());
324 }
325 }
326
327
328
329
330 @Test
331 public void testTruncateToBiggerSizeDoesntChangeAnything() throws Exception {
332 try (SeekableByteChannel c = new SeekableInMemoryByteChannel(testData)) {
333 assertEquals(testData.length, c.size());
334 c.truncate(testData.length + 1);
335 assertEquals(testData.length, c.size());
336 final ByteBuffer readBuffer = ByteBuffer.allocate(testData.length);
337 assertEquals(testData.length, c.read(readBuffer));
338 assertArrayEquals(testData, Arrays.copyOf(readBuffer.array(), testData.length));
339 }
340 }
341
342
343
344
345 @Test
346 public void testTruncateToCurrentSizeDoesntChangeAnything() throws Exception {
347 try (SeekableByteChannel c = new SeekableInMemoryByteChannel(testData)) {
348 assertEquals(testData.length, c.size());
349 c.truncate(testData.length);
350 assertEquals(testData.length, c.size());
351 final ByteBuffer readBuffer = ByteBuffer.allocate(testData.length);
352 assertEquals(testData.length, c.read(readBuffer));
353 assertArrayEquals(testData, Arrays.copyOf(readBuffer.array(), testData.length));
354 }
355 }
356
357
358
359
360 @Test
361 @Disabled("we deliberately violate the spec")
362 public void throwsClosedChannelExceptionWhenPositionIsReadOnClosedChannel() throws Exception {
363 try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) {
364 c.close();
365 c.position();
366 }
367 }
368
369
370
371
372 @Test
373 @Disabled("we deliberately violate the spec")
374 public void throwsClosedChannelExceptionWhenSizeIsReadOnClosedChannel() throws Exception {
375 try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) {
376 c.close();
377 c.size();
378 }
379 }
380
381
382
383
384 @Test
385 @Disabled("we deliberately violate the spec")
386 public void throwsClosedChannelExceptionWhenTruncateIsCalledOnClosedChannel() throws Exception {
387 try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) {
388 c.close();
389 c.truncate(0);
390 }
391 }
392
393
394
395
396
397
398 public void writingToAPositionAfterEndGrowsChannel() throws Exception {
399 try (SeekableByteChannel c = new SeekableInMemoryByteChannel()) {
400 c.position(2);
401 assertEquals(2, c.position());
402 final ByteBuffer inData = ByteBuffer.wrap(testData);
403 assertEquals(testData.length, c.write(inData));
404 assertEquals(testData.length + 2, c.size());
405
406 c.position(2);
407 final ByteBuffer readBuffer = ByteBuffer.allocate(testData.length);
408 c.read(readBuffer);
409 assertArrayEquals(testData, Arrays.copyOf(readBuffer.array(), testData.length));
410 }
411 }
412
413 }