1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
//===-- ListenerTest.cpp --------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "gtest/gtest.h"
#include "lldb/Utility/Broadcaster.h"
#include "lldb/Utility/Event.h"
#include "lldb/Utility/Listener.h"
#include <future>
#include <thread>
using namespace lldb;
using namespace lldb_private;
TEST(ListenerTest, GetEventImmediate) {
EventSP event_sp;
Broadcaster broadcaster(nullptr, "test-broadcaster");
// Create a listener, sign it up, make sure it receives an event.
ListenerSP listener_sp = Listener::MakeListener("test-listener");
const uint32_t event_mask = 1;
ASSERT_EQ(event_mask,
listener_sp->StartListeningForEvents(&broadcaster, event_mask));
const std::chrono::seconds timeout(0);
// Without any events sent, these should return false.
EXPECT_FALSE(listener_sp->GetEvent(event_sp, timeout));
EXPECT_FALSE(listener_sp->GetEventForBroadcaster(nullptr, event_sp, timeout));
EXPECT_FALSE(
listener_sp->GetEventForBroadcaster(&broadcaster, event_sp, timeout));
EXPECT_FALSE(listener_sp->GetEventForBroadcasterWithType(
&broadcaster, event_mask, event_sp, timeout));
// Now send events and make sure they get it.
broadcaster.BroadcastEvent(event_mask, nullptr);
EXPECT_TRUE(listener_sp->GetEvent(event_sp, timeout));
broadcaster.BroadcastEvent(event_mask, nullptr);
EXPECT_TRUE(listener_sp->GetEventForBroadcaster(nullptr, event_sp, timeout));
broadcaster.BroadcastEvent(event_mask, nullptr);
EXPECT_TRUE(
listener_sp->GetEventForBroadcaster(&broadcaster, event_sp, timeout));
broadcaster.BroadcastEvent(event_mask, nullptr);
EXPECT_FALSE(listener_sp->GetEventForBroadcasterWithType(
&broadcaster, event_mask * 2, event_sp, timeout));
EXPECT_TRUE(listener_sp->GetEventForBroadcasterWithType(
&broadcaster, event_mask, event_sp, timeout));
}
TEST(ListenerTest, GetEventWait) {
EventSP event_sp;
Broadcaster broadcaster(nullptr, "test-broadcaster");
// Create a listener, sign it up, make sure it receives an event.
ListenerSP listener_sp = Listener::MakeListener("test-listener");
const uint32_t event_mask = 1;
ASSERT_EQ(event_mask,
listener_sp->StartListeningForEvents(&broadcaster, event_mask));
// Without any events sent, these should make a short wait and return false.
std::chrono::microseconds timeout(10);
EXPECT_FALSE(listener_sp->GetEvent(event_sp, timeout));
EXPECT_FALSE(listener_sp->GetEventForBroadcaster(nullptr, event_sp, timeout));
EXPECT_FALSE(
listener_sp->GetEventForBroadcaster(&broadcaster, event_sp, timeout));
EXPECT_FALSE(listener_sp->GetEventForBroadcasterWithType(
&broadcaster, event_mask, event_sp, timeout));
// Now send events and make sure they get it.
broadcaster.BroadcastEvent(event_mask, nullptr);
EXPECT_TRUE(listener_sp->GetEvent(event_sp, timeout));
broadcaster.BroadcastEvent(event_mask, nullptr);
EXPECT_TRUE(listener_sp->GetEventForBroadcaster(nullptr, event_sp, timeout));
broadcaster.BroadcastEvent(event_mask, nullptr);
EXPECT_TRUE(
listener_sp->GetEventForBroadcaster(&broadcaster, event_sp, timeout));
broadcaster.BroadcastEvent(event_mask, nullptr);
EXPECT_FALSE(listener_sp->GetEventForBroadcasterWithType(
&broadcaster, event_mask * 2, event_sp, timeout));
EXPECT_TRUE(listener_sp->GetEventForBroadcasterWithType(
&broadcaster, event_mask, event_sp, timeout));
auto delayed_broadcast = [&] {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
broadcaster.BroadcastEvent(event_mask, nullptr);
};
// These should do an infinite wait at return the event our asynchronous
// broadcast sends.
std::future<void> async_broadcast =
std::async(std::launch::async, delayed_broadcast);
EXPECT_TRUE(listener_sp->GetEvent(event_sp, std::nullopt));
async_broadcast.get();
async_broadcast = std::async(std::launch::async, delayed_broadcast);
EXPECT_TRUE(listener_sp->GetEventForBroadcaster(&broadcaster, event_sp,
std::nullopt));
async_broadcast.get();
async_broadcast = std::async(std::launch::async, delayed_broadcast);
EXPECT_TRUE(listener_sp->GetEventForBroadcasterWithType(
&broadcaster, event_mask, event_sp, std::nullopt));
async_broadcast.get();
}
TEST(ListenerTest, StartStopListeningForEventSpec) {
constexpr uint32_t event_mask = 1;
static constexpr llvm::StringLiteral broadcaster_class = "broadcaster-class";
class TestBroadcaster : public Broadcaster {
using Broadcaster::Broadcaster;
llvm::StringRef GetBroadcasterClass() const override {
return broadcaster_class;
}
};
BroadcasterManagerSP manager_sp =
BroadcasterManager::MakeBroadcasterManager();
ListenerSP listener_sp = Listener::MakeListener("test-listener");
// Create two broadcasters, one while we're waiting for new broadcasters, and
// one when we're not.
ASSERT_EQ(listener_sp->StartListeningForEventSpec(
manager_sp, BroadcastEventSpec(broadcaster_class, event_mask)),
event_mask);
TestBroadcaster broadcaster1(manager_sp, "test-broadcaster-1");
broadcaster1.CheckInWithManager();
ASSERT_TRUE(listener_sp->StopListeningForEventSpec(
manager_sp, BroadcastEventSpec(broadcaster_class, event_mask)));
TestBroadcaster broadcaster2(manager_sp, "test-broadcaster-2");
broadcaster2.CheckInWithManager();
// Use both broadcasters to send an event.
for (auto *b : {&broadcaster1, &broadcaster2})
b->BroadcastEvent(event_mask, nullptr);
// Use should only get the event from the first one.
EventSP event_sp;
ASSERT_TRUE(listener_sp->GetEvent(event_sp, std::chrono::seconds(0)));
ASSERT_EQ(event_sp->GetBroadcaster(), &broadcaster1);
ASSERT_FALSE(listener_sp->GetEvent(event_sp, std::chrono::seconds(0)));
}
|