1 //===-- AlarmTest.cpp -----------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Host/Alarm.h"
10 #include "gtest/gtest.h"
15 using namespace lldb_private
;
16 using namespace std::chrono_literals
;
18 // Increase the timeout tenfold when running under ASan as it can have about the
19 // same performance overhead.
20 #if __has_feature(address_sanitizer)
21 static constexpr auto TEST_TIMEOUT
= 10000ms
;
23 static constexpr auto TEST_TIMEOUT
= 1000ms
;
26 // The time between scheduling a callback and it getting executed. This should
27 // NOT be increased under ASan.
28 static constexpr auto ALARM_TIMEOUT
= 500ms
;
30 // If there are any pending callbacks, make sure they run before the Alarm
31 // object is destroyed.
32 static constexpr bool RUN_CALLBACKS_ON_EXIT
= true;
34 TEST(AlarmTest
, Create
) {
37 std::vector
<Alarm::TimePoint
> callbacks_actual
;
38 std::vector
<Alarm::TimePoint
> callbacks_expected
;
40 Alarm
alarm(ALARM_TIMEOUT
, RUN_CALLBACKS_ON_EXIT
);
42 // Create 5 alarms some time apart.
43 for (size_t i
= 0; i
< 5; ++i
) {
44 callbacks_actual
.emplace_back();
45 callbacks_expected
.emplace_back(std::chrono::system_clock::now() +
48 alarm
.Create([&callbacks_actual
, &m
, i
]() {
49 std::lock_guard
<std::mutex
> guard(m
);
50 callbacks_actual
[i
] = std::chrono::system_clock::now();
53 std::this_thread::sleep_for(ALARM_TIMEOUT
/ 5);
56 // Leave plenty of time for all the alarms to fire.
57 std::this_thread::sleep_for(TEST_TIMEOUT
);
59 // Acquire the lock to check the callbacks.
60 std::lock_guard
<std::mutex
> guard(m
);
62 // Make sure all the alarms fired around the expected time.
63 for (size_t i
= 0; i
< 5; ++i
)
64 EXPECT_GE(callbacks_actual
[i
], callbacks_expected
[i
]);
67 TEST(AlarmTest
, Exit
) {
70 std::vector
<Alarm::Handle
> handles
;
71 std::vector
<bool> callbacks
;
74 Alarm
alarm(ALARM_TIMEOUT
, RUN_CALLBACKS_ON_EXIT
);
77 for (size_t i
= 0; i
< 5; ++i
) {
78 callbacks
.emplace_back(false);
80 handles
.push_back(alarm
.Create([&callbacks
, &m
, i
]() {
81 std::lock_guard
<std::mutex
> guard(m
);
86 // Let the alarm go out of scope before any alarm had a chance to fire.
89 // Acquire the lock to check the callbacks.
90 std::lock_guard
<std::mutex
> guard(m
);
92 // Make sure none of the alarms fired.
93 for (bool callback
: callbacks
)
94 EXPECT_TRUE(callback
);
97 TEST(AlarmTest
, Cancel
) {
100 std::vector
<Alarm::Handle
> handles
;
101 std::vector
<bool> callbacks
;
103 Alarm
alarm(ALARM_TIMEOUT
, RUN_CALLBACKS_ON_EXIT
);
106 for (size_t i
= 0; i
< 5; ++i
) {
107 callbacks
.emplace_back(false);
109 handles
.push_back(alarm
.Create([&callbacks
, &m
, i
]() {
110 std::lock_guard
<std::mutex
> guard(m
);
115 // Make sure we can cancel the first 4 alarms.
116 for (size_t i
= 0; i
< 4; ++i
)
117 EXPECT_TRUE(alarm
.Cancel(handles
[i
]));
119 // Leave plenty of time for all the alarms to fire.
120 std::this_thread::sleep_for(TEST_TIMEOUT
);
122 // Acquire the lock to check the callbacks.
123 std::lock_guard
<std::mutex
> guard(m
);
125 // Make sure none of the first 4 alarms fired.
126 for (size_t i
= 0; i
< 4; ++i
)
127 EXPECT_FALSE(callbacks
[i
]);
129 // Make sure the fifth alarm still fired.
130 EXPECT_TRUE(callbacks
[4]);
133 TEST(AlarmTest
, Restart
) {
136 std::vector
<Alarm::Handle
> handles
;
137 std::vector
<Alarm::TimePoint
> callbacks_actual
;
138 std::vector
<Alarm::TimePoint
> callbacks_expected
;
140 Alarm
alarm(ALARM_TIMEOUT
, RUN_CALLBACKS_ON_EXIT
);
142 // Create 5 alarms some time apart.
143 for (size_t i
= 0; i
< 5; ++i
) {
144 callbacks_actual
.emplace_back();
145 callbacks_expected
.emplace_back(std::chrono::system_clock::now() +
148 handles
.push_back(alarm
.Create([&callbacks_actual
, &m
, i
]() {
149 std::lock_guard
<std::mutex
> guard(m
);
150 callbacks_actual
[i
] = std::chrono::system_clock::now();
153 std::this_thread::sleep_for(ALARM_TIMEOUT
/ 5);
156 // Update the last 2 alarms.
157 for (size_t i
= 3; i
< 5; ++i
) {
158 std::lock_guard
<std::mutex
> guard(m
);
159 callbacks_expected
[i
] = std::chrono::system_clock::now() + ALARM_TIMEOUT
;
160 EXPECT_TRUE(alarm
.Restart(handles
[i
]));
163 // Leave plenty of time for all the alarms to fire.
164 std::this_thread::sleep_for(TEST_TIMEOUT
);
166 // Acquire the lock to check the callbacks.
167 std::lock_guard
<std::mutex
> guard(m
);
169 // Make sure all the alarms around the expected time.
170 for (size_t i
= 0; i
< 5; ++i
)
171 EXPECT_GE(callbacks_actual
[i
], callbacks_expected
[i
]);