Skip to content

Commit 5493990

Browse files
Fix flaky tests (#840)
* Seems better * Converting all tests * Adding new API * Splitting test_helper * formatting * Adding unit tests & moving to use CVs
1 parent 42fb022 commit 5493990

61 files changed

Lines changed: 604 additions & 426 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎score/launch_manager/src/lm_control/BUILD‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ cc_library(
3434
deps = [
3535
"//score/launch_manager:error",
3636
"//score/launch_manager/src/daemon/src/common:log",
37+
"@score_baselibs//score/concurrency:condition_variable",
3738
"@score_baselibs//score/language/futurecpp",
3839
"@score_baselibs//score/language/safecpp/scoped_function:copyable_scoped_function",
3940
"@score_baselibs//score/language/safecpp/scoped_function:scope",

‎score/launch_manager/src/lm_control/src/details/lm_control_impl.hpp‎

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#ifndef SCORE_MW_LIFECYCLE_LM_CONTROL_IMPL_HPP
1414
#define SCORE_MW_LIFECYCLE_LM_CONTROL_IMPL_HPP
1515

16+
#include <chrono>
17+
#include <condition_variable>
1618
#include <cstddef>
1719
#include <exception>
1820
#include <memory>
@@ -22,6 +24,7 @@
2224
#include <string_view>
2325
#include <utility>
2426

27+
#include "score/concurrency/condition_variable.h"
2528
#include "score/language/safecpp/scoped_function/copyable_scoped_function.h"
2629
#include "score/language/safecpp/scoped_function/scope.h"
2730
#include "score/mw/launch_manager/common/log.hpp"
@@ -245,6 +248,20 @@ class BasicLmControlImpl final : public ILmControl
245248
return response.run_target;
246249
}
247250

251+
score::Result<void> wait_for_connection(std::chrono::milliseconds timeout, const score::cpp::stop_token& stop_token)
252+
override
253+
{
254+
std::unique_lock<std::mutex> lock{mutex_};
255+
const bool connected = connection_cv_.wait_for(lock, stop_token, timeout, [this] {
256+
return proxy_.has_value();
257+
});
258+
if (!connected)
259+
{
260+
return score::MakeUnexpected(ExecErrc::kCommunicationError);
261+
}
262+
return {};
263+
}
264+
248265
private:
249266
using ProxyType = typename Traits::Proxy;
250267
using HandleType = typename Traits::HandleType;
@@ -282,9 +299,9 @@ class BasicLmControlImpl final : public ILmControl
282299
return;
283300
}
284301

285-
if (createProxy(handles.front()))
302+
if (createProxy(handles.front()) && subscribeToActivationResults())
286303
{
287-
static_cast<void>(subscribeToActivationResults());
304+
connection_cv_.notify_all();
288305
}
289306
}
290307

@@ -430,6 +447,8 @@ class BasicLmControlImpl final : public ILmControl
430447

431448
// Guards proxy_
432449
std::mutex mutex_;
450+
// Signalled (under mutex_) once proxy_ is set up, wakes wait_for_connection()
451+
concurrency::InterruptibleConditionalVariableBasic<std::mutex, std::condition_variable> connection_cv_;
433452
std::optional<ProxyType> proxy_;
434453

435454
// Handle of the running discovery search, stopped by the destructor. Written once by init()

‎score/launch_manager/src/lm_control/src/details/lm_control_impl_UT.cpp‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <gtest/gtest.h>
1616

1717
#include <algorithm>
18+
#include <chrono>
1819
#include <cstddef>
1920
#include <functional>
2021
#include <memory>
@@ -391,6 +392,42 @@ TEST_F(LmControlUT, DiscoveryCreatesProxySubscribesAndSetsHandler)
391392
EXPECT_TRUE(receive_handler_);
392393
}
393394

