@@ -261,7 +261,8 @@ impl SendBuffer {
261261 }
262262
263263 pub ( super ) fn retransmit_all_for_0rtt ( & mut self ) {
264- debug_assert_eq ! ( self . offset( ) , self . data. len( ) as u64 ) ;
264+ // check that we still got all data - we didn't get any acks.
265+ debug_assert_eq ! ( self . data. range( ) . start, 0 ) ;
265266 self . unsent = 0 ;
266267 }
267268
@@ -291,6 +292,10 @@ impl SendBuffer {
291292
292293#[ cfg( test) ]
293294mod tests {
295+ use test_strategy:: { Arbitrary , proptest} ;
296+ use proptest:: prelude:: * ;
297+ use rand:: { SeedableRng , rngs:: StdRng } ;
298+
294299 use super :: * ;
295300
296301 #[ test]
@@ -501,6 +506,80 @@ mod tests {
501506 let mut buf = Vec :: new ( ) ;
502507 data. get_into ( 0 ..1 , & mut buf) ;
503508 }
509+
510+ #[ derive( Debug , Clone , Arbitrary ) ]
511+ enum Op {
512+ // write the given bytes
513+ Write ( #[ strategy( proptest:: collection:: vec( any:: <u8 >( ) , 0 ..1024 ) ) ] Vec < u8 > ) ,
514+ // ack a random range, the value is the rng seed
515+ Ack ( u64 ) ,
516+ // retransmit a random range, the value is the rng seed
517+ Retransmit ( u64 ) ,
518+ // poll_transmit with the given max len
519+ PollTransmit ( #[ strategy( 16usize ..1024 ) ] usize ) ,
520+ }
521+
522+ fn random_range ( seed : u64 , range : Range < u64 > ) -> Range < u64 > {
523+ if range. is_empty ( ) {
524+ return range;
525+ }
526+ let mut rng = StdRng :: seed_from_u64 ( seed) ;
527+ let a = rng. random_range ( range. clone ( ) ) ;
528+ let b = rng. random_range ( range) ;
529+ if a < b { a..b } else { b..a }
530+ }
531+
532+ #[ proptest]
533+ fn send_buffer_matches_reference (
534+ #[ strategy( proptest:: collection:: vec( any:: <Op >( ) , 1 ..100 ) ) ] ops : Vec < Op > ,
535+ ) {
536+ let mut sb = SendBuffer :: new ( ) ;
537+ // total bytes written so far
538+ let mut total_bytes = 0u64 ;
539+ // max offset that has been returned by poll_transmit
540+ let mut max_send_offset = 0u64 ;
541+ // max offset up to which data has been fully acked
542+ let mut max_full_send_offset = 0u64 ;
543+ println ! ( "" ) ;
544+ for op in ops {
545+ match op {
546+ Op :: Write ( data) => {
547+ total_bytes += data. len ( ) as u64 ;
548+ println ! ( "Writing {} bytes" , data. len( ) ) ;
549+ sb. write ( Bytes :: from ( data) ) ;
550+ }
551+ Op :: Ack ( seed) => {
552+ // only generate acks for data that has been sent
553+ let range = random_range ( seed, 0 ..max_send_offset + 1 ) ;
554+ if range. is_empty ( ) {
555+ continue ;
556+ }
557+ // update fully acked range
558+ if range. contains ( & max_full_send_offset) {
559+ max_full_send_offset = range. end ;
560+ }
561+ println ! ( "Acking range: {:?}" , range) ;
562+ sb. ack ( range) ;
563+ }
564+ Op :: Retransmit ( seed) => {
565+ let range = random_range ( seed, max_full_send_offset..max_send_offset + 1 ) ;
566+ if range. is_empty ( ) {
567+ continue ;
568+ }
569+ println ! ( "Retransmitting range: {:?}" , range) ;
570+ sb. retransmit ( range) ;
571+ }
572+ Op :: PollTransmit ( max_len) => {
573+ let ( range, _partial) = sb. poll_transmit ( max_len) ;
574+ max_send_offset = max_send_offset. max ( range. end ) ;
575+ let mut buf = Vec :: new ( ) ;
576+ println ! ( "Getting data for range: {:?}" , range) ;
577+ sb. get_into ( range, & mut buf) ;
578+ }
579+ }
580+
581+ }
582+ }
504583}
505584
506585#[ cfg( feature = "bench" ) ]
0 commit comments