From eda0701887346dc726ba0daf4e8ef075525738d0 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Tue, 24 Nov 2020 23:13:34 +0300 Subject: [PATCH] Add util tests --- libs/util/CMakeLists.txt | 2 + libs/util/tests/array.cpp | 123 +++++++++++++++++++++ libs/util/tests/blob.cpp | 98 ++++++++++++++++ libs/util/tests/function.cpp | 209 +++++++++++++++++++++++++++++++++++ 4 files changed, 432 insertions(+) create mode 100644 libs/util/tests/array.cpp create mode 100644 libs/util/tests/blob.cpp create mode 100644 libs/util/tests/function.cpp diff --git a/libs/util/CMakeLists.txt b/libs/util/CMakeLists.txt index 3f74f9fa..5c2a34ef 100644 --- a/libs/util/CMakeLists.txt +++ b/libs/util/CMakeLists.txt @@ -6,3 +6,5 @@ file(GLOB_RECURSE PSEMEK_UTIL_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "so add_library(psemek-util ${PSEMEK_UTIL_HEADERS} ${PSEMEK_UTIL_SOURCES}) target_include_directories(psemek-util PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") target_link_libraries(psemek-util PUBLIC psemek-log ${CMAKE_THREAD_LIBS_INIT}) + +psemek_glob_tests(psemek-util tests) diff --git a/libs/util/tests/array.cpp b/libs/util/tests/array.cpp new file mode 100644 index 00000000..2f93addb --- /dev/null +++ b/libs/util/tests/array.cpp @@ -0,0 +1,123 @@ +#include + +#include + +using namespace psemek::util; + +test_case(util_array_empty) +{ + array a; + expect_equal(a.size(), 0); + expect(a.empty()); + + array b; + expect_equal(b.size(), 0); + expect(b.empty()); + + array c; + expect_equal(c.size(), 0); + expect(c.empty()); +} + +test_case(util_array_size) +{ + array a({16}); + expect(!a.empty()); + expect_equal(a.size(), 16); + expect_equal(a.width(), 16); + + array b({8, 16}); + expect(!b.empty()); + expect_equal(b.size(), 8 * 16); + expect_equal(b.width(), 8); + expect_equal(b.height(), 16); + + array c({4, 8, 16}); + expect(!c.empty()); + expect_equal(c.size(), 4 * 8 * 16); + expect_equal(c.width(), 4); + expect_equal(c.height(), 8); + expect_equal(c.depth(), 16); +} + +test_case(util_array_init) +{ + array a({16, 16}, 42); + for (std::size_t i = 0; i < a.width(); ++i) + for (std::size_t j = 0; j < a.height(); ++j) + expect_equal(a(i, j), 42); +} + +test_case(util_array_release) +{ + std::unique_ptr p(new int[256]); + auto q = p.get(); + + array a({16, 16}, std::move(p)); + expect_equal(a.size(), 256); + expect_equal(a.width(), 16); + expect_equal(a.height(), 16); + expect_equal_ptr(a.data(), q); + + p = a.release(); + expect_equal(a.size(), 0); + expect(a.empty()); + expect_equal_ptr(a.data(), nullptr); + expect_equal_ptr(p.get(), q); +} + +test_case(util_array_move) +{ + array a({16, 16}, 42); + + auto p = a.data(); + + array b(std::move(a)); + expect(a.empty()); + expect_equal(a.size(), 0); + expect(!b.empty()); + expect_equal(b.size(), 256); + expect_equal_ptr(b.data(), p); + + array c; + c = std::move(b); + expect(b.empty()); + expect_equal(b.size(), 0); + expect(!c.empty()); + expect_equal(c.size(), 256); + expect_equal_ptr(c.data(), p); +} + +test_case(util_array_copy) +{ + array a({16, 16}, 42); + + array b(a.copy()); + expect(!a.empty()); + expect(!b.empty()); + expect_equal(a.size(), b.size()); + expect_equal(a.size(), 256); + expect_different_ptr(a.data(), b.data()); +} + +test_case(util_array_lifetime) +{ + std::weak_ptr p; + + { + array, 2> a({16, 16}, std::make_shared(42)); + p = a(0, 0); + for (std::size_t i = 0; i < a.width(); ++i) + { + for (std::size_t j = 0; j < a.height(); ++j) + { + expect(a(i, j)); + expect_equal(*a(i, j), 42); + expect_equal(a(i, j).use_count(), a.size()); + } + } + } + + expect(!p.lock()); + expect_equal(p.use_count(), 0); +} diff --git a/libs/util/tests/blob.cpp b/libs/util/tests/blob.cpp new file mode 100644 index 00000000..cf03fc78 --- /dev/null +++ b/libs/util/tests/blob.cpp @@ -0,0 +1,98 @@ +#include + +#include + +using namespace psemek::util; + +test_case(util_blob_empty) +{ + blob b; + expect(!b); + expect_equal(b.size(), 0); + expect_equal_ptr(b.data(), nullptr); +} + +test_case(util_blob_alloc) +{ + blob b(16); + expect(b); + expect_equal(b.size(), 16); + expect_different_ptr(b.data(), nullptr); + + for (int i = 0; i < b.size(); ++i) + b[i] = static_cast(i); + + for (int i = 0; i < b.size(); ++i) + expect_equal((int)b[i], i); +} + +test_case(util_blob_release) +{ + blob b; + expect(!b); + expect_equal(b.size(), 0); + expect_equal_ptr(b.data(), nullptr); + + std::unique_ptr p(new char[16]); + auto q = p.get(); + + b = blob(16, std::move(p)); + expect(b); + expect_equal(b.size(), 16); + expect_equal_ptr(b.data(), q); + + p = b.release(); + + expect(!b); + expect_equal(b.size(), 0); + expect_equal_ptr(b.data(), nullptr); + expect_equal(p.get(), q); +} + +test_case(util_blob_copy) +{ + blob b(16); + expect(b); + expect_equal(b.size(), 16); + expect_different_ptr(b.data(), nullptr); + + blob c(b); + expect(c); + expect_equal(c.size(), 16); + expect_different_ptr(c.data(), nullptr); + + blob d; + expect(!d); + expect_equal(d.size(), 0); + expect_equal_ptr(d.data(), nullptr); + + d = c; + expect(d); + expect_equal(d.size(), 16); + expect_different_ptr(d.data(), nullptr); +} + +test_case(util_blob_move) +{ + blob b(16); + expect(b); + expect_equal(b.size(), 16); + expect_different_ptr(b.data(), nullptr); + + auto p = b.data(); + + blob c(std::move(b)); + expect(c); + expect_equal(c.size(), 16); + expect_equal_ptr(c.data(), p); + + blob d; + expect(!d); + expect_equal(d.size(), 0); + expect_equal_ptr(d.data(), nullptr); + + d = std::move(c); + expect(d); + expect_equal(d.size(), 16); + expect_equal_ptr(d.data(), p); +} diff --git a/libs/util/tests/function.cpp b/libs/util/tests/function.cpp new file mode 100644 index 00000000..92f09d5e --- /dev/null +++ b/libs/util/tests/function.cpp @@ -0,0 +1,209 @@ +#include + +#include + +#include + +using namespace psemek::util; + +test_case(util_function_empty_call) +{ + function f; + expect_throw(f(), std::bad_function_call); +} + +using heavy = std::array; + +static void util_function_assign_test(bool light) +{ + function f; + expect(!f); + + int counter = 0; + if (light) + f = [&counter]{ ++counter; }; + else + f = [&counter, h = heavy{}]{ ++counter; }; + expect(f); + + expect_equal(counter, 0); + f(); + expect_equal(counter, 1); + f(); + expect_equal(counter, 2); +} + +static void util_function_move_test(bool light) +{ + function f; + expect(!f); + + int counter = 0; + if (light) + f = [&counter]{ ++counter; }; + else + f = [&counter, h = heavy{}]{ ++counter; }; + expect(f); + + function g; + expect(!g); + + g = std::move(f); + expect(!f); + expect(g); + + expect_equal(counter, 0); + g(); + expect_equal(counter, 1); + g(); + expect_equal(counter, 2); + + function h = std::move(g); + expect(!f); + expect(!g); + expect(h); + + expect_equal(counter, 2); + h(); + expect_equal(counter, 3); + h(); + expect_equal(counter, 4); +} + +static void util_function_destroy_test(bool light) +{ + std::shared_ptr p = std::make_shared(0); + + auto wp = std::weak_ptr(p); + + { + function f, g; + expect(!f); + expect(!g); + + if (light) + { + f = [p]{ ++*p; }; + g = [p]{ --*p; }; + } + else + { + f = [p, h = heavy{}]{ ++*p; }; + g = [p, h = heavy{}]{ --*p; }; + } + expect(f); + expect(g); + expect(p); + expect_equal(p.use_count(), 3); + expect_equal(*p, 0); + + p.reset(); + expect(wp.lock()); + expect_equal(wp.use_count(), 2); + + expect_equal(*wp.lock(), 0); + f(); + expect_equal(*wp.lock(), 1); + f(); + expect_equal(*wp.lock(), 2); + g(); + expect_equal(*wp.lock(), 1); + g(); + expect_equal(*wp.lock(), 0); + + f.reset(); + expect(!f); + expect(wp.lock()); + expect_equal(wp.use_count(), 1); + } + + expect(!wp.lock()); + expect_equal(wp.use_count(), 0); +} + +namespace +{ + + struct fake_exception + : std::exception + { + char const * what() const noexcept { return "fake"; } + }; + + template + struct throw_on_move + { + Heavy heavy; + + throw_on_move() = default; + throw_on_move(throw_on_move &&) + { + throw fake_exception{}; + } + + void operator()() + {} + }; + +} + +static void util_function_guarantee_test(bool light) +{ + function f; + expect(!f); + + int counter = 0; + f = [&counter]{ ++counter; }; + expect(f); + expect_equal(counter, 0); + + if (light) + expect_throw(f = throw_on_move{}, fake_exception); + else + expect_throw(f = throw_on_move{}, fake_exception); + + expect(f); + expect_equal(counter, 0); + f(); + expect_equal(counter, 1); +} + +test_case(util_function_light_assign) +{ + util_function_assign_test(true); +} + +test_case(util_function_light_move) +{ + util_function_move_test(true); +} + +test_case(util_function_light_destroy) +{ + util_function_destroy_test(true); +} + +test_case(util_function_light_guarantee) +{ + util_function_guarantee_test(true); +} + +test_case(util_function_heavy_assign) +{ + util_function_assign_test(false); +} + +test_case(util_function_heavy_move) +{ + util_function_move_test(false); +} + +test_case(util_function_heavy_destroy) +{ + util_function_destroy_test(false); +} + +test_case(util_function_heavy_guarantee) +{ + util_function_guarantee_test(false); +}