11#include <boost/test/unit_test.hpp>
14#include <condition_variable>
17#include <unordered_set>
48 n_calls.fetch_add(1, std::memory_order_relaxed);
113 static std::condition_variable
cv;
126 std::unique_lock<std::mutex> l(
m);
127 nFrozen.store(1, std::memory_order_relaxed);
129 cv.wait(l, []{
return nFrozen.load(std::memory_order_relaxed) == 0;});
140std::unordered_multiset<size_t> UniqueCheck::results;
161 std::vector<FakeCheckCheckCompletion> vChecks;
162 for (
const size_t i : range) {
168 total -= vChecks.size();
169 control.
Add(vChecks);
171 BOOST_REQUIRE(control.
Wait());
176 small_queue->StopWorkerThreads();
183 std::vector<size_t> range;
184 range.push_back((
size_t)0);
191 std::vector<size_t> range;
192 range.push_back((
size_t)1);
199 std::vector<size_t> range;
200 range.push_back(100000);
207 std::vector<size_t> range;
208 range.reserve(100000/1000);
209 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))))
221 for (
size_t i = 0; i < 1001; ++i) {
223 size_t remaining = i;
227 std::vector<FailingCheck> vChecks;
229 for (
size_t k = 0; k < r && remaining; k++, remaining--)
230 vChecks.emplace_back(remaining == 1);
231 control.
Add(vChecks);
233 bool success = control.
Wait();
235 BOOST_REQUIRE(!success);
237 BOOST_REQUIRE(success);
240 fail_queue->StopWorkerThreads();
249 for (
auto times = 0; times < 10; ++times) {
250 for (
const bool end_fails : {
true,
false}) {
253 std::vector<FailingCheck> vChecks;
254 vChecks.resize(100,
false);
255 vChecks[99] = end_fails;
256 control.
Add(vChecks);
258 bool r =control.
Wait();
259 BOOST_REQUIRE(r != end_fails);
262 fail_queue->StopWorkerThreads();
273 size_t COUNT = 100000;
274 size_t total = COUNT;
279 std::vector<UniqueCheck> vChecks;
280 for (
size_t k = 0; k < r && total; k++)
281 vChecks.emplace_back(--total);
282 control.
Add(vChecks);
288 BOOST_REQUIRE_EQUAL(UniqueCheck::results.size(), COUNT);
289 for (
size_t i = 0; i < COUNT; ++i) {
290 r = r && UniqueCheck::results.count(i) == 1;
294 queue->StopWorkerThreads();
307 for (
size_t i = 0; i < 1000; ++i) {
313 std::vector<MemoryCheck> vChecks;
314 for (
size_t k = 0; k < r && total; k++) {
318 vChecks.emplace_back(total == 0 || total == i || total == i/2);
320 control.
Add(vChecks);
325 queue->StopWorkerThreads();
335 std::thread t0([&]() {
337 std::vector<FrozenCleanupCheck> vChecks(1);
341 vChecks[0].should_freeze =
true;
342 control.
Add(vChecks);
343 bool waitResult = control.
Wait();
352 for (
auto x = 0; x < 100 && !fails; ++x) {
353 fails = queue->m_control_mutex.try_lock();
364 BOOST_REQUIRE(!fails);
365 queue->StopWorkerThreads();
374 std::vector<std::thread> tg;
375 std::atomic<int> nThreads {0};
376 std::atomic<int> fails {0};
377 for (
size_t i = 0; i < 3; ++i) {
382 auto observed = ++nThreads;
384 fails += observed != nThreads;
387 for (
auto& thread: tg) {
388 if (thread.joinable()) thread.join();
390 BOOST_REQUIRE_EQUAL(fails, 0);
393 std::vector<std::thread> tg;
395 std::condition_variable cv;
396 bool has_lock{
false};
397 bool has_tried{
false};
399 bool done_ack{
false};
401 std::unique_lock<std::mutex> l(m);
404 std::unique_lock<std::mutex> ll(m);
407 cv.wait(ll, [&]{
return has_tried;});
412 cv.wait(ll, [&]{
return done_ack;});
415 cv.wait(l, [&](){
return has_lock;});
417 for (
auto x = 0; x < 100 && !fails; ++x) {
418 fails = queue->m_control_mutex.try_lock();
422 cv.wait(l, [&](){
return done;});
426 BOOST_REQUIRE(!fails);
428 for (
auto& thread: tg) {
429 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
CBaseChainParams defines the base parameters (shared between bitcoin-cli and bitcoind) of a given ins...
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()
#define BOOST_FIXTURE_TEST_SUITE(a, b)
static uint64_t InsecureRandRange(uint64_t range)
void swap(FailingCheck &x)
FailingCheck(bool _fails)
void swap(FakeCheckCheckCompletion &x)
static std::atomic< size_t > n_calls
static std::atomic< uint64_t > nFrozen
static std::condition_variable cv
void swap(FrozenCleanupCheck &x)
static std::atomic< size_t > fake_allocated_memory
void swap(MemoryCheck &x)
MemoryCheck(const MemoryCheck &x)
Identical to TestingSetup but excludes lock contention logging, as some of these tests are designed t...
NoLockLoggingTestingSetup()
Testing setup that configures a complete environment.
static std::unordered_multiset< size_t > results GUARDED_BY(m)
void swap(UniqueCheck &x)
UniqueCheck(size_t check_id_in)
void UninterruptibleSleep(const std::chrono::microseconds &n)