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