395+
TEST_F(LmControlUT, WaitForConnectionTimesOut)
396+
{
397+
RecordProperty(
398+
"Description",
399+
"wait_for_connection returns kCommunicationError on timeout and when stopped via the stop token, and "
400+
"succeeds once the service has been discovered.");
401+
402+
auto impl = MakeLmControl();
403+
ILmControl* const sut = impl.get();
404+
405+
auto timed_out = sut->wait_for_connection(std::chrono::milliseconds(1));
406+
ASSERT_FALSE(timed_out.has_value());
407+
EXPECT_EQ(timed_out.error(), ExecErrc::kCommunicationError);
408+
}
409+
410+
TEST_F(LmControlUT, WaitForConnectionStops)
411+
{
412+
auto impl = MakeLmControl();
413+
ILmControl* const sut = impl.get();
414+
415+
score::cpp::stop_source stop_source;
416+
stop_source.request_stop();
417+
auto stopped = sut->wait_for_connection(std::chrono::hours(1), stop_source.get_token());
418+
ASSERT_FALSE(stopped.has_value());
419+
EXPECT_EQ(stopped.error(), ExecErrc::kCommunicationError);
420+
}
421+
422+
TEST_F(LmControlUT, WaitForConnectionWorks)
423+
{
424+
auto impl = MakeLmControl();
425+
ILmControl* const sut = impl.get();
426+
427+
ConnectService();
428+
EXPECT_TRUE(sut->wait_for_connection(std::chrono::milliseconds(1)).has_value());
429+
}
430+
394431
TEST_F(LmControlUT, EmptyHandlesAreIgnored)
395432
{
396433
RecordProperty(

‎score/launch_manager/src/lm_control/src/ilm_control.hpp‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef SCORE_MW_LIFECYCLE_ILM_CONTROL_H_
1414
#define SCORE_MW_LIFECYCLE_ILM_CONTROL_H_
1515

16+
#include <chrono>
1617
#include <functional>
1718
#include <memory>
1819

@@ -21,6 +22,8 @@
2122
#include "score/mw/lifecycle/run_target_activation_source.hpp"
2223
#include "score/result/result.h"
2324

25+
#include <score/stop_token.hpp>
26+
2427
namespace score::mw::lifecycle
2528
{
2629

@@ -95,6 +98,23 @@ class ILmControl
9598
/// @error kCommunicationError The service discovery could not be started.
9699
static score::Result<std::unique_ptr<ILmControl>> Create(std::string_view instance_specifier);
97100

101+
/// @brief Blocks until the client is connected to the Launch Manager.
102+
///
103+
/// Sleeps on a condition variable until service discovery has produced a connected
104+
/// proxy, the timeout expires, or a stop is requested via the stop token.
105+
///
106+
/// @param[in] timeout Maximum time to wait for the connection.
107+
/// @param[in] stop_token Allows another thread to abort the wait early. A default
108+
/// constructed token can never be stopped.
109+
///
110+
/// @returns void once connected.
111+
///
112+
/// @error kCommunicationError The connection was not established within the timeout,
113+
/// or the wait was stopped via the stop token.
114+
virtual score::Result<void> wait_for_connection(
115+
std::chrono::milliseconds timeout = std::chrono::milliseconds(500),
116+
const score::cpp::stop_token& stop_token = score::cpp::stop_token{}) = 0;
117+
98118
/// @brief Virtual destructor for safe deletion through this interface.
99119
virtual ~ILmControl() noexcept = default;
100120

‎tests/integration/complex_monitoring/component_complex_monitoring.cpp‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
#include "score/mw/lifecycle/report_running.h"
1717
#include "score/mw/log/rust/stdout_logger_init.h"
18-
#include "tests/utils/test_helper/test_helper.hpp"
18+
#include "tests/utils/test_helper/test_runner.hpp"
1919
#include <score/mw/health/common.h>
2020
#include <score/mw/health/health_monitor.h>
2121

@@ -59,14 +59,15 @@ TEST(ComplexMonitoring, ComponentComplexMonitoring)
5959
std::this_thread::sleep_for(75ms);
6060
heartbeat_monitor.Heartbeat();
6161
}
62-
EXPECT_FALSE(TestRunner::exitRequested) << "Process should not be terminated yet";
62+
EXPECT_FALSE(TestRunner::g_exit_requested) << "Process should not be terminated yet";
6363
}
6464
// When heartbeats are no longer sent...
6565
}
6666

6767
int main()
6868
{
69-
TestRunner(__FILE__, TerminationBehavior::kContinue).RunTests();
69+
TestRunner::Init();
70+
TestRunner::RunTests();
7071
// Then expect kill due to recovery action (verified by state manager)
7172
while (true) // Stop reporting, wait for sigkill
7273
{

‎tests/integration/complex_monitoring/control_client_test_driver.cpp‎

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <unistd.h>
1515

1616
#include "tests/utils/test_helper/test_helper.hpp"
17+
#include "tests/utils/test_helper/test_runner.hpp"
1718
#include <score/mw/lifecycle/ilm_control.hpp>
1819
#include <score/mw/lifecycle/report_running.h>
1920

@@ -79,15 +80,13 @@ TEST(ComplexMonitoring, ControlClientTestDriver)
7980
// did not just send an event without taking the action.
8081
EXPECT_TRUE(std::filesystem::exists(fallback_file)) << "Fallback Run Target was not activated";
8182
}
82-
83-
TEST_STEP("Activate Off Run Target")
84-
{
85-
const auto result = client->activate_run_target("Off", true);
86-
EXPECT_TRUE(result.has_value()) << result.error().Message();
87-
}
8883
}
8984

