1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.commons.compress.archivers.zip;
20
21 import static org.junit.jupiter.api.Assertions.assertThrows;
22 import static org.mockito.ArgumentMatchers.any;
23 import static org.mockito.ArgumentMatchers.eq;
24 import static org.mockito.Mockito.doNothing;
25 import static org.mockito.Mockito.mock;
26 import static org.mockito.Mockito.spy;
27 import static org.mockito.Mockito.times;
28 import static org.mockito.Mockito.verify;
29 import static org.mockito.Mockito.when;
30
31 import java.io.IOException;
32 import java.nio.ByteBuffer;
33 import java.nio.channels.FileChannel;
34 import java.nio.channels.SeekableByteChannel;
35 import java.nio.charset.StandardCharsets;
36
37 import org.apache.commons.compress.AbstractTempDirTest;
38 import org.junit.jupiter.api.Test;
39
40
41
42
43 class ZipIoUtilTest extends AbstractTempDirTest {
44
45 private FileChannel mockFileChannel() throws IOException {
46 final FileChannel spy = spy(FileChannel.class);
47 doNothing().when(spy).close();
48 return spy;
49 }
50
51 private SeekableByteChannel mockSeekableByteChannel() {
52 return mock(SeekableByteChannel.class);
53 }
54
55 @Test
56 void testWriteFully_whenFullAtOnce_thenSucceed() throws IOException {
57 try (SeekableByteChannel channel = mockSeekableByteChannel()) {
58 when(channel.write((ByteBuffer) any())).thenAnswer(answer -> {
59 ((ByteBuffer) answer.getArgument(0)).position(5);
60 return 5;
61 }).thenAnswer(answer -> {
62 ((ByteBuffer) answer.getArgument(0)).position(6);
63 return 6;
64 });
65 ZipIoUtil.writeAll(channel, ByteBuffer.wrap("hello".getBytes(StandardCharsets.UTF_8)));
66 ZipIoUtil.writeAll(channel, ByteBuffer.wrap("world\n".getBytes(StandardCharsets.UTF_8)));
67 verify(channel, times(2)).write((ByteBuffer) any());
68 }
69 }
70
71 @Test
72 void testWriteFully_whenFullButPartial_thenSucceed() throws IOException {
73 try (SeekableByteChannel channel = mockSeekableByteChannel()) {
74 when(channel.write((ByteBuffer) any())).thenAnswer(answer -> {
75 ((ByteBuffer) answer.getArgument(0)).position(3);
76 return 3;
77 }).thenAnswer(answer -> {
78 ((ByteBuffer) answer.getArgument(0)).position(5);
79 return 2;
80 }).thenAnswer(answer -> {
81 ((ByteBuffer) answer.getArgument(0)).position(6);
82 return 6;
83 });
84 ZipIoUtil.writeAll(channel, ByteBuffer.wrap("hello".getBytes(StandardCharsets.UTF_8)));
85 ZipIoUtil.writeAll(channel, ByteBuffer.wrap("world\n".getBytes(StandardCharsets.UTF_8)));
86 verify(channel, times(3)).write((ByteBuffer) any());
87 }
88 }
89
90 @Test
91 void testWriteFully_whenPartial_thenFail() throws IOException {
92 try (SeekableByteChannel channel = mockSeekableByteChannel()) {
93 when(channel.write((ByteBuffer) any())).thenAnswer(answer -> {
94 ((ByteBuffer) answer.getArgument(0)).position(3);
95 return 3;
96 }).thenAnswer(answer -> 0).thenAnswer(answer -> -1);
97 assertThrows(IOException.class, () -> ZipIoUtil.writeAll(channel, ByteBuffer.wrap("hello".getBytes(StandardCharsets.UTF_8))));
98 verify(channel, times(3)).write((ByteBuffer) any());
99 }
100 }
101
102 @Test
103 void testWriteFullyAt_whenFullAtOnce_thenSucceed() throws IOException {
104 try (FileChannel channel = mockFileChannel()) {
105 when(channel.write((ByteBuffer) any(), eq(20L))).thenAnswer(answer -> {
106 ((ByteBuffer) answer.getArgument(0)).position(5);
107 return 5;
108 });
109 when(channel.write((ByteBuffer) any(), eq(30L))).thenAnswer(answer -> {
110 ((ByteBuffer) answer.getArgument(0)).position(6);
111 return 6;
112 });
113 ZipIoUtil.writeAll(channel, ByteBuffer.wrap("hello".getBytes(StandardCharsets.UTF_8)), 20);
114 ZipIoUtil.writeAll(channel, ByteBuffer.wrap("world\n".getBytes(StandardCharsets.UTF_8)), 30);
115 verify(channel, times(1)).write((ByteBuffer) any(), eq(20L));
116 verify(channel, times(1)).write((ByteBuffer) any(), eq(30L));
117 }
118 }
119
120 @Test
121 void testWriteFullyAt_whenFullButPartial_thenSucceed() throws IOException {
122 try (FileChannel channel = mockFileChannel()) {
123 when(channel.write((ByteBuffer) any(), eq(20L))).thenAnswer(answer -> {
124 ((ByteBuffer) answer.getArgument(0)).position(3);
125 return 3;
126 });
127 when(channel.write((ByteBuffer) any(), eq(23L))).thenAnswer(answer -> {
128 ((ByteBuffer) answer.getArgument(0)).position(5);
129 return 2;
130 });
131 when(channel.write((ByteBuffer) any(), eq(30L))).thenAnswer(answer -> {
132 ((ByteBuffer) answer.getArgument(0)).position(6);
133 return 6;
134 });
135 ZipIoUtil.writeAll(channel, ByteBuffer.wrap("hello".getBytes(StandardCharsets.UTF_8)), 20);
136 ZipIoUtil.writeAll(channel, ByteBuffer.wrap("world\n".getBytes(StandardCharsets.UTF_8)), 30);
137 verify(channel, times(1)).write((ByteBuffer) any(), eq(20L));
138 verify(channel, times(1)).write((ByteBuffer) any(), eq(23L));
139 verify(channel, times(1)).write((ByteBuffer) any(), eq(30L));
140 }
141 }
142
143 @Test
144 void testWriteFullyAt_whenPartial_thenFail() throws IOException {
145 try (FileChannel channel = mockFileChannel()) {
146 when(channel.write((ByteBuffer) any(), eq(20L))).thenAnswer(answer -> {
147 ((ByteBuffer) answer.getArgument(0)).position(3);
148 return 3;
149 });
150 when(channel.write((ByteBuffer) any(), eq(23L))).thenAnswer(answer -> 0).thenAnswer(answer -> -1);
151 assertThrows(IOException.class, () -> ZipIoUtil.writeAll(channel, ByteBuffer.wrap("hello".getBytes(StandardCharsets.UTF_8)), 20));
152 verify(channel, times(1)).write((ByteBuffer) any(), eq(20L));
153 verify(channel, times(2)).write((ByteBuffer) any(), eq(23L));
154 verify(channel, times(0)).write((ByteBuffer) any(), eq(25L));
155 }
156 }
157 }