123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512 |
- #include "intrlist.h"
- #include <library/cpp/testing/unittest/registar.h>
- #include <util/stream/output.h>
- class TListTest: public TTestBase {
- UNIT_TEST_SUITE(TListTest);
- UNIT_TEST(TestIterate);
- UNIT_TEST(TestRIterate);
- UNIT_TEST(TestForEach);
- UNIT_TEST(TestForEachWithDelete);
- UNIT_TEST(TestSize);
- UNIT_TEST(TestQuickSort);
- UNIT_TEST(TestCut);
- UNIT_TEST(TestAppend);
- UNIT_TEST(TestMoveCtor);
- UNIT_TEST(TestMoveOpEq);
- UNIT_TEST(TestListWithAutoDelete);
- UNIT_TEST(TestListWithAutoDeleteMoveCtor);
- UNIT_TEST(TestListWithAutoDeleteMoveOpEq);
- UNIT_TEST(TestListWithAutoDeleteClear);
- UNIT_TEST(TestSecondTag);
- UNIT_TEST_SUITE_END();
- private:
- void TestSize();
- void TestIterate();
- void TestRIterate();
- void TestForEach();
- void TestForEachWithDelete();
- void TestQuickSort();
- void TestCut();
- void TestAppend();
- void TestMoveCtor();
- void TestMoveOpEq();
- void TestListWithAutoDelete();
- void TestListWithAutoDeleteMoveCtor();
- void TestListWithAutoDeleteMoveOpEq();
- void TestListWithAutoDeleteClear();
- void TestSecondTag();
- };
- UNIT_TEST_SUITE_REGISTRATION(TListTest);
- class TInt: public TIntrusiveListItem<TInt> {
- public:
- inline TInt(int value) noexcept
- : Value_(value)
- {
- }
- TInt(TInt&& rhs) noexcept
- : Value_(rhs.Value_)
- {
- rhs.Value_ = 0xDEAD;
- }
- TInt& operator=(TInt&& rhs) noexcept {
- Value_ = rhs.Value_;
- rhs.Value_ = 0xBEEF;
- return *this;
- }
- inline operator int&() noexcept {
- return Value_;
- }
- inline operator const int&() const noexcept {
- return Value_;
- }
- private:
- int Value_;
- };
- class TMyList: public TIntrusiveList<TInt> {
- public:
- inline TMyList(int count) {
- while (count > 0) {
- PushFront(new TInt(count--));
- }
- }
- // TMyList(const TMyList& rhs) = default;
- TMyList(TMyList&& rhs) noexcept = default;
- // operator=(const TMyList& rhs) = default;
- TMyList& operator=(TMyList&& rhs) noexcept = default;
- inline ~TMyList() {
- while (!Empty()) {
- delete PopBack();
- }
- }
- };
- struct TIntGreater: private TGreater<int> {
- inline bool operator()(const TInt& l, const TInt& r) const noexcept {
- return TGreater<int>::operator()(l, r);
- }
- };
- void TListTest::TestQuickSort() {
- TMyList l(1000);
- size_t c = 0;
- l.QuickSort(TIntGreater());
- UNIT_ASSERT_EQUAL(l.Size(), 1000);
- for (TMyList::TIterator it = l.Begin(); it != l.End(); ++it) {
- UNIT_ASSERT_EQUAL(*it, int(1000 - c++));
- }
- }
- void TListTest::TestSize() {
- TMyList l(1024);
- UNIT_ASSERT_EQUAL(l.Size(), 1024);
- }
- void TListTest::TestIterate() {
- TMyList l(1000);
- size_t c = 0;
- for (TMyList::TIterator it = l.Begin(); it != l.End(); ++it) {
- ++c;
- UNIT_ASSERT_EQUAL(*it, (int)c);
- }
- UNIT_ASSERT_EQUAL(c, 1000);
- }
- void TListTest::TestRIterate() {
- TMyList l(1000);
- size_t c = 1000;
- UNIT_ASSERT_EQUAL(l.RBegin(), TMyList::TReverseIterator(l.End()));
- UNIT_ASSERT_EQUAL(l.REnd(), TMyList::TReverseIterator(l.Begin()));
- for (TMyList::TReverseIterator it = l.RBegin(); it != l.REnd(); ++it) {
- UNIT_ASSERT_EQUAL(*it, (int)c--);
- }
- UNIT_ASSERT_EQUAL(c, 0);
- }
- class TSum {
- public:
- inline TSum(size_t& sum)
- : Sum_(sum)
- {
- }
- inline void operator()(const TInt* v) noexcept {
- Sum_ += *v;
- }
- private:
- size_t& Sum_;
- };
- class TSumWithDelete {
- public:
- inline TSumWithDelete(size_t& sum)
- : Sum_(sum)
- {
- }
- inline void operator()(TInt* v) noexcept {
- if (*v % 2) {
- Sum_ += *v;
- } else {
- delete v;
- }
- }
- private:
- size_t& Sum_;
- };
- void TListTest::TestForEach() {
- TMyList l(1000);
- size_t sum = 0;
- TSum functor(sum);
- l.ForEach(functor);
- UNIT_ASSERT_EQUAL(sum, 1000 * 1001 / 2);
- }
- void TListTest::TestForEachWithDelete() {
- TMyList l(1000);
- size_t sum = 0;
- TSumWithDelete functor(sum);
- l.ForEach(functor);
- UNIT_ASSERT_EQUAL(sum, 500 * 500 /*== n * (x + y * (n - 1) / 2), x == 1, y == 2*/);
- }
- static void CheckIterationAfterCut(const TMyList& l, const TMyList& l2, size_t N, size_t M) {
- size_t c = 0;
- for (TMyList::TConstIterator it = l.Begin(); it != l.End(); ++it) {
- ++c;
- UNIT_ASSERT_EQUAL(*it, (int)c);
- }
- UNIT_ASSERT_EQUAL(c, M);
- for (TMyList::TConstIterator it = l2.Begin(); it != l2.End(); ++it) {
- ++c;
- UNIT_ASSERT_EQUAL(*it, (int)c);
- }
- UNIT_ASSERT_EQUAL(c, N);
- for (TMyList::TConstIterator it = l2.End(); it != l2.Begin(); --c) {
- --it;
- UNIT_ASSERT_EQUAL(*it, (int)c);
- }
- UNIT_ASSERT_EQUAL(c, M);
- for (TMyList::TConstIterator it = l.End(); it != l.Begin(); --c) {
- --it;
- UNIT_ASSERT_EQUAL(*it, (int)c);
- }
- UNIT_ASSERT_EQUAL(c, 0);
- }
- static void TestCutFront(int N, int M) {
- TMyList l(N);
- TMyList l2(0);
- TMyList::TIterator it = l.Begin();
- for (int i = 0; i < M; ++i) {
- ++it;
- }
- TMyList::Cut(l.Begin(), it, l2.End());
- CheckIterationAfterCut(l2, l, N, M);
- }
- static void TestCutBack(int N, int M) {
- TMyList l(N);
- TMyList l2(0);
- TMyList::TIterator it = l.Begin();
- for (int i = 0; i < M; ++i) {
- ++it;
- }
- TMyList::Cut(it, l.End(), l2.End());
- CheckIterationAfterCut(l, l2, N, M);
- }
- void TListTest::TestCut() {
- TestCutFront(1000, 500);
- TestCutBack(1000, 500);
- TestCutFront(1, 0);
- TestCutBack(1, 0);
- TestCutFront(1, 1);
- TestCutBack(1, 1);
- TestCutFront(2, 0);
- TestCutBack(2, 0);
- TestCutFront(2, 1);
- TestCutBack(2, 1);
- TestCutFront(2, 2);
- TestCutBack(2, 2);
- }
- static void CheckIterationAfterAppend(const TMyList& l, size_t N, size_t M) {
- TMyList::TConstIterator it = l.Begin();
- for (size_t i = 1; i <= N; ++i, ++it) {
- UNIT_ASSERT_EQUAL((int)i, *it);
- }
- for (size_t i = 1; i <= M; ++i, ++it) {
- UNIT_ASSERT_EQUAL((int)i, *it);
- }
- UNIT_ASSERT_EQUAL(it, l.End());
- }
- static void TestAppend(int N, int M) {
- TMyList l(N);
- TMyList l2(M);
- l.Append(l2);
- UNIT_ASSERT(l2.Empty());
- CheckIterationAfterAppend(l, N, M);
- }
- void TListTest::TestAppend() {
- ::TestAppend(500, 500);
- ::TestAppend(0, 0);
- ::TestAppend(1, 0);
- ::TestAppend(0, 1);
- ::TestAppend(1, 1);
- }
- template <typename TListType>
- static void CheckList(const TListType& lst) {
- int i = 1;
- for (typename TListType::TConstIterator it = lst.Begin(); it != lst.End(); ++it, ++i) {
- UNIT_ASSERT_EQUAL(*it, i);
- }
- }
- void TListTest::TestMoveCtor() {
- const int N{42};
- TMyList lst{N};
- UNIT_ASSERT(!lst.Empty());
- UNIT_ASSERT_EQUAL(lst.Size(), N);
- CheckList(lst);
- TMyList nextLst{std::move(lst)};
- UNIT_ASSERT(lst.Empty());
- CheckList(nextLst);
- }
- void TListTest::TestMoveOpEq() {
- const int N{42};
- TMyList lst{N};
- UNIT_ASSERT(!lst.Empty());
- UNIT_ASSERT_EQUAL(lst.Size(), N);
- CheckList(lst);
- const int M{2};
- TMyList nextLst(M);
- UNIT_ASSERT(!nextLst.Empty());
- UNIT_ASSERT_EQUAL(nextLst.Size(), M);
- CheckList(nextLst);
- nextLst = std::move(lst);
- UNIT_ASSERT(!nextLst.Empty());
- UNIT_ASSERT_EQUAL(nextLst.Size(), N);
- CheckList(nextLst);
- }
- class TSelfCountingInt: public TIntrusiveListItem<TSelfCountingInt> {
- public:
- TSelfCountingInt(int& counter, int value) noexcept
- : Counter_(counter)
- , Value_(value)
- {
- ++Counter_;
- }
- TSelfCountingInt(TSelfCountingInt&& rhs) noexcept
- : Counter_(rhs.Counter_)
- , Value_(rhs.Value_)
- {
- rhs.Value_ = 0xDEAD;
- }
- TSelfCountingInt& operator=(TSelfCountingInt&& rhs) noexcept {
- Value_ = rhs.Value_;
- rhs.Value_ = 0xBEEF;
- return *this;
- }
- ~TSelfCountingInt() noexcept {
- --Counter_;
- }
- inline operator int&() noexcept {
- return Value_;
- }
- inline operator const int&() const noexcept {
- return Value_;
- }
- private:
- int& Counter_;
- int Value_;
- };
- struct TSelfCountingIntDelete {
- static void Destroy(TSelfCountingInt* i) noexcept {
- delete i;
- }
- };
- void TListTest::TestListWithAutoDelete() {
- using TListType = TIntrusiveListWithAutoDelete<TSelfCountingInt, TSelfCountingIntDelete>;
- int counter{0};
- {
- TListType lst;
- UNIT_ASSERT(lst.Empty());
- lst.PushFront(new TSelfCountingInt(counter, 2));
- UNIT_ASSERT_EQUAL(lst.Size(), 1);
- UNIT_ASSERT_EQUAL(counter, 1);
- lst.PushFront(new TSelfCountingInt(counter, 1));
- UNIT_ASSERT_EQUAL(lst.Size(), 2);
- UNIT_ASSERT_EQUAL(counter, 2);
- CheckList(lst);
- }
- UNIT_ASSERT_EQUAL(counter, 0);
- }
- void TListTest::TestListWithAutoDeleteMoveCtor() {
- using TListType = TIntrusiveListWithAutoDelete<TSelfCountingInt, TSelfCountingIntDelete>;
- int counter{0};
- {
- TListType lst;
- lst.PushFront(new TSelfCountingInt(counter, 2));
- lst.PushFront(new TSelfCountingInt(counter, 1));
- UNIT_ASSERT_EQUAL(lst.Size(), 2);
- UNIT_ASSERT_EQUAL(counter, 2);
- CheckList(lst);
- TListType nextList(std::move(lst));
- UNIT_ASSERT_EQUAL(nextList.Size(), 2);
- CheckList(nextList);
- UNIT_ASSERT_EQUAL(counter, 2);
- }
- UNIT_ASSERT_EQUAL(counter, 0);
- }
- void TListTest::TestListWithAutoDeleteMoveOpEq() {
- using TListType = TIntrusiveListWithAutoDelete<TSelfCountingInt, TSelfCountingIntDelete>;
- int counter{0};
- {
- TListType lst;
- lst.PushFront(new TSelfCountingInt(counter, 2));
- lst.PushFront(new TSelfCountingInt(counter, 1));
- UNIT_ASSERT_EQUAL(lst.Size(), 2);
- UNIT_ASSERT_EQUAL(counter, 2);
- CheckList(lst);
- TListType nextList;
- UNIT_ASSERT(nextList.Empty());
- nextList = std::move(lst);
- UNIT_ASSERT_EQUAL(nextList.Size(), 2);
- CheckList(nextList);
- UNIT_ASSERT_EQUAL(counter, 2);
- }
- UNIT_ASSERT_EQUAL(counter, 0);
- }
- void TListTest::TestListWithAutoDeleteClear() {
- using TListType = TIntrusiveListWithAutoDelete<TSelfCountingInt, TSelfCountingIntDelete>;
- int counter{0};
- {
- TListType lst;
- UNIT_ASSERT(lst.Empty());
- lst.PushFront(new TSelfCountingInt(counter, 2));
- UNIT_ASSERT_EQUAL(lst.Size(), 1);
- UNIT_ASSERT_EQUAL(counter, 1);
- lst.PushFront(new TSelfCountingInt(counter, 1));
- UNIT_ASSERT_EQUAL(lst.Size(), 2);
- UNIT_ASSERT_EQUAL(counter, 2);
- CheckList(lst);
- lst.Clear();
- UNIT_ASSERT(lst.Empty());
- UNIT_ASSERT_EQUAL(counter, 0);
- lst.PushFront(new TSelfCountingInt(counter, 1));
- UNIT_ASSERT_EQUAL(lst.Size(), 1);
- }
- UNIT_ASSERT_EQUAL(counter, 0);
- }
- struct TSecondTag {};
- class TDoubleNode
- : public TInt,
- public TIntrusiveListItem<TDoubleNode, TSecondTag> {
- public:
- TDoubleNode(int value) noexcept
- : TInt(value)
- {
- }
- };
- void TListTest::TestSecondTag() {
- TDoubleNode zero(0), one(1);
- TIntrusiveList<TInt> first;
- TIntrusiveList<TDoubleNode, TSecondTag> second;
- first.PushFront(&zero);
- first.PushFront(&one);
- second.PushBack(&zero);
- second.PushBack(&one);
- UNIT_ASSERT_EQUAL(*first.Front(), 1);
- UNIT_ASSERT_EQUAL(*++first.Begin(), 0);
- UNIT_ASSERT_EQUAL(*first.Back(), 0);
- UNIT_ASSERT_EQUAL(*second.Front(), 0);
- UNIT_ASSERT_EQUAL(*++second.Begin(), 1);
- UNIT_ASSERT_EQUAL(*second.Back(), 1);
- second.Remove(&zero);
- UNIT_ASSERT_EQUAL(*second.Front(), 1);
- UNIT_ASSERT_EQUAL(*first.Back(), 0);
- }
|