View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.http.impl.nio.codecs;
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  
37  import org.apache.http.ConnectionClosedException;
38  import org.apache.http.Consts;
39  import org.apache.http.ReadableByteChannelMock;
40  import org.apache.http.impl.io.HttpTransportMetricsImpl;
41  import org.apache.http.impl.nio.reactor.SessionInputBufferImpl;
42  import org.apache.http.nio.reactor.SessionInputBuffer;
43  import org.apache.http.util.EncodingUtils;
44  import org.junit.After;
45  import org.junit.Assert;
46  import org.junit.Test;
47  
48  /**
49   * Simple tests for {@link LengthDelimitedDecoder}.
50   */
51  public class TestLengthDelimitedDecoder {
52  
53      private File tmpfile;
54  
55      protected File createTempFile() throws IOException {
56          this.tmpfile = File.createTempFile("testFile", ".txt");
57          return this.tmpfile;
58      }
59  
60      @After
61      public void deleteTempFile() {
62          if (this.tmpfile != null && this.tmpfile.exists()) {
63              this.tmpfile.delete();
64          }
65      }
66  
67      @Test
68      public void testBasicDecoding() throws Exception {
69          final ReadableByteChannel channel = new ReadableByteChannelMock(
70                  new String[] {"stuff;", "more stuff"}, Consts.ASCII);
71  
72          final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, Consts.ASCII);
73          final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
74          final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
75                  channel, inbuf, metrics, 16);
76  
77          final ByteBuffer dst = ByteBuffer.allocate(1024);
78  
79          int bytesRead = decoder.read(dst);
80          Assert.assertEquals(6, bytesRead);
81          Assert.assertEquals("stuff;", CodecTestUtils.convert(dst));
82          Assert.assertFalse(decoder.isCompleted());
83          Assert.assertEquals(6, metrics.getBytesTransferred());
84  
85          dst.clear();
86          bytesRead = decoder.read(dst);
87          Assert.assertEquals(10, bytesRead);
88          Assert.assertEquals("more stuff", CodecTestUtils.convert(dst));
89          Assert.assertTrue(decoder.isCompleted());
90          Assert.assertEquals(16, metrics.getBytesTransferred());
91  
92          dst.clear();
93          bytesRead = decoder.read(dst);
94          Assert.assertEquals(-1, bytesRead);
95          Assert.assertTrue(decoder.isCompleted());
96          Assert.assertEquals(16, metrics.getBytesTransferred());
97  
98          Assert.assertEquals("[content length: 16; pos: 16; completed: true]", decoder.toString());
99      }
100 
101     @Test
102     public void testCodingBeyondContentLimit() throws Exception {
103         final ReadableByteChannel channel = new ReadableByteChannelMock(
104                 new String[] {
105                         "stuff;",
106                         "more stuff; and a lot more stuff"}, Consts.ASCII);
107 
108         final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, Consts.ASCII);
109         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
110         final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
111                 channel, inbuf, metrics, 16);
112 
113         final ByteBuffer dst = ByteBuffer.allocate(1024);
114 
115         int bytesRead = decoder.read(dst);
116         Assert.assertEquals(6, bytesRead);
117         Assert.assertEquals("stuff;", CodecTestUtils.convert(dst));
118         Assert.assertFalse(decoder.isCompleted());
119         Assert.assertEquals(6, metrics.getBytesTransferred());
120 
121         dst.clear();
122         bytesRead = decoder.read(dst);
123         Assert.assertEquals(10, bytesRead);
124         Assert.assertEquals("more stuff", CodecTestUtils.convert(dst));
125         Assert.assertTrue(decoder.isCompleted());
126         Assert.assertEquals(16, metrics.getBytesTransferred());
127 
128         dst.clear();
129         bytesRead = decoder.read(dst);
130         Assert.assertEquals(-1, bytesRead);
131         Assert.assertTrue(decoder.isCompleted());
132         Assert.assertEquals(16, metrics.getBytesTransferred());
133     }
134 
135     @Test
136     public void testBasicDecodingSmallBuffer() throws Exception {
137         final ReadableByteChannel channel = new ReadableByteChannelMock(
138                 new String[] {"stuff;", "more stuff"}, Consts.ASCII);
139 
140         final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, Consts.ASCII);
141         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
142         final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
143                 channel, inbuf, metrics, 16);
144 
145         final ByteBuffer dst = ByteBuffer.allocate(4);
146 
147         int bytesRead = decoder.read(dst);
148         Assert.assertEquals(4, bytesRead);
149         Assert.assertEquals("stuf", CodecTestUtils.convert(dst));
150         Assert.assertFalse(decoder.isCompleted());
151         Assert.assertEquals(4, metrics.getBytesTransferred());
152 
153         dst.clear();
154         bytesRead = decoder.read(dst);
155         Assert.assertEquals(2, bytesRead);
156         Assert.assertEquals("f;", CodecTestUtils.convert(dst));
157         Assert.assertFalse(decoder.isCompleted());
158         Assert.assertEquals(6, metrics.getBytesTransferred());
159 
160         dst.clear();
161         bytesRead = decoder.read(dst);
162         Assert.assertEquals(4, bytesRead);
163         Assert.assertEquals("more", CodecTestUtils.convert(dst));
164         Assert.assertFalse(decoder.isCompleted());
165         Assert.assertEquals(10, metrics.getBytesTransferred());
166 
167         dst.clear();
168         bytesRead = decoder.read(dst);
169         Assert.assertEquals(4, bytesRead);
170         Assert.assertEquals(" stu", CodecTestUtils.convert(dst));
171         Assert.assertFalse(decoder.isCompleted());
172         Assert.assertEquals(14, metrics.getBytesTransferred());
173 
174         dst.clear();
175         bytesRead = decoder.read(dst);
176         Assert.assertEquals(2, bytesRead);
177         Assert.assertEquals("ff", CodecTestUtils.convert(dst));
178         Assert.assertTrue(decoder.isCompleted());
179         Assert.assertEquals(16, metrics.getBytesTransferred());
180 
181         dst.clear();
182         bytesRead = decoder.read(dst);
183         Assert.assertEquals(-1, bytesRead);
184         Assert.assertTrue(decoder.isCompleted());
185         Assert.assertEquals(16, metrics.getBytesTransferred());
186     }
187 
188     @Test
189     public void testDecodingFromSessionBuffer1() throws Exception {
190         final ReadableByteChannel channel = new ReadableByteChannelMock(
191                 new String[] {"stuff;", "more stuff"}, Consts.ASCII);
192 
193         final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, Consts.ASCII);
194         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
195 
196         inbuf.fill(channel);
197 
198         Assert.assertEquals(6, inbuf.length());
199 
200         final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
201                 channel, inbuf, metrics, 16);
202 
203         final ByteBuffer dst = ByteBuffer.allocate(1024);
204 
205         int bytesRead = decoder.read(dst);
206         Assert.assertEquals(6, bytesRead);
207         Assert.assertEquals("stuff;", CodecTestUtils.convert(dst));
208         Assert.assertFalse(decoder.isCompleted());
209         Assert.assertEquals(0, metrics.getBytesTransferred());
210 
211         dst.clear();
212         bytesRead = decoder.read(dst);
213         Assert.assertEquals(10, bytesRead);
214         Assert.assertEquals("more stuff", CodecTestUtils.convert(dst));
215         Assert.assertTrue(decoder.isCompleted());
216         Assert.assertEquals(10, metrics.getBytesTransferred());
217 
218         dst.clear();
219         bytesRead = decoder.read(dst);
220         Assert.assertEquals(-1, bytesRead);
221         Assert.assertTrue(decoder.isCompleted());
222         Assert.assertEquals(10, metrics.getBytesTransferred());
223     }
224 
225     @Test
226     public void testDecodingFromSessionBuffer2() throws Exception {
227         final ReadableByteChannel channel = new ReadableByteChannelMock(
228                 new String[] {
229                         "stuff;",
230                         "more stuff; and a lot more stuff"}, Consts.ASCII);
231 
232         final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, Consts.ASCII);
233         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
234 
235         inbuf.fill(channel);
236         inbuf.fill(channel);
237 
238         Assert.assertEquals(38, inbuf.length());
239 
240         final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
241                 channel, inbuf, metrics, 16);
242 
243         final ByteBuffer dst = ByteBuffer.allocate(1024);
244 
245         int bytesRead = decoder.read(dst);
246         Assert.assertEquals(16, bytesRead);
247         Assert.assertEquals("stuff;more stuff", CodecTestUtils.convert(dst));
248         Assert.assertTrue(decoder.isCompleted());
249         Assert.assertEquals(0, metrics.getBytesTransferred());
250 
251         dst.clear();
252         bytesRead = decoder.read(dst);
253         Assert.assertEquals(-1, bytesRead);
254         Assert.assertTrue(decoder.isCompleted());
255         Assert.assertEquals(0, metrics.getBytesTransferred());
256     }
257 
258     /* ----------------- FileChannel Part testing --------------------------- */
259     @Test
260     public void testBasicDecodingFile() throws Exception {
261         final ReadableByteChannel channel = new ReadableByteChannelMock(
262                 new String[] {"stuff; ", "more stuff; ", "a lot more stuff!!!"}, Consts.ASCII);
263 
264         final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, Consts.ASCII);
265         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
266         final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
267                 channel, inbuf, metrics, 36);
268 
269         createTempFile();
270         final RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
271         try {
272             final FileChannel fchannel = testfile.getChannel();
273             long pos = 0;
274             while (!decoder.isCompleted()) {
275                 final long bytesRead = decoder.transfer(fchannel, pos, 10);
276                 if (bytesRead > 0) {
277                     pos += bytesRead;
278                 }
279             }
280         } finally {
281             testfile.close();
282         }
283         Assert.assertEquals(this.tmpfile.length(), metrics.getBytesTransferred());
284         Assert.assertEquals("stuff; more stuff; a lot more stuff!",
285             CodecTestUtils.readFromFile(this.tmpfile));
286     }
287 
288     @Test
289     public void testDecodingFileWithBufferedSessionData() throws Exception {
290         final ReadableByteChannel channel = new ReadableByteChannelMock(
291                 new String[] {"stuff; ", "more stuff; ", "a lot more stuff!!!"}, Consts.ASCII);
292 
293         final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, Consts.ASCII);
294         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
295         final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
296                 channel, inbuf, metrics, 36);
297 
298         final int i = inbuf.fill(channel);
299         Assert.assertEquals(7, i);
300 
301         createTempFile();
302         final RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
303         try {
304             final FileChannel fchannel = testfile.getChannel();
305             long pos = 0;
306             while (!decoder.isCompleted()) {
307                 final long bytesRead = decoder.transfer(fchannel, pos, 10);
308                 if (bytesRead > 0) {
309                     pos += bytesRead;
310                 }
311             }
312         } finally {
313             testfile.close();
314         }
315         Assert.assertEquals(this.tmpfile.length() - 7, metrics.getBytesTransferred());
316         Assert.assertEquals("stuff; more stuff; a lot more stuff!",
317             CodecTestUtils.readFromFile(this.tmpfile));
318     }
319 
320     @Test
321     public void testDecodingFileWithOffsetAndBufferedSessionData() throws Exception {
322         final ReadableByteChannel channel = new ReadableByteChannelMock(
323                 new String[] {"stuff; ", "more stuff; ", "a lot more stuff!"}, Consts.ASCII);
324 
325         final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, Consts.ASCII);
326         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
327         final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
328                 channel, inbuf, metrics, 36);
329 
330         final int i = inbuf.fill(channel);
331         Assert.assertEquals(7, i);
332 
333         final byte[] beginning =  EncodingUtils.getAsciiBytes("beginning; ");
334 
335         createTempFile();
336         RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
337         try {
338             testfile.write(beginning);
339         } finally {
340             testfile.close();
341         }
342 
343         testfile = new RandomAccessFile(this.tmpfile, "rw");
344         try {
345             final FileChannel fchannel = testfile.getChannel();
346 
347             long pos = beginning.length;
348             while (!decoder.isCompleted()) {
349                 if(testfile.length() < pos) {
350                     testfile.setLength(pos);
351                 }
352                 final long bytesRead = decoder.transfer(fchannel, pos, 10);
353                 if (bytesRead > 0) {
354                     pos += bytesRead;
355                 }
356             }
357         } finally {
358             testfile.close();
359         }
360 
361         // count everything except the initial 7 bytes that went to the session buffer
362         Assert.assertEquals(this.tmpfile.length() - 7 - beginning.length, metrics.getBytesTransferred());
363         Assert.assertEquals("beginning; stuff; more stuff; a lot more stuff!",
364             CodecTestUtils.readFromFile(this.tmpfile));
365     }
366 
367     @Test
368     public void testDecodingFileWithLimit() throws Exception {
369         final ReadableByteChannel channel = new ReadableByteChannelMock(
370                 new String[] {"stuff; more stuff; ", "a lot more stuff!!!"}, Consts.ASCII);
371 
372         final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, Consts.ASCII);
373         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
374         final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
375                 channel, inbuf, metrics, 36);
376 
377         final int i = inbuf.fill(channel);
378         Assert.assertEquals(19, i);
379 
380         createTempFile();
381         final RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
382         try {
383             final FileChannel fchannel = testfile.getChannel();
384             long pos = 0;
385 
386             // transferred from buffer
387             long bytesRead = decoder.transfer(fchannel, pos, 1);
388             Assert.assertEquals(1, bytesRead);
389             Assert.assertFalse(decoder.isCompleted());
390             Assert.assertEquals(0, metrics.getBytesTransferred());
391             pos += bytesRead;
392 
393             bytesRead = decoder.transfer(fchannel, pos, 2);
394             Assert.assertEquals(2, bytesRead);
395             Assert.assertFalse(decoder.isCompleted());
396             Assert.assertEquals(0, metrics.getBytesTransferred());
397             pos += bytesRead;
398 
399             bytesRead = decoder.transfer(fchannel, pos, 17);
400             Assert.assertEquals(16, bytesRead);
401             Assert.assertFalse(decoder.isCompleted());
402             Assert.assertEquals(0, metrics.getBytesTransferred());
403             pos += bytesRead;
404 
405             // transferred from channel
406             bytesRead = decoder.transfer(fchannel, pos, 1);
407             Assert.assertEquals(1, bytesRead);
408             Assert.assertFalse(decoder.isCompleted());
409             Assert.assertEquals(1, metrics.getBytesTransferred());
410             pos += bytesRead;
411 
412             bytesRead = decoder.transfer(fchannel, pos, 2);
413             Assert.assertEquals(2, bytesRead);
414             Assert.assertFalse(decoder.isCompleted());
415             Assert.assertEquals(3, metrics.getBytesTransferred());
416             pos += bytesRead;
417 
418             bytesRead = decoder.transfer(fchannel, pos, 15);
419             Assert.assertEquals(14, bytesRead);
420             Assert.assertTrue(decoder.isCompleted());
421             Assert.assertEquals(17, metrics.getBytesTransferred());
422             pos += bytesRead;
423 
424             bytesRead = decoder.transfer(fchannel, pos, 1);
425             Assert.assertEquals(-1, bytesRead);
426             Assert.assertTrue(decoder.isCompleted());
427             Assert.assertEquals(17, metrics.getBytesTransferred());
428         } finally {
429             testfile.close();
430         }
431         Assert.assertEquals("stuff; more stuff; a lot more stuff!",
432                 CodecTestUtils.readFromFile(this.tmpfile));
433     }
434 
435     @Test
436     public void testWriteBeyondFileSize() throws Exception {
437         final ReadableByteChannel channel = new ReadableByteChannelMock(
438                 new String[] {"a"}, Consts.ASCII);
439 
440         final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, Consts.ASCII);
441         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
442         final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
443                 channel, inbuf, metrics, 1);
444 
445         createTempFile();
446         final RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
447         try {
448             final FileChannel fchannel = testfile.getChannel();
449             Assert.assertEquals(0, testfile.length());
450             try {
451                 decoder.transfer(fchannel, 5, 10);
452                 Assert.fail("IOException should have been thrown");
453             } catch(final IOException expected) {
454             }
455         } finally {
456             testfile.close();
457         }
458     }
459 
460     @Test
461     public void testCodingBeyondContentLimitFile() throws Exception {
462         final ReadableByteChannel channel = new ReadableByteChannelMock(
463                 new String[] {
464                         "stuff;",
465                         "more stuff; and a lot more stuff"}, Consts.ASCII);
466 
467         final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, Consts.ASCII);
468         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
469         final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
470                 channel, inbuf, metrics, 16);
471 
472         createTempFile();
473         final RandomAccessFile testfile  = new RandomAccessFile(this.tmpfile, "rw");
474         try {
475             final FileChannel fchannel = testfile.getChannel();
476 
477             long bytesRead = decoder.transfer(fchannel, 0, 6);
478             Assert.assertEquals(6, bytesRead);
479             Assert.assertFalse(decoder.isCompleted());
480             Assert.assertEquals(6, metrics.getBytesTransferred());
481 
482             bytesRead = decoder.transfer(fchannel,0 , 10);
483             Assert.assertEquals(10, bytesRead);
484             Assert.assertTrue(decoder.isCompleted());
485             Assert.assertEquals(16, metrics.getBytesTransferred());
486 
487             bytesRead = decoder.transfer(fchannel, 0, 1);
488             Assert.assertEquals(-1, bytesRead);
489             Assert.assertTrue(decoder.isCompleted());
490             Assert.assertEquals(16, metrics.getBytesTransferred());
491         } finally {
492             testfile.close();
493         }
494     }
495 
496     @Test
497     public void testInvalidConstructor() {
498         final ReadableByteChannel channel = new ReadableByteChannelMock(
499                 new String[] {"stuff;", "more stuff"}, Consts.ASCII);
500 
501         final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, Consts.ASCII);
502         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
503         try {
504             new LengthDelimitedDecoder(null, null, null, 10);
505             Assert.fail("IllegalArgumentException should have been thrown");
506         } catch (final IllegalArgumentException ex) {
507             // ignore
508         }
509         try {
510             new LengthDelimitedDecoder(channel, null, null, 10);
511             Assert.fail("IllegalArgumentException should have been thrown");
512         } catch (final IllegalArgumentException ex) {
513             // ignore
514         }
515         try {
516             new LengthDelimitedDecoder(channel, inbuf, null, 10);
517             Assert.fail("IllegalArgumentException should have been thrown");
518         } catch (final IllegalArgumentException ex) {
519             // ignore
520         }
521         try {
522             new LengthDelimitedDecoder(channel, inbuf, metrics, -10);
523             Assert.fail("IllegalArgumentException should have been thrown");
524         } catch (final IllegalArgumentException ex) {
525             // ignore
526         }
527     }
528 
529     @Test
530     public void testInvalidInput() throws Exception {
531         final String s = "stuff";
532         final ReadableByteChannel channel = new ReadableByteChannelMock(
533                 new String[] {s}, Consts.ASCII);
534 
535         final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, Consts.ASCII);
536         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
537         final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
538                 channel, inbuf, metrics, 3);
539 
540         try {
541             decoder.read(null);
542             Assert.fail("IllegalArgumentException should have been thrown");
543         } catch (final IllegalArgumentException ex) {
544             // expected
545         }
546     }
547 
548     @Test
549     public void testZeroLengthDecoding() throws Exception {
550         final ReadableByteChannel channel = new ReadableByteChannelMock(
551                 new String[] {"stuff"}, Consts.ASCII);
552 
553         final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, Consts.ASCII);
554         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
555         final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
556                 channel, inbuf, metrics, 0);
557 
558         final ByteBuffer dst = ByteBuffer.allocate(1024);
559 
560         final int bytesRead = decoder.read(dst);
561         Assert.assertEquals(-1, bytesRead);
562         Assert.assertTrue(decoder.isCompleted());
563         Assert.assertEquals(0, metrics.getBytesTransferred());
564     }
565 
566     @Test(expected=ConnectionClosedException.class)
567     public void testTruncatedContent() throws Exception {
568         final ReadableByteChannel channel = new ReadableByteChannelMock(
569                 new String[] {"1234567890"}, Consts.ASCII);
570 
571         final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, Consts.ASCII);
572         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
573         final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
574                 channel, inbuf, metrics, 20);
575 
576         final ByteBuffer dst = ByteBuffer.allocate(1024);
577 
578         final int bytesRead = decoder.read(dst);
579         Assert.assertEquals(10, bytesRead);
580         decoder.read(dst);
581     }
582 
583     @Test(expected=ConnectionClosedException.class)
584     public void testTruncatedContentWithFile() throws Exception {
585         final ReadableByteChannel channel = new ReadableByteChannelMock(
586                 new String[] {"1234567890"}, Consts.ASCII);
587 
588         final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, Consts.ASCII);
589         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
590         final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
591                 channel, inbuf, metrics, 20);
592 
593         createTempFile();
594         final RandomAccessFile testfile  = new RandomAccessFile(this.tmpfile, "rw");
595         try {
596             final FileChannel fchannel = testfile.getChannel();
597             final long bytesRead = decoder.transfer(fchannel, 0, Integer.MAX_VALUE);
598             Assert.assertEquals(10, bytesRead);
599             decoder.transfer(fchannel, 0, Integer.MAX_VALUE);
600         } finally {
601             testfile.close();
602         }
603     }
604 
605 }