| /* |
| * Copyright (C) 2021 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. 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 APPLE INC. ``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 APPLE INC. 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 "config.h" |
| #include <wtf/SentinelLinkedList.h> |
| |
| #include <wtf/Bag.h> |
| |
| namespace TestWebKitAPI { |
| |
| class TestNode : public BasicRawSentinelNode<TestNode> { |
| public: |
| TestNode(int value) |
| : m_value(value) |
| { |
| } |
| |
| int value() const { return m_value; } |
| |
| private: |
| int m_value { 0 }; |
| }; |
| |
| TEST(WTF_SentinelLinkedList, Basic) |
| { |
| Bag<TestNode> bag; |
| SentinelLinkedList<TestNode> list; |
| EXPECT_TRUE(list.isEmpty()); |
| |
| auto* first = bag.add(0); |
| list.push(first); |
| EXPECT_EQ(first, &*list.begin()); |
| EXPECT_EQ(0, list.begin()->value()); |
| |
| auto* second = bag.add(1); |
| list.push(second); |
| EXPECT_EQ(second, &*list.begin()); |
| EXPECT_EQ(1, list.begin()->value()); |
| EXPECT_EQ(first, list.begin()->next()); |
| EXPECT_EQ(0, list.begin()->next()->value()); |
| EXPECT_EQ(&*list.end(), list.begin()->next()->next()); |
| |
| auto* third = bag.add(2); |
| first->prepend(third); |
| EXPECT_EQ(second, &*list.begin()); |
| EXPECT_EQ(1, list.begin()->value()); |
| EXPECT_EQ(third, list.begin()->next()); |
| EXPECT_EQ(2, list.begin()->next()->value()); |
| EXPECT_EQ(first, list.begin()->next()->next()); |
| EXPECT_EQ(0, list.begin()->next()->next()->value()); |
| EXPECT_EQ(&*list.end(), list.begin()->next()->next()->next()); |
| |
| auto* fourth = bag.add(3); |
| first->append(fourth); |
| EXPECT_EQ(second, &*list.begin()); |
| EXPECT_EQ(1, list.begin()->value()); |
| EXPECT_EQ(third, list.begin()->next()); |
| EXPECT_EQ(2, list.begin()->next()->value()); |
| EXPECT_EQ(first, list.begin()->next()->next()); |
| EXPECT_EQ(0, list.begin()->next()->next()->value()); |
| EXPECT_EQ(fourth, list.begin()->next()->next()->next()); |
| EXPECT_EQ(3, list.begin()->next()->next()->next()->value()); |
| EXPECT_EQ(&*list.end(), list.begin()->next()->next()->next()->next()); |
| |
| EXPECT_TRUE(first->isOnList()); |
| EXPECT_TRUE(second->isOnList()); |
| EXPECT_TRUE(third->isOnList()); |
| EXPECT_TRUE(fourth->isOnList()); |
| |
| first->remove(); |
| second->remove(); |
| third->remove(); |
| fourth->remove(); |
| |
| EXPECT_TRUE(!first->isOnList()); |
| EXPECT_TRUE(!second->isOnList()); |
| EXPECT_TRUE(!third->isOnList()); |
| EXPECT_TRUE(!fourth->isOnList()); |
| |
| EXPECT_TRUE(list.isEmpty()); |
| } |
| |
| TEST(WTF_SentinelLinkedList, Remove) |
| { |
| Bag<TestNode> bag; |
| SentinelLinkedList<TestNode> list; |
| EXPECT_TRUE(list.isEmpty()); |
| |
| for (int i = 0; i < 10; ++i) |
| list.append(bag.add(i)); |
| |
| int i = 0; |
| while (!list.isEmpty()) { |
| auto& node = *list.begin(); |
| EXPECT_EQ(i++, node.value()); |
| node.remove(); |
| } |
| EXPECT_EQ(10, i); |
| } |
| |
| TEST(WTF_SentinelLinkedList, TakeFrom) |
| { |
| Bag<TestNode> bag; |
| SentinelLinkedList<TestNode> list; |
| SentinelLinkedList<TestNode> from; |
| EXPECT_TRUE(list.isEmpty()); |
| EXPECT_TRUE(from.isEmpty()); |
| |
| list.takeFrom(from); |
| EXPECT_TRUE(list.isEmpty()); |
| EXPECT_TRUE(from.isEmpty()); |
| |
| list.append(bag.add(0)); |
| list.takeFrom(from); |
| EXPECT_TRUE(!list.isEmpty()); |
| EXPECT_EQ(0, list.begin()->value()); |
| EXPECT_TRUE(from.isEmpty()); |
| |
| from.append(bag.add(1)); |
| from.append(bag.add(2)); |
| EXPECT_TRUE(!list.isEmpty()); |
| EXPECT_TRUE(!from.isEmpty()); |
| list.takeFrom(from); |
| EXPECT_TRUE(from.isEmpty()); |
| EXPECT_EQ(0, list.begin()->value()); |
| EXPECT_EQ(1, list.begin()->next()->value()); |
| EXPECT_EQ(2, list.begin()->next()->next()->value()); |
| EXPECT_EQ(&*list.end(), list.begin()->next()->next()->next()); |
| } |
| |
| TEST(WTF_SentinelLinkedList, ForEach) |
| { |
| Bag<TestNode> bag; |
| SentinelLinkedList<TestNode> list; |
| EXPECT_TRUE(list.isEmpty()); |
| |
| bool executed = false; |
| list.forEach([&](auto*) { |
| executed = true; |
| }); |
| EXPECT_FALSE(executed); |
| |
| for (int i = 0; i < 10; ++i) |
| list.append(bag.add(i)); |
| |
| int i = 0; |
| list.forEach([&](auto* node) { |
| EXPECT_EQ(i++, node->value()); |
| }); |
| EXPECT_EQ(10, i); |
| } |
| |
| TEST(WTF_SentinelLinkedList, Const) |
| { |
| Bag<TestNode> bag; |
| SentinelLinkedList<TestNode> nonConstList; |
| for (int i = 0; i < 10; ++i) |
| nonConstList.append(bag.add(i)); |
| |
| const SentinelLinkedList<TestNode>& constList = nonConstList; |
| int i = 0; |
| for (auto& node : constList) |
| EXPECT_EQ(i++, node.value()); |
| EXPECT_EQ(10, i); |
| } |
| |
| } // namespace TestWebKitAPI |