#define BOOST_TEST_MODULE test_collection #include #include #include #include #include #include namespace { class Base { public: Base() = default; virtual ~Base() = default; DEFAULT_MOVE_COPY(Base); virtual bool add() { total += 1; return false; } [[nodiscard]] virtual bool yes() const { return true; } unsigned int total {0}; }; class Sub : public Base { public: bool add() override { total += 2; return true; } }; class Sub1 : public Sub { }; class Sub2 : public Sub { }; class Base2 { public: Base2() = default; virtual ~Base2() = default; DEFAULT_MOVE_COPY(Base2); }; class Multi : public Sub1, public Base2 { }; using TestCollection = SharedCollection; } BOOST_TEST_DONT_PRINT_LOG_VALUE(TestCollection::Objects::iterator) BOOST_TEST_DONT_PRINT_LOG_VALUE(TestCollection::Objects::const_iterator) BOOST_TEST_DONT_PRINT_LOG_VALUE(TestCollection::Objects::const_reverse_iterator) BOOST_TEST_DONT_PRINT_LOG_VALUE(TestCollection::OtherObjects::iterator) BOOST_TEST_DONT_PRINT_LOG_VALUE(TestCollection::OtherObjects::const_iterator) BOOST_FIXTURE_TEST_SUITE(tc, TestCollection) BOOST_AUTO_TEST_CASE(Empty) { BOOST_CHECK(TestCollection::empty()); BOOST_REQUIRE(!apply(&Base::add)); const auto appliedTo = applyOne(&Base::add); BOOST_CHECK_EQUAL(appliedTo, end()); BOOST_CHECK(!find()); BOOST_CHECK(!find()); BOOST_CHECK(!find()); } BOOST_AUTO_TEST_CASE(ABaseApply) { auto base = create(); BOOST_CHECK_EQUAL(objects.size(), 1); BOOST_CHECK(std::get>(otherObjects).empty()); BOOST_REQUIRE(apply(&Base::add)); BOOST_CHECK_EQUAL(base->total, 1); const auto appliedTo = applyOne(&Base::add); BOOST_CHECK_EQUAL(appliedTo, end()); BOOST_CHECK_EQUAL(base.get(), find()); BOOST_CHECK(!find()); BOOST_CHECK(!find()); } BOOST_AUTO_TEST_CASE(EmplaceOthers) { auto base = emplace(std::make_shared()); BOOST_CHECK_EQUAL(objects.size(), 1); BOOST_CHECK(std::get>(otherObjects).empty()); auto sub = emplace(std::make_shared()); BOOST_CHECK_EQUAL(objects.size(), 2); BOOST_CHECK_EQUAL(std::get>(otherObjects).size(), 1); BOOST_CHECK_EQUAL(base.get(), find()); BOOST_CHECK_EQUAL(sub.get(), find()); BOOST_CHECK(!find()); } BOOST_AUTO_TEST_CASE(ABaseRApply) { auto base = create(); BOOST_REQUIRE(rapply(&Base::add)); BOOST_CHECK_EQUAL(base->total, 1); const auto appliedTo = rapplyOne(&Base::add); BOOST_CHECK_EQUAL(appliedTo, rend()); } BOOST_AUTO_TEST_CASE(ASubApply) { auto sub = create(); BOOST_CHECK_EQUAL(objects.size(), 1); BOOST_CHECK_EQUAL(std::get>(otherObjects).size(), 1); BOOST_REQUIRE(apply(&Base::add)); BOOST_CHECK_EQUAL(sub->total, 2); const auto appliedTo = applyOne(&Base::add); BOOST_CHECK_NE(appliedTo, end()); BOOST_CHECK_EQUAL(*appliedTo, sub); } BOOST_AUTO_TEST_CASE(Filter) { static_assert(TestCollection::idx() == 0); static_assert(TestCollection::idx() == 0); static_assert(TestCollection::idx() == 0); static_assert(TestCollection::idx() == 0); create(); BOOST_CHECK_EQUAL(1, apply(&Base::yes)); BOOST_CHECK_EQUAL(0, apply(&Base::yes)); BOOST_CHECK_EQUAL(0, apply(&Base::yes)); BOOST_CHECK_EQUAL(objects.begin(), applyOne(&Base::yes)); BOOST_CHECK_EQUAL(std::get<0>(otherObjects).end(), applyOne(&Base::yes)); BOOST_CHECK_EQUAL(std::get<0>(otherObjects).end(), applyOne(&Base::yes)); create(); BOOST_CHECK_EQUAL(2, apply(&Base::yes)); BOOST_CHECK_EQUAL(1, apply(&Base::yes)); BOOST_CHECK_EQUAL(0, apply(&Base::yes)); BOOST_CHECK_EQUAL(objects.begin(), applyOne(&Base::yes)); BOOST_CHECK_EQUAL(std::get<0>(otherObjects).begin(), applyOne(&Base::yes)); BOOST_CHECK_EQUAL(std::get<0>(otherObjects).end(), applyOne(&Base::yes)); create(); BOOST_CHECK_EQUAL(3, apply(&Base::yes)); BOOST_CHECK_EQUAL(2, apply(&Base::yes)); BOOST_CHECK_EQUAL(1, apply(&Base::yes)); BOOST_CHECK_EQUAL(objects.begin(), applyOne(&Base::yes)); BOOST_CHECK_EQUAL(std::get<0>(otherObjects).begin(), applyOne(&Base::yes)); BOOST_CHECK_EQUAL(std::get<0>(otherObjects).begin() + 1, applyOne(&Base::yes)); BOOST_CHECK_EQUAL(std::get()>(otherObjects).size(), 2); BOOST_CHECK_EQUAL(std::get()>(otherObjects).size(), 2); BOOST_CHECK_EQUAL(&objects, &containerFor()); BOOST_CHECK_EQUAL(&std::get<0>(otherObjects), &containerFor()); BOOST_CHECK_EQUAL(&std::get<0>(otherObjects), &containerFor()); } BOOST_AUTO_TEST_CASE(BeginEnd) { BOOST_CHECK_EQUAL(0, std::distance(begin(), end())); create(); create(); BOOST_CHECK_EQUAL(2, std::distance(begin(), end())); } BOOST_AUTO_TEST_CASE(RBeginREnd) { BOOST_CHECK_EQUAL(0, std::distance(rbegin(), rend())); create(); create(); BOOST_CHECK_EQUAL(2, std::distance(rbegin(), rend())); } BOOST_AUTO_TEST_CASE(CreateCreate) { auto base1 = findOrCreate(); BOOST_CHECK(base1); auto base2 = findOrCreate(); BOOST_CHECK_EQUAL(base1, base2); auto sub1 = findOrCreate(); BOOST_CHECK_NE(sub1, base1); auto sub2 = findOrCreate(); BOOST_CHECK_EQUAL(sub1, sub2); } BOOST_AUTO_TEST_CASE(CreateCreateSub) { auto sub = findOrCreate(); auto base = findOrCreate(); BOOST_CHECK_EQUAL(sub, base); } BOOST_AUTO_TEST_SUITE_END() using TestUniqueCollection = UniqueCollection; BOOST_TEST_DONT_PRINT_LOG_VALUE(TestUniqueCollection::Objects::const_iterator) BOOST_TEST_DONT_PRINT_LOG_VALUE(TestUniqueCollection::Objects::const_reverse_iterator) BOOST_TEST_DONT_PRINT_LOG_VALUE(TestUniqueCollection::Objects::iterator) BOOST_TEST_DONT_PRINT_LOG_VALUE(TestUniqueCollection::Objects::reverse_iterator) BOOST_FIXTURE_TEST_SUITE(utc, TestUniqueCollection) BOOST_AUTO_TEST_CASE(UniqueCreate) { create(); BOOST_CHECK_EQUAL(objects.size(), 1); BOOST_CHECK(std::get>(otherObjects).empty()); create(); BOOST_CHECK_EQUAL(objects.size(), 2); BOOST_CHECK_EQUAL(std::get>(otherObjects).size(), 1); } BOOST_AUTO_TEST_CASE(MoveAssign) { create(); create(); TestUniqueCollection::Objects other; TestUniqueCollection::operator=(std::move(other)); BOOST_CHECK(objects.empty()); BOOST_CHECK(std::get>(otherObjects).empty()); other.push_back(std::make_unique()); other.push_back(std::make_unique()); TestUniqueCollection::operator=(std::move(other)); BOOST_CHECK_EQUAL(objects.size(), 2); BOOST_CHECK_EQUAL(std::get>(otherObjects).size(), 1); BOOST_CHECK(other.empty()); } BOOST_AUTO_TEST_CASE(ClearAll) { create(); create(); emplace(std::make_unique()); emplace(std::make_unique()); clear(); BOOST_CHECK(objects.empty()); BOOST_CHECK(std::get>(otherObjects).empty()); } BOOST_AUTO_TEST_CASE(RemoveAllOfSub) { create(); create(); emplace(std::make_unique()); emplace(std::make_unique()); emplace(std::make_unique()); BOOST_CHECK_EQUAL(removeAll(), 3); BOOST_CHECK_EQUAL(objects.size(), 2); BOOST_CHECK(std::get>(otherObjects).empty()); } BOOST_AUTO_TEST_SUITE_END() BOOST_FIXTURE_TEST_SUITE(btc, UniqueCollection) BOOST_AUTO_TEST_CASE(NoOthers) { create(); create(); emplace(std::make_unique()); emplace(std::make_unique()); } BOOST_AUTO_TEST_CASE(ApplyAll) { create(); BOOST_CHECK_EQUAL(0, apply(&Base::add)); BOOST_CHECK_EQUAL(1, apply(&Base::add)); create(); BOOST_CHECK_EQUAL(1, apply(&Base::add)); BOOST_CHECK_EQUAL(2, apply(&Base::add)); } BOOST_AUTO_TEST_CASE(ApplyOneType) { create(); BOOST_CHECK_EQUAL(objects.end(), applyOne(&Base::yes)); BOOST_CHECK_EQUAL(objects.begin(), applyOne(&Base::yes)); create(); BOOST_CHECK_EQUAL(objects.begin() + 1, applyOne(&Base::yes)); BOOST_CHECK_EQUAL(objects.begin(), applyOne(&Base::yes)); create(); BOOST_CHECK_EQUAL(objects.begin() + 2, applyOne(&Base::yes)); } BOOST_AUTO_TEST_SUITE_END() using MultiCollection = Collection, Multi, Sub, Base2>; BOOST_FIXTURE_TEST_SUITE(multi, MultiCollection) BOOST_AUTO_TEST_CASE(AddMulti) { static_assert(MultiCollection::idx() == 0); static_assert(MultiCollection::idx() == 1); static_assert(MultiCollection::idx() == 2); create(); BOOST_CHECK_EQUAL(objects.size(), 1); BOOST_CHECK_EQUAL(std::get<0>(otherObjects).size(), 0); BOOST_CHECK_EQUAL(std::get<1>(otherObjects).size(), 0); BOOST_CHECK_EQUAL(std::get<2>(otherObjects).size(), 0); create(); BOOST_CHECK_EQUAL(objects.size(), 2); BOOST_CHECK_EQUAL(std::get<0>(otherObjects).size(), 0); BOOST_CHECK_EQUAL(std::get<1>(otherObjects).size(), 1); BOOST_CHECK_EQUAL(std::get<2>(otherObjects).size(), 0); create(); BOOST_CHECK_EQUAL(objects.size(), 3); BOOST_CHECK_EQUAL(std::get<0>(otherObjects).size(), 0); BOOST_CHECK_EQUAL(std::get<1>(otherObjects).size(), 2); BOOST_CHECK_EQUAL(std::get<2>(otherObjects).size(), 0); create(); BOOST_CHECK_EQUAL(objects.size(), 4); BOOST_CHECK_EQUAL(std::get<0>(otherObjects).size(), 0); BOOST_CHECK_EQUAL(std::get<1>(otherObjects).size(), 3); BOOST_CHECK_EQUAL(std::get<2>(otherObjects).size(), 0); create(); BOOST_CHECK_EQUAL(size(), 5); BOOST_CHECK_EQUAL(size(), 1); BOOST_CHECK_EQUAL(size(), 4); BOOST_CHECK_EQUAL(size(), 1); } BOOST_AUTO_TEST_CASE(RemoveMulti) { create(); create(); create(); create(); create(); BOOST_CHECK_EQUAL(objects.size(), 5); BOOST_CHECK_EQUAL(std::get<0>(otherObjects).size(), 1); BOOST_CHECK_EQUAL(std::get<1>(otherObjects).size(), 4); BOOST_CHECK_EQUAL(std::get<2>(otherObjects).size(), 1); BOOST_CHECK_EQUAL(removeAll(), 1); BOOST_CHECK_EQUAL(objects.size(), 4); BOOST_CHECK_EQUAL(std::get<0>(otherObjects).size(), 0); BOOST_CHECK_EQUAL(std::get<1>(otherObjects).size(), 3); BOOST_CHECK_EQUAL(std::get<2>(otherObjects).size(), 0); BOOST_CHECK_EQUAL(removeAll(), 3); BOOST_CHECK_EQUAL(objects.size(), 1); BOOST_CHECK_EQUAL(std::get<0>(otherObjects).size(), 0); BOOST_CHECK_EQUAL(std::get<1>(otherObjects).size(), 0); BOOST_CHECK_EQUAL(std::get<2>(otherObjects).size(), 0); BOOST_CHECK_EQUAL(removeAll(), 1); BOOST_CHECK_EQUAL(objects.size(), 0); BOOST_CHECK_EQUAL(std::get<0>(otherObjects).size(), 0); BOOST_CHECK_EQUAL(std::get<1>(otherObjects).size(), 0); BOOST_CHECK_EQUAL(std::get<2>(otherObjects).size(), 0); } BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_CASE(WrappedPtrFileCons) { using FilePtr = wrapped_ptr; const FilePtr file {fopen, "/dev/null", "r"}; BOOST_REQUIRE(file); BOOST_CHECK_NO_THROW(fflush(file)); BOOST_CHECK_EQUAL(file.get(), file.operator->()); BOOST_CHECK_EQUAL(file.get(), file.operator FILE *()); } BOOST_AUTO_TEST_CASE(WrappedPtrFileMove) { using FilePtr = wrapped_ptr; FilePtr file {fopen, "/dev/null", "r"}; BOOST_REQUIRE(file); FilePtr fp2 {std::move(file)}; BOOST_REQUIRE(!file); BOOST_REQUIRE(fp2); file = std::move(fp2); BOOST_REQUIRE(file); BOOST_REQUIRE(!fp2); FilePtr fp3 {fopen, "/dev/null", "r"}; file = std::move(fp3); } BOOST_AUTO_TEST_CASE(WrappedPtrFileTyped) { using FilePtr = wrapped_ptrt; const FilePtr file {"/dev/null", "r"}; BOOST_REQUIRE(file); BOOST_CHECK_NO_THROW(fflush(file)); }