Coverage/stress test for a stalled receiver: the application stops draining its receive queue while the peer keeps blasting reliable data, under loss and reorder. This drives a code path almost nothing else in the suite reaches. Simulates an app stall (e.g. loading assets from disk) while the server is blasting reliable state data. The client never calls ReceiveMessagesOnConnection, so its appl
| 1110 | // server keeps advancing its stop_waiting. Layering loss and reorder on the |
| 1111 | // server->client path keeps the gap map churning throughout. |
| 1112 | void Test_recv_buf_full() |
| 1113 | { |
| 1114 | TEST_Printf( "***************************************************\n" ); |
| 1115 | TEST_Printf( "Test: recv buffer full / stalled receiver under loss+reorder\n" ); |
| 1116 | TEST_Printf( "***************************************************\n" ); |
| 1117 | |
| 1118 | // Network loopback so packets go through the full SNP encode/decode path. |
| 1119 | HSteamNetConnection hServer, hClient; |
| 1120 | assert( SteamNetworkingSockets()->CreateSocketPair( &hServer, &hClient, true, nullptr, nullptr ) ); |
| 1121 | SteamNetworkingSockets()->SetConnectionName( hServer, "Server" ); |
| 1122 | SteamNetworkingSockets()->SetConnectionName( hClient, "Client" ); |
| 1123 | |
| 1124 | // Small application receive queue on the client. After this many messages |
| 1125 | // are queued without the app draining them, ReceivedMessage() returns false, |
| 1126 | // which propagates to bInhibitMarkReceived in the SNP decoder. |
| 1127 | SteamNetworkingUtils()->SetConnectionConfigValueInt32( hClient, |
| 1128 | k_ESteamNetworkingConfig_RecvBufferMessages, 32 ); |
| 1129 | |
| 1130 | // Moderate send rate -- enough to fill the queue quickly but not so fast |
| 1131 | // that the service thread starves the client's keepalive sending. |
| 1132 | const int k_nSendRate = 256 * 1024; |
| 1133 | SteamNetworkingUtils()->SetConnectionConfigValueInt32( hServer, |
| 1134 | k_ESteamNetworkingConfig_SendRateMin, k_nSendRate ); |
| 1135 | SteamNetworkingUtils()->SetConnectionConfigValueInt32( hServer, |
| 1136 | k_ESteamNetworkingConfig_SendRateMax, k_nSendRate ); |
| 1137 | |
| 1138 | // Simulate real-world network conditions: packet loss and reordering on |
| 1139 | // the server->client path. This creates non-trivial gap map state on the |
| 1140 | // client before and during the buffer-full condition, which may interact |
| 1141 | // with the stop_waiting/sentinel relationship differently. |
| 1142 | SteamNetworkingUtils()->SetConnectionConfigValueInt32( hClient, |
| 1143 | k_ESteamNetworkingConfig_FakePacketLoss_Recv, 5 ); |
| 1144 | SteamNetworkingUtils()->SetConnectionConfigValueInt32( hClient, |
| 1145 | k_ESteamNetworkingConfig_FakePacketReorder_Recv, 10 ); |
| 1146 | SteamNetworkingUtils()->SetConnectionConfigValueInt32( hClient, |
| 1147 | k_ESteamNetworkingConfig_FakePacketReorder_Time, 20 ); |
| 1148 | |
| 1149 | // Let the connection settle so all handshake traffic is complete and acks |
| 1150 | // have drained before the burst begins. |
| 1151 | for ( int i = 0; i < 20; ++i ) |
| 1152 | { |
| 1153 | TEST_PumpCallbacks(); |
| 1154 | std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) ); |
| 1155 | } |
| 1156 | |
| 1157 | // Queue up a large initial burst of reliable data -- far more than the |
| 1158 | // client's RecvBufferMessages limit. The server drains this at k_nSendRate. |
| 1159 | static const char kData[ 1000 ] = {}; |
| 1160 | int nSent = 0; |
| 1161 | for ( int i = 0; i < 2000; ++i ) |
| 1162 | { |
| 1163 | EResult r = SteamNetworkingSockets()->SendMessageToConnection( |
| 1164 | hServer, kData, sizeof(kData), k_nSteamNetworkingSend_Reliable, nullptr ); |
| 1165 | if ( r == k_EResultOK ) |
| 1166 | ++nSent; |
| 1167 | } |
| 1168 | TEST_Printf( "Queued %d messages (~%d KB) for server to send\n", nSent, nSent * (int)sizeof(kData) / 1024 ); |
| 1169 |
nothing calls this directly
no test coverage detected