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