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