From 85a7c3a21b9639da48ff5335155d0d5b1968e46c Mon Sep 17 00:00:00 2001 From: Dimitrios Siganos Date: Tue, 20 Feb 2024 10:13:50 +0000 Subject: [PATCH] Documentation and code clarity improvements to work_pool unit tests --- nano/core_test/work_pool.cpp | 91 ++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/nano/core_test/work_pool.cpp b/nano/core_test/work_pool.cpp index 59ada8938c..63eae4cf7f 100644 --- a/nano/core_test/work_pool.cpp +++ b/nano/core_test/work_pool.cpp @@ -12,6 +12,7 @@ #include +// produce one proof of work for a block and check that its difficulty is higher than the base difficulty TEST (work, one) { nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; @@ -27,6 +28,7 @@ TEST (work, one) ASSERT_LT (nano::dev::network_params.work.threshold_base (block->work_version ()), nano::dev::network_params.work.difficulty (*block)); } +// create a work_pool with zero threads and check that pool.generate returns no result TEST (work, disabled) { nano::work_pool pool{ nano::dev::network_params.network, 0 }; @@ -34,6 +36,7 @@ TEST (work, disabled) ASSERT_FALSE (result.is_initialized ()); } +// create a block with bad pow then fix it and check that it validates TEST (work, validate) { nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; @@ -48,19 +51,19 @@ TEST (work, validate) .build (); ASSERT_LT (nano::dev::network_params.work.difficulty (*send_block), nano::dev::network_params.work.threshold_base (send_block->work_version ())); send_block->block_work_set (*pool.generate (send_block->root ())); - ASSERT_LT (nano::dev::network_params.work.threshold_base (send_block->work_version ()), nano::dev::network_params.work.difficulty (*send_block)); + ASSERT_GE (nano::dev::network_params.work.difficulty (*send_block), nano::dev::network_params.work.threshold_base (send_block->work_version ())); } +// repeatedly start and cancel a work calculation and check that the callback is eventually called TEST (work, cancel) { nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - auto iterations (0); - auto done (false); + const nano::root key (1); + auto iterations = 0; + auto done = false; while (!done) { - nano::root key (1); - pool.generate ( - nano::work_version::work_1, key, nano::dev::network_params.work.base, [&done] (boost::optional work_a) { + pool.generate (nano::work_version::work_1, key, nano::dev::network_params.work.base, [&done] (boost::optional work_a) { done = !work_a; }); pool.cancel (key); @@ -69,7 +72,7 @@ TEST (work, cancel) } } -TEST (work, cancel_many) +TEST (work, cancel_one_out_of_many) { nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; nano::root key1 (1); @@ -87,59 +90,66 @@ TEST (work, cancel_many) pool.cancel (key1); } +// check that opencl hardware offloading works TEST (work, opencl) { nano::logger logger; - bool error (false); + bool error = false; nano::opencl_environment environment (error); ASSERT_TRUE (!error || !nano::opencl_loaded); - if (!environment.platforms.empty () && !environment.platforms.begin ()->devices.empty ()) + + if (environment.platforms.empty () || environment.platforms.begin ()->devices.empty ()) { - nano::opencl_config config (0, 0, 16 * 1024); - auto opencl (nano::opencl_work::create (true, config, logger, nano::dev::network_params.work)); - if (opencl != nullptr) - { - // 0 threads, should add 1 for managing OpenCL - nano::work_pool pool{ nano::dev::network_params.network, 0, std::chrono::nanoseconds (0), [&opencl] (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::atomic & ticket_a) { - return opencl->generate_work (version_a, root_a, difficulty_a); - } }; - ASSERT_NE (nullptr, pool.opencl); - nano::root root; - uint64_t difficulty (0xff00000000000000); - uint64_t difficulty_add (0x000f000000000000); - for (auto i (0); i < 16; ++i) - { - nano::random_pool::generate_block (root.bytes.data (), root.bytes.size ()); - auto result (*pool.generate (nano::work_version::work_1, root, difficulty)); - ASSERT_GE (nano::dev::network_params.work.difficulty (nano::work_version::work_1, root, result), difficulty); - difficulty += difficulty_add; - } - } - else - { - std::cerr << "Error starting OpenCL test" << std::endl; - } + GTEST_SKIP () << "Device with OpenCL support not found. Skipping OpenCL test" << std::endl; } - else + + nano::opencl_config config (0, 0, 16 * 1024); + auto opencl = nano::opencl_work::create (true, config, logger, nano::dev::network_params.work); + ASSERT_TRUE (opencl); + + // 0 threads, should add 1 for managing OpenCL + bool opencl_function_called = false; + nano::work_pool pool{ nano::dev::network_params.network, 0, std::chrono::nanoseconds (0), + [&opencl, &opencl_function_called] (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::atomic & ticket_a) { + opencl_function_called = true; + return opencl->generate_work (version_a, root_a, difficulty_a); + } }; + ASSERT_NE (nullptr, pool.opencl); + + nano::root root; + uint64_t difficulty (0xffff000000000000); + uint64_t difficulty_add (0x00000f0000000000); + for (auto i (0); i < 16; ++i) { - std::cout << "Device with OpenCL support not found. Skipping OpenCL test" << std::endl; + nano::random_pool::generate_block (root.bytes.data (), root.bytes.size ()); + auto nonce_opt = pool.generate (nano::work_version::work_1, root, difficulty); + ASSERT_TRUE (nonce_opt.has_value ()); + auto nonce = nonce_opt.get (); + ASSERT_GE (nano::dev::network_params.work.difficulty (nano::work_version::work_1, root, nonce), difficulty); + difficulty += difficulty_add; } + ASSERT_TRUE (opencl_function_called); } +// repeat difficulty calculations until a difficulty in a certain range is found TEST (work, difficulty) { nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::root root (1); - uint64_t difficulty1 (0xff00000000000000); - uint64_t difficulty2 (0xfff0000000000000); - uint64_t difficulty3 (0xffff000000000000); - uint64_t result_difficulty1 (0); + const nano::root root (1); + uint64_t difficulty1 = 0xff00000000000000; + uint64_t difficulty2 = 0xfff0000000000000; + uint64_t difficulty3 = 0xffff000000000000; + + // find a difficulty between difficulty1 and difficulty2 + uint64_t result_difficulty1 = 0; do { auto work1 = *pool.generate (nano::work_version::work_1, root, difficulty1); result_difficulty1 = nano::dev::network_params.work.difficulty (nano::work_version::work_1, root, work1); } while (result_difficulty1 > difficulty2); ASSERT_GT (result_difficulty1, difficulty1); + + // find a difficulty between difficulty2 and difficulty3 uint64_t result_difficulty2 (0); do { @@ -149,6 +159,7 @@ TEST (work, difficulty) ASSERT_GT (result_difficulty2, difficulty2); } +// check that the pow_rate_limiter of work_pool works, this test can fail occasionally TEST (work, eco_pow) { auto work_func = [] (std::promise & promise, std::chrono::nanoseconds interval) {