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  
36  import org.apache.http.Consts;
37  import org.apache.http.WritableByteChannelMock;
38  import org.apache.http.impl.io.HttpTransportMetricsImpl;
39  import org.apache.http.impl.nio.reactor.SessionOutputBufferImpl;
40  import org.apache.http.nio.reactor.SessionOutputBuffer;
41  import org.junit.After;
42  import org.junit.Assert;
43  import org.junit.Test;
44  import org.mockito.Matchers;
45  import org.mockito.Mockito;
46  
47  /**
48   * Simple tests for {@link IdentityEncoder}.
49   */
50  public class TestIdentityEncoder {
51  
52      private File tmpfile;
53  
54      protected File createTempFile() throws IOException {
55          this.tmpfile = File.createTempFile("testFile", ".txt");
56          return this.tmpfile;
57      }
58  
59      @After
60      public void deleteTempFile() {
61          if (this.tmpfile != null && this.tmpfile.exists()) {
62              this.tmpfile.delete();
63          }
64      }
65  
66      @Test
67      public void testBasicCoding() throws Exception {
68          final WritableByteChannelMock channel = new WritableByteChannelMock(64);
69          final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
70          final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
71  
72          final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics);
73          Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
74          encoder.complete();
75  
76          Assert.assertTrue(encoder.isCompleted());
77          Assert.assertEquals(5, metrics.getBytesTransferred());
78  
79          outbuf.flush(channel);
80          final String s = channel.dump(Consts.ASCII);
81  
82          Assert.assertEquals("stuff", s);
83          Assert.assertEquals("[identity; completed: true]", encoder.toString());
84      }
85  
86      @Test
87      public void testCodingEmptySrcBuffer() throws Exception {
88          final WritableByteChannelMock channel = new WritableByteChannelMock(64);
89          final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
90          final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
91  
92          final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics);
93          encoder.write(CodecTestUtils.wrap("stuff"));
94  
95          final ByteBuffer empty = ByteBuffer.allocate(100);
96          empty.flip();
97          encoder.write(empty);
98          encoder.write(null);
99          encoder.complete();
100 
101         outbuf.flush(channel);
102         final String s = channel.dump(Consts.ASCII);
103 
104         Assert.assertTrue(encoder.isCompleted());
105         Assert.assertEquals("stuff", s);
106     }
107 
108     @Test
109     public void testCodingCompleted() throws Exception {
110         final WritableByteChannelMock channel = new WritableByteChannelMock(64);
111         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
112         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
113 
114         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics);
115         encoder.write(CodecTestUtils.wrap("stuff"));
116         encoder.complete();
117 
118         try {
119             encoder.write(CodecTestUtils.wrap("more stuff"));
120             Assert.fail("IllegalStateException should have been thrown");
121         } catch (final IllegalStateException ex) {
122             // ignore
123         }
124     }
125 
126     @Test
127     public void testInvalidConstructor() {
128         final WritableByteChannelMock channel = new WritableByteChannelMock(64);
129         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
130 
131         try {
132             new IdentityEncoder(null, null, null);
133             Assert.fail("IllegalArgumentException should have been thrown");
134         } catch (final IllegalArgumentException ex) {
135             // ignore
136         }
137         try {
138             new IdentityEncoder(channel, null, null);
139             Assert.fail("IllegalArgumentException should have been thrown");
140         } catch (final IllegalArgumentException ex) {
141             // ignore
142         }
143         try {
144             new IdentityEncoder(channel, outbuf, null);
145             Assert.fail("IllegalArgumentException should have been thrown");
146         } catch (final IllegalArgumentException ex) {
147             // ignore
148         }
149     }
150 
151     @Test
152     public void testCodingFromFile() throws Exception {
153         final WritableByteChannelMock channel = new WritableByteChannelMock(64);
154         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
155         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
156 
157         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics);
158 
159         createTempFile();
160         RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
161         try {
162             testfile.write("stuff;".getBytes(Consts.ASCII));
163             testfile.write("more stuff".getBytes(Consts.ASCII));
164         } finally {
165             testfile.close();
166         }
167 
168         testfile = new RandomAccessFile(this.tmpfile, "rw");
169         try {
170             final FileChannel fchannel = testfile.getChannel();
171             encoder.transfer(fchannel, 0, 20);
172         } finally {
173             testfile.close();
174         }
175 
176         final String s = channel.dump(Consts.ASCII);
177 
178         Assert.assertFalse(encoder.isCompleted());
179         Assert.assertEquals("stuff;more stuff", s);
180     }
181 
182     @Test
183     public void testCodingEmptyFile() throws Exception {
184         final WritableByteChannelMock channel = new WritableByteChannelMock(64);
185         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
186         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
187 
188         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics);
189         encoder.write(CodecTestUtils.wrap("stuff;"));
190 
191         //Create an empty file
192         createTempFile();
193         RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
194         testfile.close();
195 
196         testfile = new RandomAccessFile(this.tmpfile, "rw");
197         try {
198             final FileChannel fchannel = testfile.getChannel();
199             encoder.transfer(fchannel, 0, 20);
200             encoder.write(CodecTestUtils.wrap("more stuff"));
201         } finally {
202             testfile.close();
203         }
204 
205         final String s = channel.dump(Consts.ASCII);
206 
207         Assert.assertFalse(encoder.isCompleted());
208         Assert.assertEquals("stuff;more stuff", s);
209     }
210 
211     @Test
212     public void testCodingFromFileSmaller() throws Exception {
213         final WritableByteChannelMock channel = new WritableByteChannelMock(64);
214         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
215         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
216 
217         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics);
218 
219         createTempFile();
220         RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
221         try {
222             testfile.write("stuff;".getBytes(Consts.ASCII));
223             testfile.write("more stuff".getBytes(Consts.ASCII));
224         } finally {
225             testfile.close();
226         }
227 
228         testfile = new RandomAccessFile(this.tmpfile, "rw");
229         try {
230             final FileChannel fchannel = testfile.getChannel();
231             encoder.transfer(fchannel, 0, 20);
232         } finally {
233             testfile.close();
234         }
235         final String s = channel.dump(Consts.ASCII);
236 
237         Assert.assertFalse(encoder.isCompleted());
238         Assert.assertEquals("stuff;more stuff", s);
239     }
240 
241     @Test
242     public void testCodingFromFileFlushBuffer() throws Exception {
243         final WritableByteChannelMock channel = new WritableByteChannelMock(64);
244         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
245         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
246 
247         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics);
248 
249         outbuf.writeLine("header");
250 
251         createTempFile();
252         RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
253         try {
254             testfile.write("stuff;".getBytes(Consts.ASCII));
255             testfile.write("more stuff".getBytes(Consts.ASCII));
256         } finally {
257             testfile.close();
258         }
259 
260         testfile = new RandomAccessFile(this.tmpfile, "rw");
261         try {
262             final FileChannel fchannel = testfile.getChannel();
263             encoder.transfer(fchannel, 0, 20);
264         } finally {
265             testfile.close();
266         }
267         final String s = channel.dump(Consts.ASCII);
268 
269         Assert.assertFalse(encoder.isCompleted());
270         Assert.assertEquals("header\r\nstuff;more stuff", s);
271     }
272 
273     @Test
274     public void testCodingFromFileChannelSaturated() throws Exception {
275         final WritableByteChannelMock channel = new WritableByteChannelMock(64, 4);
276         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
277         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
278 
279         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics);
280 
281         outbuf.writeLine("header");
282 
283         createTempFile();
284         RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
285         try {
286             testfile.write("stuff".getBytes(Consts.ASCII));
287         } finally {
288             testfile.close();
289         }
290 
291         testfile = new RandomAccessFile(this.tmpfile, "rw");
292         try {
293             final FileChannel fchannel = testfile.getChannel();
294             encoder.transfer(fchannel, 0, 20);
295             encoder.transfer(fchannel, 0, 20);
296         } finally {
297             testfile.close();
298         }
299         final String s = channel.dump(Consts.ASCII);
300 
301         Assert.assertFalse(encoder.isCompleted());
302         Assert.assertEquals("head", s);
303     }
304 
305     @Test
306     public void testCodingNoFragmentBuffering() throws Exception {
307         final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
308         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
309         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
310 
311         outbuf.writeLine("header");
312         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 0);
313         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
314 
315         Mockito.verify(channel, Mockito.times(2)).write(Matchers.<ByteBuffer>any());
316         Mockito.verify(outbuf, Mockito.never()).write(Matchers.<ByteBuffer>any());
317         Mockito.verify(outbuf, Mockito.times(1)).flush(channel);
318 
319         Assert.assertEquals(13, metrics.getBytesTransferred());
320 
321         outbuf.flush(channel);
322         final String s = channel.dump(Consts.ASCII);
323 
324         Assert.assertEquals("header\r\nstuff", s);
325     }
326 
327     @Test
328     public void testCodingFragmentBuffering() throws Exception {
329         final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
330         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
331         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
332 
333         outbuf.writeLine("header");
334         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 32);
335         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
336 
337         Mockito.verify(channel, Mockito.never()).write(Matchers.<ByteBuffer>any());
338         Mockito.verify(outbuf, Mockito.times(1)).write(Matchers.<ByteBuffer>any());
339         Mockito.verify(outbuf, Mockito.never()).flush(channel);
340 
341         Assert.assertEquals(0, metrics.getBytesTransferred());
342 
343         outbuf.flush(channel);
344         final String s = channel.dump(Consts.ASCII);
345 
346         Assert.assertEquals("header\r\nstuff", s);
347     }
348 
349     @Test
350     public void testCodingFragmentBufferingMultipleFragments() throws Exception {
351         final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
352         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
353         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
354 
355         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 32);
356         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
357         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
358         Assert.assertEquals(10, encoder.write(CodecTestUtils.wrap("more stuff")));
359 
360         Mockito.verify(channel, Mockito.never()).write(Matchers.<ByteBuffer>any());
361         Mockito.verify(outbuf, Mockito.times(3)).write(Matchers.<ByteBuffer>any());
362         Mockito.verify(outbuf, Mockito.never()).flush(channel);
363 
364         Assert.assertEquals(0, metrics.getBytesTransferred());
365 
366         outbuf.flush(channel);
367         final String s = channel.dump(Consts.ASCII);
368 
369         Assert.assertEquals("stuff-more stuff", s);
370     }
371 
372     @Test
373     public void testCodingFragmentBufferingLargeFragment() throws Exception {
374         final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
375         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
376         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
377 
378         outbuf.writeLine("header");
379         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 2);
380         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
381 
382         Mockito.verify(channel, Mockito.times(2)).write(Matchers.<ByteBuffer>any());
383         Mockito.verify(outbuf, Mockito.never()).write(Matchers.<ByteBuffer>any());
384         Mockito.verify(outbuf, Mockito.times(1)).flush(channel);
385 
386         Assert.assertEquals(13, metrics.getBytesTransferred());
387 
388         outbuf.flush(channel);
389         final String s = channel.dump(Consts.ASCII);
390         Assert.assertEquals("header\r\nstuff", s);
391     }
392 
393     @Test
394     public void testCodingFragmentBufferingTinyFragments() throws Exception {
395         final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
396         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
397         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
398 
399         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 1);
400         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
401         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
402         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
403         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
404         Assert.assertEquals(10, encoder.write(CodecTestUtils.wrap("more stuff")));
405 
406         Mockito.verify(channel, Mockito.times(5)).write(Matchers.<ByteBuffer>any());
407         Mockito.verify(outbuf, Mockito.times(3)).write(Matchers.<ByteBuffer>any());
408         Mockito.verify(outbuf, Mockito.times(3)).flush(channel);
409 
410         Assert.assertEquals(18, metrics.getBytesTransferred());
411 
412         outbuf.flush(channel);
413         final String s = channel.dump(Consts.ASCII);
414 
415         Assert.assertEquals("stuff---more stuff", s);
416     }
417 
418     @Test
419     public void testCodingFragmentBufferingTinyFragments2() throws Exception {
420         final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
421         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
422         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
423 
424         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 2);
425         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
426         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
427         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
428         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
429         Assert.assertEquals(10, encoder.write(CodecTestUtils.wrap("more stuff")));
430 
431         Mockito.verify(channel, Mockito.times(4)).write(Matchers.<ByteBuffer>any());
432         Mockito.verify(outbuf, Mockito.times(3)).write(Matchers.<ByteBuffer>any());
433         Mockito.verify(outbuf, Mockito.times(2)).flush(channel);
434 
435         Assert.assertEquals(18, metrics.getBytesTransferred());
436 
437         outbuf.flush(channel);
438         final String s = channel.dump(Consts.ASCII);
439 
440         Assert.assertEquals("stuff---more stuff", s);
441     }
442 
443     @Test
444     public void testCodingFragmentBufferingTinyFragments3() throws Exception {
445         final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
446         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
447         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
448 
449         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 3);
450         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
451         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
452         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
453         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
454         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
455         Assert.assertEquals(2, encoder.write(CodecTestUtils.wrap("--")));
456         Assert.assertEquals(10, encoder.write(CodecTestUtils.wrap("more stuff")));
457 
458         Mockito.verify(channel, Mockito.times(4)).write(Matchers.<ByteBuffer>any());
459         Mockito.verify(outbuf, Mockito.times(5)).write(Matchers.<ByteBuffer>any());
460         Mockito.verify(outbuf, Mockito.times(2)).flush(channel);
461 
462         Assert.assertEquals(21, metrics.getBytesTransferred());
463 
464         outbuf.flush(channel);
465         final String s = channel.dump(Consts.ASCII);
466 
467         Assert.assertEquals("stuff------more stuff", s);
468     }
469 
470     @Test
471     public void testCodingFragmentBufferingBufferFlush() throws Exception {
472         final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
473         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
474         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
475 
476         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 8);
477         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
478         Assert.assertEquals(6, encoder.write(CodecTestUtils.wrap("-stuff")));
479 
480         Mockito.verify(channel, Mockito.times(1)).write(Matchers.<ByteBuffer>any());
481         Mockito.verify(outbuf, Mockito.times(3)).write(Matchers.<ByteBuffer>any());
482         Mockito.verify(outbuf, Mockito.times(1)).flush(channel);
483 
484         Assert.assertEquals(8, metrics.getBytesTransferred());
485         Assert.assertEquals(3, outbuf.length());
486 
487         outbuf.flush(channel);
488         final String s = channel.dump(Consts.ASCII);
489 
490         Assert.assertEquals("stuff-stuff", s);
491     }
492 
493     @Test
494     public void testCodingFragmentBufferingBufferFlush2() throws Exception {
495         final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
496         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
497         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
498 
499         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 8);
500         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
501         Assert.assertEquals(16, encoder.write(CodecTestUtils.wrap("-much more stuff")));
502 
503         Mockito.verify(channel, Mockito.times(2)).write(Matchers.<ByteBuffer>any());
504         Mockito.verify(outbuf, Mockito.times(1)).write(Matchers.<ByteBuffer>any());
505         Mockito.verify(outbuf, Mockito.times(1)).flush(channel);
506 
507         Assert.assertEquals(21, metrics.getBytesTransferred());
508         Assert.assertEquals(0, outbuf.length());
509 
510         outbuf.flush(channel);
511         final String s = channel.dump(Consts.ASCII);
512 
513         Assert.assertEquals("stuff-much more stuff", s);
514     }
515 
516     @Test
517     public void testCodingFragmentBufferingChannelSaturated() throws Exception {
518         final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64, 8));
519         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
520         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
521 
522         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 3);
523         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
524         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
525         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
526         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
527         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
528         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
529         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
530         Assert.assertEquals(0, encoder.write(CodecTestUtils.wrap("-")));
531         Assert.assertEquals(0, encoder.write(CodecTestUtils.wrap("more stuff")));
532 
533         Mockito.verify(channel, Mockito.times(5)).write(Matchers.<ByteBuffer>any());
534         Mockito.verify(outbuf, Mockito.times(6)).write(Matchers.<ByteBuffer>any());
535         Mockito.verify(outbuf, Mockito.times(4)).flush(channel);
536 
537         Assert.assertEquals(8, metrics.getBytesTransferred());
538 
539         outbuf.flush(channel);
540         final String s = channel.dump(Consts.ASCII);
541 
542         Assert.assertEquals("stuff---", s);
543         Assert.assertEquals(3, outbuf.length());
544     }
545 
546     @Test
547     public void testCodingFragmentBufferingChannelSaturated2() throws Exception {
548         final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64, 8));
549         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
550         final HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
551 
552         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 8);
553         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
554         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
555         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
556         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("much more stuff")));
557 
558         Mockito.verify(channel, Mockito.times(3)).write(Matchers.<ByteBuffer>any());
559         Mockito.verify(outbuf, Mockito.times(3)).write(Matchers.<ByteBuffer>any());
560         Mockito.verify(outbuf, Mockito.times(1)).flush(channel);
561 
562         Assert.assertEquals(8, metrics.getBytesTransferred());
563 
564         outbuf.flush(channel);
565         final String s = channel.dump(Consts.ASCII);
566 
567         Assert.assertEquals("stuff--m", s);
568         Assert.assertEquals(0, outbuf.length());
569     }
570 
571 }