diff options
Diffstat (limited to 'src/test/test_any.cc')
-rw-r--r-- | src/test/test_any.cc | 812 |
1 files changed, 812 insertions, 0 deletions
diff --git a/src/test/test_any.cc b/src/test/test_any.cc new file mode 100644 index 000000000..82d4a43f1 --- /dev/null +++ b/src/test/test_any.cc @@ -0,0 +1,812 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2018 Adam C. Emerson <aemerson@redhat.com> + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#include <initializer_list> +#include <optional> + +#include "gtest/gtest.h" + +#include "include/any.h" + +using std::optional; +using std::bad_any_cast; + +using ceph::immobile_any; +using ceph::unique_any; +using ceph::shared_any; + +using ceph::make_immobile_any; +using ceph::make_unique_any; +using ceph::make_shared_any; + +using ceph::any_cast; +using std::swap; + +template<typename A> +static void test_empty() { + A a; + EXPECT_FALSE(a.has_value()); + EXPECT_EQ(typeid(void), a.type()); + a.reset(); + EXPECT_FALSE(a.has_value()); + EXPECT_EQ(typeid(void), a.type()); + +} + +TEST(Empty, Immobile) { + static_assert(std::is_nothrow_default_constructible_v<immobile_any<1024>>); + test_empty<immobile_any<1024>>(); +} + +TEST(Empty, Unique) { + static_assert(std::is_nothrow_default_constructible_v<unique_any>); + test_empty<unique_any>(); +} + +TEST(Empty, Shared) { + static_assert(std::is_nothrow_default_constructible_v<shared_any>); + test_empty<shared_any>(); +} + +struct cmd_tattler { + static thread_local bool copied; + static thread_local bool moved; + static thread_local bool destructed; + + static void reset() { + copied = false; + moved = false; + destructed = false; + } + + cmd_tattler() noexcept = default; + ~cmd_tattler() noexcept { + if (destructed) { + std::terminate(); + } + destructed = true; + } + cmd_tattler(const cmd_tattler&) noexcept { + if (copied) { + std::terminate(); + } + copied = true; + } + cmd_tattler& operator =(const cmd_tattler&) noexcept { + if (copied) { + std::terminate(); + } + copied = true; + return *this; + } + + cmd_tattler(cmd_tattler&&) noexcept { + if (moved) { + std::terminate(); + } + moved = true; + } + cmd_tattler& operator =(cmd_tattler&&) noexcept { + if (moved) { + std::terminate(); + } + moved = true; + return *this; + } +}; + +thread_local bool cmd_tattler::copied = false; +thread_local bool cmd_tattler::moved = false; +thread_local bool cmd_tattler::destructed = false; + +struct not_noexcept { + not_noexcept() = default; + + not_noexcept(const not_noexcept&) noexcept(false) { + } + not_noexcept& operator =(const not_noexcept&) noexcept(false) { + return *this; + } + + not_noexcept(not_noexcept&&) noexcept(false) { + } + not_noexcept& operator =(not_noexcept&&) noexcept(false) { + return *this; + } + + template<typename ...Args> + explicit not_noexcept(Args&& ...) noexcept(false) { + } + + template<typename U, typename ...Args> + not_noexcept(std::initializer_list<U>, Args&& ...) noexcept(false) { + } +}; + +template<typename A> +static void test_value_CMD() { + { + cmd_tattler::reset(); + cmd_tattler c; + A a(c); + EXPECT_TRUE(cmd_tattler::copied); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(cmd_tattler), a.type()); + a.reset(); + EXPECT_TRUE(cmd_tattler::destructed); + EXPECT_FALSE(a.has_value()); + EXPECT_EQ(typeid(void), a.type()); + + cmd_tattler::reset(); + a = c; + EXPECT_TRUE(cmd_tattler::copied); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(cmd_tattler), a.type()); + + cmd_tattler::reset(); + a = c; + EXPECT_TRUE(cmd_tattler::copied); + EXPECT_TRUE(cmd_tattler::destructed); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(cmd_tattler), a.type()); + cmd_tattler::reset(); + a.reset(); + EXPECT_TRUE(cmd_tattler::destructed); + cmd_tattler::reset(); + } + { + cmd_tattler::reset(); + cmd_tattler c; + A a(std::move(c)); + EXPECT_TRUE(cmd_tattler::moved); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(cmd_tattler), a.type()); + a.reset(); + EXPECT_TRUE(cmd_tattler::destructed); + EXPECT_FALSE(a.has_value()); + EXPECT_EQ(typeid(void), a.type()); + + cmd_tattler::reset(); + a = std::move(c); + EXPECT_TRUE(cmd_tattler::moved); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(cmd_tattler), a.type()); + + cmd_tattler::reset(); + a = std::move(c); + EXPECT_TRUE(cmd_tattler::moved); + EXPECT_TRUE(cmd_tattler::destructed); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(cmd_tattler), a.type()); + cmd_tattler::reset(); + a.reset(); + EXPECT_TRUE(cmd_tattler::destructed); + cmd_tattler::reset(); + } + { + cmd_tattler::reset(); + A a(cmd_tattler{}); + EXPECT_TRUE(cmd_tattler::moved); + EXPECT_TRUE(cmd_tattler::destructed); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(cmd_tattler), a.type()); + + cmd_tattler::reset(); + a.reset(); + EXPECT_TRUE(cmd_tattler::destructed); + EXPECT_FALSE(a.has_value()); + EXPECT_EQ(typeid(void), a.type()); + + cmd_tattler::reset(); + a = cmd_tattler{}; + EXPECT_TRUE(cmd_tattler::moved); + EXPECT_TRUE(cmd_tattler::destructed); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(cmd_tattler), a.type()); + cmd_tattler::reset(); + a.reset(); + EXPECT_TRUE(cmd_tattler::destructed); + cmd_tattler::reset(); + } +} + + + +TEST(Value_CMD, Immobile) { + static_assert(std::is_nothrow_constructible_v< + immobile_any<1024>, const cmd_tattler&>); + static_assert(std::is_nothrow_assignable_v< + immobile_any<1024>, const cmd_tattler&>); + static_assert(std::is_nothrow_constructible_v< + immobile_any<1024>, cmd_tattler&&>); + static_assert(std::is_nothrow_assignable_v< + immobile_any<1024>, cmd_tattler&&>); + + static_assert(!std::is_nothrow_constructible_v< + immobile_any<1024>, const not_noexcept&>); + static_assert(!std::is_nothrow_assignable_v< + immobile_any<1024>, const not_noexcept&>); + static_assert(!std::is_nothrow_constructible_v< + immobile_any<1024>, not_noexcept&&>); + static_assert(!std::is_nothrow_assignable_v< + immobile_any<1024>, not_noexcept&&>); + + test_value_CMD<immobile_any<1024>>(); +} + +TEST(Value_CMD, Unique) { + static_assert(!std::is_nothrow_constructible_v< + unique_any, const cmd_tattler&>); + static_assert(!std::is_nothrow_assignable_v< + unique_any, const cmd_tattler&>); + static_assert(!std::is_nothrow_constructible_v< + unique_any, cmd_tattler&&>); + static_assert(!std::is_nothrow_assignable_v< + unique_any, cmd_tattler&&>); + + static_assert(!std::is_nothrow_constructible_v< + unique_any, const not_noexcept&>); + static_assert(!std::is_nothrow_assignable_v< + unique_any, const not_noexcept&>); + static_assert(!std::is_nothrow_constructible_v< + unique_any, not_noexcept&&>); + static_assert(!std::is_nothrow_assignable_v< + unique_any, not_noexcept&&>); + + test_value_CMD<unique_any>(); +} + +TEST(Value_CMD, Shared) { + static_assert(!std::is_nothrow_constructible_v< + shared_any, const cmd_tattler&>); + static_assert(!std::is_nothrow_assignable_v< + shared_any, const cmd_tattler&>); + static_assert(!std::is_nothrow_constructible_v< + shared_any, cmd_tattler&&>); + static_assert(!std::is_nothrow_assignable_v< + shared_any, cmd_tattler&&>); + + static_assert(!std::is_nothrow_constructible_v< + shared_any, const not_noexcept&>); + static_assert(!std::is_nothrow_assignable_v< + shared_any, const not_noexcept&>); + static_assert(!std::is_nothrow_constructible_v< + shared_any, not_noexcept&&>); + static_assert(!std::is_nothrow_assignable_v< + shared_any, not_noexcept&&>); + + test_value_CMD<shared_any>(); +} + +template<typename A> +static void test_move() { + { + A a(5); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(int), a.type()); + + A b(std::move(a)); + EXPECT_TRUE(b.has_value()); + EXPECT_EQ(typeid(int), b.type()); + + EXPECT_FALSE(a.has_value()); + EXPECT_EQ(typeid(void), a.type()); + } + { + cmd_tattler::reset(); + A a(cmd_tattler{}); + + A b(5); + EXPECT_TRUE(b.has_value()); + EXPECT_EQ(typeid(int), b.type()); + cmd_tattler::reset(); + + a = std::move(b); + EXPECT_TRUE(cmd_tattler::destructed); + + EXPECT_FALSE(b.has_value()); + EXPECT_EQ(typeid(void), b.type()); + + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(int), a.type()); + } +} + +static_assert(!std::is_move_constructible_v<immobile_any<1024>>); +static_assert(!std::is_move_assignable_v<immobile_any<1024>>); + +TEST(Move, Unique) { + static_assert(std::is_nothrow_move_constructible_v<unique_any>); + static_assert(std::is_nothrow_move_assignable_v<unique_any>); + + test_move<unique_any>(); +} + +TEST(Move, Shared) { + static_assert(std::is_nothrow_move_constructible_v<shared_any>); + static_assert(std::is_nothrow_move_assignable_v<shared_any>); + + test_move<shared_any>(); +} + +template<typename A> +static void test_copy() { + { + const A a(5); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(int), a.type()); + + A b(a); + EXPECT_TRUE(b.has_value()); + EXPECT_EQ(typeid(int), b.type()); + + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(int), a.type()); + + EXPECT_EQ(any_cast<int>(a), any_cast<int>(b)); + } + { + cmd_tattler::reset(); + A a(cmd_tattler{}); + + const A b(5); + EXPECT_TRUE(b.has_value()); + EXPECT_EQ(typeid(int), b.type()); + cmd_tattler::reset(); + + a = b; + EXPECT_TRUE(cmd_tattler::destructed); + + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(int), a.type()); + + EXPECT_TRUE(b.has_value()); + EXPECT_EQ(typeid(int), b.type()); + + EXPECT_EQ(any_cast<int>(a), any_cast<int>(b)); + } +} + +static_assert(!std::is_copy_constructible_v<immobile_any<1024>>); +static_assert(!std::is_copy_assignable_v<immobile_any<1024>>); + +static_assert(!std::is_copy_constructible_v<unique_any>); +static_assert(!std::is_copy_assignable_v<unique_any>); + +TEST(Copy, Shared) { + static_assert(std::is_nothrow_copy_constructible_v<shared_any>); + test_copy<shared_any>(); +} + +struct unmoving { + optional<int> a; + + unmoving() noexcept {} + + template<typename... Args> + explicit unmoving(Args&& ...args) noexcept + : a(sizeof...(Args)) {} + + template<typename U, typename... Args> + explicit unmoving(std::initializer_list<U> l) noexcept + : a(-l.size()) {} + + template<typename U, typename... Args> + unmoving(std::initializer_list<U> l, Args&& ...args) noexcept + : a(-l.size() * sizeof...(Args)) {} + + unmoving(const unmoving&) = delete; + unmoving& operator =(const unmoving&) = delete; + + unmoving(unmoving&&) = delete; + unmoving& operator =(unmoving&&) = delete; +}; + +template<typename A> +static void test_unmoving_pack_il() { + // Nothing! + { + const A a(std::in_place_type<unmoving>); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_FALSE(any_cast<const unmoving&>(a).a); + } + { + cmd_tattler::reset(); + A a(cmd_tattler{}); + + cmd_tattler::reset(); + a.template emplace<unmoving>(); + EXPECT_TRUE(cmd_tattler::destructed); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_FALSE(any_cast<unmoving&>(a).a); + } + + // Pack! + { + const A a(std::in_place_type<unmoving>, nullptr, 5, 3.1); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_TRUE(any_cast<const unmoving&>(a).a); + EXPECT_EQ(3, *any_cast<const unmoving&>(a).a); + } + { + cmd_tattler::reset(); + A a(cmd_tattler{}); + + cmd_tattler::reset(); + a.template emplace<unmoving>(nullptr, 5, 3.1); + EXPECT_TRUE(cmd_tattler::destructed); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_EQ(3, *any_cast<unmoving&>(a).a); + } + + // List! + { + const A a(std::in_place_type<unmoving>, {true, true, true, true}); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_TRUE(any_cast<const unmoving&>(a).a); + EXPECT_EQ(-4, *any_cast<const unmoving&>(a).a); + } + { + cmd_tattler::reset(); + A a(cmd_tattler{}); + + cmd_tattler::reset(); + a.template emplace<unmoving>({true, true, true, true}); + EXPECT_TRUE(cmd_tattler::destructed); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_EQ(-4, *any_cast<unmoving&>(a).a); + } + + // List + pack!! + { + const A a(std::in_place_type<unmoving>, {true, true, true, true}, + nullptr, 5, 3.1); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_TRUE(any_cast<const unmoving&>(a).a); + EXPECT_EQ(-12, *any_cast<const unmoving&>(a).a); + } + { + cmd_tattler::reset(); + A a(cmd_tattler{}); + + cmd_tattler::reset(); + a.template emplace<unmoving>({true, true, true, true}, nullptr, 5, 3.1); + EXPECT_TRUE(cmd_tattler::destructed); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_EQ(-12, *any_cast<unmoving&>(a).a); + } +} + +TEST(UmovingPackIl, Immobile) { + static_assert(std::is_nothrow_constructible_v<immobile_any<1024>, + std::in_place_type_t<unmoving>>); + static_assert(noexcept(immobile_any<1024>{}.emplace<unmoving>())); + + static_assert(std::is_nothrow_constructible_v<immobile_any<1024>, + std::in_place_type_t<unmoving>, std::nullptr_t, int, double>); + static_assert(noexcept(immobile_any<1024>{}.emplace<unmoving>( + nullptr, 5, 3.1))); + + static_assert(std::is_nothrow_constructible_v<immobile_any<1024>, + std::in_place_type_t<unmoving>, std::initializer_list<int>>); + static_assert(noexcept(immobile_any<1024>{}.emplace<unmoving>( + {true, true, true, true}))); + + static_assert(std::is_nothrow_constructible_v<immobile_any<1024>, + std::in_place_type_t<unmoving>, std::initializer_list<int>, + std::nullptr_t, int, double>); + static_assert(noexcept(immobile_any<1024>{}.emplace<unmoving>( + {true, true, true, true}, nullptr, 5, 3.1))); + + test_unmoving_pack_il<immobile_any<1024>>(); +} + +TEST(UmovingPackIl, Unique) { + static_assert(!std::is_nothrow_constructible_v<unique_any, + std::in_place_type_t<unmoving>>); + static_assert(!noexcept(unique_any{}.emplace<unmoving>())); + + static_assert(!std::is_nothrow_constructible_v<unique_any, + std::in_place_type_t<unmoving>, std::nullptr_t, int, double>); + static_assert(!noexcept(unique_any{}.emplace<unmoving>( + nullptr, 5, 3.1))); + + static_assert(!std::is_nothrow_constructible_v<unique_any, + std::in_place_type_t<unmoving>, std::initializer_list<int>>); + static_assert(!noexcept(unique_any{}.emplace<unmoving>( + {true, true, true, true}))); + + static_assert(!std::is_nothrow_constructible_v<unique_any, + std::in_place_type_t<unmoving>, std::initializer_list<int>, + std::nullptr_t, int, double>); + static_assert(!noexcept(unique_any{}.emplace<unmoving>( + {true, true, true, true}, nullptr, 5, 3.1))); + + test_unmoving_pack_il<unique_any>(); +} + +TEST(UmovingPackIl, Shared) { + static_assert(!std::is_nothrow_constructible_v<shared_any, + std::in_place_type_t<unmoving>>); + static_assert(!noexcept(shared_any{}.emplace<unmoving>())); + + static_assert(!std::is_nothrow_constructible_v<shared_any, + std::in_place_type_t<unmoving>, std::nullptr_t, int, double>); + static_assert(!noexcept(shared_any{}.emplace<unmoving>( + nullptr, 5, 3.1))); + + static_assert(!std::is_nothrow_constructible_v<shared_any, + std::in_place_type_t<unmoving>, std::initializer_list<int>>); + static_assert(!noexcept(shared_any{}.emplace<unmoving>( + {true, true, true, true}))); + + static_assert(!std::is_nothrow_constructible_v<shared_any, + std::in_place_type_t<unmoving>, std::initializer_list<int>, + std::nullptr_t, int, double>); + static_assert(!noexcept(shared_any{}.emplace<unmoving>( + {true, true, true, true}, nullptr, 5, 3.1))); + + test_unmoving_pack_il<shared_any>(); +} + +template<typename A> +static void test_swap() { + A a(true); + ASSERT_TRUE(a.has_value()); + ASSERT_EQ(typeid(bool), a.type()); + ASSERT_EQ(true, any_cast<bool>(a)); + + A b(5); + ASSERT_TRUE(b.has_value()); + ASSERT_EQ(typeid(int), b.type()); + ASSERT_EQ(5, any_cast<int>(b)); + + a.swap(b); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(int), a.type()); + EXPECT_EQ(5, any_cast<int>(a)); + + EXPECT_TRUE(b.has_value()); + ASSERT_EQ(typeid(bool), b.type()); + ASSERT_EQ(true, any_cast<bool>(b)); + + swap(a,b); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(bool), a.type()); + EXPECT_EQ(true, any_cast<bool>(a)); + + EXPECT_TRUE(b.has_value()); + EXPECT_EQ(typeid(int), b.type()); + EXPECT_EQ(5, any_cast<int>(b)); +} + +static_assert(!std::is_swappable_v<immobile_any<1024>>); + +TEST(Swap, Unique) { + static_assert(std::is_nothrow_swappable_v<unique_any>); + test_swap<unique_any>(); +} + +TEST(Swap, Shared) { + static_assert(std::is_nothrow_swappable_v<shared_any>); + test_swap<shared_any>(); +} + +template<typename A> +static void test_cast() { + // Empty + { + A a; + EXPECT_EQ(nullptr, any_cast<int>(&a)); + EXPECT_THROW({any_cast<int>(a);}, bad_any_cast); + EXPECT_THROW({any_cast<int&>(a);}, bad_any_cast); + EXPECT_THROW({any_cast<int>(std::move(a));}, bad_any_cast); + EXPECT_THROW({any_cast<int&&>(std::move(a));}, bad_any_cast); + } + + // Constant Empty + { + const A a{}; + EXPECT_EQ(nullptr, any_cast<int>(const_cast<const A*>(&a))); + EXPECT_THROW({any_cast<int>(a);}, bad_any_cast); + EXPECT_THROW({any_cast<const int&>(a);}, bad_any_cast); + } + + // Filled! + { + A a(true); + EXPECT_TRUE(*any_cast<bool>(&a)); + EXPECT_EQ(nullptr, any_cast<int>(&a)); + + EXPECT_TRUE(any_cast<bool>(a)); + EXPECT_THROW({any_cast<int>(a);}, bad_any_cast); + + EXPECT_TRUE(any_cast<bool&>(a)); + EXPECT_THROW({any_cast<int&>(a);}, bad_any_cast); + + EXPECT_TRUE(any_cast<bool>(std::move(a))); + EXPECT_THROW({any_cast<int>(std::move(a));}, bad_any_cast); + + EXPECT_TRUE(any_cast<bool&&>(std::move(a))); + EXPECT_THROW({any_cast<int&&>(std::move(a));}, bad_any_cast); + } + + // Constant filled + { + const A a(true); + EXPECT_TRUE(*any_cast<const bool>(&a)); + EXPECT_EQ(nullptr, any_cast<const int>(&a)); + + EXPECT_TRUE(any_cast<bool>(a)); + EXPECT_THROW({any_cast<int>(a);}, bad_any_cast); + + EXPECT_TRUE(any_cast<const bool&>(a)); + EXPECT_THROW({any_cast<const int&>(a);}, bad_any_cast); + } + + // Move! + { + cmd_tattler::reset(); + A a(cmd_tattler{}); + cmd_tattler::reset(); + + auto q = any_cast<cmd_tattler>(std::move(a)); + EXPECT_TRUE(cmd_tattler::moved); + cmd_tattler::reset(); + a.reset(); + cmd_tattler::reset(); + } + + // Move! Again! + { + cmd_tattler::reset(); + auto q = any_cast<cmd_tattler>(A(std::in_place_type<cmd_tattler>)); + EXPECT_TRUE(cmd_tattler::moved); + cmd_tattler::reset(); + } +} + +TEST(Cast, Immobile) { + test_cast<immobile_any<1024>>(); +} + +TEST(Cast, Unique) { + test_cast<unique_any>(); +} + +TEST(Cast, Shared) { + test_cast<shared_any>(); +} + +TEST(Make, Immobile) { + // Nothing! + { + auto a{make_immobile_any<unmoving, 1024>()}; + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_FALSE(any_cast<const unmoving&>(a).a); + } + + // Pack! + { + auto a(make_immobile_any<unmoving, 1024>(nullptr, 5, 3.1)); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_TRUE(any_cast<const unmoving&>(a).a); + EXPECT_EQ(3, *any_cast<const unmoving&>(a).a); + } + + // List! + { + auto a(make_immobile_any<unmoving, 1024>({true, true, true, true})); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_TRUE(any_cast<const unmoving&>(a).a); + EXPECT_EQ(-4, *any_cast<const unmoving&>(a).a); + } + + // List + pack!! + { + auto a{make_immobile_any<unmoving, 1024>({true, true, true, true}, + nullptr, 5, 3.1)}; + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_TRUE(any_cast<const unmoving&>(a).a); + EXPECT_EQ(-12, *any_cast<const unmoving&>(a).a); + } +} + +TEST(Make, Unique) { + // Nothing! + { + auto a{make_unique_any<unmoving>()}; + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_FALSE(any_cast<const unmoving&>(a).a); + } + + // Pack! + { + auto a(make_unique_any<unmoving>(nullptr, 5, 3.1)); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_TRUE(any_cast<const unmoving&>(a).a); + EXPECT_EQ(3, *any_cast<const unmoving&>(a).a); + } + + // List! + { + auto a(make_unique_any<unmoving>({true, true, true, true})); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_TRUE(any_cast<const unmoving&>(a).a); + EXPECT_EQ(-4, *any_cast<const unmoving&>(a).a); + } + + // List + pack!! + { + auto a{make_unique_any<unmoving>({true, true, true, true}, + nullptr, 5, 3.1)}; + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_TRUE(any_cast<const unmoving&>(a).a); + EXPECT_EQ(-12, *any_cast<const unmoving&>(a).a); + } +} + +TEST(Make, Shared) { + // Nothing! + { + auto a{make_shared_any<unmoving>()}; + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_FALSE(any_cast<const unmoving&>(a).a); + } + + // Pack! + { + auto a(make_shared_any<unmoving>(nullptr, 5, 3.1)); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_TRUE(any_cast<const unmoving&>(a).a); + EXPECT_EQ(3, *any_cast<const unmoving&>(a).a); + } + + // List! + { + auto a(make_shared_any<unmoving>({true, true, true, true})); + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_TRUE(any_cast<const unmoving&>(a).a); + EXPECT_EQ(-4, *any_cast<const unmoving&>(a).a); + } + + // List + pack!! + { + auto a{make_shared_any<unmoving>({true, true, true, true}, + nullptr, 5, 3.1)}; + EXPECT_TRUE(a.has_value()); + EXPECT_EQ(typeid(unmoving), a.type()); + EXPECT_TRUE(any_cast<const unmoving&>(a).a); + EXPECT_EQ(-12, *any_cast<const unmoving&>(a).a); + } +} |