@@ -438,6 +438,107 @@ def before
438438 expect ( write_buffer ) . to be ( :empty? )
439439 end
440440 end
441+
442+ with "#discard_until" do
443+ it "can discard data until pattern" do
444+ server . write ( "hello\n world\n test" )
445+ server . close
446+
447+ # Discard until "\n" - should return chunk ending with the pattern
448+ chunk = client . discard_until ( "\n " )
449+ expect ( chunk ) . not . to be_nil
450+ expect ( chunk ) . to be ( :end_with? , "\n " )
451+ # Read the remaining data to verify it starts with "world"
452+ expect ( client . read ( 5 ) ) . to be == "world"
453+
454+ # Discard until "t" - should return chunk ending with the pattern
455+ chunk = client . discard_until ( "t" )
456+ expect ( chunk ) . not . to be_nil
457+ expect ( chunk ) . to be ( :end_with? , "t" )
458+ # Read remaining data
459+ expect ( client . read ) . to be == "est"
460+ end
461+
462+ it "returns nil when pattern not found and discards all data" do
463+ server . write ( "hello world" )
464+ server . close
465+
466+ expect ( client . discard_until ( "\n " ) ) . to be_nil
467+ # Data should still be available since pattern was not found
468+ expect ( client . read ) . to be == "hello world"
469+ end
470+
471+ it "can discard with a limit" do
472+ server . write ( "hello\n world\n " )
473+ server . close
474+
475+ # Use peek to verify initial buffer state
476+ expect ( client . peek ) . to be == "hello\n world\n "
477+
478+ # Limit too small to find pattern - discards up to limit
479+ expect ( client . discard_until ( "\n " , limit : 4 ) ) . to be_nil
480+
481+ # Use peek to verify that 4 bytes were discarded
482+ expect ( client . peek ) . to be == "o\n world\n "
483+
484+ # After discarding 4 bytes, should find pattern in remaining data
485+ chunk = client . discard_until ( "\n " , limit : 5 )
486+ expect ( chunk ) . not . to be_nil
487+ expect ( chunk ) . to be ( :end_with? , "\n " )
488+
489+ # Use peek to verify final buffer state
490+ expect ( client . peek ) . to be == "world\n "
491+ expect ( client . read ) . to be == "world\n "
492+ end
493+
494+ it "handles patterns spanning buffer boundaries" do
495+ # Use a small block size to force the pattern to span boundaries
496+ client . block_size = 3
497+
498+ server . write ( "ab" )
499+ server . flush
500+ server . write ( "cdef" )
501+ server . close
502+
503+ # Pattern "cd" spans the boundary between "ab" and "cdef"
504+ chunk = client . discard_until ( "cd" )
505+ expect ( chunk ) . not . to be_nil
506+ expect ( chunk ) . to be ( :end_with? , "cd" )
507+ expect ( client . read ) . to be == "ef"
508+ end
509+
510+ it "handles large patterns efficiently" do
511+ large_pattern = "X" * 20 # Trigger sliding window logic
512+ server . write ( "some data before" )
513+ server . write ( large_pattern )
514+ server . write ( "some data after" )
515+ server . close
516+
517+ chunk = client . discard_until ( large_pattern )
518+ expect ( chunk ) . not . to be_nil
519+ expect ( chunk ) . to be ( :end_with? , large_pattern )
520+ expect ( client . read ) . to be == "some data after"
521+ end
522+
523+ with "with 1-byte block size" do
524+ it "can discard data with a multi-byte pattern" do
525+ server . write ( "hello\n world\n " )
526+ server . close
527+
528+ client . block_size = 1
529+
530+ chunk1 = client . discard_until ( "\n " )
531+ expect ( chunk1 ) . not . to be_nil
532+ expect ( chunk1 ) . to be ( :end_with? , "\n " )
533+
534+ chunk2 = client . discard_until ( "\n " )
535+ expect ( chunk2 ) . not . to be_nil
536+ expect ( chunk2 ) . to be ( :end_with? , "\n " )
537+
538+ expect ( client . discard_until ( "\n " ) ) . to be_nil
539+ end
540+ end
541+ end
441542end
442543
443544ABidirectionalStream = Sus ::Shared ( "a bidirectional stream" ) do
0 commit comments