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.reactor;
29  
30  import java.io.ByteArrayInputStream;
31  import java.io.ByteArrayOutputStream;
32  import java.nio.ByteBuffer;
33  import java.nio.channels.Channels;
34  import java.nio.channels.ReadableByteChannel;
35  import java.nio.channels.WritableByteChannel;
36  import java.nio.charset.CharacterCodingException;
37  import java.nio.charset.Charset;
38  import java.nio.charset.CharsetDecoder;
39  import java.nio.charset.CharsetEncoder;
40  import java.nio.charset.CodingErrorAction;
41  import java.util.Arrays;
42  import java.util.Collection;
43  
44  import org.apache.http.Consts;
45  import org.apache.http.MessageConstraintException;
46  import org.apache.http.config.MessageConstraints;
47  import org.apache.http.nio.reactor.SessionInputBuffer;
48  import org.apache.http.nio.reactor.SessionOutputBuffer;
49  import org.apache.http.nio.util.ByteBufferAllocator;
50  import org.apache.http.nio.util.DirectByteBufferAllocator;
51  import org.apache.http.nio.util.HeapByteBufferAllocator;
52  import org.apache.http.util.CharArrayBuffer;
53  import org.junit.Assert;
54  import org.junit.Test;
55  import org.junit.runner.RunWith;
56  import org.junit.runners.Parameterized;
57  import org.junit.runners.Parameterized.Parameters;
58  
59  /**
60   * Simple tests for {@link SessionInputBuffer} and {@link SessionOutputBuffer}.
61   */
62  @RunWith(Parameterized.class)
63  public class TestSessionInOutBuffers {
64  
65      private final ByteBufferAllocator allocator;
66  
67      public TestSessionInOutBuffers(final ByteBufferAllocator allocator) {
68          super();
69          this.allocator = allocator;
70      }
71  
72      @Parameters
73      public static Collection<Object[]> getParameters() {
74  
75          return Arrays.asList(
76                  new Object[] { HeapByteBufferAllocator.INSTANCE },
77                  new Object[] { DirectByteBufferAllocator.INSTANCE });
78      }
79  
80      private static WritableByteChannel newChannel(final ByteArrayOutputStream outStream) {
81          return Channels.newChannel(outStream);
82      }
83  
84      private static ReadableByteChannel newChannel(final byte[] bytes) {
85          return Channels.newChannel(new ByteArrayInputStream(bytes));
86      }
87  
88      private static ReadableByteChannel newChannel(final String s, final Charset charset) {
89          return Channels.newChannel(new ByteArrayInputStream(s.getBytes(charset)));
90      }
91  
92      private static ReadableByteChannel newChannel(final String s) {
93          return newChannel(s, Consts.ASCII);
94      }
95  
96      @Test
97      public void testReadLineChunks() throws Exception {
98          final SessionInputBuffer inbuf = new SessionInputBufferImpl(16, 16, null, this.allocator);
99  
100         ReadableByteChannel channel = newChannel("One\r\nTwo\r\nThree");
101 
102         inbuf.fill(channel);
103 
104         final CharArrayBuffer line = new CharArrayBuffer(64);
105 
106         line.clear();
107         Assert.assertTrue(inbuf.readLine(line, false));
108         Assert.assertEquals("One", line.toString());
109 
110         line.clear();
111         Assert.assertTrue(inbuf.readLine(line, false));
112         Assert.assertEquals("Two", line.toString());
113 
114         line.clear();
115         Assert.assertFalse(inbuf.readLine(line, false));
116 
117         channel = newChannel("\r\nFour");
118         inbuf.fill(channel);
119 
120         line.clear();
121         Assert.assertTrue(inbuf.readLine(line, false));
122         Assert.assertEquals("Three", line.toString());
123 
124         inbuf.fill(channel);
125 
126         line.clear();
127         Assert.assertTrue(inbuf.readLine(line, true));
128         Assert.assertEquals("Four", line.toString());
129 
130         line.clear();
131         Assert.assertFalse(inbuf.readLine(line, true));
132     }
133 
134     @Test
135     public void testLineLimit() throws Exception {
136         final String s = "LoooooooooooooooooooooooooOOOOOOOOOOOOOOOOOOoooooooooooooooooooooong line\r\n";
137         final CharArrayBuffer line = new CharArrayBuffer(64);
138         final SessionInputBuffer inbuf1 = new SessionInputBufferImpl(128, 128,
139                 MessageConstraints.DEFAULT, null, this.allocator);
140         final ReadableByteChannel channel1 = newChannel(s);
141         inbuf1.fill(channel1);
142 
143         Assert.assertTrue(inbuf1.readLine(line, false));
144 
145         line.clear();
146         final SessionInputBuffer inbuf2 = new SessionInputBufferImpl(128, 128,
147                 MessageConstraints.lineLen(10), null, this.allocator);
148         final ReadableByteChannel channel2 = newChannel(s);
149         inbuf2.fill(channel2);
150         try {
151             inbuf2.readLine(line, false);
152             Assert.fail("MessageConstraintException expected");
153         } catch (final MessageConstraintException ex) {
154         }
155     }
156 
157     @Test
158     public void testLineLimitBufferFull() throws Exception {
159         final String s = "LoooooooooooooooooooooooooOOOOOOOOOOOOOOOOOOoooooooooooooooooooooong line\r\n";
160         final CharArrayBuffer line = new CharArrayBuffer(64);
161         final SessionInputBuffer inbuf1 = new SessionInputBufferImpl(32, 32,
162                 MessageConstraints.DEFAULT, null, this.allocator);
163         final ReadableByteChannel channel1 = newChannel(s);
164         inbuf1.fill(channel1);
165 
166         Assert.assertFalse(inbuf1.readLine(line, false));
167 
168         line.clear();
169         final SessionInputBuffer inbuf2 = new SessionInputBufferImpl(32, 32,
170                 MessageConstraints.lineLen(10), null, this.allocator);
171         final ReadableByteChannel channel2 = newChannel(s);
172         inbuf2.fill(channel2);
173         try {
174             inbuf2.readLine(line, false);
175             Assert.fail("MessageConstraintException expected");
176         } catch (final MessageConstraintException ex) {
177         }
178     }
179 
180     @Test
181     public void testWriteLineChunks() throws Exception {
182         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(16, 16, null, this.allocator);
183         final SessionInputBuffer inbuf = new SessionInputBufferImpl(16, 16, null, this.allocator);
184 
185         ReadableByteChannel inChannel = newChannel("One\r\nTwo\r\nThree");
186 
187         inbuf.fill(inChannel);
188 
189         final CharArrayBuffer line = new CharArrayBuffer(64);
190 
191         line.clear();
192         Assert.assertTrue(inbuf.readLine(line, false));
193         Assert.assertEquals("One", line.toString());
194 
195         outbuf.writeLine(line);
196 
197         line.clear();
198         Assert.assertTrue(inbuf.readLine(line, false));
199         Assert.assertEquals("Two", line.toString());
200 
201         outbuf.writeLine(line);
202 
203         line.clear();
204         Assert.assertFalse(inbuf.readLine(line, false));
205 
206         inChannel = newChannel("\r\nFour");
207         inbuf.fill(inChannel);
208 
209         line.clear();
210         Assert.assertTrue(inbuf.readLine(line, false));
211         Assert.assertEquals("Three", line.toString());
212 
213         outbuf.writeLine(line);
214 
215         inbuf.fill(inChannel);
216 
217         line.clear();
218         Assert.assertTrue(inbuf.readLine(line, true));
219         Assert.assertEquals("Four", line.toString());
220 
221         outbuf.writeLine(line);
222 
223         line.clear();
224         Assert.assertFalse(inbuf.readLine(line, true));
225 
226         final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
227         final WritableByteChannel outChannel = newChannel(outStream);
228         outbuf.flush(outChannel);
229 
230         final String s = new String(outStream.toByteArray(), "US-ASCII");
231         Assert.assertEquals("One\r\nTwo\r\nThree\r\nFour\r\n", s);
232     }
233 
234     @Test
235     public void testBasicReadWriteLine() throws Exception {
236 
237         final String[] teststrs = new String[5];
238         teststrs[0] = "Hello";
239         teststrs[1] = "This string should be much longer than the size of the line buffer " +
240                 "which is only 16 bytes for this test";
241         final StringBuilder buffer = new StringBuilder();
242         for (int i = 0; i < 15; i++) {
243             buffer.append("123456789 ");
244         }
245         buffer.append("and stuff like that");
246         teststrs[2] = buffer.toString();
247         teststrs[3] = "";
248         teststrs[4] = "And goodbye";
249 
250         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 16, null, this.allocator);
251         for (final String teststr : teststrs) {
252             outbuf.writeLine(teststr);
253         }
254         //this write operation should have no effect
255         outbuf.writeLine((String)null);
256         outbuf.writeLine((CharArrayBuffer)null);
257 
258         final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
259         final WritableByteChannel outChannel = newChannel(outStream);
260         outbuf.flush(outChannel);
261 
262         final ReadableByteChannel channel = newChannel(outStream.toByteArray());
263 
264         final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 16, null, this.allocator);
265         inbuf.fill(channel);
266 
267         for (final String teststr : teststrs) {
268             Assert.assertEquals(teststr, inbuf.readLine(true));
269         }
270         Assert.assertNull(inbuf.readLine(true));
271         Assert.assertNull(inbuf.readLine(true));
272     }
273 
274     @Test
275     public void testComplexReadWriteLine() throws Exception {
276         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 16, null, this.allocator);
277         outbuf.write(ByteBuffer.wrap(new byte[] {'a', '\n'}));
278         outbuf.write(ByteBuffer.wrap(new byte[] {'\r', '\n'}));
279         outbuf.write(ByteBuffer.wrap(new byte[] {'\r', '\r', '\n'}));
280         outbuf.write(ByteBuffer.wrap(new byte[] {'\n'}));
281 
282         final StringBuilder buffer = new StringBuilder();
283         for (int i = 0; i < 14; i++) {
284             buffer.append("a");
285         }
286         final String s1 = buffer.toString();
287         buffer.append("\r\n");
288         outbuf.write(ByteBuffer.wrap(buffer.toString().getBytes(Consts.ASCII)));
289 
290         buffer.setLength(0);
291         for (int i = 0; i < 15; i++) {
292             buffer.append("a");
293         }
294         final String s2 = buffer.toString();
295         buffer.append("\r\n");
296         outbuf.write(ByteBuffer.wrap(buffer.toString().getBytes(Consts.ASCII)));
297 
298         buffer.setLength(0);
299         for (int i = 0; i < 16; i++) {
300             buffer.append("a");
301         }
302         final String s3 = buffer.toString();
303         buffer.append("\r\n");
304         outbuf.write(ByteBuffer.wrap(buffer.toString().getBytes(Consts.ASCII)));
305 
306         outbuf.write(ByteBuffer.wrap(new byte[] {'a'}));
307 
308         final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
309         final WritableByteChannel outChannel = newChannel(outStream);
310         outbuf.flush(outChannel);
311 
312         final ReadableByteChannel channel = newChannel(outStream.toByteArray());
313 
314         final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 16, null, this.allocator);
315         inbuf.fill(channel);
316 
317         Assert.assertEquals("a", inbuf.readLine(true));
318         Assert.assertEquals("", inbuf.readLine(true));
319         Assert.assertEquals("\r", inbuf.readLine(true));
320         Assert.assertEquals("", inbuf.readLine(true));
321         Assert.assertEquals(s1, inbuf.readLine(true));
322         Assert.assertEquals(s2, inbuf.readLine(true));
323         Assert.assertEquals(s3, inbuf.readLine(true));
324         Assert.assertEquals("a", inbuf.readLine(true));
325         Assert.assertNull(inbuf.readLine(true));
326         Assert.assertNull(inbuf.readLine(true));
327     }
328 
329     @Test
330     public void testReadOneByte() throws Exception {
331         // make the buffer larger than that of transmitter
332         final byte[] out = new byte[40];
333         for (int i = 0; i < out.length; i++) {
334             out[i] = (byte)('0' + i);
335         }
336         final ReadableByteChannel channel = newChannel(out);
337         final SessionInputBuffer inbuf = new SessionInputBufferImpl(16, 16, null, this.allocator);
338         while (inbuf.fill(channel) > 0) {
339         }
340 
341         final byte[] in = new byte[40];
342         for (int i = 0; i < in.length; i++) {
343             in[i] = (byte)inbuf.read();
344         }
345         for (int i = 0; i < out.length; i++) {
346             Assert.assertEquals(out[i], in[i]);
347         }
348     }
349 
350     @Test
351     public void testReadByteBuffer() throws Exception {
352         final byte[] pattern = "0123456789ABCDEF".getBytes(Consts.ASCII);
353         final ReadableByteChannel channel = newChannel(pattern);
354         final SessionInputBuffer inbuf = new SessionInputBufferImpl(4096, 1024, null, this.allocator);
355         while (inbuf.fill(channel) > 0) {
356         }
357         final ByteBuffer dst = ByteBuffer.allocate(10);
358         Assert.assertEquals(10, inbuf.read(dst));
359         dst.flip();
360         Assert.assertEquals(dst, ByteBuffer.wrap(pattern, 0, 10));
361         dst.clear();
362         Assert.assertEquals(6, inbuf.read(dst));
363         dst.flip();
364         Assert.assertEquals(dst, ByteBuffer.wrap(pattern, 10, 6));
365     }
366 
367     @Test
368     public void testReadByteBufferWithMaxLen() throws Exception {
369         final byte[] pattern = "0123456789ABCDEF".getBytes(Consts.ASCII);
370         final ReadableByteChannel channel = newChannel(pattern);
371         final SessionInputBuffer inbuf = new SessionInputBufferImpl(4096, 1024, null, this.allocator);
372         while (inbuf.fill(channel) > 0) {
373         }
374         final ByteBuffer dst = ByteBuffer.allocate(16);
375         Assert.assertEquals(10, inbuf.read(dst, 10));
376         dst.flip();
377         Assert.assertEquals(dst, ByteBuffer.wrap(pattern, 0, 10));
378         dst.clear();
379         Assert.assertEquals(3, inbuf.read(dst, 3));
380         dst.flip();
381         Assert.assertEquals(dst, ByteBuffer.wrap(pattern, 10, 3));
382         Assert.assertEquals(3, inbuf.read(dst, 20));
383         dst.flip();
384         Assert.assertEquals(dst, ByteBuffer.wrap(pattern, 13, 3));
385     }
386 
387     @Test
388     public void testReadToChannel() throws Exception {
389         final byte[] pattern = "0123456789ABCDEF".getBytes(Consts.ASCII);
390         final ReadableByteChannel channel = newChannel(pattern);
391         final SessionInputBuffer inbuf = new SessionInputBufferImpl(4096, 1024, null, this.allocator);
392         while (inbuf.fill(channel) > 0) {
393         }
394 
395         final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
396         final WritableByteChannel dst = newChannel(outStream);
397 
398         Assert.assertEquals(16, inbuf.read(dst));
399         Assert.assertEquals(ByteBuffer.wrap(pattern), ByteBuffer.wrap(outStream.toByteArray()));
400     }
401 
402     @Test
403     public void testReadToChannelWithMaxLen() throws Exception {
404         final byte[] pattern = "0123456789ABCDEF".getBytes(Consts.ASCII);
405         final ReadableByteChannel channel = newChannel(pattern);
406         final SessionInputBuffer inbuf = new SessionInputBufferImpl(4096, 1024, null, this.allocator);
407         while (inbuf.fill(channel) > 0) {
408         }
409 
410         final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
411         final WritableByteChannel dst = newChannel(outStream);
412 
413         Assert.assertEquals(10, inbuf.read(dst, 10));
414         Assert.assertEquals(3, inbuf.read(dst, 3));
415         Assert.assertEquals(3, inbuf.read(dst, 10));
416         Assert.assertEquals(ByteBuffer.wrap(pattern), ByteBuffer.wrap(outStream.toByteArray()));
417     }
418 
419     @Test
420     public void testWriteByteBuffer() throws Exception {
421         final byte[] pattern = "0123456789ABCDEF0123456789ABCDEF".getBytes(Consts.ASCII);
422 
423         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(4096, 1024, null, this.allocator);
424         final ReadableByteChannel src = newChannel(pattern);
425         outbuf.write(src);
426 
427         final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
428         final WritableByteChannel channel = newChannel(outStream);
429         while (outbuf.flush(channel) > 0) {
430         }
431         Assert.assertEquals(ByteBuffer.wrap(pattern), ByteBuffer.wrap(outStream.toByteArray()));
432     }
433 
434     @Test
435     public void testWriteFromChannel() throws Exception {
436         final byte[] pattern = "0123456789ABCDEF0123456789ABCDEF".getBytes(Consts.ASCII);
437 
438         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(4096, 1024, null, this.allocator);
439         outbuf.write(ByteBuffer.wrap(pattern, 0, 16));
440         outbuf.write(ByteBuffer.wrap(pattern, 16, 10));
441         outbuf.write(ByteBuffer.wrap(pattern, 26, 6));
442 
443         final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
444         final WritableByteChannel channel = newChannel(outStream);
445         while (outbuf.flush(channel) > 0) {
446         }
447         Assert.assertEquals(ByteBuffer.wrap(pattern), ByteBuffer.wrap(outStream.toByteArray()));
448     }
449 
450     static final int SWISS_GERMAN_HELLO [] = {
451         0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
452     };
453 
454     static final int RUSSIAN_HELLO [] = {
455         0x412, 0x441, 0x435, 0x43C, 0x5F, 0x43F, 0x440, 0x438,
456         0x432, 0x435, 0x442
457     };
458 
459     private static String constructString(final int [] unicodeChars) {
460         final StringBuilder buffer = new StringBuilder();
461         if (unicodeChars != null) {
462             for (final int unicodeChar : unicodeChars) {
463                 buffer.append((char)unicodeChar);
464             }
465         }
466         return buffer.toString();
467     }
468 
469     @Test
470     public void testMultibyteCodedReadWriteLine() throws Exception {
471         final String s1 = constructString(SWISS_GERMAN_HELLO);
472         final String s2 = constructString(RUSSIAN_HELLO);
473         final String s3 = "Like hello and stuff";
474 
475         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 16,
476                 Consts.UTF_8.newEncoder(), this.allocator);
477 
478         for (int i = 0; i < 10; i++) {
479             outbuf.writeLine(s1);
480             outbuf.writeLine(s2);
481             outbuf.writeLine(s3);
482         }
483 
484         final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
485         final WritableByteChannel outChannel = newChannel(outStream);
486         outbuf.flush(outChannel);
487 
488         final byte[] tmp = outStream.toByteArray();
489 
490         final ReadableByteChannel channel = newChannel(tmp);
491         final SessionInputBuffer inbuf = new SessionInputBufferImpl(16, 16,
492                 Consts.UTF_8.newDecoder(), this.allocator);
493 
494         while (inbuf.fill(channel) > 0) {
495         }
496 
497         for (int i = 0; i < 10; i++) {
498             Assert.assertEquals(s1, inbuf.readLine(true));
499             Assert.assertEquals(s2, inbuf.readLine(true));
500             Assert.assertEquals(s3, inbuf.readLine(true));
501         }
502     }
503 
504     @Test
505     public void testInputMatchesBufferLength() throws Exception {
506         final String s1 = "abcde";
507         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 5, null, this.allocator);
508         outbuf.writeLine(s1);
509     }
510 
511     @Test(expected=CharacterCodingException.class)
512     public void testMalformedInputActionReport() throws Exception {
513         final String s = constructString(SWISS_GERMAN_HELLO);
514         final byte[] tmp = s.getBytes(Consts.ISO_8859_1);
515 
516         final CharsetDecoder decoder = Consts.UTF_8.newDecoder();
517         decoder.onMalformedInput(CodingErrorAction.REPORT);
518         decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
519         final SessionInputBuffer inbuf = new SessionInputBufferImpl(16, 16, decoder, this.allocator);
520         final ReadableByteChannel channel = newChannel(tmp);
521         while (inbuf.fill(channel) > 0) {
522         }
523         inbuf.readLine(true);
524     }
525 
526     @Test
527     public void testMalformedInputActionIgnore() throws Exception {
528         final String s = constructString(SWISS_GERMAN_HELLO);
529         final byte[] tmp = s.getBytes(Consts.ISO_8859_1);
530 
531         final CharsetDecoder decoder = Consts.UTF_8.newDecoder();
532         decoder.onMalformedInput(CodingErrorAction.IGNORE);
533         decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
534         final SessionInputBuffer inbuf = new SessionInputBufferImpl(16, 16, decoder, this.allocator);
535         final ReadableByteChannel channel = newChannel(tmp);
536         while (inbuf.fill(channel) > 0) {
537         }
538         final String result = inbuf.readLine(true);
539         Assert.assertEquals("Grezi_zm", result);
540     }
541 
542     @Test
543     public void testMalformedInputActionReplace() throws Exception {
544         final String s = constructString(SWISS_GERMAN_HELLO);
545         final byte[] tmp = s.getBytes(Consts.ISO_8859_1);
546 
547         final CharsetDecoder decoder = Consts.UTF_8.newDecoder();
548         decoder.onMalformedInput(CodingErrorAction.REPLACE);
549         decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
550         final SessionInputBuffer inbuf = new SessionInputBufferImpl(16, 16, decoder, this.allocator);
551         final ReadableByteChannel channel = newChannel(tmp);
552         while (inbuf.fill(channel) > 0) {
553         }
554         final String result = inbuf.readLine(true);
555         Assert.assertEquals("Gr\ufffdezi_z\ufffdm\ufffd", result);
556     }
557 
558     @Test(expected=CharacterCodingException.class)
559     public void testUnmappableInputActionReport() throws Exception {
560         final String s = "This text contains a circumflex \u0302!!!";
561         final CharsetEncoder encoder = Consts.ISO_8859_1.newEncoder();
562         encoder.onMalformedInput(CodingErrorAction.IGNORE);
563         encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
564         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 16, encoder, this.allocator);
565         outbuf.writeLine(s);
566     }
567 
568     @Test
569     public void testUnmappableInputActionIgnore() throws Exception {
570         final String s = "This text contains a circumflex \u0302!!!";
571         final CharsetEncoder encoder = Consts.ISO_8859_1.newEncoder();
572         encoder.onMalformedInput(CodingErrorAction.IGNORE);
573         encoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
574         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 16, encoder, this.allocator);
575         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
576         final WritableByteChannel channel = newChannel(baos);
577         outbuf.writeLine(s);
578         outbuf.flush(channel);
579 
580         final String result = new String(baos.toByteArray(), "US-ASCII");
581         Assert.assertEquals("This text contains a circumflex !!!\r\n", result);
582     }
583 
584     @Test
585     public void testUnmappableInputActionReplace() throws Exception {
586         final String s = "This text contains a circumflex \u0302 !!!";
587         final CharsetEncoder encoder = Consts.ISO_8859_1.newEncoder();
588         encoder.onMalformedInput(CodingErrorAction.IGNORE);
589         encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
590         final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 16, encoder, this.allocator);
591         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
592         final WritableByteChannel channel = newChannel(baos);
593         outbuf.writeLine(s);
594         outbuf.flush(channel);
595 
596         final String result = new String(baos.toByteArray(), "US-ASCII");
597         Assert.assertEquals("This text contains a circumflex ? !!!\r\n", result);
598     }
599 
600 }