| 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);
|
| }
|
|
|