Changeset View
Changeset View
Standalone View
Standalone View
src/test/checkqueue_tests.cpp
Show First 20 Lines • Show All 121 Lines • ▼ Show 20 Lines | |||||
typedef CCheckQueue<UniqueCheck> Unique_Queue; | typedef CCheckQueue<UniqueCheck> Unique_Queue; | ||||
typedef CCheckQueue<MemoryCheck> Memory_Queue; | typedef CCheckQueue<MemoryCheck> Memory_Queue; | ||||
typedef CCheckQueue<FrozenCleanupCheck> FrozenCleanup_Queue; | typedef CCheckQueue<FrozenCleanupCheck> FrozenCleanup_Queue; | ||||
/** This test case checks that the CCheckQueue works properly | /** This test case checks that the CCheckQueue works properly | ||||
* with each specified size_t Checks pushed. | * with each specified size_t Checks pushed. | ||||
*/ | */ | ||||
static void Correct_Queue_range(std::vector<size_t> range) { | static void Correct_Queue_range(std::vector<size_t> range) { | ||||
auto small_queue = | auto small_queue = std::make_unique<Correct_Queue>(QUEUE_BATCH_SIZE); | ||||
std::unique_ptr<Correct_Queue>(new Correct_Queue{QUEUE_BATCH_SIZE}); | |||||
boost::thread_group tg; | boost::thread_group tg; | ||||
for (auto x = 0; x < nScriptCheckThreads; ++x) { | for (auto x = 0; x < nScriptCheckThreads; ++x) { | ||||
tg.create_thread([&] { small_queue->Thread(); }); | tg.create_thread([&] { small_queue->Thread(); }); | ||||
} | } | ||||
// Make vChecks here to save on malloc (this test can be slow...) | // Make vChecks here to save on malloc (this test can be slow...) | ||||
std::vector<FakeCheckCheckCompletion> vChecks; | std::vector<FakeCheckCheckCompletion> vChecks; | ||||
for (const size_t i : range) { | for (const size_t i : range) { | ||||
size_t total = i; | size_t total = i; | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | for (size_t i = 2; i < 100000; | ||||
i += std::max((size_t)1, (size_t)InsecureRandRange(std::min( | i += std::max((size_t)1, (size_t)InsecureRandRange(std::min( | ||||
(size_t)1000, ((size_t)100000) - i)))) | (size_t)1000, ((size_t)100000) - i)))) | ||||
range.push_back(i); | range.push_back(i); | ||||
Correct_Queue_range(range); | Correct_Queue_range(range); | ||||
} | } | ||||
/** Test that failing checks are caught */ | /** Test that failing checks are caught */ | ||||
BOOST_AUTO_TEST_CASE(test_CheckQueue_Catches_Failure) { | BOOST_AUTO_TEST_CASE(test_CheckQueue_Catches_Failure) { | ||||
auto fail_queue = | auto fail_queue = std::make_unique<Failing_Queue>(QUEUE_BATCH_SIZE); | ||||
std::unique_ptr<Failing_Queue>(new Failing_Queue{QUEUE_BATCH_SIZE}); | |||||
boost::thread_group tg; | boost::thread_group tg; | ||||
for (auto x = 0; x < nScriptCheckThreads; ++x) { | for (auto x = 0; x < nScriptCheckThreads; ++x) { | ||||
tg.create_thread([&] { fail_queue->Thread(); }); | tg.create_thread([&] { fail_queue->Thread(); }); | ||||
} | } | ||||
for (size_t i = 0; i < 1001; ++i) { | for (size_t i = 0; i < 1001; ++i) { | ||||
CCheckQueueControl<FailingCheck> control(fail_queue.get()); | CCheckQueueControl<FailingCheck> control(fail_queue.get()); | ||||
Show All 15 Lines | for (size_t i = 0; i < 1001; ++i) { | ||||
} | } | ||||
} | } | ||||
tg.interrupt_all(); | tg.interrupt_all(); | ||||
tg.join_all(); | tg.join_all(); | ||||
} | } | ||||
// Test that a block validation which fails does not interfere with | // Test that a block validation which fails does not interfere with | ||||
// future blocks, ie, the bad state is cleared. | // future blocks, ie, the bad state is cleared. | ||||
BOOST_AUTO_TEST_CASE(test_CheckQueue_Recovers_From_Failure) { | BOOST_AUTO_TEST_CASE(test_CheckQueue_Recovers_From_Failure) { | ||||
auto fail_queue = | auto fail_queue = std::make_unique<Failing_Queue>(QUEUE_BATCH_SIZE); | ||||
std::unique_ptr<Failing_Queue>(new Failing_Queue{QUEUE_BATCH_SIZE}); | |||||
boost::thread_group tg; | boost::thread_group tg; | ||||
for (auto x = 0; x < nScriptCheckThreads; ++x) { | for (auto x = 0; x < nScriptCheckThreads; ++x) { | ||||
tg.create_thread([&] { fail_queue->Thread(); }); | tg.create_thread([&] { fail_queue->Thread(); }); | ||||
} | } | ||||
for (auto times = 0; times < 10; ++times) { | for (auto times = 0; times < 10; ++times) { | ||||
for (const bool end_fails : {true, false}) { | for (const bool end_fails : {true, false}) { | ||||
CCheckQueueControl<FailingCheck> control(fail_queue.get()); | CCheckQueueControl<FailingCheck> control(fail_queue.get()); | ||||
Show All 10 Lines | BOOST_AUTO_TEST_CASE(test_CheckQueue_Recovers_From_Failure) { | ||||
tg.interrupt_all(); | tg.interrupt_all(); | ||||
tg.join_all(); | tg.join_all(); | ||||
} | } | ||||
// Test that unique checks are actually all called individually, rather than | // Test that unique checks are actually all called individually, rather than | ||||
// just one check being called repeatedly. Test that checks are not called | // just one check being called repeatedly. Test that checks are not called | ||||
// more than once as well | // more than once as well | ||||
BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck) { | BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck) { | ||||
auto queue = | auto queue = std::make_unique<Unique_Queue>(QUEUE_BATCH_SIZE); | ||||
std::unique_ptr<Unique_Queue>(new Unique_Queue{QUEUE_BATCH_SIZE}); | |||||
boost::thread_group tg; | boost::thread_group tg; | ||||
for (auto x = 0; x < nScriptCheckThreads; ++x) { | for (auto x = 0; x < nScriptCheckThreads; ++x) { | ||||
tg.create_thread([&] { queue->Thread(); }); | tg.create_thread([&] { queue->Thread(); }); | ||||
} | } | ||||
size_t COUNT = 100000; | size_t COUNT = 100000; | ||||
size_t total = COUNT; | size_t total = COUNT; | ||||
{ | { | ||||
Show All 17 Lines | |||||
// Test that blocks which might allocate lots of memory free their memory | // Test that blocks which might allocate lots of memory free their memory | ||||
// aggressively. | // aggressively. | ||||
// | // | ||||
// This test attempts to catch a pathological case where by lazily freeing | // This test attempts to catch a pathological case where by lazily freeing | ||||
// checks might mean leaving a check un-swapped out, and decreasing by 1 each | // checks might mean leaving a check un-swapped out, and decreasing by 1 each | ||||
// time could leave the data hanging across a sequence of blocks. | // time could leave the data hanging across a sequence of blocks. | ||||
BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory) { | BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory) { | ||||
auto queue = | auto queue = std::make_unique<Memory_Queue>(QUEUE_BATCH_SIZE); | ||||
std::unique_ptr<Memory_Queue>(new Memory_Queue{QUEUE_BATCH_SIZE}); | |||||
boost::thread_group tg; | boost::thread_group tg; | ||||
for (auto x = 0; x < nScriptCheckThreads; ++x) { | for (auto x = 0; x < nScriptCheckThreads; ++x) { | ||||
tg.create_thread([&] { queue->Thread(); }); | tg.create_thread([&] { queue->Thread(); }); | ||||
} | } | ||||
for (size_t i = 0; i < 1000; ++i) { | for (size_t i = 0; i < 1000; ++i) { | ||||
size_t total = i; | size_t total = i; | ||||
{ | { | ||||
CCheckQueueControl<MemoryCheck> control(queue.get()); | CCheckQueueControl<MemoryCheck> control(queue.get()); | ||||
Show All 14 Lines | BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory) { | ||||
} | } | ||||
tg.interrupt_all(); | tg.interrupt_all(); | ||||
tg.join_all(); | tg.join_all(); | ||||
} | } | ||||
// Test that a new verification cannot occur until all checks | // Test that a new verification cannot occur until all checks | ||||
// have been destructed | // have been destructed | ||||
BOOST_AUTO_TEST_CASE(test_CheckQueue_FrozenCleanup) { | BOOST_AUTO_TEST_CASE(test_CheckQueue_FrozenCleanup) { | ||||
auto queue = std::unique_ptr<FrozenCleanup_Queue>( | auto queue = std::make_unique<FrozenCleanup_Queue>(QUEUE_BATCH_SIZE); | ||||
new FrozenCleanup_Queue{QUEUE_BATCH_SIZE}); | |||||
boost::thread_group tg; | boost::thread_group tg; | ||||
bool fails = false; | bool fails = false; | ||||
for (auto x = 0; x < nScriptCheckThreads; ++x) { | for (auto x = 0; x < nScriptCheckThreads; ++x) { | ||||
tg.create_thread([&] { queue->Thread(); }); | tg.create_thread([&] { queue->Thread(); }); | ||||
} | } | ||||
std::thread t0([&]() { | std::thread t0([&]() { | ||||
CCheckQueueControl<FrozenCleanupCheck> control(queue.get()); | CCheckQueueControl<FrozenCleanupCheck> control(queue.get()); | ||||
std::vector<FrozenCleanupCheck> vChecks(1); | std::vector<FrozenCleanupCheck> vChecks(1); | ||||
Show All 26 Lines | BOOST_AUTO_TEST_CASE(test_CheckQueue_FrozenCleanup) { | ||||
t0.join(); | t0.join(); | ||||
tg.interrupt_all(); | tg.interrupt_all(); | ||||
tg.join_all(); | tg.join_all(); | ||||
BOOST_REQUIRE(!fails); | BOOST_REQUIRE(!fails); | ||||
} | } | ||||
/** Test that CCheckQueueControl is threadsafe */ | /** Test that CCheckQueueControl is threadsafe */ | ||||
BOOST_AUTO_TEST_CASE(test_CheckQueueControl_Locks) { | BOOST_AUTO_TEST_CASE(test_CheckQueueControl_Locks) { | ||||
auto queue = | auto queue = std::make_unique<Standard_Queue>(QUEUE_BATCH_SIZE); | ||||
std::unique_ptr<Standard_Queue>(new Standard_Queue{QUEUE_BATCH_SIZE}); | |||||
{ | { | ||||
boost::thread_group tg; | boost::thread_group tg; | ||||
std::atomic<int> nThreads{0}; | std::atomic<int> nThreads{0}; | ||||
std::atomic<int> fails{0}; | std::atomic<int> fails{0}; | ||||
for (size_t i = 0; i < 3; ++i) { | for (size_t i = 0; i < 3; ++i) { | ||||
tg.create_thread([&] { | tg.create_thread([&] { | ||||
CCheckQueueControl<FakeCheck> control(queue.get()); | CCheckQueueControl<FakeCheck> control(queue.get()); | ||||
// While sleeping, no other thread should execute to this point | // While sleeping, no other thread should execute to this point | ||||
▲ Show 20 Lines • Show All 48 Lines • Show Last 20 Lines |