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