diff options
author | Jack Lloyd <[email protected]> | 2019-01-31 11:06:04 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2019-01-31 11:07:59 -0500 |
commit | f52cde49f5fcf8aa3a72c15c665940c16756a16b (patch) | |
tree | b31eb1030d7c3d1bad779488def4c26cc3e8a4c9 | |
parent | b508bcf6c9f29319a198ad97975343d5ba3e8516 (diff) |
Add a simple Thread_Pool test
And allow registering one-off functions as tests
-rw-r--r-- | src/tests/test_thread_utils.cpp | 56 | ||||
-rw-r--r-- | src/tests/tests.h | 32 |
2 files changed, 88 insertions, 0 deletions
diff --git a/src/tests/test_thread_utils.cpp b/src/tests/test_thread_utils.cpp new file mode 100644 index 000000000..2374df860 --- /dev/null +++ b/src/tests/test_thread_utils.cpp @@ -0,0 +1,56 @@ +/* +* (C) 2019 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "tests.h" + +#if defined(BOTAN_TARGET_OS_HAS_THREADS) && defined(BOTAN_HAS_THREAD_UTILS) + +#include <botan/internal/thread_pool.h> +#include <chrono> + +namespace Botan_Tests { + +// TODO test Barrier +// TODO test Semaphore + +namespace { + +Test::Result thread_pool() + { + Test::Result result("Thread_Pool"); + + // Using lots of threads since here the works spend most of the time sleeping + Botan::Thread_Pool pool(16); + + auto sleep_and_return = [](size_t x) -> size_t { + std::this_thread::sleep_for(std::chrono::milliseconds((x*97)%127)); + return x; + }; + + std::vector<std::future<size_t>> futures; + for(size_t i = 0; i != 100; ++i) + { + auto fut = pool.run(sleep_and_return, i); + futures.push_back(std::move(fut)); + } + + for(size_t i = 0; i != futures.size(); ++i) + { + result.test_eq("Expected return value", futures[i].get(), i); + } + + pool.shutdown(); + + return result; + } + +BOTAN_REGISTER_TEST_FN("thread_pool", thread_pool); + +} + +} + +#endif diff --git a/src/tests/tests.h b/src/tests/tests.h index 4bf9fb0db..22651ff8c 100644 --- a/src/tests/tests.h +++ b/src/tests/tests.h @@ -530,6 +530,38 @@ class Test #define BOTAN_REGISTER_TEST(type, Test_Class) \ Test::Registration<Test_Class> reg_ ## Test_Class ## _tests(type) +typedef Test::Result (*test_fn)(); + +class FnTest : public Test + { + public: + FnTest(test_fn fn) : m_fn(fn) {} + + std::vector<Test::Result> run() override + { + return {m_fn()}; + } + + private: + test_fn m_fn; + }; + +class FnRegistration + { + public: + FnRegistration(const std::string& name, test_fn fn) + { + if(Test::global_registry().count(name) != 0) + throw Test_Error("Duplicate registration of test '" + name + "'"); + + auto maker = [=]() -> Test* { return new FnTest(fn); }; + Test::global_registry().insert(std::make_pair(name, maker)); + } + }; + +#define BOTAN_REGISTER_TEST_FN(test_name, fn_name) \ + FnRegistration reg_ ## fn_name(test_name, fn_name) + class VarMap { public: |