@@ -1274,6 +1274,88 @@ TEST_F(CubicTest, GetNetworkStatistics_RetrieveStats)
12741274 ASSERT_EQ (NetworkStats.IdealBytes , 0u );
12751275}
12761276
1277+ //
1278+ // Test: GetNetworkStatistics - Zero SmoothedRtt returns zero Bandwidth
1279+ // Scenario: Verifies no division-by-zero occurs when SmoothedRtt is 0 at the
1280+ // time GetNetworkStatistics is called (e.g. before the first RTT sample).
1281+ // Bandwidth must be reported as 0 rather than crashing.
1282+ //
1283+ TEST_F (CubicTest, GetNetworkStatistics_ZeroSmoothedRtt_BandwidthIsZero)
1284+ {
1285+ // Initialize without an RTT sample so SmoothedRtt stays 0.
1286+ InitializeWithDefaults (
1287+ /* WindowPackets=*/ 10 ,
1288+ /* HyStart=*/ false ,
1289+ /* Mtu=*/ 1280 ,
1290+ /* IdleTimeoutMs=*/ 1000 ,
1291+ /* GotRttSample=*/ false
1292+ );
1293+
1294+ ASSERT_EQ (Connection.Paths [0 ].SmoothedRtt , 0u );
1295+
1296+ CC->QuicCongestionControlOnDataSent (CC, 5000 );
1297+
1298+ QUIC_NETWORK_STATISTICS NetworkStats;
1299+ CxPlatZeroMemory (&NetworkStats, sizeof (NetworkStats));
1300+
1301+ // Must not crash with divide-by-zero when SmoothedRtt == 0.
1302+ CC->QuicCongestionControlGetNetworkStatistics (&Connection, CC, &NetworkStats);
1303+
1304+ ASSERT_EQ (NetworkStats.Bandwidth , 0u );
1305+ ASSERT_EQ (NetworkStats.SmoothedRTT , 0u );
1306+ ASSERT_EQ (NetworkStats.CongestionWindow , Cubic->CongestionWindow );
1307+ }
1308+
1309+ //
1310+ // Test: OnDataAcknowledged NetStats path - Zero SmoothedRtt returns zero Bandwidth
1311+ // Scenario: Verifies no division-by-zero occurs inside the NetStatsEventEnabled
1312+ // path of OnDataAcknowledged when an ACK arrives before the first RTT sample
1313+ // (SmoothedRtt == 0). The NETWORK_STATISTICS event must fire without crashing.
1314+ //
1315+ static QUIC_STATUS
1316+ QUIC_API
1317+ NetStatsDummyCallback (
1318+ _In_ HQUIC /* Connection */ ,
1319+ _In_opt_ void * /* Context */ ,
1320+ _Inout_ QUIC_CONNECTION_EVENT* /* Event */ )
1321+ {
1322+ return QUIC_STATUS_SUCCESS;
1323+ }
1324+
1325+ TEST_F (CubicTest, OnDataAcknowledged_NetStats_ZeroSmoothedRtt_BandwidthIsZero)
1326+ {
1327+ // Initialize without an RTT sample so SmoothedRtt stays 0.
1328+ InitializeWithDefaults (
1329+ /* WindowPackets=*/ 10 ,
1330+ /* HyStart=*/ false ,
1331+ /* Mtu=*/ 1280 ,
1332+ /* IdleTimeoutMs=*/ 1000 ,
1333+ /* GotRttSample=*/ false
1334+ );
1335+
1336+ // Enable the NetStats event path and supply a no-op callback so
1337+ // QuicConnIndicateEvent does not dereference a null function pointer.
1338+ Connection.Settings .NetStatsEventEnabled = TRUE ;
1339+ Connection.ClientCallbackHandler = NetStatsDummyCallback;
1340+
1341+ ASSERT_EQ (Connection.Paths [0 ].SmoothedRtt , 0u );
1342+
1343+ Cubic->BytesInFlight = 5000 ;
1344+
1345+ // Construct an ACK event with SmoothedRtt == 0 (no RTT sample yet).
1346+ QUIC_ACK_EVENT AckEvent = MakeAckEvent (
1347+ /* TimeNow=*/ 1000000 ,
1348+ /* LargestAck=*/ 5 ,
1349+ /* LargestSentPacketNumber=*/ 10 ,
1350+ /* BytesAcked=*/ 1000 ,
1351+ /* SmoothedRtt=*/ 0 ,
1352+ /* MinRtt=*/ 0 ,
1353+ /* MinRttValid=*/ FALSE );
1354+
1355+ // Must not crash with STATUS_INTEGER_DIVIDE_BY_ZERO.
1356+ CC->QuicCongestionControlOnDataAcknowledged (CC, &AckEvent);
1357+ }
1358+
12771359//
12781360// Test: Spurious Congestion Event - No-Op When Not In Recovery
12791361// Scenario: Verifies OnSpuriousCongestionEvent returns FALSE with no state change
0 commit comments