tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestLinkedList.cpp (3592B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "gtest/gtest.h"
      8 
      9 #include "mozilla/LinkedList.h"
     10 #include "mozilla/RefPtr.h"
     11 #include "mozilla/ReverseIterator.h"
     12 
     13 using mozilla::AutoCleanLinkedList;
     14 using mozilla::LinkedList;
     15 using mozilla::LinkedListElement;
     16 
     17 class PtrClass : public LinkedListElement<PtrClass> {
     18 public:
     19  bool* mResult;
     20 
     21  explicit PtrClass(bool* result) : mResult(result) { EXPECT_TRUE(!*mResult); }
     22 
     23  virtual ~PtrClass() { *mResult = true; }
     24 };
     25 
     26 class InheritedPtrClass : public PtrClass {
     27 public:
     28  bool* mInheritedResult;
     29 
     30  InheritedPtrClass(bool* result, bool* inheritedResult)
     31      : PtrClass(result), mInheritedResult(inheritedResult) {
     32    EXPECT_TRUE(!*mInheritedResult);
     33  }
     34 
     35  virtual ~InheritedPtrClass() { *mInheritedResult = true; }
     36 };
     37 
     38 TEST(LinkedList, AutoCleanLinkedList)
     39 {
     40  bool rv1 = false;
     41  bool rv2 = false;
     42  bool rv3 = false;
     43  {
     44    AutoCleanLinkedList<PtrClass> list;
     45    list.insertBack(new PtrClass(&rv1));
     46    list.insertBack(new InheritedPtrClass(&rv2, &rv3));
     47  }
     48 
     49  EXPECT_TRUE(rv1);
     50  EXPECT_TRUE(rv2);
     51  EXPECT_TRUE(rv3);
     52 }
     53 
     54 class CountedClass final : public LinkedListElement<RefPtr<CountedClass>> {
     55 public:
     56  int mCount;
     57  void AddRef() { mCount++; }
     58  void Release() { mCount--; }
     59 
     60  CountedClass() : mCount(0) {}
     61  ~CountedClass() { EXPECT_TRUE(mCount == 0); }
     62 };
     63 
     64 TEST(LinkedList, AutoCleanLinkedListRefPtr)
     65 {
     66  RefPtr<CountedClass> elt1 = new CountedClass;
     67  CountedClass* elt2 = new CountedClass;
     68  {
     69    AutoCleanLinkedList<RefPtr<CountedClass>> list;
     70    list.insertBack(elt1);
     71    list.insertBack(elt2);
     72 
     73    EXPECT_TRUE(elt1->mCount == 2);
     74    EXPECT_TRUE(elt2->mCount == 1);
     75  }
     76 
     77  EXPECT_TRUE(elt1->mCount == 1);
     78  EXPECT_TRUE(elt2->mCount == 0);
     79 }
     80 
     81 struct SomeClass : public LinkedListElement<SomeClass> {
     82  unsigned int mValue;
     83  explicit SomeClass(int aValue = 0) : mValue(aValue) {}
     84  SomeClass(SomeClass&&) = default;
     85  SomeClass& operator=(SomeClass&&) = default;
     86  void incr() { ++mValue; }
     87 };
     88 
     89 TEST(LinkedList, TestReverseIterators)
     90 {
     91  LinkedList<SomeClass> list;
     92  SomeClass one(1), two(2), three(3);
     93  list.insertBack(&one);
     94  list.insertBack(&two);
     95  list.insertBack(&three);
     96 
     97  // Traverse in reverse using rbegin/rend.
     98  unsigned int expect1[]{3, 2, 1};
     99  size_t idx = 0;
    100  for (auto it = list.rbegin(); it != list.rend(); ++it, ++idx) {
    101    EXPECT_EQ((*it)->mValue, expect1[idx]);
    102  }
    103  EXPECT_EQ(idx, 3u);
    104 
    105  // Const reverse iteration.
    106  const LinkedList<SomeClass>& clist = list;
    107  unsigned int expect2[]{3, 2, 1};
    108  idx = 0;
    109  for (auto it = clist.crbegin(); it != clist.crend(); ++it, ++idx) {
    110    EXPECT_EQ((*it)->mValue, expect2[idx]);
    111  }
    112  EXPECT_EQ(idx, 3u);
    113 
    114  // Use Reversed helper.
    115  unsigned int expect3[]{3, 2, 1};
    116  idx = 0;
    117  for (SomeClass* entry : mozilla::Reversed(list)) {
    118    EXPECT_EQ(entry->mValue, expect3[idx++]);
    119  }
    120  EXPECT_EQ(idx, 3u);
    121 
    122  // Mutation safety: remove after advancing.
    123  auto rit = list.rbegin();
    124  EXPECT_EQ((*rit)->mValue, 3u);
    125  SomeClass* toRemove = *rit;
    126  ++rit;               // advance before removal to avoid invalidating 'rit'
    127  toRemove->remove();  // remove 3
    128  EXPECT_EQ((*rit)->mValue, 2u);
    129  toRemove = *rit;
    130  ++rit;               // now at 1
    131  toRemove->remove();  // remove 2
    132  EXPECT_EQ(list.length(), 1u);
    133  EXPECT_EQ(list.getFirst()->mValue, 1u);
    134 }