@@ -287,4 +287,174 @@ private void splitAndAdd(String value) {
287287
288288 assertEquals (value .length (), composite .readableBytes ());
289289 }
290+
291+ @ Test
292+ public void coalesceOnMaxSmallBuffers () {
293+ composite = new CompositeReadableBuffer ();
294+ // 1000 1-byte buffers
295+ for (int i = 0 ; i < 1000 ; i ++) {
296+ composite .addBuffer (ReadableBuffers .wrap (new byte [] {1 }));
297+ }
298+ assertEquals (1 , composite .getBufferCount ());
299+ assertEquals (1000 , composite .readableBytes ());
300+ }
301+
302+ @ Test
303+ public void coalesceBeyondMaxSmallBuffers () {
304+ composite = new CompositeReadableBuffer ();
305+ // 1001 1-byte buffers
306+ for (int i = 0 ; i < 1001 ; i ++) {
307+ composite .addBuffer (ReadableBuffers .wrap (new byte [] {1 }));
308+ }
309+ assertEquals (2 , composite .getBufferCount ());
310+ assertEquals (1001 , composite .readableBytes ());
311+ }
312+
313+ @ Test
314+ public void coalesceMultipleBatchesOfSmallBuffers () {
315+ composite = new CompositeReadableBuffer ();
316+ // 2000 1-byte buffers
317+ for (int i = 0 ; i < 2000 ; i ++) {
318+ composite .addBuffer (ReadableBuffers .wrap (new byte [] {1 }));
319+ }
320+ assertEquals (2 , composite .getBufferCount ());
321+ assertEquals (2000 , composite .readableBytes ());
322+ }
323+
324+ @ Test
325+ public void coalesceBeforeLargeBuffer () {
326+ composite = new CompositeReadableBuffer ();
327+ // 500 small frames
328+ for (int i = 0 ; i < 500 ; i ++) {
329+ composite .addBuffer (ReadableBuffers .wrap (new byte [] {1 }));
330+ }
331+ // 1 large frame
332+ composite .addBuffer (ReadableBuffers .wrap (new byte [1024 ]));
333+
334+ // The 500 small frames should be coalesced into 1, followed by the 1 large frame
335+ assertEquals (2 , composite .getBufferCount ());
336+ assertEquals (1524 , composite .readableBytes ());
337+ }
338+
339+ @ Test
340+ public void largeBufferResetsTailSmallBufferCount () {
341+ composite = new CompositeReadableBuffer ();
342+ // Add 1 large buffer
343+ composite .addBuffer (ReadableBuffers .wrap (new byte [1024 ]));
344+ assertEquals (1 , composite .getBufferCount ());
345+
346+ // Add 999 small buffers right after the large buffer (leaving total small tail at 999)
347+ for (int i = 0 ; i < 999 ; i ++) {
348+ composite .addBuffer (ReadableBuffers .wrap (new byte [] {1 }));
349+ }
350+
351+ // Since only 999 small buffers are at the tail right after the large buffer,
352+ // they must NOT be coalesced yet. Total buffers in queue should be 1 + 999 = 1000.
353+ assertEquals (1000 , composite .getBufferCount ());
354+ assertEquals (1024 + 999 , composite .readableBytes ());
355+ }
356+
357+ @ Test
358+ public void noCoalesceOnLargeFrames () {
359+ composite = new CompositeReadableBuffer ();
360+ // 1001 1024-byte frames
361+ for (int i = 0 ; i < 1001 ; i ++) {
362+ composite .addBuffer (ReadableBuffers .wrap (new byte [1024 ]));
363+ }
364+ assertEquals (1001 , composite .getBufferCount ());
365+ assertEquals (1001 * 1024 , composite .readableBytes ());
366+ }
367+
368+ @ Test
369+ public void skipCoalesceIfMarked () {
370+ composite = new CompositeReadableBuffer ();
371+ composite .addBuffer (ReadableBuffers .wrap (new byte [] {1 }));
372+ composite .mark ();
373+
374+ // Add 1000 more 1-byte buffers, reaching 1001 total
375+ for (int i = 0 ; i < 1000 ; i ++) {
376+ composite .addBuffer (ReadableBuffers .wrap (new byte [] {1 }));
377+ }
378+
379+ // Should skip coalescing due to marked=true
380+ assertEquals (1001 , composite .getBufferCount ());
381+ assertEquals (1001 , composite .readableBytes ());
382+ }
383+
384+ @ Test
385+ public void readBytesAdjustsTailSmallBufferCount () {
386+ composite = new CompositeReadableBuffer ();
387+ // Add 500 1-byte buffers
388+ for (int i = 0 ; i < 500 ; i ++) {
389+ composite .addBuffer (ReadableBuffers .wrap (new byte [] {1 }));
390+ }
391+ // Read 200 buffers via readBytes(int) without mark
392+ ReadableBuffer read = composite .readBytes (200 );
393+ read .close ();
394+
395+ // Now add 500 more 1-byte buffers
396+ for (int i = 0 ; i < 500 ; i ++) {
397+ composite .addBuffer (ReadableBuffers .wrap (new byte [] {1 }));
398+ }
399+ assertEquals (800 , composite .getBufferCount ());
400+ assertEquals (800 , composite .readableBytes ());
401+ }
402+
403+ @ Test
404+ public void advanceBufferAdjustsTailSmallBufferCount () {
405+ composite = new CompositeReadableBuffer ();
406+ // Add 500 1-byte buffers
407+ for (int i = 0 ; i < 500 ; i ++) {
408+ composite .addBuffer (ReadableBuffers .wrap (new byte [] {1 }));
409+ }
410+ // Read 200 buffers via skipBytes (which calls advanceBuffer)
411+ composite .skipBytes (200 );
412+
413+ // Now add 500 more 1-byte buffers
414+ for (int i = 0 ; i < 500 ; i ++) {
415+ composite .addBuffer (ReadableBuffers .wrap (new byte [] {1 }));
416+ }
417+ assertEquals (800 , composite .getBufferCount ());
418+ assertEquals (800 , composite .readableBytes ());
419+ }
420+
421+ @ Test
422+ public void coalesceClosesCoalescedBuffers () {
423+ composite = new CompositeReadableBuffer ();
424+ ReadableBuffer mock1 = mock (ReadableBuffer .class );
425+ when (mock1 .readableBytes ()).thenReturn (1 );
426+ ReadableBuffer mock2 = mock (ReadableBuffer .class );
427+ when (mock2 .readableBytes ()).thenReturn (1 );
428+ composite .addBuffer (mock1 );
429+ composite .addBuffer (mock2 );
430+
431+ // Large buffer triggers coalesce of mock1 and mock2 around line 76
432+ composite .addBuffer (ReadableBuffers .wrap (new byte [1024 ]));
433+
434+ verify (mock1 ).close ();
435+ verify (mock2 ).close ();
436+ }
437+
438+ @ Test
439+ public void closeResetsTailSmallBufferCount () {
440+ composite = new CompositeReadableBuffer ();
441+ // Add 500 small buffers
442+ for (int i = 0 ; i < 500 ; i ++) {
443+ composite .addBuffer (ReadableBuffers .wrap (new byte [] {1 }));
444+ }
445+ composite .close ();
446+ assertEquals (0 , composite .getBufferCount ());
447+
448+ // After close(), tailSmallBufferCount should be exactly 0.
449+ // Adding 999 (MAX_SMALL_BUFFERS - 1) small buffers right after close should NOT trigger
450+ // coalescing, resulting in exactly 999 buffers.
451+ for (int i = 0 ; i < 999 ; i ++) {
452+ composite .addBuffer (ReadableBuffers .wrap (new byte [] {1 }));
453+ }
454+ assertEquals (999 , composite .getBufferCount ());
455+
456+ // Adding the 1000th small buffer should trigger coalescing down to 1 buffer.
457+ composite .addBuffer (ReadableBuffers .wrap (new byte [] {1 }));
458+ assertEquals (1 , composite .getBufferCount ());
459+ }
290460}
0 commit comments