github.com/daeuniverse/quic-go@v0.0.0-20240413031024-943f218e0810/internal/utils/rtt_stats_test.go (about)

     1  package utils
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/daeuniverse/quic-go/internal/protocol"
     7  
     8  	. "github.com/onsi/ginkgo/v2"
     9  	. "github.com/onsi/gomega"
    10  )
    11  
    12  var _ = Describe("RTT stats", func() {
    13  	var rttStats *RTTStats
    14  
    15  	BeforeEach(func() {
    16  		rttStats = NewRTTStats()
    17  	})
    18  
    19  	It("DefaultsBeforeUpdate", func() {
    20  		Expect(rttStats.MinRTT()).To(Equal(time.Duration(0)))
    21  		Expect(rttStats.SmoothedRTT()).To(Equal(time.Duration(0)))
    22  	})
    23  
    24  	It("SmoothedRTT", func() {
    25  		// Verify that ack_delay is ignored in the first measurement.
    26  		rttStats.UpdateRTT((300 * time.Millisecond), (100 * time.Millisecond), time.Time{})
    27  		Expect(rttStats.LatestRTT()).To(Equal((300 * time.Millisecond)))
    28  		Expect(rttStats.SmoothedRTT()).To(Equal((300 * time.Millisecond)))
    29  		// Verify that Smoothed RTT includes max ack delay if it's reasonable.
    30  		rttStats.UpdateRTT((350 * time.Millisecond), (50 * time.Millisecond), time.Time{})
    31  		Expect(rttStats.LatestRTT()).To(Equal((300 * time.Millisecond)))
    32  		Expect(rttStats.SmoothedRTT()).To(Equal((300 * time.Millisecond)))
    33  		// Verify that large erroneous ack_delay does not change Smoothed RTT.
    34  		rttStats.UpdateRTT((200 * time.Millisecond), (300 * time.Millisecond), time.Time{})
    35  		Expect(rttStats.LatestRTT()).To(Equal((200 * time.Millisecond)))
    36  		Expect(rttStats.SmoothedRTT()).To(Equal((287500 * time.Microsecond)))
    37  	})
    38  
    39  	It("MinRTT", func() {
    40  		rttStats.UpdateRTT((200 * time.Millisecond), 0, time.Time{})
    41  		Expect(rttStats.MinRTT()).To(Equal((200 * time.Millisecond)))
    42  		rttStats.UpdateRTT((10 * time.Millisecond), 0, time.Time{}.Add((10 * time.Millisecond)))
    43  		Expect(rttStats.MinRTT()).To(Equal((10 * time.Millisecond)))
    44  		rttStats.UpdateRTT((50 * time.Millisecond), 0, time.Time{}.Add((20 * time.Millisecond)))
    45  		Expect(rttStats.MinRTT()).To(Equal((10 * time.Millisecond)))
    46  		rttStats.UpdateRTT((50 * time.Millisecond), 0, time.Time{}.Add((30 * time.Millisecond)))
    47  		Expect(rttStats.MinRTT()).To(Equal((10 * time.Millisecond)))
    48  		rttStats.UpdateRTT((50 * time.Millisecond), 0, time.Time{}.Add((40 * time.Millisecond)))
    49  		Expect(rttStats.MinRTT()).To(Equal((10 * time.Millisecond)))
    50  		// Verify that ack_delay does not go into recording of MinRTT_.
    51  		rttStats.UpdateRTT((7 * time.Millisecond), (2 * time.Millisecond), time.Time{}.Add((50 * time.Millisecond)))
    52  		Expect(rttStats.MinRTT()).To(Equal((7 * time.Millisecond)))
    53  	})
    54  
    55  	It("MaxAckDelay", func() {
    56  		rttStats.SetMaxAckDelay(42 * time.Minute)
    57  		Expect(rttStats.MaxAckDelay()).To(Equal(42 * time.Minute))
    58  	})
    59  
    60  	It("computes the PTO", func() {
    61  		maxAckDelay := 42 * time.Minute
    62  		rttStats.SetMaxAckDelay(maxAckDelay)
    63  		rtt := time.Second
    64  		rttStats.UpdateRTT(rtt, 0, time.Time{})
    65  		Expect(rttStats.SmoothedRTT()).To(Equal(rtt))
    66  		Expect(rttStats.MeanDeviation()).To(Equal(rtt / 2))
    67  		Expect(rttStats.PTO(false)).To(Equal(rtt + 4*(rtt/2)))
    68  		Expect(rttStats.PTO(true)).To(Equal(rtt + 4*(rtt/2) + maxAckDelay))
    69  	})
    70  
    71  	It("uses the granularity for computing the PTO for short RTTs", func() {
    72  		rtt := time.Microsecond
    73  		rttStats.UpdateRTT(rtt, 0, time.Time{})
    74  		Expect(rttStats.PTO(true)).To(Equal(rtt + protocol.TimerGranularity))
    75  	})
    76  
    77  	It("ExpireSmoothedMetrics", func() {
    78  		initialRtt := (10 * time.Millisecond)
    79  		rttStats.UpdateRTT(initialRtt, 0, time.Time{})
    80  		Expect(rttStats.MinRTT()).To(Equal(initialRtt))
    81  		Expect(rttStats.SmoothedRTT()).To(Equal(initialRtt))
    82  
    83  		Expect(rttStats.MeanDeviation()).To(Equal(initialRtt / 2))
    84  
    85  		// Update once with a 20ms RTT.
    86  		doubledRtt := initialRtt * (2)
    87  		rttStats.UpdateRTT(doubledRtt, 0, time.Time{})
    88  		Expect(rttStats.SmoothedRTT()).To(Equal(time.Duration(float32(initialRtt) * 1.125)))
    89  
    90  		// Expire the smoothed metrics, increasing smoothed rtt and mean deviation.
    91  		rttStats.ExpireSmoothedMetrics()
    92  		Expect(rttStats.SmoothedRTT()).To(Equal(doubledRtt))
    93  		Expect(rttStats.MeanDeviation()).To(Equal(time.Duration(float32(initialRtt) * 0.875)))
    94  
    95  		// Now go back down to 5ms and expire the smoothed metrics, and ensure the
    96  		// mean deviation increases to 15ms.
    97  		halfRtt := initialRtt / 2
    98  		rttStats.UpdateRTT(halfRtt, 0, time.Time{})
    99  		Expect(doubledRtt).To(BeNumerically(">", rttStats.SmoothedRTT()))
   100  		Expect(initialRtt).To(BeNumerically("<", rttStats.MeanDeviation()))
   101  	})
   102  
   103  	It("UpdateRTTWithBadSendDeltas", func() {
   104  		// Make sure we ignore bad RTTs.
   105  		// base::test::MockLog log;
   106  
   107  		initialRtt := (10 * time.Millisecond)
   108  		rttStats.UpdateRTT(initialRtt, 0, time.Time{})
   109  		Expect(rttStats.MinRTT()).To(Equal(initialRtt))
   110  		Expect(rttStats.SmoothedRTT()).To(Equal(initialRtt))
   111  
   112  		badSendDeltas := []time.Duration{
   113  			0,
   114  			InfDuration,
   115  			-1000 * time.Microsecond,
   116  		}
   117  		// log.StartCapturingLogs();
   118  
   119  		for _, badSendDelta := range badSendDeltas {
   120  			// SCOPED_TRACE(Message() << "bad_send_delta = "
   121  			//  << bad_send_delta.ToMicroseconds());
   122  			// EXPECT_CALL(log, Log(LOG_WARNING, _, _, _, HasSubstr("Ignoring")));
   123  			rttStats.UpdateRTT(badSendDelta, 0, time.Time{})
   124  			Expect(rttStats.MinRTT()).To(Equal(initialRtt))
   125  			Expect(rttStats.SmoothedRTT()).To(Equal(initialRtt))
   126  		}
   127  	})
   128  
   129  	It("ResetAfterConnectionMigrations", func() {
   130  		rttStats.UpdateRTT(200*time.Millisecond, 0, time.Time{})
   131  		Expect(rttStats.LatestRTT()).To(Equal((200 * time.Millisecond)))
   132  		Expect(rttStats.SmoothedRTT()).To(Equal((200 * time.Millisecond)))
   133  		Expect(rttStats.MinRTT()).To(Equal((200 * time.Millisecond)))
   134  		rttStats.UpdateRTT((300 * time.Millisecond), (100 * time.Millisecond), time.Time{})
   135  		Expect(rttStats.LatestRTT()).To(Equal((200 * time.Millisecond)))
   136  		Expect(rttStats.SmoothedRTT()).To(Equal((200 * time.Millisecond)))
   137  		Expect(rttStats.MinRTT()).To(Equal((200 * time.Millisecond)))
   138  
   139  		// Reset rtt stats on connection migrations.
   140  		rttStats.OnConnectionMigration()
   141  		Expect(rttStats.LatestRTT()).To(Equal(time.Duration(0)))
   142  		Expect(rttStats.SmoothedRTT()).To(Equal(time.Duration(0)))
   143  		Expect(rttStats.MinRTT()).To(Equal(time.Duration(0)))
   144  	})
   145  
   146  	It("restores the RTT", func() {
   147  		rttStats.SetInitialRTT(10 * time.Second)
   148  		Expect(rttStats.LatestRTT()).To(Equal(10 * time.Second))
   149  		Expect(rttStats.SmoothedRTT()).To(Equal(10 * time.Second))
   150  		Expect(rttStats.MeanDeviation()).To(BeZero())
   151  		// update the RTT and make sure that the initial value is immediately forgotten
   152  		rttStats.UpdateRTT(200*time.Millisecond, 0, time.Time{})
   153  		Expect(rttStats.LatestRTT()).To(Equal(200 * time.Millisecond))
   154  		Expect(rttStats.SmoothedRTT()).To(Equal(200 * time.Millisecond))
   155  		Expect(rttStats.MeanDeviation()).To(Equal(100 * time.Millisecond))
   156  	})
   157  
   158  	It("doesn't restore the RTT if we already have a measurement", func() {
   159  		const rtt = 10 * time.Millisecond
   160  		rttStats.UpdateRTT(rtt, 0, time.Now())
   161  		Expect(rttStats.LatestRTT()).To(Equal(rtt))
   162  		Expect(rttStats.SmoothedRTT()).To(Equal(rtt))
   163  		rttStats.SetInitialRTT(time.Minute)
   164  		Expect(rttStats.LatestRTT()).To(Equal(rtt))
   165  		Expect(rttStats.SmoothedRTT()).To(Equal(rtt))
   166  	})
   167  })