1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.core5.http.impl.nio;
29
30 import java.io.File;
31 import java.io.IOException;
32 import java.io.RandomAccessFile;
33 import java.nio.ByteBuffer;
34 import java.nio.channels.FileChannel;
35 import java.nio.channels.ReadableByteChannel;
36 import java.nio.charset.StandardCharsets;
37
38 import org.apache.hc.core5.http.ReadableByteChannelMock;
39 import org.apache.hc.core5.http.impl.BasicHttpTransportMetrics;
40 import org.apache.hc.core5.http.nio.SessionInputBuffer;
41 import org.junit.After;
42 import org.junit.Assert;
43 import org.junit.Test;
44
45
46
47
48 public class TestIdentityDecoder {
49
50 private File tmpfile;
51
52 protected File createTempFile() throws IOException {
53 this.tmpfile = File.createTempFile("testFile", ".txt");
54 return this.tmpfile;
55 }
56
57 @After
58 public void deleteTempFile() {
59 if (this.tmpfile != null && this.tmpfile.exists()) {
60 this.tmpfile.delete();
61 }
62 }
63
64 @Test
65 public void testBasicDecoding() throws Exception {
66 final ReadableByteChannel channel = new ReadableByteChannelMock(
67 new String[] {"stuff;", "more stuff"}, StandardCharsets.US_ASCII);
68
69 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
70 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
71 final IdentityDecoder decoder = new IdentityDecoder(channel, inbuf, metrics);
72
73 final ByteBuffer dst = ByteBuffer.allocate(1024);
74
75 int bytesRead = decoder.read(dst);
76 Assert.assertEquals(6, bytesRead);
77 Assert.assertEquals("stuff;", CodecTestUtils.convert(dst));
78 Assert.assertFalse(decoder.isCompleted());
79 Assert.assertEquals(6, metrics.getBytesTransferred());
80
81 dst.clear();
82 bytesRead = decoder.read(dst);
83 Assert.assertEquals(10, bytesRead);
84 Assert.assertEquals("more stuff", CodecTestUtils.convert(dst));
85 Assert.assertFalse(decoder.isCompleted());
86 Assert.assertEquals(16, metrics.getBytesTransferred());
87
88 dst.clear();
89 bytesRead = decoder.read(dst);
90 Assert.assertEquals(-1, bytesRead);
91 Assert.assertTrue(decoder.isCompleted());
92 Assert.assertEquals(16, metrics.getBytesTransferred());
93
94 dst.clear();
95 bytesRead = decoder.read(dst);
96 Assert.assertEquals(-1, bytesRead);
97 Assert.assertTrue(decoder.isCompleted());
98 Assert.assertEquals(16, metrics.getBytesTransferred());
99
100 Assert.assertEquals("[identity; completed: true]", decoder.toString());
101 }
102
103 @Test
104 public void testDecodingFromSessionBuffer() throws Exception {
105 final ReadableByteChannel channel = new ReadableByteChannelMock(
106 new String[] {"stuff;", "more stuff"}, StandardCharsets.US_ASCII);
107
108 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
109 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
110
111 inbuf.fill(channel);
112
113 Assert.assertEquals(6, inbuf.length());
114
115 final IdentityDecoder decoder = new IdentityDecoder(channel, inbuf, metrics);
116
117 final ByteBuffer dst = ByteBuffer.allocate(1024);
118
119 int bytesRead = decoder.read(dst);
120 Assert.assertEquals(6, bytesRead);
121 Assert.assertEquals("stuff;", CodecTestUtils.convert(dst));
122 Assert.assertFalse(decoder.isCompleted());
123 Assert.assertEquals(0, metrics.getBytesTransferred());
124
125 dst.clear();
126 bytesRead = decoder.read(dst);
127 Assert.assertEquals(10, bytesRead);
128 Assert.assertEquals("more stuff", CodecTestUtils.convert(dst));
129 Assert.assertFalse(decoder.isCompleted());
130 Assert.assertEquals(10, metrics.getBytesTransferred());
131
132 dst.clear();
133 bytesRead = decoder.read(dst);
134 Assert.assertEquals(-1, bytesRead);
135 Assert.assertTrue(decoder.isCompleted());
136 Assert.assertEquals(10, metrics.getBytesTransferred());
137
138 dst.clear();
139 bytesRead = decoder.read(dst);
140 Assert.assertEquals(-1, bytesRead);
141 Assert.assertTrue(decoder.isCompleted());
142 Assert.assertEquals(10, metrics.getBytesTransferred());
143
144 }
145
146 @Test
147 public void testBasicDecodingFile() throws Exception {
148 final ReadableByteChannel channel = new ReadableByteChannelMock(
149 new String[] {"stuff; ", "more stuff; ", "a lot more stuff!"}, StandardCharsets.US_ASCII);
150
151 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
152 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
153 final IdentityDecoder decoder = new IdentityDecoder(
154 channel, inbuf, metrics);
155
156 createTempFile();
157 try (RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw")) {
158 final FileChannel fchannel = testfile.getChannel();
159 long pos = 0;
160 while (!decoder.isCompleted()) {
161 final long bytesRead = decoder.transfer(fchannel, pos, 10);
162 if (bytesRead > 0) {
163 pos += bytesRead;
164 }
165 }
166
167 Assert.assertEquals(testfile.length(), metrics.getBytesTransferred());
168 }
169 Assert.assertEquals("stuff; more stuff; a lot more stuff!",
170 CodecTestUtils.readFromFile(this.tmpfile));
171 }
172
173 @Test
174 public void testDecodingFileWithBufferedSessionData() throws Exception {
175 final ReadableByteChannel channel = new ReadableByteChannelMock(
176 new String[] {"stuff; ", "more stuff; ", "a lot more stuff!"}, StandardCharsets.US_ASCII);
177
178 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
179 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
180 final IdentityDecoder decoder = new IdentityDecoder(
181 channel, inbuf, metrics);
182
183 final int i = inbuf.fill(channel);
184 Assert.assertEquals(7, i);
185
186 createTempFile();
187 try (RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw")) {
188 final FileChannel fchannel = testfile.getChannel();
189 long pos = 0;
190 while (!decoder.isCompleted()) {
191 final long bytesRead = decoder.transfer(fchannel, pos, 10);
192 if (bytesRead > 0) {
193 pos += bytesRead;
194 }
195 }
196
197
198 Assert.assertEquals(testfile.length() - 7, metrics.getBytesTransferred());
199 }
200 Assert.assertEquals("stuff; more stuff; a lot more stuff!",
201 CodecTestUtils.readFromFile(this.tmpfile));
202 }
203
204 @Test
205 public void testDecodingFileWithOffsetAndBufferedSessionData() throws Exception {
206 final ReadableByteChannel channel = new ReadableByteChannelMock(
207 new String[] {"stuff; ", "more stuff; ", "a lot more stuff!"}, StandardCharsets.US_ASCII);
208
209 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
210 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
211 final IdentityDecoder decoder = new IdentityDecoder(
212 channel, inbuf, metrics);
213
214 final int i = inbuf.fill(channel);
215 Assert.assertEquals(7, i);
216
217 final byte[] beginning = "beginning; ".getBytes(StandardCharsets.US_ASCII);
218
219 createTempFile();
220 RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
221 try {
222 testfile.write(beginning);
223 } finally {
224 testfile.close();
225 }
226
227 testfile = new RandomAccessFile(this.tmpfile, "rw");
228 try {
229 final FileChannel fchannel = testfile.getChannel();
230 long pos = beginning.length;
231 while (!decoder.isCompleted()) {
232 if(testfile.length() < pos) {
233 testfile.setLength(pos);
234 }
235 final long bytesRead = decoder.transfer(fchannel, pos, 10);
236 if (bytesRead > 0) {
237 pos += bytesRead;
238 }
239 }
240
241
242 Assert.assertEquals(testfile.length() - 7 - beginning.length, metrics.getBytesTransferred());
243 } finally {
244 testfile.close();
245 }
246
247 Assert.assertEquals("beginning; stuff; more stuff; a lot more stuff!",
248 CodecTestUtils.readFromFile(this.tmpfile));
249 }
250
251 @Test
252 public void testDecodingFileWithLimit() throws Exception {
253 final ReadableByteChannel channel = new ReadableByteChannelMock(
254 new String[] {"stuff; more stuff; ", "a lot more stuff!"}, StandardCharsets.US_ASCII);
255
256 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
257 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
258 final IdentityDecoder decoder = new IdentityDecoder(channel, inbuf, metrics);
259
260 final int i = inbuf.fill(channel);
261 Assert.assertEquals(19, i);
262
263 createTempFile();
264 try (RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw")) {
265 final FileChannel fchannel = testfile.getChannel();
266 long pos = 0;
267
268
269 long bytesRead = decoder.transfer(fchannel, pos, 1);
270 Assert.assertEquals(1, bytesRead);
271 Assert.assertFalse(decoder.isCompleted());
272 Assert.assertEquals(0, metrics.getBytesTransferred());
273 pos += bytesRead;
274
275 bytesRead = decoder.transfer(fchannel, pos, 2);
276 Assert.assertEquals(2, bytesRead);
277 Assert.assertFalse(decoder.isCompleted());
278 Assert.assertEquals(0, metrics.getBytesTransferred());
279 pos += bytesRead;
280
281 bytesRead = decoder.transfer(fchannel, pos, 17);
282 Assert.assertEquals(16, bytesRead);
283 Assert.assertFalse(decoder.isCompleted());
284 Assert.assertEquals(0, metrics.getBytesTransferred());
285 pos += bytesRead;
286
287
288 bytesRead = decoder.transfer(fchannel, pos, 1);
289 Assert.assertEquals(1, bytesRead);
290 Assert.assertFalse(decoder.isCompleted());
291 Assert.assertEquals(1, metrics.getBytesTransferred());
292 pos += bytesRead;
293
294 bytesRead = decoder.transfer(fchannel, pos, 2);
295 Assert.assertEquals(2, bytesRead);
296 Assert.assertFalse(decoder.isCompleted());
297 Assert.assertEquals(3, metrics.getBytesTransferred());
298 pos += bytesRead;
299
300 bytesRead = decoder.transfer(fchannel, pos, 15);
301 Assert.assertEquals(14, bytesRead);
302 Assert.assertFalse(decoder.isCompleted());
303 Assert.assertEquals(17, metrics.getBytesTransferred());
304 pos += bytesRead;
305
306 bytesRead = decoder.transfer(fchannel, pos, 1);
307 Assert.assertEquals(-1, bytesRead);
308 Assert.assertTrue(decoder.isCompleted());
309 Assert.assertEquals(17, metrics.getBytesTransferred());
310 }
311 Assert.assertEquals("stuff; more stuff; a lot more stuff!",
312 CodecTestUtils.readFromFile(this.tmpfile));
313 }
314
315 @Test
316 public void testWriteBeyondFileSize() throws Exception {
317 final ReadableByteChannel channel = new ReadableByteChannelMock(
318 new String[] {"a"}, StandardCharsets.US_ASCII);
319
320 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
321 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
322 final IdentityDecoder decoder = new IdentityDecoder(
323 channel, inbuf, metrics);
324
325 createTempFile();
326 try (RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw")) {
327 Assert.assertEquals(0, testfile.length());
328 final FileChannel fchannel = testfile.getChannel();
329 try {
330 decoder.transfer(fchannel, 5, 10);
331 Assert.fail("expected IOException");
332 } catch(final IOException iox) {}
333 }
334 }
335
336 @Test
337 public void testInvalidConstructor() {
338 final ReadableByteChannel channel = new ReadableByteChannelMock(
339 new String[] {"stuff;", "more stuff"}, StandardCharsets.US_ASCII);
340
341 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
342 try {
343 new IdentityDecoder(null, null, null);
344 Assert.fail("NullPointerException should have been thrown");
345 } catch (final NullPointerException ex) {
346
347 }
348 try {
349 new IdentityDecoder(channel, null, null);
350 Assert.fail("NullPointerException should have been thrown");
351 } catch (final NullPointerException ex) {
352
353 }
354 try {
355 new IdentityDecoder(channel, inbuf, null);
356 Assert.fail("NullPointerException should have been thrown");
357 } catch (final NullPointerException ex) {
358
359 }
360 }
361
362 @Test
363 public void testInvalidInput() throws Exception {
364 final String s = "stuff";
365 final ReadableByteChannel channel = new ReadableByteChannelMock(
366 new String[] {s}, StandardCharsets.US_ASCII);
367
368 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
369 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
370 final IdentityDecoder decoder = new IdentityDecoder(channel, inbuf, metrics);
371
372 try {
373 decoder.read(null);
374 Assert.fail("NullPointerException should have been thrown");
375 } catch (final NullPointerException ex) {
376
377 }
378 }
379
380 }