104 lines · cpp
1//===-- DAPSessionManagerTest.cpp ----------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "DAPSessionManager.h"10#include "TestBase.h"11#include "lldb/API/SBDebugger.h"12#include "gmock/gmock.h"13#include "gtest/gtest.h"14 15using namespace lldb_dap;16using namespace lldb;17using namespace lldb_dap_tests;18 19class DAPSessionManagerTest : public DAPTestBase {};20 21TEST_F(DAPSessionManagerTest, GetInstanceReturnsSameSingleton) {22 DAPSessionManager &instance1 = DAPSessionManager::GetInstance();23 DAPSessionManager &instance2 = DAPSessionManager::GetInstance();24 25 EXPECT_EQ(&instance1, &instance2);26}27 28// UnregisterSession uses std::notify_all_at_thread_exit, so it must be called29// from a separate thread to properly release the mutex on thread exit.30TEST_F(DAPSessionManagerTest, RegisterAndUnregisterSession) {31 DAPSessionManager &manager = DAPSessionManager::GetInstance();32 33 // Initially not registered.34 std::vector<DAP *> sessions_before = manager.GetActiveSessions();35 EXPECT_EQ(36 std::count(sessions_before.begin(), sessions_before.end(), dap.get()), 0);37 38 manager.RegisterSession(&loop, dap.get());39 40 // Should be in active sessions after registration.41 std::vector<DAP *> sessions_after = manager.GetActiveSessions();42 EXPECT_EQ(std::count(sessions_after.begin(), sessions_after.end(), dap.get()),43 1);44 45 // Unregister.46 std::thread unregister_thread([&]() { manager.UnregisterSession(&loop); });47 48 unregister_thread.join();49 50 // There should no longer be active sessions.51 std::vector<DAP *> sessions_final = manager.GetActiveSessions();52 EXPECT_EQ(std::count(sessions_final.begin(), sessions_final.end(), dap.get()),53 0);54}55 56TEST_F(DAPSessionManagerTest, DisconnectAllSessions) {57 DAPSessionManager &manager = DAPSessionManager::GetInstance();58 59 manager.RegisterSession(&loop, dap.get());60 61 std::vector<DAP *> sessions = manager.GetActiveSessions();62 EXPECT_EQ(std::count(sessions.begin(), sessions.end(), dap.get()), 1);63 64 manager.DisconnectAllSessions();65 66 // DisconnectAllSessions shutdown but doesn't wait for67 // sessions to complete or remove them from the active sessions map.68 sessions = manager.GetActiveSessions();69 EXPECT_EQ(std::count(sessions.begin(), sessions.end(), dap.get()), 1);70 71 std::thread unregister_thread([&]() { manager.UnregisterSession(&loop); });72 unregister_thread.join();73}74 75TEST_F(DAPSessionManagerTest, WaitForAllSessionsToDisconnect) {76 DAPSessionManager &manager = DAPSessionManager::GetInstance();77 78 manager.RegisterSession(&loop, dap.get());79 80 std::vector<DAP *> sessions = manager.GetActiveSessions();81 EXPECT_EQ(std::count(sessions.begin(), sessions.end(), dap.get()), 1);82 83 // Unregister after a delay to test blocking behavior.84 std::thread unregister_thread([&]() {85 std::this_thread::sleep_for(std::chrono::milliseconds(100));86 manager.UnregisterSession(&loop);87 });88 89 // WaitForAllSessionsToDisconnect should block until unregistered.90 auto start = std::chrono::steady_clock::now();91 llvm::Error err = manager.WaitForAllSessionsToDisconnect();92 EXPECT_FALSE(err);93 auto duration = std::chrono::steady_clock::now() - start;94 95 // Verify it waited at least 100ms.96 EXPECT_GE(duration, std::chrono::milliseconds(100));97 98 // Session should be unregistered now.99 sessions = manager.GetActiveSessions();100 EXPECT_EQ(std::count(sessions.begin(), sessions.end(), dap.get()), 0);101 102 unregister_thread.join();103}104