@@ -848,4 +848,98 @@ TEST_F(RpcStressTest, HighThroughputBurst) {
848848 receiver_room.reset ();
849849}
850850
851+ // Long-running soak test: sends a mix of payload sizes for approximately one
852+ // minute and verifies every call is received. Moved out of the integration
853+ // suite so it does not run on every PR CI invocation.
854+ TEST_F (RpcStressTest, OneMinuteIntegration) {
855+ skipIfNotConfigured ();
856+
857+ auto receiver_room = std::make_unique<Room>();
858+ RoomOptions options;
859+ options.auto_subscribe = true ;
860+
861+ ASSERT_TRUE (receiver_room->connect (config_.url , config_.token_b , options)) << " Receiver failed to connect" ;
862+
863+ std::string receiver_identity = lockLocalParticipant (*receiver_room)->identity ();
864+
865+ std::atomic<int > total_received{0 };
866+ std::atomic<size_t > total_bytes_received{0 };
867+
868+ lockLocalParticipant (*receiver_room)
869+ ->registerRpcMethod (" integration-test" , [&](const RpcInvocationData& data) -> std::optional<std::string> {
870+ total_received++;
871+ total_bytes_received += data.payload .size ();
872+ return " ack:" + std::to_string (data.payload .size ());
873+ });
874+
875+ auto caller_room = std::make_unique<Room>();
876+ ASSERT_TRUE (caller_room->connect (config_.url , config_.token_a , options)) << " Caller failed to connect" ;
877+
878+ bool receiver_visible = waitForParticipant (caller_room.get (), receiver_identity, 10s);
879+ ASSERT_TRUE (receiver_visible) << " Receiver not visible to caller" ;
880+
881+ // Hold the local participant alive for the duration of the sender thread so
882+ // it cannot expire mid-call while RPCs are in flight.
883+ ASSERT_NO_THROW (lockLocalParticipant (*caller_room));
884+
885+ // Run for 1 minute
886+ const auto test_duration = 60s;
887+ const auto start_time = std::chrono::steady_clock::now ();
888+
889+ std::atomic<int > total_sent{0 };
890+ std::atomic<int > successful_calls{0 };
891+ std::atomic<int > failed_calls{0 };
892+ std::atomic<bool > running{true };
893+
894+ // Sender thread
895+ std::thread sender ([&]() {
896+ std::vector<size_t > payload_sizes = {100 , 1024 , 5 * 1024 , 10 * 1024 , kMaxRpcPayloadSize };
897+ int size_index = 0 ;
898+
899+ while (running.load ()) {
900+ size_t payload_size = payload_sizes[size_index % payload_sizes.size ()];
901+ std::string payload = generateRandomPayload (payload_size);
902+
903+ try {
904+ auto caller_lp = lockLocalParticipant (*caller_room);
905+ ASSERT_NE (caller_lp, nullptr );
906+ std::string response = caller_lp->performRpc (receiver_identity, " integration-test" , payload, 30.0 );
907+ if (response == " ack:" + std::to_string (payload_size)) {
908+ successful_calls++;
909+ }
910+ } catch (const std::exception& e) {
911+ failed_calls++;
912+ }
913+
914+ total_sent++;
915+ size_index++;
916+ std::this_thread::sleep_for (100ms); // Rate limit
917+ }
918+ });
919+
920+ // Wait for test duration
921+ while (std::chrono::steady_clock::now () - start_time < test_duration) {
922+ std::this_thread::sleep_for (1s);
923+ std::cout << " Progress: sent=" << total_sent.load () << " successful=" << successful_calls.load ()
924+ << " failed=" << failed_calls.load () << " received=" << total_received.load () << std::endl;
925+ }
926+
927+ running.store (false );
928+ sender.join ();
929+
930+ std::cout << " \n === Integration Test Results (1 minute) ===" << std::endl;
931+ std::cout << " Total sent: " << total_sent.load () << std::endl;
932+ std::cout << " Successful: " << successful_calls.load () << std::endl;
933+ std::cout << " Failed: " << failed_calls.load () << std::endl;
934+ std::cout << " Total received: " << total_received.load () << std::endl;
935+ std::cout << " Total bytes received: " << total_bytes_received.load () << std::endl;
936+
937+ EXPECT_GT (successful_calls.load (), 0 );
938+ EXPECT_EQ (total_sent.load (), total_received.load ());
939+
940+ lockLocalParticipant (*receiver_room)->unregisterRpcMethod (" integration-test" );
941+ caller_room.reset ();
942+ receiver_room.reset ();
943+ }
944+
851945} // namespace livekit::test
0 commit comments