/* * Copyright 2020-2022 Max Kellermann * All rights reserved. * * author: Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "util/IntrusiveList.hxx" #include TEST(IntrusiveList, Basic) { struct Item final : IntrusiveListHook {}; Item a, b, c; IntrusiveList list; list.push_back(b); list.push_back(c); list.push_front(a); 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); --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()); 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); list.splice(std::next(list.begin()), other_list, other_list.iterator_to(e), other_list.iterator_to(g), 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()); 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()); } TEST(IntrusiveList, SafeLink) { struct Item final : SafeLinkIntrusiveListHook {}; Item a, b, c; ASSERT_FALSE(a.is_linked()); ASSERT_FALSE(b.is_linked()); ASSERT_FALSE(c.is_linked()); IntrusiveList list; list.push_back(b); list.push_back(c); list.push_front(a); ASSERT_TRUE(a.is_linked()); 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()); b.unlink(); ASSERT_TRUE(a.is_linked()); ASSERT_FALSE(b.is_linked()); ASSERT_TRUE(c.is_linked()); i = list.begin(); ASSERT_EQ(&*i, &a); ++i; ASSERT_EQ(&*i, &c); ++i; ASSERT_EQ(i, list.end()); list.erase(list.iterator_to(a)); ASSERT_FALSE(a.is_linked()); ASSERT_FALSE(b.is_linked()); ASSERT_TRUE(c.is_linked()); i = list.begin(); ASSERT_EQ(&*i, &c); ++i; ASSERT_EQ(i, list.end()); list.clear(); ASSERT_FALSE(a.is_linked()); ASSERT_FALSE(b.is_linked()); ASSERT_FALSE(c.is_linked()); { IntrusiveList list2; list2.push_back(a); ASSERT_TRUE(a.is_linked()); } ASSERT_FALSE(a.is_linked()); } TEST(IntrusiveList, AutoUnlink) { struct Item final : AutoUnlinkIntrusiveListHook {}; Item a; ASSERT_FALSE(a.is_linked()); IntrusiveList list; Item b; ASSERT_FALSE(b.is_linked()); { Item c; list.push_back(a); list.push_back(b); list.push_back(c); ASSERT_TRUE(a.is_linked()); 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()); } auto i = list.begin(); ASSERT_EQ(&*i, &a); ++i; ASSERT_EQ(&*i, &b); ++i; ASSERT_EQ(i, list.end()); ASSERT_TRUE(a.is_linked()); ASSERT_TRUE(b.is_linked()); }