Index: tests/LListTest.cpp |
diff --git a/tests/LListTest.cpp b/tests/LListTest.cpp |
index e0e55d0419d81555fade501092197e621ebbdb7c..70f320f977ba7dfa156ad52592ef38606c5ae2da 100644 |
--- a/tests/LListTest.cpp |
+++ b/tests/LListTest.cpp |
@@ -41,7 +41,7 @@ static void check_list(const SkTInternalLList<ListElement>& list, |
#endif |
} |
-static void TestTInternalLList(skiatest::Reporter* reporter) { |
+static void test_tinternallist(skiatest::Reporter* reporter) { |
SkTInternalLList<ListElement> list; |
ListElement elements[4] = { |
ListElement(0), |
@@ -114,175 +114,175 @@ static void TestTInternalLList(skiatest::Reporter* reporter) { |
} |
} |
-static void TestTLList(skiatest::Reporter* reporter) { |
- typedef SkTLList<ListElement> ElList; |
- typedef ElList::Iter Iter; |
+template <unsigned int N> static void test_tllist(skiatest::Reporter* reporter) { |
+ typedef SkTLList<ListElement, N> ElList; |
+ typedef typename ElList::Iter Iter; |
SkRandom random; |
- for (int i = 1; i <= 16; i *= 2) { |
- |
- ElList list1(i); |
- ElList list2(i); |
- Iter iter1; |
- Iter iter2; |
- Iter iter3; |
- Iter iter4; |
- |
- REPORTER_ASSERT(reporter, list1.isEmpty()); |
- REPORTER_ASSERT(reporter, nullptr == iter1.init(list1, Iter::kHead_IterStart)); |
- REPORTER_ASSERT(reporter, nullptr == iter1.init(list1, Iter::kTail_IterStart)); |
- // Try popping an empty list |
- list1.popHead(); |
- list1.popTail(); |
- REPORTER_ASSERT(reporter, list1.isEmpty()); |
- REPORTER_ASSERT(reporter, list1 == list2); |
- |
- // Create two identical lists, one by appending to head and the other to the tail. |
- list1.addToHead(ListElement(1)); |
- list2.addToTail(ListElement(1)); |
- iter1.init(list1, Iter::kHead_IterStart); |
- iter2.init(list1, Iter::kTail_IterStart); |
- REPORTER_ASSERT(reporter, iter1.get()->fID == iter2.get()->fID); |
- iter3.init(list2, Iter::kHead_IterStart); |
- iter4.init(list2, Iter::kTail_IterStart); |
- REPORTER_ASSERT(reporter, iter3.get()->fID == iter1.get()->fID); |
- REPORTER_ASSERT(reporter, iter4.get()->fID == iter1.get()->fID); |
- REPORTER_ASSERT(reporter, list1 == list2); |
- |
- list2.reset(); |
- |
- // use both before/after in-place construction on an empty list |
- list2.addBefore(list2.headIter(), 1); |
- REPORTER_ASSERT(reporter, list2 == list1); |
- list2.reset(); |
- |
- list2.addAfter(list2.tailIter(), 1); |
- REPORTER_ASSERT(reporter, list2 == list1); |
- |
- // add an element to the second list, check that iters are still valid |
- iter3.init(list2, Iter::kHead_IterStart); |
- iter4.init(list2, Iter::kTail_IterStart); |
- list2.addToHead(ListElement(2)); |
- |
- REPORTER_ASSERT(reporter, iter3.get()->fID == iter1.get()->fID); |
- REPORTER_ASSERT(reporter, iter4.get()->fID == iter1.get()->fID); |
- REPORTER_ASSERT(reporter, 1 == Iter(list2, Iter::kTail_IterStart).get()->fID); |
- REPORTER_ASSERT(reporter, 2 == Iter(list2, Iter::kHead_IterStart).get()->fID); |
- REPORTER_ASSERT(reporter, list1 != list2); |
- list1.addToHead(ListElement(2)); |
- REPORTER_ASSERT(reporter, list1 == list2); |
- REPORTER_ASSERT(reporter, !list1.isEmpty()); |
- |
- list1.reset(); |
- list2.reset(); |
- REPORTER_ASSERT(reporter, list1.isEmpty() && list2.isEmpty()); |
- |
- // randomly perform insertions and deletions on a list and perform tests |
- int count = 0; |
- for (int j = 0; j < 100; ++j) { |
- if (list1.isEmpty() || random.nextBiasedBool(3 * SK_Scalar1 / 4)) { |
- int id = j; |
- // Choose one of three ways to insert a new element: at the head, at the tail, |
- // before a random element, after a random element |
- int numValidMethods = 0 == count ? 2 : 4; |
- int insertionMethod = random.nextULessThan(numValidMethods); |
- switch (insertionMethod) { |
- case 0: |
- list1.addToHead(ListElement(id)); |
- break; |
- case 1: |
- list1.addToTail(ListElement(id)); |
- break; |
- case 2: // fallthru to share code that picks random element. |
- case 3: { |
- int n = random.nextULessThan(list1.count()); |
- Iter iter = list1.headIter(); |
- // remember the elements before/after the insertion point. |
- while (n--) { |
- iter.next(); |
+ ElList list1; |
+ ElList list2; |
+ Iter iter1; |
+ Iter iter2; |
+ Iter iter3; |
+ Iter iter4; |
+ |
+ REPORTER_ASSERT(reporter, list1.isEmpty()); |
+ REPORTER_ASSERT(reporter, nullptr == iter1.init(list1, Iter::kHead_IterStart)); |
+ REPORTER_ASSERT(reporter, nullptr == iter1.init(list1, Iter::kTail_IterStart)); |
+ // Try popping an empty list |
+ list1.popHead(); |
+ list1.popTail(); |
+ REPORTER_ASSERT(reporter, list1.isEmpty()); |
+ REPORTER_ASSERT(reporter, list1 == list2); |
+ |
+ // Create two identical lists, one by appending to head and the other to the tail. |
+ list1.addToHead(ListElement(1)); |
+ list2.addToTail(ListElement(1)); |
+ iter1.init(list1, Iter::kHead_IterStart); |
+ iter2.init(list1, Iter::kTail_IterStart); |
+ REPORTER_ASSERT(reporter, iter1.get()->fID == iter2.get()->fID); |
+ iter3.init(list2, Iter::kHead_IterStart); |
+ iter4.init(list2, Iter::kTail_IterStart); |
+ REPORTER_ASSERT(reporter, iter3.get()->fID == iter1.get()->fID); |
+ REPORTER_ASSERT(reporter, iter4.get()->fID == iter1.get()->fID); |
+ REPORTER_ASSERT(reporter, list1 == list2); |
+ |
+ list2.reset(); |
+ |
+ // use both before/after in-place construction on an empty list |
+ list2.addBefore(list2.headIter(), 1); |
+ REPORTER_ASSERT(reporter, list2 == list1); |
+ list2.reset(); |
+ |
+ list2.addAfter(list2.tailIter(), 1); |
+ REPORTER_ASSERT(reporter, list2 == list1); |
+ |
+ // add an element to the second list, check that iters are still valid |
+ iter3.init(list2, Iter::kHead_IterStart); |
+ iter4.init(list2, Iter::kTail_IterStart); |
+ list2.addToHead(ListElement(2)); |
+ |
+ REPORTER_ASSERT(reporter, iter3.get()->fID == iter1.get()->fID); |
+ REPORTER_ASSERT(reporter, iter4.get()->fID == iter1.get()->fID); |
+ REPORTER_ASSERT(reporter, 1 == Iter(list2, Iter::kTail_IterStart).get()->fID); |
+ REPORTER_ASSERT(reporter, 2 == Iter(list2, Iter::kHead_IterStart).get()->fID); |
+ REPORTER_ASSERT(reporter, list1 != list2); |
+ list1.addToHead(ListElement(2)); |
+ REPORTER_ASSERT(reporter, list1 == list2); |
+ REPORTER_ASSERT(reporter, !list1.isEmpty()); |
+ |
+ list1.reset(); |
+ list2.reset(); |
+ REPORTER_ASSERT(reporter, list1.isEmpty() && list2.isEmpty()); |
+ |
+ // randomly perform insertions and deletions on a list and perform tests |
+ int count = 0; |
+ for (int j = 0; j < 100; ++j) { |
+ if (list1.isEmpty() || random.nextBiasedBool(3 * SK_Scalar1 / 4)) { |
+ int id = j; |
+ // Choose one of three ways to insert a new element: at the head, at the tail, |
+ // before a random element, after a random element |
+ int numValidMethods = 0 == count ? 2 : 4; |
+ int insertionMethod = random.nextULessThan(numValidMethods); |
+ switch (insertionMethod) { |
+ case 0: |
+ list1.addToHead(ListElement(id)); |
+ break; |
+ case 1: |
+ list1.addToTail(ListElement(id)); |
+ break; |
+ case 2: // fallthru to share code that picks random element. |
+ case 3: { |
+ int n = random.nextULessThan(list1.count()); |
+ Iter iter = list1.headIter(); |
+ // remember the elements before/after the insertion point. |
+ while (n--) { |
+ iter.next(); |
+ } |
+ Iter prev(iter); |
+ Iter next(iter); |
+ next.next(); |
+ prev.prev(); |
+ |
+ SkASSERT(iter.get()); |
+ // insert either before or after the iterator, then check that the |
+ // surrounding sequence is correct. |
+ if (2 == insertionMethod) { |
+ list1.addBefore(iter, id); |
+ Iter newItem(iter); |
+ newItem.prev(); |
+ REPORTER_ASSERT(reporter, newItem.get()->fID == id); |
+ |
+ if (next.get()) { |
+ REPORTER_ASSERT(reporter, next.prev()->fID == iter.get()->fID); |
+ } |
+ if (prev.get()) { |
+ REPORTER_ASSERT(reporter, prev.next()->fID == id); |
} |
- Iter prev(iter); |
- Iter next(iter); |
- next.next(); |
- prev.prev(); |
- |
- SkASSERT(iter.get()); |
- // insert either before or after the iterator, then check that the |
- // surrounding sequence is correct. |
- if (2 == insertionMethod) { |
- list1.addBefore(iter, id); |
- Iter newItem(iter); |
- newItem.prev(); |
- REPORTER_ASSERT(reporter, newItem.get()->fID == id); |
- |
- if (next.get()) { |
- REPORTER_ASSERT(reporter, next.prev()->fID == iter.get()->fID); |
- } |
- if (prev.get()) { |
- REPORTER_ASSERT(reporter, prev.next()->fID == id); |
- } |
- } else { |
- list1.addAfter(iter, id); |
- Iter newItem(iter); |
- newItem.next(); |
- REPORTER_ASSERT(reporter, newItem.get()->fID == id); |
- |
- if (next.get()) { |
- REPORTER_ASSERT(reporter, next.prev()->fID == id); |
- } |
- if (prev.get()) { |
- REPORTER_ASSERT(reporter, prev.next()->fID == iter.get()->fID); |
- } |
+ } else { |
+ list1.addAfter(iter, id); |
+ Iter newItem(iter); |
+ newItem.next(); |
+ REPORTER_ASSERT(reporter, newItem.get()->fID == id); |
+ |
+ if (next.get()) { |
+ REPORTER_ASSERT(reporter, next.prev()->fID == id); |
+ } |
+ if (prev.get()) { |
+ REPORTER_ASSERT(reporter, prev.next()->fID == iter.get()->fID); |
} |
} |
} |
- ++count; |
+ } |
+ ++count; |
+ } else { |
+ // walk to a random place either forward or backwards and remove. |
+ int n = random.nextULessThan(list1.count()); |
+ typename Iter::IterStart start; |
+ ListElement* (Iter::*incrFunc)(); |
+ |
+ if (random.nextBool()) { |
+ start = Iter::kHead_IterStart; |
+ incrFunc = &Iter::next; |
} else { |
- // walk to a random place either forward or backwards and remove. |
- int n = random.nextULessThan(list1.count()); |
- Iter::IterStart start; |
- ListElement* (Iter::*incrFunc)(); |
- |
- if (random.nextBool()) { |
- start = Iter::kHead_IterStart; |
- incrFunc = &Iter::next; |
- } else { |
- start = Iter::kTail_IterStart; |
- incrFunc = &Iter::prev; |
- } |
+ start = Iter::kTail_IterStart; |
+ incrFunc = &Iter::prev; |
+ } |
- // find the element |
- Iter iter(list1, start); |
- while (n--) { |
- REPORTER_ASSERT(reporter, iter.get()); |
- (iter.*incrFunc)(); |
- } |
+ // find the element |
+ Iter iter(list1, start); |
+ while (n--) { |
REPORTER_ASSERT(reporter, iter.get()); |
- |
- // remember the prev and next elements from the element to be removed |
- Iter prev = iter; |
- Iter next = iter; |
- prev.prev(); |
- next.next(); |
- list1.remove(iter.get()); |
- |
- // make sure the remembered next/prev iters still work |
- Iter pn = prev; pn.next(); |
- Iter np = next; np.prev(); |
- // pn should match next unless the target node was the head, in which case prev |
- // walked off the list. |
- REPORTER_ASSERT(reporter, pn.get() == next.get() || nullptr == prev.get()); |
- // Similarly, np should match prev unless next originally walked off the tail. |
- REPORTER_ASSERT(reporter, np.get() == prev.get() || nullptr == next.get()); |
- --count; |
+ (iter.*incrFunc)(); |
} |
- REPORTER_ASSERT(reporter, count == list1.count()); |
+ REPORTER_ASSERT(reporter, iter.get()); |
+ |
+ // remember the prev and next elements from the element to be removed |
+ Iter prev = iter; |
+ Iter next = iter; |
+ prev.prev(); |
+ next.next(); |
+ list1.remove(iter.get()); |
+ |
+ // make sure the remembered next/prev iters still work |
+ Iter pn = prev; pn.next(); |
+ Iter np = next; np.prev(); |
+ // pn should match next unless the target node was the head, in which case prev |
+ // walked off the list. |
+ REPORTER_ASSERT(reporter, pn.get() == next.get() || nullptr == prev.get()); |
+ // Similarly, np should match prev unless next originally walked off the tail. |
+ REPORTER_ASSERT(reporter, np.get() == prev.get() || nullptr == next.get()); |
+ --count; |
} |
- list1.reset(); |
+ REPORTER_ASSERT(reporter, count == list1.count()); |
} |
} |
DEF_TEST(LList, reporter) { |
- TestTInternalLList(reporter); |
- TestTLList(reporter); |
+ test_tinternallist(reporter); |
+ test_tllist<1>(reporter); |
+ test_tllist<3>(reporter); |
+ test_tllist<8>(reporter); |
+ test_tllist<10>(reporter); |
+ test_tllist<16>(reporter); |
} |