@@ -333,7 +333,7 @@ TEST_F(RoomTest, RemoteParticipantLookupBeforeConnect) {
333333 << " Looking up participant before connect should return an empty handle" ;
334334}
335335
336- TEST_F (RoomTest, ServerDisconnectNotifiesBeforeEosTearsDownRoom ) {
336+ TEST_F (RoomTest, ServerDisconnectMarksDisconnectedBeforeEosTearsDownRoom ) {
337337 Room room;
338338 UnitLifecycleTrackingDelegate delegate;
339339 std::atomic<int > listener_calls{0 };
@@ -348,7 +348,7 @@ TEST_F(RoomTest, ServerDisconnectNotifiesBeforeEosTearsDownRoom) {
348348 emitFfiEvent (disconnected_event);
349349
350350 EXPECT_EQ (listener_calls.load (std::memory_order_relaxed), 1 );
351- EXPECT_EQ (room.connectionState (), ConnectionState::Connected );
351+ EXPECT_EQ (room.connectionState (), ConnectionState::Disconnected );
352352 EXPECT_TRUE (RoomTestAccess::hasRoomHandle (room));
353353 EXPECT_NE (RoomTestAccess::listenerId (room), 0 );
354354 ASSERT_EQ (delegate.callbacks .size (), 1 );
@@ -374,4 +374,31 @@ TEST_F(RoomTest, ServerDisconnectNotifiesBeforeEosTearsDownRoom) {
374374 EXPECT_FALSE (room.disconnect ()) << " disconnect after EOS teardown must be a no-op" ;
375375}
376376
377+ TEST_F (RoomTest, DisconnectAfterServerDisconnectCleansUpWithoutDuplicateNotification) {
378+ Room room;
379+ UnitLifecycleTrackingDelegate delegate;
380+ std::atomic<int > listener_calls{0 };
381+ room.setDelegate (&delegate);
382+ RoomTestAccess::installConnectedListener (room, listener_calls);
383+
384+ proto::FfiEvent disconnected_event;
385+ auto * disconnected_room_event = disconnected_event.mutable_room_event ();
386+ disconnected_room_event->set_room_handle (0 );
387+ disconnected_room_event->mutable_disconnected ()->set_reason (proto::ROOM_DELETED );
388+
389+ emitFfiEvent (disconnected_event);
390+
391+ ASSERT_EQ (delegate.callbacks .size (), 1 );
392+ EXPECT_EQ (delegate.callbacks [0 ], LifecycleCallback::Disconnected);
393+ EXPECT_EQ (delegate.reason , DisconnectReason::RoomDeleted);
394+ EXPECT_EQ (room.connectionState (), ConnectionState::Disconnected);
395+ EXPECT_TRUE (RoomTestAccess::hasRoomHandle (room));
396+
397+ EXPECT_FALSE (room.disconnect ()) << " disconnect must not reclaim an already-disconnected transition" ;
398+ EXPECT_EQ (room.connectionState (), ConnectionState::Disconnected);
399+ EXPECT_FALSE (RoomTestAccess::hasRoomHandle (room));
400+ EXPECT_EQ (RoomTestAccess::listenerId (room), 0 );
401+ EXPECT_EQ (delegate.callbacks .size (), 1 ) << " onDisconnected must not fire twice" ;
402+ }
403+
377404} // namespace livekit::test
0 commit comments