11 #include <boost/test/unit_test.hpp> 14 #include <condition_variable> 17 #include <unordered_set> 28 #ifdef DEBUG_LOCKCONTENTION 52 n_calls.fetch_add(1, std::memory_order_relaxed);
68 std::swap(
fails, x.fails);
74 static std::unordered_multiset<size_t> results
GUARDED_BY(
m);
123 static std::condition_variable
cv;
136 std::unique_lock<std::mutex> l(
m);
137 nFrozen.store(1, std::memory_order_relaxed);
139 cv.wait(l, []{
return nFrozen.load(std::memory_order_relaxed) == 0;});
153 std::unordered_multiset<size_t> UniqueCheck::results;
174 std::vector<FakeCheckCheckCompletion> vChecks;
175 for (
const size_t i : range) {
181 total -= vChecks.size();
182 control.
Add(vChecks);
184 BOOST_REQUIRE(control.Wait());
189 small_queue->StopWorkerThreads();
196 std::vector<size_t> range;
197 range.push_back((
size_t)0);
204 std::vector<size_t> range;
205 range.push_back((
size_t)1);
212 std::vector<size_t> range;
213 range.push_back(100000);
220 std::vector<size_t> range;
221 range.reserve(100000/1000);
222 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))))
234 for (
size_t i = 0; i < 1001; ++i) {
236 size_t remaining = i;
240 std::vector<FailingCheck> vChecks;
242 for (
size_t k = 0;
k < r && remaining;
k++, remaining--)
243 vChecks.emplace_back(remaining == 1);
244 control.Add(vChecks);
246 bool success = control.Wait();
248 BOOST_REQUIRE(!success);
250 BOOST_REQUIRE(success);
253 fail_queue->StopWorkerThreads();
262 for (
auto times = 0; times < 10; ++times) {
263 for (
const bool end_fails : {
true,
false}) {
266 std::vector<FailingCheck> vChecks;
267 vChecks.resize(100,
false);
268 vChecks[99] = end_fails;
269 control.
Add(vChecks);
271 bool r =control.Wait();
272 BOOST_REQUIRE(r != end_fails);
275 fail_queue->StopWorkerThreads();
286 size_t COUNT = 100000;
287 size_t total = COUNT;
292 std::vector<UniqueCheck> vChecks;
293 for (
size_t k = 0;
k < r && total;
k++)
294 vChecks.emplace_back(--total);
295 control.Add(vChecks);
301 BOOST_REQUIRE_EQUAL(UniqueCheck::results.size(), COUNT);
302 for (
size_t i = 0; i < COUNT; ++i) {
303 r = r && UniqueCheck::results.count(i) == 1;
307 queue->StopWorkerThreads();
320 for (
size_t i = 0; i < 1000; ++i) {
326 std::vector<MemoryCheck> vChecks;
327 for (
size_t k = 0;
k < r && total;
k++) {
331 vChecks.emplace_back(total == 0 || total == i || total == i/2);
333 control.Add(vChecks);
338 queue->StopWorkerThreads();
348 std::thread t0([&]() {
350 std::vector<FrozenCleanupCheck> vChecks(1);
354 vChecks[0].should_freeze =
true;
355 control.
Add(vChecks);
356 bool waitResult = control.Wait();
365 for (
auto x = 0; x < 100 && !fails; ++x) {
366 fails = queue->m_control_mutex.try_lock();
377 BOOST_REQUIRE(!fails);
378 queue->StopWorkerThreads();
387 std::vector<std::thread> tg;
388 std::atomic<int> nThreads {0};
389 std::atomic<int> fails {0};
390 for (
size_t i = 0; i < 3; ++i) {
395 auto observed = ++nThreads;
397 fails += observed != nThreads;
400 for (
auto& thread: tg) {
401 if (thread.joinable()) thread.join();
403 BOOST_REQUIRE_EQUAL(fails, 0);
406 std::vector<std::thread> tg;
408 std::condition_variable cv;
409 bool has_lock{
false};
410 bool has_tried{
false};
412 bool done_ack{
false};
414 std::unique_lock<std::mutex> l(
m);
417 std::unique_lock<std::mutex> ll(
m);
420 cv.wait(ll, [&]{
return has_tried;});
425 cv.wait(ll, [&]{
return done_ack;});
428 cv.wait(l, [&](){
return has_lock;});
430 for (
auto x = 0; x < 100 && !fails; ++x) {
431 fails = queue->m_control_mutex.try_lock();
435 cv.wait(l, [&](){
return done;});
439 BOOST_REQUIRE(!fails);
441 for (
auto& thread: tg) {
442 if (thread.joinable()) thread.join();
CCheckQueue< FakeCheckCheckCompletion > Correct_Queue
CCheckQueue< FakeCheck > Standard_Queue
static std::atomic< uint64_t > nFrozen
CCheckQueue< MemoryCheck > Memory_Queue
void Add(std::vector< T > &vChecks)
static std::atomic< size_t > n_calls
void swap(FrozenCleanupCheck &x) noexcept
void swap(FakeCheck &x) noexcept
CCheckQueue< UniqueCheck > Unique_Queue
static const int SCRIPT_CHECK_THREADS
RAII-style controller object for a CCheckQueue that guarantees the passed queue is finished before co...
void swap(FakeCheckCheckCompletion &x) noexcept
void swap(FailingCheck &x) noexcept
FailingCheck(bool _fails)
static const std::string MAIN
Chain name strings.
UniqueCheck(size_t check_id_in)
void swap(MemoryCheck &x) noexcept
static uint64_t InsecureRandRange(uint64_t range)
NoLockLoggingTestingSetup()
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...
BOOST_AUTO_TEST_SUITE_END()
CCheckQueue< FrozenCleanupCheck > FrozenCleanup_Queue
BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Zero)
Test that 0 checks is correct.
static std::unordered_multiset< size_t > results GUARDED_BY(m)
Identical to TestingSetup but excludes lock contention logging if DEBUG_LOCKCONTENTION is defined...
Queue for verifications that have to be performed.
void swap(UniqueCheck &x) noexcept
Template mixin that adds -Wthread-safety locking annotations and lock order checking to a subset of t...
void UninterruptibleSleep(const std::chrono::microseconds &n)
static std::atomic< size_t > fake_allocated_memory
FrozenCleanupCheck()=default
static const unsigned int QUEUE_BATCH_SIZE
CCheckQueue< FailingCheck > Failing_Queue
MemoryCheck(const MemoryCheck &x)
static std::condition_variable cv
Testing setup that configures a complete environment.