9085
int main()
9186
{
92-
return TestRunner(__FILE__, TerminationBehavior::kWait, TerminationNotification::kTestEnd).RunTests();
87+
TestRunner::Init();
88+
const auto result = TestRunner::RunTests();
89+
TestRunner::EndTest();
90+
TestRunner::WaitForTermination();
91+
return result;
9392
}

‎tests/integration/crash_ignores_dependents/process_crashing_once.cpp‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <gtest/gtest.h>
1414

1515
#include "tests/utils/test_helper/test_helper.hpp"
16+
#include "tests/utils/test_helper/test_runner.hpp"
1617
#include <score/mw/lifecycle/report_running.h>
1718

1819
TEST(CrashIgnoresDependents, CrashingProcess)
@@ -46,5 +47,6 @@ TEST(CrashIgnoresDependents, CrashingProcess)
4647

4748
int main()
4849
{
49-
TestRunner(__FILE__, TerminationBehavior::kContinue).RunTests();
50+
TestRunner::Init();
51+
TestRunner::RunTests();
5052
}

‎tests/integration/crash_ignores_dependents/test_process.cpp‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <gtest/gtest.h>
1414

1515
#include "tests/utils/test_helper/test_helper.hpp"
16+
#include "tests/utils/test_helper/test_runner.hpp"
1617
#include <fcntl.h>
1718
#include <score/mw/lifecycle/report_running.h>
1819
#include <chrono>
@@ -52,5 +53,8 @@ TEST(CrashIgnoresDependents, TestProcess)
5253

5354
int main()
5455
{
55-
return TestRunner(__FILE__, TerminationBehavior::kContinue, TerminationNotification::kTestEnd).RunTests();
56+
TestRunner::Init();
57+
const auto result = TestRunner::RunTests();
58+
TestRunner::EndTest();
59+
return result;
5660
}

‎tests/integration/crash_on_startup/control_client_test_driver.cpp‎

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <filesystem>
1515

1616
#include "tests/utils/test_helper/test_helper.hpp"
17+
#include "tests/utils/test_helper/test_runner.hpp"
1718
#include <score/mw/lifecycle/ilm_control.hpp>
1819
#include <score/mw/lifecycle/report_running.h>
1920

@@ -100,15 +101,13 @@ TEST(CrashOnStartup, ControlClientTestDriver)
100101
// did not just send an event without taking the action.
101102
EXPECT_TRUE(std::filesystem::exists(fallback_file)) << "Fallback Run Target should have been activated";
102103
}
103-
104-
TEST_STEP("Activate Run Target Off")
105-
{
106-
const auto result = client->activate_run_target("Off", true);
107-
EXPECT_TRUE(result.has_value()) << result.error().Message();
108-
}
109104
}
110105

111106
int main()
112107
{
113-
return TestRunner(__FILE__, TerminationBehavior::kWait, TerminationNotification::kTestEnd).RunTests();
108+
TestRunner::Init();
109+
const auto result = TestRunner::RunTests();
110+
TestRunner::EndTest();
111+
TestRunner::WaitForTermination();
112+
return result;
114113
}

‎tests/integration/explicit_fallback_request/control_client_test_driver.cpp‎

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <gtest/gtest.h>
1414

1515
#include "tests/utils/test_helper/test_helper.hpp"
16+
#include "tests/utils/test_helper/test_runner.hpp"
1617
#include <score/mw/lifecycle/ilm_control.hpp>
1718
#include <score/mw/lifecycle/report_running.h>
1819

@@ -62,15 +63,13 @@ TEST(ExplicitFallbackRequest, ControlClientTestDriver)
6263
EXPECT_EQ(target, "fallback_run_target");
6364
}
6465
});
65-
66-
TEST_STEP("Activate Run Target Off")
67-
{
68-
const auto result = client->activate_run_target("Off", true);
69-
EXPECT_TRUE(result.has_value()) << result.error().Message();
70-
}
7166
}
7267

7368
int main()
7469
{
75-
return TestRunner(__FILE__, TerminationBehavior::kWait, TerminationNotification::kTestEnd).RunTests();
70+
TestRunner::Init();
71+
const auto result = TestRunner::RunTests();
72+
TestRunner::EndTest();
73+
TestRunner::WaitForTermination();
74+
return result;
7675
}

0 commit comments

Comments
 (0)