13 #include <boost/test/unit_test.hpp>
16 #include <condition_variable>
19 #include <unordered_set>
30 #ifdef DEBUG_LOCKCONTENTION
53 n_calls.fetch_add(1, std::memory_order_relaxed);
108 static std::condition_variable
cv;
119 std::unique_lock<std::mutex> l(
m);
120 nFrozen.store(1, std::memory_order_relaxed);
122 cv.wait(l, []{
return nFrozen.load(std::memory_order_relaxed) == 0;});
128 other.should_freeze =
false;
133 other.should_freeze =
false;
143 std::unordered_multiset<size_t> UniqueCheck::results;
163 std::vector<FakeCheckCheckCompletion> vChecks;
165 for (
const size_t i : range) {
172 total -= vChecks.size();
173 control.
Add(std::move(vChecks));
175 BOOST_REQUIRE(control.
Wait());
184 std::vector<size_t> range;
185 range.push_back(
size_t{0});
192 std::vector<size_t> range;
193 range.push_back(
size_t{1});
200 std::vector<size_t> range;
201 range.push_back(100000);
208 std::vector<size_t> range;
209 range.reserve(100000/1000);
210 for (
size_t i = 2; i < 100000; i += std::max((
size_t)1, (
size_t)
InsecureRandRange(std::min((
size_t)1000, ((
size_t)100000) - i))))
220 for (
size_t i = 0; i < 1001; ++i) {
222 size_t remaining = i;
226 std::vector<FailingCheck> vChecks;
228 for (
size_t k = 0;
k < r && remaining;
k++, remaining--)
229 vChecks.emplace_back(remaining == 1);
230 control.
Add(std::move(vChecks));
232 bool success = control.
Wait();
234 BOOST_REQUIRE(!success);
236 BOOST_REQUIRE(success);
245 for (
auto times = 0; times < 10; ++times) {
246 for (
const bool end_fails : {
true,
false}) {
249 std::vector<FailingCheck> vChecks;
250 vChecks.resize(100,
false);
251 vChecks[99] = end_fails;
252 control.
Add(std::move(vChecks));
254 bool r =control.
Wait();
255 BOOST_REQUIRE(r != end_fails);
266 size_t COUNT = 100000;
267 size_t total =
COUNT;
272 std::vector<UniqueCheck> vChecks;
273 for (
size_t k = 0;
k < r && total;
k++)
274 vChecks.emplace_back(--total);
275 control.
Add(std::move(vChecks));
281 BOOST_REQUIRE_EQUAL(UniqueCheck::results.size(),
COUNT);
282 for (
size_t i = 0; i <
COUNT; ++i) {
283 r = r && UniqueCheck::results.count(i) == 1;
298 for (
size_t i = 0; i < 1000; ++i) {
304 std::vector<MemoryCheck> vChecks;
305 for (
size_t k = 0;
k < r && total;
k++) {
309 vChecks.emplace_back(total == 0 || total == i || total == i/2);
311 control.
Add(std::move(vChecks));
324 std::thread t0([&]() {
326 std::vector<FrozenCleanupCheck> vChecks(1);
327 control.
Add(std::move(vChecks));
328 bool waitResult = control.
Wait();
337 for (
auto x = 0; x < 100 && !fails; ++x) {
338 fails = queue->m_control_mutex.try_lock();
349 BOOST_REQUIRE(!fails);
358 std::vector<std::thread> tg;
359 std::atomic<int> nThreads {0};
360 std::atomic<int> fails {0};
361 for (
size_t i = 0; i < 3; ++i) {
366 auto observed = ++nThreads;
368 fails += observed != nThreads;
371 for (
auto& thread: tg) {
372 if (thread.joinable()) thread.join();
374 BOOST_REQUIRE_EQUAL(fails, 0);
377 std::vector<std::thread> tg;
379 std::condition_variable cv;
380 bool has_lock{
false};
381 bool has_tried{
false};
383 bool done_ack{
false};
385 std::unique_lock<std::mutex> l(
m);
388 std::unique_lock<std::mutex> ll(
m);
391 cv.wait(ll, [&]{
return has_tried;});
396 cv.wait(ll, [&]{
return done_ack;});
399 cv.wait(l, [&](){
return has_lock;});
401 for (
auto x = 0; x < 100 && !fails; ++x) {
402 fails = queue->m_control_mutex.try_lock();
406 cv.wait(l, [&](){
return done;});
410 BOOST_REQUIRE(!fails);
412 for (
auto& thread: tg) {
413 if (thread.joinable()) thread.join();
CCheckQueue< FakeCheckCheckCompletion > Correct_Queue
CCheckQueue< FrozenCleanupCheck > FrozenCleanup_Queue
static const int SCRIPT_CHECK_THREADS
CCheckQueue< UniqueCheck > Unique_Queue
CCheckQueue< FakeCheck > Standard_Queue
static void Correct_Queue_range(std::vector< size_t > range)
This test case checks that the CCheckQueue works properly with each specified size_t Checks pushed.
CCheckQueue< FailingCheck > Failing_Queue
CCheckQueue< MemoryCheck > Memory_Queue
BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Zero)
Test that 0 checks is correct.
static const unsigned int QUEUE_BATCH_SIZE
RAII-style controller object for a CCheckQueue that guarantees the passed queue is finished before co...
void Add(std::vector< T > &&vChecks)
Queue for verifications that have to be performed.
BOOST_AUTO_TEST_SUITE_END()
FailingCheck(bool _fails)
static std::atomic< size_t > n_calls
static std::atomic< uint64_t > nFrozen
static std::condition_variable cv
FrozenCleanupCheck & operator=(FrozenCleanupCheck &&other) noexcept
FrozenCleanupCheck(FrozenCleanupCheck &&other) noexcept
FrozenCleanupCheck()=default
static std::atomic< size_t > fake_allocated_memory
MemoryCheck(const MemoryCheck &x)
Identical to TestingSetup but excludes lock contention logging if DEBUG_LOCKCONTENTION is defined,...
NoLockLoggingTestingSetup()
Testing setup that configures a complete environment.
static std::unordered_multiset< size_t > results GUARDED_BY(m)
UniqueCheck(size_t check_id_in)
static uint64_t InsecureRandRange(uint64_t range)
void UninterruptibleSleep(const std::chrono::microseconds &n)