Skip to content

Commit

Permalink
Refactor unit tests (#201)
Browse files Browse the repository at this point in the history
  • Loading branch information
mingxwa authored Nov 19, 2024
1 parent b172bae commit b61bab4
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 234 deletions.
80 changes: 33 additions & 47 deletions tests/proxy_creation_tests.cpp

Large diffs are not rendered by default.

14 changes: 8 additions & 6 deletions tests/proxy_dispatch_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#pragma warning(pop)
#endif // defined(_MSC_VER) && !defined(__clang__)

namespace {
namespace proxy_dispatch_tests_details {

struct CommaTester {
public:
Expand All @@ -35,7 +35,9 @@ struct PtrToMemTester {

PRO_DEF_FREE_AS_MEM_DISPATCH(FreeMemToString, std::to_string, ToString);

} // namespace
} // namespace proxy_dispatch_tests_details

namespace details = proxy_dispatch_tests_details;

TEST(ProxyDispatchTests, TestOpPlus) {
struct TestFacade : pro::facade_builder::add_convention<pro::operator_dispatch<"+">, int(), int(int val)>::build {};
Expand Down Expand Up @@ -297,7 +299,7 @@ TEST(ProxyDispatchTests, TestOpRightShiftAssignment) {

TEST(ProxyDispatchTests, TestOpComma) {
struct TestFacade : pro::facade_builder::add_convention<pro::operator_dispatch<",">, int(int val)>::build {};
CommaTester v{3};
details::CommaTester v{3};
pro::proxy<TestFacade> p = &v;
ASSERT_EQ((*p, 6), 9);
}
Expand Down Expand Up @@ -572,14 +574,14 @@ TEST(ProxyDispatchTests, TestRhsOpRightShiftAssignment) {

TEST(ProxyDispatchTests, TestRhsOpComma) {
struct TestFacade : pro::facade_builder::add_convention<pro::operator_dispatch<",", true>, int(int val)>::build {};
CommaTester v{3};
details::CommaTester v{3};
pro::proxy<TestFacade> p = &v;
ASSERT_EQ((7, *p), 21);
}

TEST(ProxyDispatchTests, TestRhsOpPtrToMem) {
struct TestFacade : pro::facade_builder::add_convention<pro::operator_dispatch<"->*", true>, int(int val)>::build {};
PtrToMemTester v{3};
details::PtrToMemTester v{3};
pro::proxy<TestFacade> p = &v;
ASSERT_EQ(2->**p, 6);
}
Expand Down Expand Up @@ -618,7 +620,7 @@ TEST(ProxyDispatchTests, TestImplciitConversion) {
}

TEST(ProxyDispatchTests, TestFreeAsMemDispatch) {
struct TestFacade : pro::facade_builder::add_convention<FreeMemToString, std::string() const>::build {};
struct TestFacade : pro::facade_builder::add_convention<details::FreeMemToString, std::string() const>::build {};
int v = 123;
pro::proxy<TestFacade> p = &v;
ASSERT_EQ(p->ToString(), "123");
Expand Down
34 changes: 16 additions & 18 deletions tests/proxy_integration_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
#include <vector>
#include "proxy.h"

namespace {

namespace spec {
namespace proxy_integration_tests_details {

PRO_DEF_MEM_DISPATCH(MemDraw, Draw);
PRO_DEF_MEM_DISPATCH(MemArea, Area);
Expand All @@ -29,8 +27,6 @@ struct Logger : pro::facade_builder
::add_convention<MemLog, void(const char*), void(const char*, const std::exception&)>
::build {};

} // namespace spec

class Rectangle {
public:
explicit Rectangle(double width, double height) : width_(width), height_(height) {}
Expand Down Expand Up @@ -61,7 +57,7 @@ class Point {
constexpr double Area() const noexcept { return 0; }
};

std::string PrintDrawableToString(pro::proxy<spec::Drawable> p) {
std::string PrintDrawableToString(pro::proxy<Drawable> p) {
std::stringstream result;
result << std::fixed << std::setprecision(5) << "shape = ";
p->Draw(result);
Expand Down Expand Up @@ -92,19 +88,19 @@ std::vector<std::string> ParseCommand(const std::string& s) {
return result;
}

pro::proxy<spec::Drawable> MakeDrawableFromCommand(const std::string& s) {
pro::proxy<Drawable> MakeDrawableFromCommand(const std::string& s) {
std::vector<std::string> parsed = ParseCommand(s);
if (!parsed.empty()) {
if (parsed[0u] == "Rectangle") {
if (parsed.size() == 3u) {
static std::pmr::unsynchronized_pool_resource rectangle_memory_pool;
std::pmr::polymorphic_allocator<> alloc{&rectangle_memory_pool};
return pro::allocate_proxy<spec::Drawable, Rectangle>(alloc, std::stod(parsed[1u]), std::stod(parsed[2u]));
return pro::allocate_proxy<Drawable, Rectangle>(alloc, std::stod(parsed[1u]), std::stod(parsed[2u]));
}
} else if (parsed[0u] == "Circle") {
if (parsed.size() == 2u) {
Circle circle{std::stod(parsed[1u])};
return pro::make_proxy<spec::Drawable>(circle);
return pro::make_proxy<Drawable>(circle);
}
} else if (parsed[0u] == "Point") {
if (parsed.size() == 1u) {
Expand Down Expand Up @@ -132,31 +128,33 @@ class StreamLogger {
std::ostream* out_;
};

} // namespace
} // namespace proxy_integration_tests_details

namespace details = proxy_integration_tests_details;

TEST(ProxyIntegrationTests, TestDrawable) {
pro::proxy<spec::Drawable> p = MakeDrawableFromCommand("Rectangle 2 3");
std::string s = PrintDrawableToString(std::move(p));
pro::proxy<details::Drawable> p = details::MakeDrawableFromCommand("Rectangle 2 3");
std::string s = details::PrintDrawableToString(std::move(p));
ASSERT_EQ(s, "shape = {Rectangle: width = 2.00000, height = 3.00000}, area = 6.00000");

p = MakeDrawableFromCommand("Circle 1");
s = PrintDrawableToString(std::move(p));
p = details::MakeDrawableFromCommand("Circle 1");
s = details::PrintDrawableToString(std::move(p));
ASSERT_EQ(s, "shape = {Circle: radius = 1.00000}, area = 3.14159");

p = MakeDrawableFromCommand("Point");
s = PrintDrawableToString(std::move(p));
p = details::MakeDrawableFromCommand("Point");
s = details::PrintDrawableToString(std::move(p));
ASSERT_EQ(s, "shape = {Point}, area = 0.00000");

try {
p = MakeDrawableFromCommand("Triangle 2 3");
p = details::MakeDrawableFromCommand("Triangle 2 3");
} catch (const std::runtime_error& e) {
ASSERT_STREQ(e.what(), "Invalid command");
}
}

TEST(ProxyIntegrationTests, TestLogger) {
std::ostringstream out;
auto logger = pro::make_proxy<spec::Logger, StreamLogger>(out);
auto logger = pro::make_proxy<details::Logger, details::StreamLogger>(out);
logger->Log("hello");
try {
throw std::runtime_error{"runtime error!"};
Expand Down
68 changes: 33 additions & 35 deletions tests/proxy_invocation_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@
#endif // defined(_MSC_VER) && !defined(__clang__)
#include "utils.h"

namespace {

namespace spec {
namespace proxy_invocation_tests_details {

template <class... Os>
struct MovableCallable : pro::facade_builder
Expand Down Expand Up @@ -113,8 +111,6 @@ struct SharedStringable : pro::facade_builder
::add_direct_convention<FreeGetWeak<SharedStringable>, pro::proxy<Weak<SharedStringable>>() const&>
::build {};

} // namespace spec

template <class F, bool NE, class... Args>
concept CallableFacade =
requires(pro::proxy<F> p, Args... args) {
Expand All @@ -123,16 +119,18 @@ concept CallableFacade =
};

// Static assertions for facade Callable
static_assert(!CallableFacade<spec::Callable<int(double)>, false, std::nullptr_t>); // Wrong arguments
static_assert(CallableFacade<spec::Callable<int(double)>, false, float>); // Invoking without specifying a dispatch
static_assert(CallableFacade<spec::Callable<int(double), void(int) noexcept>, true, int>); // Invoking noexcept overloads
static_assert(CallableFacade<spec::Callable<int(double), void(int) noexcept>, false, double>); // Invoking overloads that may throw
static_assert(!CallableFacade<Callable<int(double)>, false, std::nullptr_t>); // Wrong arguments
static_assert(CallableFacade<Callable<int(double)>, false, float>); // Invoking without specifying a dispatch
static_assert(CallableFacade<Callable<int(double), void(int) noexcept>, true, int>); // Invoking noexcept overloads
static_assert(CallableFacade<Callable<int(double), void(int) noexcept>, false, double>); // Invoking overloads that may throw

template <class... Args>
std::vector<std::type_index> GetTypeIndices()
{ return {std::type_index{typeid(Args)}...}; }

} // namespace
} // namespace proxy_invocation_tests_details

namespace details = proxy_invocation_tests_details;

TEST(ProxyInvocationTests, TestArgumentForwarding) {
std::string arg1 = "My string";
Expand All @@ -146,7 +144,7 @@ TEST(ProxyInvocationTests, TestArgumentForwarding) {
arg2_received = std::move(v);
return expected_result;
};
pro::proxy<spec::Callable<int(std::string, std::vector<int>)>> p = &f;
pro::proxy<details::Callable<int(std::string, std::vector<int>)>> p = &f;
int result = (*p)(arg1, std::move(arg2));
ASSERT_TRUE(p.has_value());
ASSERT_EQ(arg1_received, arg1);
Expand All @@ -159,7 +157,7 @@ TEST(ProxyInvocationTests, TestThrow) {
const char* expected_error_message = "My exception";
auto f = [&] { throw std::runtime_error{ expected_error_message }; };
bool exception_thrown = false;
pro::proxy<spec::Callable<void()>> p = &f;
pro::proxy<details::Callable<void()>> p = &f;
try {
(*p)();
} catch (const std::runtime_error& e) {
Expand All @@ -172,7 +170,7 @@ TEST(ProxyInvocationTests, TestThrow) {

TEST(ProxyInvocationTests, TestMultipleDispatches_Unique) {
std::list<int> l = { 1, 2, 3 };
pro::proxy<spec::Iterable<int>> p = &l;
pro::proxy<details::Iterable<int>> p = &l;
ASSERT_EQ(Size(*p), 3);
int sum = 0;
auto accumulate_sum = [&](int x) { sum += x; };
Expand All @@ -182,12 +180,12 @@ TEST(ProxyInvocationTests, TestMultipleDispatches_Unique) {

TEST(ProxyInvocationTests, TestMultipleDispatches_Duplicated) {
struct DuplicatedIterable : pro::facade_builder
::add_convention<spec::FreeForEach, void(std::function<void(int&)>)>
::add_convention<spec::FreeSize, std::size_t()>
::add_convention<spec::FreeForEach, void(std::function<void(int&)>)>
::add_convention<details::FreeForEach, void(std::function<void(int&)>)>
::add_convention<details::FreeSize, std::size_t()>
::add_convention<details::FreeForEach, void(std::function<void(int&)>)>
::build {};
static_assert(sizeof(pro::details::facade_traits<DuplicatedIterable>::meta) ==
sizeof(pro::details::facade_traits<spec::Iterable<int>>::meta));
sizeof(pro::details::facade_traits<details::Iterable<int>>::meta));
std::list<int> l = { 1, 2, 3 };
pro::proxy<DuplicatedIterable> p = &l;
ASSERT_EQ(Size(*p), 3);
Expand All @@ -199,7 +197,7 @@ TEST(ProxyInvocationTests, TestMultipleDispatches_Duplicated) {

TEST(ProxyInvocationTests, TestRecursiveDefinition) {
std::list<int> l = { 1, 2, 3 };
pro::proxy<spec::Container<int>> p = &l;
pro::proxy<details::Container<int>> p = &l;
ASSERT_EQ(Size(*p), 3);
int sum = 0;
auto accumulate_sum = [&](int x) { sum += x; };
Expand All @@ -218,45 +216,45 @@ TEST(ProxyInvocationTests, TestOverloadResolution) {
::build {};
std::vector<std::type_index> side_effect;
auto p = pro::make_proxy<OverloadedCallable>([&](auto&&... args)
{ side_effect = GetTypeIndices<std::decay_t<decltype(args)>...>(); });
{ side_effect = details::GetTypeIndices<std::decay_t<decltype(args)>...>(); });
(*p)(123);
ASSERT_EQ(side_effect, GetTypeIndices<int>());
ASSERT_EQ(side_effect, details::GetTypeIndices<int>());
(*p)(1.23);
ASSERT_EQ(side_effect, GetTypeIndices<double>());
ASSERT_EQ(side_effect, details::GetTypeIndices<double>());
char foo[2];
(*p)(foo);
ASSERT_EQ(side_effect, GetTypeIndices<char*>());
ASSERT_EQ(side_effect, details::GetTypeIndices<char*>());
(*p)("lalala");
ASSERT_EQ(side_effect, GetTypeIndices<const char*>());
ASSERT_EQ(side_effect, details::GetTypeIndices<const char*>());
(*p)("lalala", 0);
ASSERT_EQ(side_effect, (GetTypeIndices<std::string, int>()));
ASSERT_EQ(side_effect, (details::GetTypeIndices<std::string, int>()));
ASSERT_FALSE((std::is_invocable_v<decltype(*p), std::vector<int>>));
}

TEST(ProxyInvocationTests, TestNoexcept) {
std::vector<std::type_index> side_effect;
auto p = pro::make_proxy<spec::Callable<void(int) noexcept, void(double)>>([&](auto&&... args) noexcept
{ side_effect = GetTypeIndices<std::decay_t<decltype(args)>...>(); });
auto p = pro::make_proxy<details::Callable<void(int) noexcept, void(double)>>([&](auto&&... args) noexcept
{ side_effect = details::GetTypeIndices<std::decay_t<decltype(args)>...>(); });
static_assert(noexcept((*p)(123)));
(*p)(123);
ASSERT_EQ(side_effect, GetTypeIndices<int>());
ASSERT_EQ(side_effect, details::GetTypeIndices<int>());
static_assert(!noexcept((*p)(1.23)));
(*p)(1.23);
ASSERT_EQ(side_effect, GetTypeIndices<double>());
ASSERT_EQ(side_effect, details::GetTypeIndices<double>());
ASSERT_FALSE((std::is_invocable_v<decltype(*p), char*>));
}

TEST(ProxyInvocationTests, TestFunctionPointer) {
struct TestFacade : spec::Callable<std::vector<std::type_index>()> {};
pro::proxy<TestFacade> p{ &GetTypeIndices<int, double> };
struct TestFacade : details::Callable<std::vector<std::type_index>()> {};
pro::proxy<TestFacade> p{ &details::GetTypeIndices<int, double> };
auto ret = (*p)();
ASSERT_EQ(ret, (GetTypeIndices<int, double>()));
ASSERT_EQ(ret, (details::GetTypeIndices<int, double>()));
}

TEST(ProxyInvocationTests, TestMemberDispatchDefault) {
std::vector<std::string> container1{ "hello", "world", "!"};
std::list<std::string> container2{ "hello", "world" };
pro::proxy<spec::ResourceDictionary> p = &container1;
pro::proxy<details::ResourceDictionary> p = &container1;
ASSERT_EQ(p->at(0), "hello");
p = &container2;
{
Expand All @@ -274,13 +272,13 @@ TEST(ProxyInvocationTests, TestMemberDispatchDefault) {
TEST(ProxyInvocationTests, TestFreeDispatchDefault) {
{
int side_effect = 0;
auto p = pro::make_proxy<spec::WeakCallable<void()>>([&] { side_effect = 1; });
auto p = pro::make_proxy<details::WeakCallable<void()>>([&] { side_effect = 1; });
(*p)();
ASSERT_EQ(side_effect, 1);
}
{
bool exception_thrown = false;
auto p = pro::make_proxy<spec::WeakCallable<void()>>(123);
auto p = pro::make_proxy<details::WeakCallable<void()>>(123);
try {
(*p)();
} catch (const std::runtime_error& e) {
Expand All @@ -293,7 +291,7 @@ TEST(ProxyInvocationTests, TestFreeDispatchDefault) {

TEST(ProxyInvocationTests, TestObserverDispatch) {
int test_val = 123;
pro::proxy<spec::SharedStringable> p{std::make_shared<int>(test_val)};
pro::proxy<details::SharedStringable> p{std::make_shared<int>(test_val)};
auto weak = GetWeak(p);
ASSERT_TRUE(weak.has_value());
{
Expand Down
Loading

0 comments on commit b61bab4

Please sign in to comment.