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.File;
31 import java.io.IOException;
32 import java.io.RandomAccessFile;
33 import java.nio.ByteBuffer;
34 import java.nio.channels.FileChannel;
35 import java.nio.charset.StandardCharsets;
36
37 import org.apache.hc.core5.http.WritableByteChannelMock;
38 import org.apache.hc.core5.http.impl.BasicHttpTransportMetrics;
39 import org.apache.hc.core5.http.nio.SessionOutputBuffer;
40 import org.apache.hc.core5.util.CharArrayBuffer;
41 import org.junit.jupiter.api.AfterEach;
42 import org.junit.jupiter.api.Assertions;
43 import org.junit.jupiter.api.Test;
44 import org.mockito.ArgumentMatchers;
45 import org.mockito.Mockito;
46
47
48
49
50 public class TestLengthDelimitedEncoder {
51
52 private File tmpfile;
53
54 protected File createTempFile() throws IOException {
55 this.tmpfile = File.createTempFile("testFile", ".txt");
56 return this.tmpfile;
57 }
58
59 @AfterEach
60 public void deleteTempFile() {
61 if (this.tmpfile != null && this.tmpfile.exists()) {
62 this.tmpfile.delete();
63 }
64 }
65
66 @Test
67 public void testBasicCoding() throws Exception {
68 final WritableByteChannelMock channel = new WritableByteChannelMock(64);
69 final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
70 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
71
72 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(
73 channel, outbuf, metrics, 16);
74 encoder.write(CodecTestUtils.wrap("stuff;"));
75 encoder.write(CodecTestUtils.wrap("more stuff"));
76
77 final String s = channel.dump(StandardCharsets.US_ASCII);
78
79 Assertions.assertTrue(encoder.isCompleted());
80 Assertions.assertEquals("stuff;more stuff", s);
81 Assertions.assertEquals("[content length: 16; pos: 16; completed: true]", encoder.toString());
82 }
83
84 @Test
85 public void testCodingBeyondContentLimit() throws Exception {
86 final WritableByteChannelMock channel = new WritableByteChannelMock(64);
87 final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
88 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
89
90 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(
91 channel, outbuf, metrics, 16);
92 encoder.write(CodecTestUtils.wrap("stuff;"));
93 encoder.write(CodecTestUtils.wrap("more stuff; and a lot more stuff"));
94
95 final String s = channel.dump(StandardCharsets.US_ASCII);
96
97 Assertions.assertTrue(encoder.isCompleted());
98 Assertions.assertEquals("stuff;more stuff", s);
99 }
100
101 @Test
102 public void testCodingEmptyBuffer() throws Exception {
103 final WritableByteChannelMock channel = new WritableByteChannelMock(64);
104 final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
105 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
106
107 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(
108 channel, outbuf, metrics, 16);
109 encoder.write(CodecTestUtils.wrap("stuff;"));
110
111 final ByteBuffer empty = ByteBuffer.allocate(100);
112 empty.flip();
113 encoder.write(empty);
114 encoder.write(null);
115
116 encoder.write(CodecTestUtils.wrap("more stuff"));
117
118 final String s = channel.dump(StandardCharsets.US_ASCII);
119
120 Assertions.assertTrue(encoder.isCompleted());
121 Assertions.assertEquals("stuff;more stuff", s);
122 }
123
124 @Test
125 public void testCodingCompleted() throws Exception {
126 final WritableByteChannelMock channel = new WritableByteChannelMock(64);
127 final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
128 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
129
130 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(
131 channel, outbuf, metrics, 5);
132 encoder.write(CodecTestUtils.wrap("stuff"));
133
134 Assertions.assertThrows(IllegalStateException.class, () -> encoder.write(CodecTestUtils.wrap("more stuff")));
135 }
136
137 @Test
138 public void testInvalidConstructor() {
139 final WritableByteChannelMock channel = new WritableByteChannelMock(64);
140 final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
141 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
142
143 Assertions.assertThrows(NullPointerException.class, () -> new LengthDelimitedEncoder(null, null, null, 10));
144 Assertions.assertThrows(NullPointerException.class, () -> new LengthDelimitedEncoder(channel, null, null, 10));
145 Assertions.assertThrows(NullPointerException.class, () -> new LengthDelimitedEncoder(channel, outbuf, null, 10));
146 Assertions.assertThrows(IllegalArgumentException.class, () -> new LengthDelimitedEncoder(channel, outbuf, metrics, -10));
147 }
148
149 @Test
150 public void testCodingBeyondContentLimitFromFile() throws Exception {
151 final WritableByteChannelMock channel = new WritableByteChannelMock(64);
152 final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
153 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
154
155 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(
156 channel, outbuf, metrics, 16);
157
158 createTempFile();
159 RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
160 try {
161 testfile.write("stuff;".getBytes(StandardCharsets.US_ASCII));
162 testfile.write("more stuff; and a lot more stuff".getBytes(StandardCharsets.US_ASCII));
163 } finally {
164 testfile.close();
165 }
166
167 testfile = new RandomAccessFile(this.tmpfile, "rw");
168 try {
169 final FileChannel fchannel = testfile.getChannel();
170 encoder.transfer(fchannel, 0, 20);
171 } finally {
172 testfile.close();
173 }
174
175 final String s = channel.dump(StandardCharsets.US_ASCII);
176
177 Assertions.assertTrue(encoder.isCompleted());
178 Assertions.assertEquals("stuff;more stuff", s);
179 }
180
181 @Test
182 public void testCodingEmptyFile() throws Exception {
183 final WritableByteChannelMock channel = new WritableByteChannelMock(64);
184 final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
185 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
186
187 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(
188 channel, outbuf, metrics, 16);
189 encoder.write(CodecTestUtils.wrap("stuff;"));
190
191
192 createTempFile();
193 RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
194 testfile.close();
195
196 testfile = new RandomAccessFile(this.tmpfile, "rw");
197 try {
198 final FileChannel fchannel = testfile.getChannel();
199 encoder.transfer(fchannel, 0, 20);
200 encoder.write(CodecTestUtils.wrap("more stuff"));
201 } finally {
202 testfile.close();
203 }
204
205 final String s = channel.dump(StandardCharsets.US_ASCII);
206
207 Assertions.assertTrue(encoder.isCompleted());
208 Assertions.assertEquals("stuff;more stuff", s);
209 }
210
211 @Test
212 public void testCodingCompletedFromFile() throws Exception {
213 final WritableByteChannelMock channel = new WritableByteChannelMock(64);
214 final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
215 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
216
217 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(
218 channel, outbuf, metrics, 5);
219 encoder.write(CodecTestUtils.wrap("stuff"));
220
221 createTempFile();
222 try (final RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw")) {
223 testfile.write("more stuff".getBytes(StandardCharsets.US_ASCII));
224 }
225
226 try (final FileChannel fchannel = new RandomAccessFile(this.tmpfile, "rw").getChannel()) {
227 Assertions.assertThrows(IllegalStateException.class, () -> encoder.transfer(fchannel, 0, 10));
228 }
229 }
230
231 @Test
232 public void testCodingFromFileSmaller() throws Exception {
233 final WritableByteChannelMock channel = new WritableByteChannelMock(64);
234 final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
235 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
236
237 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(
238 channel, outbuf, metrics, 16);
239
240 createTempFile();
241 RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
242 try {
243 testfile.write("stuff;".getBytes(StandardCharsets.US_ASCII));
244 testfile.write("more stuff".getBytes(StandardCharsets.US_ASCII));
245 } finally {
246 testfile.close();
247 }
248
249 testfile = new RandomAccessFile(this.tmpfile, "rw");
250 try {
251 final FileChannel fchannel = testfile.getChannel();
252 encoder.transfer(fchannel, 0, 20);
253 } finally {
254 testfile.close();
255 }
256 final String s = channel.dump(StandardCharsets.US_ASCII);
257
258 Assertions.assertTrue(encoder.isCompleted());
259 Assertions.assertEquals("stuff;more stuff", s);
260 }
261
262 @Test
263 public void testCodingFromFileFlushBuffer() throws Exception {
264 final WritableByteChannelMock channel = new WritableByteChannelMock(64);
265 final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
266 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
267
268 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(
269 channel, outbuf, metrics, 16);
270
271 final CharArrayBuffer chbuffer = new CharArrayBuffer(16);
272 chbuffer.append("header");
273 outbuf.writeLine(chbuffer);
274
275 createTempFile();
276 RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
277 try {
278 testfile.write("stuff;".getBytes(StandardCharsets.US_ASCII));
279 testfile.write("more stuff".getBytes(StandardCharsets.US_ASCII));
280 } finally {
281 testfile.close();
282 }
283
284 testfile = new RandomAccessFile(this.tmpfile, "rw");
285 try {
286 final FileChannel fchannel = testfile.getChannel();
287 encoder.transfer(fchannel, 0, 20);
288 } finally {
289 testfile.close();
290 }
291 final String s = channel.dump(StandardCharsets.US_ASCII);
292
293 Assertions.assertTrue(encoder.isCompleted());
294 Assertions.assertEquals("header\r\nstuff;more stuff", s);
295 }
296
297 @Test
298 public void testCodingFromFileChannelSaturated() throws Exception {
299 final WritableByteChannelMock channel = new WritableByteChannelMock(64, 4);
300 final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 128);
301 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
302
303 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(
304 channel, outbuf, metrics, 16);
305
306 final CharArrayBuffer chbuffer = new CharArrayBuffer(16);
307 chbuffer.append("header");
308 outbuf.writeLine(chbuffer);
309
310 createTempFile();
311 RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
312 try {
313 testfile.write("stuff".getBytes(StandardCharsets.US_ASCII));
314 } finally {
315 testfile.close();
316 }
317
318 testfile = new RandomAccessFile(this.tmpfile, "rw");
319 try {
320 final FileChannel fchannel = testfile.getChannel();
321 encoder.transfer(fchannel, 0, 20);
322 encoder.transfer(fchannel, 0, 20);
323 } finally {
324 testfile.close();
325 }
326 final String s = channel.dump(StandardCharsets.US_ASCII);
327
328 Assertions.assertFalse(encoder.isCompleted());
329 Assertions.assertEquals("head", s);
330 }
331
332 @Test
333 public void testCodingNoFragmentBuffering() throws Exception {
334 final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
335 final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
336 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
337
338 final CharArrayBuffer chbuffer = new CharArrayBuffer(16);
339 chbuffer.append("header");
340 outbuf.writeLine(chbuffer);
341 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(channel, outbuf, metrics,
342 100, 0);
343 Assertions.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
344
345 Mockito.verify(channel, Mockito.times(2)).write(ArgumentMatchers.any());
346 Mockito.verify(outbuf, Mockito.never()).write(ArgumentMatchers.<ByteBuffer>any());
347 Mockito.verify(outbuf, Mockito.times(1)).flush(channel);
348
349 Assertions.assertEquals(13, metrics.getBytesTransferred());
350
351 outbuf.flush(channel);
352 final String s = channel.dump(StandardCharsets.US_ASCII);
353
354 Assertions.assertEquals("header\r\nstuff", s);
355 }
356
357 @Test
358 public void testCodingFragmentBuffering() throws Exception {
359 final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
360 final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
361 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
362
363 final CharArrayBuffer chbuffer = new CharArrayBuffer(16);
364 chbuffer.append("header");
365 outbuf.writeLine(chbuffer);
366 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(channel, outbuf, metrics,
367 100, 32);
368 Assertions.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
369
370 Mockito.verify(channel, Mockito.never()).write(ArgumentMatchers.any());
371 Mockito.verify(outbuf, Mockito.times(1)).write(ArgumentMatchers.<ByteBuffer>any());
372 Mockito.verify(outbuf, Mockito.never()).flush(channel);
373
374 Assertions.assertEquals(0, metrics.getBytesTransferred());
375
376 outbuf.flush(channel);
377 final String s = channel.dump(StandardCharsets.US_ASCII);
378
379 Assertions.assertEquals("header\r\nstuff", s);
380 }
381
382 @Test
383 public void testCodingFragmentBufferingMultipleFragments() throws Exception {
384 final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
385 final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
386 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
387
388 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(channel, outbuf, metrics,
389 100, 32);
390 Assertions.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
391 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
392 Assertions.assertEquals(10, encoder.write(CodecTestUtils.wrap("more stuff")));
393
394 Mockito.verify(channel, Mockito.never()).write(ArgumentMatchers.any());
395 Mockito.verify(outbuf, Mockito.times(3)).write(ArgumentMatchers.<ByteBuffer>any());
396 Mockito.verify(outbuf, Mockito.never()).flush(channel);
397
398 Assertions.assertEquals(0, metrics.getBytesTransferred());
399
400 outbuf.flush(channel);
401 final String s = channel.dump(StandardCharsets.US_ASCII);
402
403 Assertions.assertEquals("stuff-more stuff", s);
404 }
405
406 @Test
407 public void testCodingFragmentBufferingMultipleFragmentsBeyondContentLimit() throws Exception {
408 final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
409 final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
410 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
411
412 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(channel, outbuf, metrics,
413 16, 32);
414 Assertions.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
415 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
416 Assertions.assertEquals(10, encoder.write(CodecTestUtils.wrap("more stuff; and a lot more stuff")));
417
418 Mockito.verify(channel, Mockito.never()).write(ArgumentMatchers.any());
419 Mockito.verify(outbuf, Mockito.times(3)).write(ArgumentMatchers.<ByteBuffer>any());
420 Mockito.verify(outbuf, Mockito.never()).flush(channel);
421
422 Assertions.assertEquals(0, metrics.getBytesTransferred());
423
424 outbuf.flush(channel);
425 final String s = channel.dump(StandardCharsets.US_ASCII);
426
427 Assertions.assertEquals("stuff-more stuff", s);
428 }
429
430 @Test
431 public void testCodingFragmentBufferingLargeFragment() throws Exception {
432 final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
433 final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
434 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
435
436 final CharArrayBuffer chbuffer = new CharArrayBuffer(16);
437 chbuffer.append("header");
438 outbuf.writeLine(chbuffer);
439 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(channel, outbuf, metrics,
440 100, 2);
441 Assertions.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
442
443 Mockito.verify(channel, Mockito.times(2)).write(ArgumentMatchers.any());
444 Mockito.verify(outbuf, Mockito.never()).write(ArgumentMatchers.<ByteBuffer>any());
445 Mockito.verify(outbuf, Mockito.times(1)).flush(channel);
446
447 Assertions.assertEquals(13, metrics.getBytesTransferred());
448
449 outbuf.flush(channel);
450 final String s = channel.dump(StandardCharsets.US_ASCII);
451 Assertions.assertEquals("header\r\nstuff", s);
452 }
453
454 @Test
455 public void testCodingFragmentBufferingTinyFragments() throws Exception {
456 final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
457 final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
458 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
459
460 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(channel, outbuf, metrics,
461 100, 1);
462 Assertions.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
463 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
464 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
465 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
466 Assertions.assertEquals(10, encoder.write(CodecTestUtils.wrap("more stuff")));
467
468 Mockito.verify(channel, Mockito.times(5)).write(ArgumentMatchers.any());
469 Mockito.verify(outbuf, Mockito.times(3)).write(ArgumentMatchers.<ByteBuffer>any());
470 Mockito.verify(outbuf, Mockito.times(3)).flush(channel);
471
472 Assertions.assertEquals(18, metrics.getBytesTransferred());
473
474 outbuf.flush(channel);
475 final String s = channel.dump(StandardCharsets.US_ASCII);
476
477 Assertions.assertEquals("stuff---more stuff", s);
478 }
479
480 @Test
481 public void testCodingFragmentBufferingTinyFragments2() throws Exception {
482 final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
483 final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
484 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
485
486 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(channel, outbuf, metrics,
487 100, 2);
488 Assertions.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
489 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
490 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
491 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
492 Assertions.assertEquals(10, encoder.write(CodecTestUtils.wrap("more stuff")));
493
494 Mockito.verify(channel, Mockito.times(4)).write(ArgumentMatchers.any());
495 Mockito.verify(outbuf, Mockito.times(3)).write(ArgumentMatchers.<ByteBuffer>any());
496 Mockito.verify(outbuf, Mockito.times(2)).flush(channel);
497
498 Assertions.assertEquals(18, metrics.getBytesTransferred());
499
500 outbuf.flush(channel);
501 final String s = channel.dump(StandardCharsets.US_ASCII);
502
503 Assertions.assertEquals("stuff---more stuff", s);
504 }
505
506 @Test
507 public void testCodingFragmentBufferingTinyFragments3() throws Exception {
508 final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
509 final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
510 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
511
512 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(channel, outbuf, metrics,
513 100, 3);
514 Assertions.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
515 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
516 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
517 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
518 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
519 Assertions.assertEquals(2, encoder.write(CodecTestUtils.wrap("--")));
520 Assertions.assertEquals(10, encoder.write(CodecTestUtils.wrap("more stuff")));
521
522 Mockito.verify(channel, Mockito.times(4)).write(ArgumentMatchers.any());
523 Mockito.verify(outbuf, Mockito.times(5)).write(ArgumentMatchers.<ByteBuffer>any());
524 Mockito.verify(outbuf, Mockito.times(2)).flush(channel);
525
526 Assertions.assertEquals(21, metrics.getBytesTransferred());
527
528 outbuf.flush(channel);
529 final String s = channel.dump(StandardCharsets.US_ASCII);
530
531 Assertions.assertEquals("stuff------more stuff", s);
532 }
533
534 @Test
535 public void testCodingFragmentBufferingBufferFlush() throws Exception {
536 final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
537 final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
538 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
539
540 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(channel, outbuf, metrics,
541 100, 8);
542 Assertions.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
543 Assertions.assertEquals(6, encoder.write(CodecTestUtils.wrap("-stuff")));
544
545 Mockito.verify(channel, Mockito.times(1)).write(ArgumentMatchers.any());
546 Mockito.verify(outbuf, Mockito.times(3)).write(ArgumentMatchers.<ByteBuffer>any());
547 Mockito.verify(outbuf, Mockito.times(1)).flush(channel);
548
549 Assertions.assertEquals(8, metrics.getBytesTransferred());
550 Assertions.assertEquals(3, outbuf.length());
551
552 outbuf.flush(channel);
553 final String s = channel.dump(StandardCharsets.US_ASCII);
554
555 Assertions.assertEquals("stuff-stuff", s);
556 }
557
558 @Test
559 public void testCodingFragmentBufferingBufferFlush2() throws Exception {
560 final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64));
561 final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
562 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
563
564 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(channel, outbuf, metrics,
565 100, 8);
566 Assertions.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
567 Assertions.assertEquals(16, encoder.write(CodecTestUtils.wrap("-much more stuff")));
568
569 Mockito.verify(channel, Mockito.times(2)).write(ArgumentMatchers.any());
570 Mockito.verify(outbuf, Mockito.times(1)).write(ArgumentMatchers.<ByteBuffer>any());
571 Mockito.verify(outbuf, Mockito.times(1)).flush(channel);
572
573 Assertions.assertEquals(21, metrics.getBytesTransferred());
574 Assertions.assertEquals(0, outbuf.length());
575
576 outbuf.flush(channel);
577 final String s = channel.dump(StandardCharsets.US_ASCII);
578
579 Assertions.assertEquals("stuff-much more stuff", s);
580 }
581
582 @Test
583 public void testCodingFragmentBufferingChannelSaturated() throws Exception {
584 final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64, 8));
585 final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
586 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
587
588 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(channel, outbuf, metrics,
589 100, 3);
590 Assertions.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
591 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
592 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
593 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
594 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
595 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
596 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
597 Assertions.assertEquals(0, encoder.write(CodecTestUtils.wrap("-")));
598 Assertions.assertEquals(0, encoder.write(CodecTestUtils.wrap("more stuff")));
599
600 Mockito.verify(channel, Mockito.times(5)).write(ArgumentMatchers.any());
601 Mockito.verify(outbuf, Mockito.times(6)).write(ArgumentMatchers.<ByteBuffer>any());
602 Mockito.verify(outbuf, Mockito.times(4)).flush(channel);
603
604 Assertions.assertEquals(8, metrics.getBytesTransferred());
605
606 outbuf.flush(channel);
607 final String s = channel.dump(StandardCharsets.US_ASCII);
608
609 Assertions.assertEquals("stuff---", s);
610 Assertions.assertEquals(3, outbuf.length());
611 }
612
613 @Test
614 public void testCodingFragmentBufferingChannelSaturated2() throws Exception {
615 final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(64, 8));
616 final SessionOutputBuffer outbuf = Mockito.spy(new SessionOutputBufferImpl(1024, 128));
617 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
618
619 final LengthDelimitedEncoder encoder = new LengthDelimitedEncoder(channel, outbuf, metrics,
620 100, 8);
621 Assertions.assertEquals(5, encoder.write(CodecTestUtils.wrap("stuff")));
622 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
623 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("-")));
624 Assertions.assertEquals(1, encoder.write(CodecTestUtils.wrap("much more stuff")));
625
626 Mockito.verify(channel, Mockito.times(3)).write(ArgumentMatchers.any());
627 Mockito.verify(outbuf, Mockito.times(3)).write(ArgumentMatchers.<ByteBuffer>any());
628 Mockito.verify(outbuf, Mockito.times(1)).flush(channel);
629
630 Assertions.assertEquals(8, metrics.getBytesTransferred());
631
632 outbuf.flush(channel);
633 final String s = channel.dump(StandardCharsets.US_ASCII);
634
635 Assertions.assertEquals("stuff--m", s);
636 Assertions.assertEquals(0, outbuf.length());
637 }
638
639 }