// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. #include "vm/intrusive_dlist.h" #include "vm/unit_test.h" namespace dart { class Base { public: explicit Base(int arg) : base(arg) {} int base; }; class Item : public Base, public IntrusiveDListEntry, public IntrusiveDListEntry { public: explicit Item(int arg0, int arg1) : Base(arg0), item(arg1) {} int item; }; UNIT_TEST_CASE(IntrusiveDListMultiEntryTest) { Item a1(1, 11), a2(2, 12), a3(3, 13); IntrusiveDList all; IntrusiveDList ready; EXPECT(all.IsEmpty()); EXPECT(ready.IsEmpty()); all.Append(&a2); all.Append(&a3); all.Prepend(&a1); EXPECT_EQ(all.First()->item, 11); EXPECT_EQ(all.Last()->item, 13); ready.Append(&a1); ready.Append(&a2); EXPECT_EQ(ready.First()->item, 11); EXPECT_EQ(ready.Last()->item, 12); int i = 0; for (auto it = all.Begin(); it != all.End(); ++it) { i++; EXPECT_EQ(it->base, i); EXPECT_EQ((*it)->base, i); EXPECT_EQ(it->item, 10 + i); EXPECT_EQ((*it)->item, 10 + i); } EXPECT_EQ(i, 3); i = 0; for (auto it = ready.Begin(); it != ready.End(); ++it) { i++; EXPECT_EQ(it->base, i); EXPECT_EQ((*it)->base, i); EXPECT_EQ(it->item, 10 + i); EXPECT_EQ((*it)->item, 10 + i); } EXPECT_EQ(i, 2); ready.Remove(&a1); ready.Remove(&a2); all.Remove(&a1); all.Remove(&a2); all.Remove(&a3); EXPECT(all.IsEmpty()); EXPECT(ready.IsEmpty()); } UNIT_TEST_CASE(IntrusiveDListRemoveFirstTest) { Item a1(1, 11), a2(2, 12), a3(3, 13); IntrusiveDList all; all.Append(&a2); all.Append(&a3); all.Prepend(&a1); EXPECT_EQ(&a1, all.RemoveFirst()); EXPECT_EQ(&a2, all.RemoveFirst()); EXPECT_EQ(&a3, all.RemoveFirst()); EXPECT(all.IsEmpty()); } UNIT_TEST_CASE(IntrusiveDListRemoveLastTest) { Item a1(1, 11), a2(2, 12), a3(3, 13); IntrusiveDList all; all.Append(&a2); all.Append(&a3); all.Prepend(&a1); EXPECT_EQ(&a3, all.RemoveLast()); EXPECT_EQ(&a2, all.RemoveLast()); EXPECT_EQ(&a1, all.RemoveLast()); EXPECT(all.IsEmpty()); } UNIT_TEST_CASE(IntrusiveDListIsInList) { Item a1(1, 11), a2(2, 12), a3(3, 13); IntrusiveDList all; all.Append(&a2); all.Append(&a3); all.Prepend(&a1); ASSERT(all.IsInList(&a1)); ASSERT(all.IsInList(&a2)); ASSERT(all.IsInList(&a3)); EXPECT_EQ(&a1, all.RemoveFirst()); EXPECT(!all.IsInList(&a1)); EXPECT_EQ(&a3, all.RemoveLast()); EXPECT(!all.IsInList(&a3)); EXPECT_EQ(&a2, all.RemoveFirst()); EXPECT(!all.IsInList(&a2)); EXPECT(all.IsEmpty()); } UNIT_TEST_CASE(IntrusiveDListEraseIterator) { Item a1(1, 11), a2(2, 12), a3(3, 13); IntrusiveDList all; all.Append(&a2); all.Append(&a3); all.Prepend(&a1); auto it = all.Begin(); it = all.Erase(++it); EXPECT_EQ(*it, &a3); EXPECT_EQ(*it, all.Last()); it = all.Erase(all.Begin()); EXPECT_EQ(*it, &a3); EXPECT_EQ(*it, all.First()); EXPECT_EQ(*it, all.Last()); it = all.Erase(all.Begin()); EXPECT(it == all.End()); EXPECT(all.IsEmpty()); } UNIT_TEST_CASE(IntrusiveDListAppendListTest) { // Append to empty list. { IntrusiveDList all; IntrusiveDList other; Item a1(1, 11), a2(2, 12); all.Append(&a1); all.Append(&a2); other.AppendList(&all); EXPECT(all.IsEmpty()); EXPECT(!other.IsEmpty()); EXPECT_EQ(&a1, other.First()); EXPECT_EQ(&a2, other.Last()); auto it = other.Begin(); EXPECT_EQ(&a1, *it); it = other.Erase(it); EXPECT_EQ(&a2, *it); it = other.Erase(it); EXPECT(it == other.end()); } // Append to non-empty list. { IntrusiveDList all; IntrusiveDList other; Item a1(1, 11), a2(2, 12); all.Append(&a1); all.Append(&a2); Item o1(1, 11); other.Append(&o1); other.AppendList(&all); EXPECT(all.IsEmpty()); EXPECT(!other.IsEmpty()); EXPECT_EQ(&o1, other.First()); EXPECT_EQ(&a2, other.Last()); auto it = other.Begin(); EXPECT_EQ(&o1, *it); it = other.Erase(it); EXPECT_EQ(&a1, *it); it = other.Erase(it); EXPECT_EQ(&a2, *it); it = other.Erase(it); EXPECT(it == other.end()); } } } // namespace dart.