Add util tests

This commit is contained in:
Nikita Lisitsa 2020-11-24 23:13:34 +03:00
parent c6a8590b2c
commit eda0701887
4 changed files with 432 additions and 0 deletions

View file

@ -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)

123
libs/util/tests/array.cpp Normal file
View file

@ -0,0 +1,123 @@
#include <psemek/test/test.hpp>
#include <psemek/util/array.hpp>
using namespace psemek::util;
test_case(util_array_empty)
{
array<int, 1> a;
expect_equal(a.size(), 0);
expect(a.empty());
array<int, 2> b;
expect_equal(b.size(), 0);
expect(b.empty());
array<int, 3> c;
expect_equal(c.size(), 0);
expect(c.empty());
}
test_case(util_array_size)
{
array<int, 1> a({16});
expect(!a.empty());
expect_equal(a.size(), 16);
expect_equal(a.width(), 16);
array<int, 2> b({8, 16});
expect(!b.empty());
expect_equal(b.size(), 8 * 16);
expect_equal(b.width(), 8);
expect_equal(b.height(), 16);
array<int, 3> 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<int, 2> 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<int[]> p(new int[256]);
auto q = p.get();
array<int, 2> 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<int, 2> a({16, 16}, 42);
auto p = a.data();
array<int, 2> 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<int, 2> 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<int, 2> a({16, 16}, 42);
array<int, 2> 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<int> p;
{
array<std::shared_ptr<int>, 2> a({16, 16}, std::make_shared<int>(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);
}

98
libs/util/tests/blob.cpp Normal file
View file

@ -0,0 +1,98 @@
#include <psemek/test/test.hpp>
#include <psemek/util/blob.hpp>
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<char>(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<char[]> 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);
}

View file

@ -0,0 +1,209 @@
#include <psemek/test/test.hpp>
#include <psemek/util/function.hpp>
#include <memory>
using namespace psemek::util;
test_case(util_function_empty_call)
{
function<void()> f;
expect_throw(f(), std::bad_function_call);
}
using heavy = std::array<int, 256>;
static void util_function_assign_test(bool light)
{
function<void()> 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<void()> f;
expect(!f);
int counter = 0;
if (light)
f = [&counter]{ ++counter; };
else
f = [&counter, h = heavy{}]{ ++counter; };
expect(f);
function<void()> 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<void()> 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<int> p = std::make_shared<int>(0);
auto wp = std::weak_ptr(p);
{
function<void()> 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 <typename Heavy>
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<void()> f;
expect(!f);
int counter = 0;
f = [&counter]{ ++counter; };
expect(f);
expect_equal(counter, 0);
if (light)
expect_throw(f = throw_on_move<int>{}, fake_exception);
else
expect_throw(f = throw_on_move<heavy>{}, 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);
}