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.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.charset.StandardCharsets;
36  
37  import org.apache.hc.core5.http.WritableByteChannelMock;
38  import org.apache.hc.core5.http.impl.BasicHttpTransportMetrics;
39  import org.apache.hc.core5.http.nio.SessionOutputBuffer;
40  import org.apache.hc.core5.util.CharArrayBuffer;
41  import org.junit.After;
42  import org.junit.Assert;
43  import org.junit.Test;
44  import org.mockito.ArgumentMatchers;
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 WritableByteChannelMockChannelMock.html#WritableByteChannelMock">WritableByteChannelMock channel = new WritableByteChannelMock(64);
69          final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
70          final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
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(StandardCharsets.US_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 WritableByteChannelMockChannelMock.html#WritableByteChannelMock">WritableByteChannelMock channel = new WritableByteChannelMock(64);
89          final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
90          final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
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(StandardCharsets.US_ASCII);
103 
104         Assert.assertTrue(encoder.isCompleted());
105         Assert.assertEquals("stuff", s);
106     }
107 
108     @Test
109     public void testCodingCompleted() throws Exception {
110         final WritableByteChannelMockChannelMock.html#WritableByteChannelMock">WritableByteChannelMock channel = new WritableByteChannelMock(64);
111         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
112         final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
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 WritableByteChannelMockChannelMock.html#WritableByteChannelMock">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("NullPointerException should have been thrown");
134         } catch (final NullPointerException ex) {
135             // ignore
136         }
137         try {
138             new IdentityEncoder(channel, null, null);
139             Assert.fail("NullPointerException should have been thrown");
140         } catch (final NullPointerException ex) {
141             // ignore
142         }
143         try {
144             new IdentityEncoder(channel, outbuf, null);
145             Assert.fail("NullPointerException should have been thrown");
146         } catch (final NullPointerException ex) {
147             // ignore
148         }
149     }
150 
151     @Test
152     public void testCodingFromFile() throws Exception {
153         final WritableByteChannelMockChannelMock.html#WritableByteChannelMock">WritableByteChannelMock channel = new WritableByteChannelMock(64);
154         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
155         final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
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(StandardCharsets.US_ASCII));
163             testfile.write("more stuff".getBytes(StandardCharsets.US_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(StandardCharsets.US_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 WritableByteChannelMockChannelMock.html#WritableByteChannelMock">WritableByteChannelMock channel = new WritableByteChannelMock(64);
185         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
186         final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
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(StandardCharsets.US_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 WritableByteChannelMockChannelMock.html#WritableByteChannelMock">WritableByteChannelMock channel = new WritableByteChannelMock(64);
214         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
215         final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
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(StandardCharsets.US_ASCII));
223             testfile.write("more stuff".getBytes(StandardCharsets.US_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(StandardCharsets.US_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 WritableByteChannelMockChannelMock.html#WritableByteChannelMock">WritableByteChannelMock channel = new WritableByteChannelMock(64);
244         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
245         final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
246 
247         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics);
248 
249         final CharArrayBuffer chbuffer = new CharArrayBuffer(16);
250         chbuffer.append("header");
251         outbuf.writeLine(chbuffer);
252 
253         createTempFile();
254         RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
255         try {
256             testfile.write("stuff;".getBytes(StandardCharsets.US_ASCII));
257             testfile.write("more stuff".getBytes(StandardCharsets.US_ASCII));
258         } finally {
259             testfile.close();
260         }
261 
262         testfile = new RandomAccessFile(this.tmpfile, "rw");
263         try {
264             final FileChannel fchannel = testfile.getChannel();
265             encoder.transfer(fchannel, 0, 20);
266         } finally {
267             testfile.close();
268         }
269         final String s = channel.dump(StandardCharsets.US_ASCII);
270 
271         Assert.assertFalse(encoder.isCompleted());
272         Assert.assertEquals("header\r\nstuff;more stuff", s);
273     }
274 
275     @Test
276     public void testCodingFromFileChannelSaturated() throws Exception {
277         final WritableByteChannelMockChannelMock.html#WritableByteChannelMock">WritableByteChannelMock channel = new WritableByteChannelMock(64, 4);
278         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
279         final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
280 
281         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics);
282 
283         final CharArrayBuffer chbuffer = new CharArrayBuffer(16);
284         chbuffer.append("header");
285         outbuf.writeLine(chbuffer);
286 
287         createTempFile();
288         RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
289         try {
290             testfile.write("stuff".getBytes(StandardCharsets.US_ASCII));
291         } finally {
292             testfile.close();
293         }
294 
295         testfile = new RandomAccessFile(this.tmpfile, "rw");
296         try {
297             final FileChannel fchannel = testfile.getChannel();
298             encoder.transfer(fchannel, 0, 20);
299             encoder.transfer(fchannel, 0, 20);
300         } finally {
301             testfile.close();
302         }
303         final String s = channel.dump(StandardCharsets.US_ASCII);
304 
305         Assert.assertFalse(encoder.isCompleted());
306         Assert.assertEquals("head", s);
307     }
308 
309     @Test
310     public void testCodingNoFragmentBuffering() throws Exception {
311         final WritableByteChannelMockhtml#WritableByteChannelMock">WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
312         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
313         final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
314 
315         final CharArrayBuffer chbuffer = new CharArrayBuffer(16);
316         chbuffer.append("header");
317         outbuf.writeLine(chbuffer);
318         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 0);
319         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
320 
321         Mockito.verify(channel, Mockito.times(2)).write(ArgumentMatchers.<ByteBuffer>any());
322         Mockito.verify(outbuf, Mockito.never()).write(ArgumentMatchers.<ByteBuffer>any());
323         Mockito.verify(outbuf, Mockito.times(1)).flush(channel);
324 
325         Assert.assertEquals(13, metrics.getBytesTransferred());
326 
327         outbuf.flush(channel);
328         final String s = channel.dump(StandardCharsets.US_ASCII);
329 
330         Assert.assertEquals("header\r\nstuff", s);
331     }
332 
333     @Test
334     public void testCodingFragmentBuffering() throws Exception {
335         final WritableByteChannelMockhtml#WritableByteChannelMock">WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
336         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
337         final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
338 
339         final CharArrayBuffer chbuffer = new CharArrayBuffer(16);
340         chbuffer.append("header");
341         outbuf.writeLine(chbuffer);
342         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 32);
343         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
344 
345         Mockito.verify(channel, Mockito.never()).write(ArgumentMatchers.<ByteBuffer>any());
346         Mockito.verify(outbuf, Mockito.times(1)).write(ArgumentMatchers.<ByteBuffer>any());
347         Mockito.verify(outbuf, Mockito.never()).flush(channel);
348 
349         Assert.assertEquals(0, metrics.getBytesTransferred());
350 
351         outbuf.flush(channel);
352         final String s = channel.dump(StandardCharsets.US_ASCII);
353 
354         Assert.assertEquals("header\r\nstuff", s);
355     }
356 
357     @Test
358     public void testCodingFragmentBufferingMultipleFragments() throws Exception {
359         final WritableByteChannelMockhtml#WritableByteChannelMock">WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
360         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
361         final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
362 
363         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 32);
364         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
365         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
366         Assert.assertEquals(10, encoder.write(CodecTestUtils.wrap("more stuff")));
367 
368         Mockito.verify(channel, Mockito.never()).write(ArgumentMatchers.<ByteBuffer>any());
369         Mockito.verify(outbuf, Mockito.times(3)).write(ArgumentMatchers.<ByteBuffer>any());
370         Mockito.verify(outbuf, Mockito.never()).flush(channel);
371 
372         Assert.assertEquals(0, metrics.getBytesTransferred());
373 
374         outbuf.flush(channel);
375         final String s = channel.dump(StandardCharsets.US_ASCII);
376 
377         Assert.assertEquals("stuff-more stuff", s);
378     }
379 
380     @Test
381     public void testCodingFragmentBufferingLargeFragment() throws Exception {
382         final WritableByteChannelMockhtml#WritableByteChannelMock">WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
383         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
384         final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
385 
386         final CharArrayBuffer chbuffer = new CharArrayBuffer(16);
387         chbuffer.append("header");
388         outbuf.writeLine(chbuffer);
389         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 2);
390         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
391 
392         Mockito.verify(channel, Mockito.times(2)).write(ArgumentMatchers.<ByteBuffer>any());
393         Mockito.verify(outbuf, Mockito.never()).write(ArgumentMatchers.<ByteBuffer>any());
394         Mockito.verify(outbuf, Mockito.times(1)).flush(channel);
395 
396         Assert.assertEquals(13, metrics.getBytesTransferred());
397 
398         outbuf.flush(channel);
399         final String s = channel.dump(StandardCharsets.US_ASCII);
400         Assert.assertEquals("header\r\nstuff", s);
401     }
402 
403     @Test
404     public void testCodingFragmentBufferingTinyFragments() throws Exception {
405         final WritableByteChannelMockhtml#WritableByteChannelMock">WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
406         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
407         final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
408 
409         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 1);
410         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
411         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
412         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
413         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
414         Assert.assertEquals(10, encoder.write(CodecTestUtils.wrap("more stuff")));
415 
416         Mockito.verify(channel, Mockito.times(5)).write(ArgumentMatchers.<ByteBuffer>any());
417         Mockito.verify(outbuf, Mockito.times(3)).write(ArgumentMatchers.<ByteBuffer>any());
418         Mockito.verify(outbuf, Mockito.times(3)).flush(channel);
419 
420         Assert.assertEquals(18, metrics.getBytesTransferred());
421 
422         outbuf.flush(channel);
423         final String s = channel.dump(StandardCharsets.US_ASCII);
424 
425         Assert.assertEquals("stuff---more stuff", s);
426     }
427 
428     @Test
429     public void testCodingFragmentBufferingTinyFragments2() throws Exception {
430         final WritableByteChannelMockhtml#WritableByteChannelMock">WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
431         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
432         final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
433 
434         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 2);
435         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
436         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
437         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
438         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
439         Assert.assertEquals(10, encoder.write(CodecTestUtils.wrap("more stuff")));
440 
441         Mockito.verify(channel, Mockito.times(4)).write(ArgumentMatchers.<ByteBuffer>any());
442         Mockito.verify(outbuf, Mockito.times(3)).write(ArgumentMatchers.<ByteBuffer>any());
443         Mockito.verify(outbuf, Mockito.times(2)).flush(channel);
444 
445         Assert.assertEquals(18, metrics.getBytesTransferred());
446 
447         outbuf.flush(channel);
448         final String s = channel.dump(StandardCharsets.US_ASCII);
449 
450         Assert.assertEquals("stuff---more stuff", s);
451     }
452 
453     @Test
454     public void testCodingFragmentBufferingTinyFragments3() throws Exception {
455         final WritableByteChannelMockhtml#WritableByteChannelMock">WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
456         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
457         final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
458 
459         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 3);
460         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
461         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
462         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
463         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
464         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
465         Assert.assertEquals(2, encoder.write(CodecTestUtils.wrap("--")));
466         Assert.assertEquals(10, encoder.write(CodecTestUtils.wrap("more stuff")));
467 
468         Mockito.verify(channel, Mockito.times(4)).write(ArgumentMatchers.<ByteBuffer>any());
469         Mockito.verify(outbuf, Mockito.times(5)).write(ArgumentMatchers.<ByteBuffer>any());
470         Mockito.verify(outbuf, Mockito.times(2)).flush(channel);
471 
472         Assert.assertEquals(21, metrics.getBytesTransferred());
473 
474         outbuf.flush(channel);
475         final String s = channel.dump(StandardCharsets.US_ASCII);
476 
477         Assert.assertEquals("stuff------more stuff", s);
478     }
479 
480     @Test
481     public void testCodingFragmentBufferingBufferFlush() throws Exception {
482         final WritableByteChannelMockhtml#WritableByteChannelMock">WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
483         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
484         final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
485 
486         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 8);
487         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
488         Assert.assertEquals(6, encoder.write(CodecTestUtils.wrap("-stuff")));
489 
490         Mockito.verify(channel, Mockito.times(1)).write(ArgumentMatchers.<ByteBuffer>any());
491         Mockito.verify(outbuf, Mockito.times(3)).write(ArgumentMatchers.<ByteBuffer>any());
492         Mockito.verify(outbuf, Mockito.times(1)).flush(channel);
493 
494         Assert.assertEquals(8, metrics.getBytesTransferred());
495         Assert.assertEquals(3, outbuf.length());
496 
497         outbuf.flush(channel);
498         final String s = channel.dump(StandardCharsets.US_ASCII);
499 
500         Assert.assertEquals("stuff-stuff", s);
501     }
502 
503     @Test
504     public void testCodingFragmentBufferingBufferFlush2() throws Exception {
505         final WritableByteChannelMockhtml#WritableByteChannelMock">WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
506         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
507         final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
508 
509         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 8);
510         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
511         Assert.assertEquals(16, encoder.write(CodecTestUtils.wrap("-much more stuff")));
512 
513         Mockito.verify(channel, Mockito.times(2)).write(ArgumentMatchers.<ByteBuffer>any());
514         Mockito.verify(outbuf, Mockito.times(1)).write(ArgumentMatchers.<ByteBuffer>any());
515         Mockito.verify(outbuf, Mockito.times(1)).flush(channel);
516 
517         Assert.assertEquals(21, metrics.getBytesTransferred());
518         Assert.assertEquals(0, outbuf.length());
519 
520         outbuf.flush(channel);
521         final String s = channel.dump(StandardCharsets.US_ASCII);
522 
523         Assert.assertEquals("stuff-much more stuff", s);
524     }
525 
526     @Test
527     public void testCodingFragmentBufferingChannelSaturated() throws Exception {
528         final WritableByteChannelMockhtml#WritableByteChannelMock">WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64, 8));
529         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
530         final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
531 
532         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 3);
533         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
534         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
535         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
536         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
537         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
538         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
539         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
540         Assert.assertEquals(0, encoder.write(CodecTestUtils.wrap("-")));
541         Assert.assertEquals(0, encoder.write(CodecTestUtils.wrap("more stuff")));
542 
543         Mockito.verify(channel, Mockito.times(5)).write(ArgumentMatchers.<ByteBuffer>any());
544         Mockito.verify(outbuf, Mockito.times(6)).write(ArgumentMatchers.<ByteBuffer>any());
545         Mockito.verify(outbuf, Mockito.times(4)).flush(channel);
546 
547         Assert.assertEquals(8, metrics.getBytesTransferred());
548 
549         outbuf.flush(channel);
550         final String s = channel.dump(StandardCharsets.US_ASCII);
551 
552         Assert.assertEquals("stuff---", s);
553         Assert.assertEquals(3, outbuf.length());
554     }
555 
556     @Test
557     public void testCodingFragmentBufferingChannelSaturated2() throws Exception {
558         final WritableByteChannelMockhtml#WritableByteChannelMock">WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64, 8));
559         final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
560         final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
561 
562         final IdentityEncoder encoder = new IdentityEncoder(channel, outbuf, metrics, 8);
563         Assert.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
564         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
565         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
566         Assert.assertEquals(1, encoder.write(CodecTestUtils.wrap("much more stuff")));
567 
568         Mockito.verify(channel, Mockito.times(3)).write(ArgumentMatchers.<ByteBuffer>any());
569         Mockito.verify(outbuf, Mockito.times(3)).write(ArgumentMatchers.<ByteBuffer>any());
570         Mockito.verify(outbuf, Mockito.times(1)).flush(channel);
571 
572         Assert.assertEquals(8, metrics.getBytesTransferred());
573 
574         outbuf.flush(channel);
575         final String s = channel.dump(StandardCharsets.US_ASCII);
576 
577         Assert.assertEquals("stuff--m", s);
578         Assert.assertEquals(0, outbuf.length());
579     }
580 
581 }