diff --git a/test/util/TestIntrusiveList.cxx b/test/util/TestIntrusiveList.cxx index 1d97df0ce..c702c706f 100644 --- a/test/util/TestIntrusiveList.cxx +++ b/test/util/TestIntrusiveList.cxx @@ -34,199 +34,156 @@ #include +#include + +namespace { + +template +struct CharItem final : Hook { + char ch; + + constexpr CharItem(char _ch) noexcept:ch(_ch) {} + + template + static auto MakeArray(const char (&src)[size]) noexcept { + std::array result; + for (std::size_t i = 0; i < result.size(); ++i) + result[i].ch = src[i]; + return result; + } +}; + +template +static std::string +ToString(const IntrusiveList> &list, + typename IntrusiveList>::const_iterator it, + std::size_t n) noexcept +{ + std::string result; + for (std::size_t i = 0; i < n; ++i, ++it) + result.push_back(it == list.end() ? '_' : it->ch); + return result; +} + +template +static std::string +ToStringReverse(const IntrusiveList> &list, + typename IntrusiveList>::const_iterator it, + std::size_t n) noexcept +{ + std::string result; + for (std::size_t i = 0; i < n; ++i, --it) + result.push_back(it == list.end() ? '_' : it->ch); + return result; +} + +} // anonymous namespace + TEST(IntrusiveList, Basic) { - struct Item final : IntrusiveListHook {}; + using Item = CharItem; - Item a, b, c; + Item items[]{'a', 'b', 'c'}; IntrusiveList list; + for (auto &i : items) + list.push_back(i); - list.push_back(b); - list.push_back(c); - list.push_front(a); + ASSERT_EQ(ToString(list, list.begin(), 5), "abc_a"); + ASSERT_EQ(ToStringReverse(list, list.begin(), 5), "a_cba"); - auto i = list.begin(); - ASSERT_EQ(&*i, &a); - ++i; - ASSERT_EQ(&*i, &b); - ++i; - ASSERT_EQ(&*i, &c); - ++i; - ASSERT_EQ(i, list.end()); - ++i; - ASSERT_EQ(&*i, &a); + items[1].unlink(); - --i; - ASSERT_EQ(i, list.end()); - --i; - ASSERT_EQ(&*i, &c); - --i; - ASSERT_EQ(&*i, &b); - --i; - ASSERT_EQ(&*i, &a); - ASSERT_EQ(i, list.begin()); - --i; - ASSERT_EQ(i, list.end()); - - b.unlink(); - - i = list.begin(); - ASSERT_EQ(&*i, &a); - ++i; - ASSERT_EQ(&*i, &c); - ++i; - ASSERT_EQ(i, list.end()); - ++i; - ASSERT_EQ(&*i, &a); - - --i; - ASSERT_EQ(i, list.end()); - --i; - ASSERT_EQ(&*i, &c); - --i; - ASSERT_EQ(&*i, &a); - ASSERT_EQ(i, list.begin()); - --i; - ASSERT_EQ(i, list.end()); + ASSERT_EQ(ToString(list, list.begin(), 4), "ac_a"); + ASSERT_EQ(ToStringReverse(list, list.begin(), 4), "a_ca"); IntrusiveList other_list; - Item d, e, f, g; - other_list.push_back(d); - other_list.push_back(e); - other_list.push_back(f); - other_list.push_back(g); + Item other_items[]{'d', 'e', 'f', 'g'}; + for (auto &i : other_items) + other_list.push_back(i); list.splice(std::next(list.begin()), other_list, - other_list.iterator_to(e), - other_list.iterator_to(g), 2); + other_list.iterator_to(other_items[1]), + other_list.iterator_to(other_items[3]), 2); - i = other_list.begin(); - ASSERT_EQ(&*i, &d); - ++i; - ASSERT_EQ(&*i, &g); - ++i; - ASSERT_EQ(i, other_list.end()); - ++i; - ASSERT_EQ(&*i, &d); - --i; - ASSERT_EQ(i, other_list.end()); - --i; - ASSERT_EQ(&*i, &g); - --i; - ASSERT_EQ(&*i, &d); - ASSERT_EQ(i, other_list.begin()); + ASSERT_EQ(ToString(other_list, other_list.begin(), 4), "dg_d"); + ASSERT_EQ(ToStringReverse(other_list, other_list.begin(), 4), "d_gd"); - i = list.begin(); - ASSERT_EQ(&*i, &a); - ++i; - ASSERT_EQ(&*i, &e); - ++i; - ASSERT_EQ(&*i, &f); - ++i; - ASSERT_EQ(&*i, &c); - ++i; - ASSERT_EQ(i, list.end()); - ++i; - ASSERT_EQ(&*i, &a); - - --i; - ASSERT_EQ(i, list.end()); - --i; - ASSERT_EQ(&*i, &c); - --i; - ASSERT_EQ(&*i, &f); - --i; - ASSERT_EQ(&*i, &e); - --i; - ASSERT_EQ(&*i, &a); - ASSERT_EQ(i, list.begin()); - --i; - ASSERT_EQ(i, list.end()); + ASSERT_EQ(ToString(list, list.begin(), 6), "aefc_a"); + ASSERT_EQ(ToStringReverse(list, list.begin(), 6), "a_cfea"); } TEST(IntrusiveList, SafeLink) { - struct Item final : SafeLinkIntrusiveListHook {}; + using Item = CharItem; - Item a, b, c; + Item items[]{'a', 'b', 'c'}; - ASSERT_FALSE(a.is_linked()); - ASSERT_FALSE(b.is_linked()); - ASSERT_FALSE(c.is_linked()); + for (const auto &i : items) + ASSERT_FALSE(i.is_linked()); IntrusiveList list; - list.push_back(b); - list.push_back(c); - list.push_front(a); + list.push_back(items[1]); + list.push_back(items[2]); + list.push_front(items[0]); - ASSERT_TRUE(a.is_linked()); - ASSERT_TRUE(b.is_linked()); - ASSERT_TRUE(c.is_linked()); + for (const auto &i : items) + ASSERT_TRUE(i.is_linked()); - auto i = list.begin(); - ASSERT_EQ(&*i, &a); - ++i; - ASSERT_EQ(&*i, &b); - ++i; - ASSERT_EQ(&*i, &c); - ++i; - ASSERT_EQ(i, list.end()); + ASSERT_EQ(ToString(list, list.begin(), 5), "abc_a"); + ASSERT_EQ(ToStringReverse(list, list.begin(), 5), "a_cba"); - b.unlink(); + items[1].unlink(); - ASSERT_TRUE(a.is_linked()); - ASSERT_FALSE(b.is_linked()); - ASSERT_TRUE(c.is_linked()); + ASSERT_TRUE(items[0].is_linked()); + ASSERT_FALSE(items[1].is_linked()); + ASSERT_TRUE(items[2].is_linked()); - i = list.begin(); - ASSERT_EQ(&*i, &a); - ++i; - ASSERT_EQ(&*i, &c); - ++i; - ASSERT_EQ(i, list.end()); + ASSERT_EQ(ToString(list, list.begin(), 4), "ac_a"); + ASSERT_EQ(ToStringReverse(list, list.begin(), 4), "a_ca"); - list.erase(list.iterator_to(a)); + list.erase(list.iterator_to(items[0])); - ASSERT_FALSE(a.is_linked()); - ASSERT_FALSE(b.is_linked()); - ASSERT_TRUE(c.is_linked()); + ASSERT_FALSE(items[0].is_linked()); + ASSERT_FALSE(items[1].is_linked()); + ASSERT_TRUE(items[2].is_linked()); - i = list.begin(); - ASSERT_EQ(&*i, &c); - ++i; - ASSERT_EQ(i, list.end()); + ASSERT_EQ(ToString(list, list.begin(), 3), "c_c"); + ASSERT_EQ(ToStringReverse(list, list.begin(), 3), "c_c"); list.clear(); - ASSERT_FALSE(a.is_linked()); - ASSERT_FALSE(b.is_linked()); - ASSERT_FALSE(c.is_linked()); + ASSERT_FALSE(items[0].is_linked()); + ASSERT_FALSE(items[1].is_linked()); + ASSERT_FALSE(items[2].is_linked()); + + ASSERT_EQ(ToString(list, list.begin(), 2), "__"); + ASSERT_EQ(ToStringReverse(list, list.begin(), 2), "__"); { IntrusiveList list2; - list2.push_back(a); - ASSERT_TRUE(a.is_linked()); + list2.push_back(items[0]); + ASSERT_TRUE(items[0].is_linked()); } - ASSERT_FALSE(a.is_linked()); + ASSERT_FALSE(items[0].is_linked()); } TEST(IntrusiveList, AutoUnlink) { - struct Item final : AutoUnlinkIntrusiveListHook {}; + using Item = CharItem; - Item a; + Item a{'a'}; ASSERT_FALSE(a.is_linked()); IntrusiveList list; - Item b; + Item b{'b'}; ASSERT_FALSE(b.is_linked()); { - Item c; + Item c{'c'}; list.push_back(a); list.push_back(b); @@ -236,22 +193,10 @@ TEST(IntrusiveList, AutoUnlink) ASSERT_TRUE(b.is_linked()); ASSERT_TRUE(c.is_linked()); - auto i = list.begin(); - ASSERT_EQ(&*i, &a); - ++i; - ASSERT_EQ(&*i, &b); - ++i; - ASSERT_EQ(&*i, &c); - ++i; - ASSERT_EQ(i, list.end()); + ASSERT_EQ(ToString(list, list.begin(), 5), "abc_a"); } - auto i = list.begin(); - ASSERT_EQ(&*i, &a); - ++i; - ASSERT_EQ(&*i, &b); - ++i; - ASSERT_EQ(i, list.end()); + ASSERT_EQ(ToString(list, list.begin(), 5), "ab_ab"); ASSERT_TRUE(a.is_linked()); ASSERT_TRUE(b.is_linked());