Skip to content

Commit 7cef5bc

Browse files
committed
Fixed unit tests for stopping solvers and made them not depend on concrete runtime
1 parent 9bcd732 commit 7cef5bc

File tree

3 files changed

+81
-59
lines changed

3 files changed

+81
-59
lines changed

src/api/GlobalStop.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ void notifyGlobalStop() {
1515
globalStopFlag = true;
1616
}
1717

18+
void resetGlobalStop() {
19+
globalStopFlag = false;
20+
}
21+
1822
bool globallyStopped() {
1923
return globalStopFlag;
2024
}

src/api/GlobalStop.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace opensmt {
99

1010
// Notify all solvers in the application to stop
1111
void notifyGlobalStop();
12+
void resetGlobalStop();
1213
// Check if a global stop flag for all solvers has been triggered
1314
bool globallyStopped();
1415

test/unit/test_Stop.cc

Lines changed: 76 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,51 @@
1212
#include <logics/ArithLogic.h>
1313

1414
#include <array>
15-
#include <chrono>
1615
#include <future>
1716
#include <thread>
18-
19-
using namespace std::chrono_literals;
17+
#include <condition_variable>
18+
#include <mutex>
2019

2120
namespace opensmt {
2221

23-
constexpr auto const sleep_amount = 10ms;
22+
std::mutex mutex;
23+
std::condition_variable condVar;
24+
size_t ackReadyCnt{0};
25+
bool reqContinueFlag{false};
26+
27+
class TestMainSolver : public MainSolver {
28+
public:
29+
using MainSolver::MainSolver;
30+
31+
protected:
32+
sstat solve_(vec<FrameId> const & enabledFrames) override {
33+
std::unique_lock lock(mutex);
34+
++ackReadyCnt;
35+
lock.unlock();
36+
condVar.notify_all();
37+
lock.lock();
38+
condVar.wait(lock, []{ return reqContinueFlag; });
39+
lock.unlock();
40+
41+
return MainSolver::solve_(enabledFrames);
42+
}
43+
};
2444

2545
class StopTest : public ::testing::Test {
46+
public:
47+
48+
~StopTest() {
49+
resetGlobalStop();
50+
51+
ackReadyCnt = 0;
52+
reqContinueFlag = false;
53+
}
2654
protected:
2755
static constexpr size_t nSolvers = 2;
2856

2957
void init() {
58+
assert(not globallyStopped());
59+
3060
for (size_t i = 0; i < nSolvers; ++i) {
3161
auto & logic = logics[i];
3262
auto & solver = solvers[i];
@@ -54,24 +84,37 @@ class StopTest : public ::testing::Test {
5484
}
5585
}
5686

57-
void notifyAll() {
87+
void waitReadyAll() {
88+
std::unique_lock lock(mutex);
89+
condVar.wait(lock, []{ return ackReadyCnt == nSolvers; });
90+
}
91+
92+
void reqContinue() {
93+
{
94+
std::lock_guard lock(mutex);
95+
reqContinueFlag = true;
96+
}
97+
condVar.notify_all();
98+
}
99+
100+
void notifyStopAll() {
58101
for (size_t i = 0; i < nSolvers; ++i) {
59102
solvers[i].notifyStop();
60103
}
61104
}
62105

63-
std::array<sstat, nSolvers> waitAll() {
106+
std::array<sstat, nSolvers> joinAll() {
64107
std::array<sstat, nSolvers> results;
65108
for (size_t i = 0; i < nSolvers; ++i) {
66-
results[i] = wait(i);
109+
results[i] = join(i);
67110
}
68111
return results;
69112
}
70113

71114
SMTConfig config{};
72115
std::array<ArithLogic, nSolvers> logics{Logic_t::QF_LRA, Logic_t::QF_LRA};
73-
std::array<MainSolver, nSolvers> solvers{MainSolver{logics[0], config, "solver 1"},
74-
MainSolver{logics[1], config, "solver 2"}};
116+
std::array<TestMainSolver, nSolvers> solvers{TestMainSolver{logics[0], config, "solver 1"},
117+
TestMainSolver{logics[1], config, "solver 2"}};
75118

76119
std::array<std::thread, nSolvers> threads;
77120
std::array<std::future<sstat>, nSolvers> futures;
@@ -85,12 +128,11 @@ class StopTest : public ::testing::Test {
85128

86129
void solveOnBackground(size_t idx) {
87130
runOnBackground(idx, [this, idx] {
88-
std::this_thread::sleep_for(sleep_amount);
89131
return solvers[idx].check();
90132
});
91133
}
92134

93-
sstat wait(size_t idx) {
135+
sstat join(size_t idx) {
94136
threads[idx].join();
95137
return futures[idx].get();
96138
}
@@ -100,7 +142,9 @@ TEST_F(StopTest, test_NoStop) {
100142
init();
101143

102144
solveAllOnBackground();
103-
auto results = waitAll();
145+
waitReadyAll();
146+
reqContinue();
147+
auto results = joinAll();
104148

105149
ASSERT_EQ(results, std::to_array({s_False, s_False}));
106150
}
@@ -110,7 +154,9 @@ TEST_F(StopTest, test_LocalPreStop) {
110154

111155
solvers.front().notifyStop();
112156
solveAllOnBackground();
113-
auto results = waitAll();
157+
waitReadyAll();
158+
reqContinue();
159+
auto results = joinAll();
114160

115161
ASSERT_EQ(results, std::to_array({s_Undef, s_False}));
116162
}
@@ -120,17 +166,21 @@ TEST_F(StopTest, test_GlobalPreStop) {
120166

121167
notifyGlobalStop();
122168
solveAllOnBackground();
123-
auto results = waitAll();
169+
waitReadyAll();
170+
reqContinue();
171+
auto results = joinAll();
124172

125173
ASSERT_EQ(results, std::to_array({s_Undef, s_Undef}));
126174
}
127175

128176
TEST_F(StopTest, test_AllLocalPreStop) {
129177
init();
130178

131-
notifyAll();
179+
notifyStopAll();
132180
solveAllOnBackground();
133-
auto results = waitAll();
181+
waitReadyAll();
182+
reqContinue();
183+
auto results = joinAll();
134184

135185
ASSERT_EQ(results, std::to_array({s_Undef, s_Undef}));
136186
}
@@ -141,9 +191,10 @@ TEST_F(StopTest, test_LocalPostStop) {
141191
init();
142192

143193
solveAllOnBackground();
144-
std::this_thread::sleep_for(sleep_amount / 10);
194+
waitReadyAll();
145195
solvers.front().notifyStop();
146-
auto results = waitAll();
196+
reqContinue();
197+
auto results = joinAll();
147198

148199
ASSERT_EQ(results, std::to_array({s_Undef, s_False}));
149200
}
@@ -152,9 +203,10 @@ TEST_F(StopTest, test_GlobalPostStop) {
152203
init();
153204

154205
solveAllOnBackground();
155-
std::this_thread::sleep_for(sleep_amount / 10);
206+
waitReadyAll();
156207
notifyGlobalStop();
157-
auto results = waitAll();
208+
reqContinue();
209+
auto results = joinAll();
158210

159211
ASSERT_EQ(results, std::to_array({s_Undef, s_Undef}));
160212
}
@@ -163,45 +215,10 @@ TEST_F(StopTest, test_AllLocalPostStop) {
163215
init();
164216

165217
solveAllOnBackground();
166-
std::this_thread::sleep_for(sleep_amount / 10);
167-
notifyAll();
168-
auto results = waitAll();
169-
170-
ASSERT_EQ(results, std::to_array({s_Undef, s_Undef}));
171-
}
172-
173-
TEST_F(StopTest, test_LocalTimeout) {
174-
init();
175-
176-
solveAllOnBackground();
177-
if (futures.front().wait_for(sleep_amount / 2) != std::future_status::timeout) { ASSERT_TRUE(false); }
178-
179-
solvers.front().notifyStop();
180-
auto results = waitAll();
181-
182-
ASSERT_EQ(results, std::to_array({s_Undef, s_False}));
183-
}
184-
185-
TEST_F(StopTest, test_GlobalTimeout) {
186-
init();
187-
188-
solveAllOnBackground();
189-
if (futures.front().wait_for(sleep_amount / 2) != std::future_status::timeout) { ASSERT_TRUE(false); }
190-
191-
notifyGlobalStop();
192-
auto results = waitAll();
193-
194-
ASSERT_EQ(results, std::to_array({s_Undef, s_Undef}));
195-
}
196-
197-
TEST_F(StopTest, test_AllLocalTimeout) {
198-
init();
199-
200-
solveAllOnBackground();
201-
if (futures.front().wait_for(sleep_amount / 2) != std::future_status::timeout) { ASSERT_TRUE(false); }
202-
203-
notifyAll();
204-
auto results = waitAll();
218+
waitReadyAll();
219+
notifyStopAll();
220+
reqContinue();
221+
auto results = joinAll();
205222

206223
ASSERT_EQ(results, std::to_array({s_Undef, s_Undef}));
207224
}

0 commit comments

Comments
 (0)