summaryrefslogtreecommitdiffstats
path: root/WebKit/chromium/tests
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit/chromium/tests')
-rw-r--r--WebKit/chromium/tests/ArenaTestHelpers.h78
-rw-r--r--WebKit/chromium/tests/PODArenaTest.cpp106
-rw-r--r--WebKit/chromium/tests/PODIntervalTreeTest.cpp323
-rw-r--r--WebKit/chromium/tests/PODRedBlackTreeTest.cpp213
-rw-r--r--WebKit/chromium/tests/TreeTestHelpers.cpp60
-rw-r--r--WebKit/chromium/tests/TreeTestHelpers.h53
6 files changed, 833 insertions, 0 deletions
diff --git a/WebKit/chromium/tests/ArenaTestHelpers.h b/WebKit/chromium/tests/ArenaTestHelpers.h
new file mode 100644
index 0000000..87f827d
--- /dev/null
+++ b/WebKit/chromium/tests/ArenaTestHelpers.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ArenaTestHelpers_h
+#define ArenaTestHelpers_h
+
+#include "PODArena.h"
+#include <gtest/gtest.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+namespace ArenaTestHelpers {
+
+// An allocator for the PODArena which tracks the regions which have
+// been allocated.
+class TrackedAllocator : public PODArena::FastMallocAllocator {
+public:
+ static PassRefPtr<TrackedAllocator> create()
+ {
+ return adoptRef(new TrackedAllocator);
+ }
+
+ virtual void* allocate(size_t size)
+ {
+ void* result = PODArena::FastMallocAllocator::allocate(size);
+ m_allocatedRegions.append(result);
+ return result;
+ }
+
+ virtual void free(void* ptr)
+ {
+ size_t slot = m_allocatedRegions.find(ptr);
+ ASSERT_GE(slot, 0);
+ m_allocatedRegions.remove(slot);
+ PODArena::FastMallocAllocator::free(ptr);
+ }
+
+ bool isEmpty() const
+ {
+ return !numRegions();
+ }
+
+ int numRegions() const
+ {
+ return m_allocatedRegions.size();
+ }
+
+private:
+ TrackedAllocator() { }
+ Vector<void*> m_allocatedRegions;
+};
+
+} // namespace ArenaTestHelpers
+} // namespace WebCore
+
+#endif // ArenaTestHelpers_h
diff --git a/WebKit/chromium/tests/PODArenaTest.cpp b/WebKit/chromium/tests/PODArenaTest.cpp
new file mode 100644
index 0000000..c5b1ede
--- /dev/null
+++ b/WebKit/chromium/tests/PODArenaTest.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "PODArena.h"
+
+#include "ArenaTestHelpers.h"
+#include <algorithm>
+#include <gtest/gtest.h>
+#include <wtf/FastMalloc.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+using ArenaTestHelpers::TrackedAllocator;
+
+namespace {
+
+// A couple of simple structs to allocate.
+struct TestClass1 {
+ TestClass1()
+ : x(0), y(0), z(0), w(1) { }
+
+ float x, y, z, w;
+};
+
+struct TestClass2 {
+ TestClass2()
+ : a(1), b(2), c(3), d(4) { }
+
+ float a, b, c, d;
+};
+
+} // anonymous namespace
+
+class PODArenaTest : public testing::Test {
+};
+
+// Make sure the arena can successfully allocate from more than one
+// region.
+TEST_F(PODArenaTest, CanAllocateFromMoreThanOneRegion)
+{
+ RefPtr<TrackedAllocator> allocator = TrackedAllocator::create();
+ RefPtr<PODArena> arena = PODArena::create(allocator);
+ int numIterations = 10 * PODArena::DefaultChunkSize / sizeof(TestClass1);
+ for (int i = 0; i < numIterations; ++i)
+ arena->allocateObject<TestClass1>();
+ EXPECT_GT(allocator->numRegions(), 1);
+}
+
+// Make sure the arena frees all allocated regions during destruction.
+TEST_F(PODArenaTest, FreesAllAllocatedRegions)
+{
+ RefPtr<TrackedAllocator> allocator = TrackedAllocator::create();
+ {
+ RefPtr<PODArena> arena = PODArena::create(allocator);
+ for (int i = 0; i < 3; i++)
+ arena->allocateObject<TestClass1>();
+ EXPECT_GT(allocator->numRegions(), 0);
+ }
+ EXPECT_TRUE(allocator->isEmpty());
+}
+
+// Make sure the arena runs constructors of the objects allocated within.
+TEST_F(PODArenaTest, RunsConstructors)
+{
+ RefPtr<PODArena> arena = PODArena::create();
+ for (int i = 0; i < 10000; i++) {
+ TestClass1* tc1 = arena->allocateObject<TestClass1>();
+ EXPECT_EQ(0, tc1->x);
+ EXPECT_EQ(0, tc1->y);
+ EXPECT_EQ(0, tc1->z);
+ EXPECT_EQ(1, tc1->w);
+ TestClass2* tc2 = arena->allocateObject<TestClass2>();
+ EXPECT_EQ(1, tc2->a);
+ EXPECT_EQ(2, tc2->b);
+ EXPECT_EQ(3, tc2->c);
+ EXPECT_EQ(4, tc2->d);
+ }
+}
+
+} // namespace WebCore
diff --git a/WebKit/chromium/tests/PODIntervalTreeTest.cpp b/WebKit/chromium/tests/PODIntervalTreeTest.cpp
new file mode 100644
index 0000000..3a8a245
--- /dev/null
+++ b/WebKit/chromium/tests/PODIntervalTreeTest.cpp
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Tests for the interval tree class.
+
+#include "config.h"
+
+#include "PODIntervalTree.h"
+
+#include "Logging.h"
+#include "TreeTestHelpers.h"
+#include <gtest/gtest.h>
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+using TreeTestHelpers::generateSeed;
+using TreeTestHelpers::initRandom;
+using TreeTestHelpers::nextRandom;
+
+inline String valueToString(const float& value)
+{
+ return String::number(value);
+}
+
+inline String valueToString(void* const& value)
+{
+ return String::format("0x%p", value);
+}
+
+TEST(PODIntervalTreeTest, TestInsertion)
+{
+ PODIntervalTree<float> tree;
+ tree.add(PODInterval<float>(2, 4));
+ ASSERT_TRUE(tree.checkInvariants());
+}
+
+TEST(PODIntervalTreeTest, TestInsertionAndQuery)
+{
+ PODIntervalTree<float> tree;
+ tree.add(PODInterval<float>(2, 4));
+ ASSERT_TRUE(tree.checkInvariants());
+ Vector<PODInterval<float> > result = tree.allOverlaps(PODInterval<float>(1, 3));
+ EXPECT_EQ(1U, result.size());
+ EXPECT_EQ(2, result[0].low());
+ EXPECT_EQ(4, result[0].high());
+}
+
+TEST(PODIntervalTreeTest, TestQueryAgainstZeroSizeInterval)
+{
+ PODIntervalTree<float> tree;
+ tree.add(PODInterval<float>(1, 2.5));
+ tree.add(PODInterval<float>(3.5, 5));
+ tree.add(PODInterval<float>(2, 4));
+ ASSERT_TRUE(tree.checkInvariants());
+ Vector<PODInterval<float> > result = tree.allOverlaps(PODInterval<float>(3, 3));
+ EXPECT_EQ(1U, result.size());
+ EXPECT_EQ(2, result[0].low());
+ EXPECT_EQ(4, result[0].high());
+}
+
+TEST(PODIntervalTreeTest, TestDuplicateElementInsertion)
+{
+ PODIntervalTree<float, int*> tree;
+ int tmp1 = 1;
+ int tmp2 = 2;
+ typedef PODIntervalTree<float, int*>::IntervalType IntervalType;
+ IntervalType interval1(1, 3, &tmp1);
+ IntervalType interval2(1, 3, &tmp2);
+ tree.add(interval1);
+ tree.add(interval2);
+ ASSERT_TRUE(tree.checkInvariants());
+ EXPECT_TRUE(tree.contains(interval1));
+ EXPECT_TRUE(tree.contains(interval2));
+ EXPECT_TRUE(tree.remove(interval1));
+ EXPECT_TRUE(tree.contains(interval2));
+ EXPECT_FALSE(tree.contains(interval1));
+ EXPECT_TRUE(tree.remove(interval2));
+ EXPECT_EQ(0, tree.size());
+}
+
+namespace {
+
+struct UserData1 {
+public:
+ UserData1()
+ : a(0), b(1) { }
+
+ float a;
+ int b;
+};
+
+inline String valueToString(const UserData1& value)
+{
+ return String("[UserData1 a=") + String::number(value.a) + " b=" + String::number(value.b) + "]";
+}
+
+} // anonymous namespace
+
+TEST(PODIntervalTreeTest, TestInsertionOfComplexUserData)
+{
+ PODIntervalTree<float, UserData1> tree;
+ UserData1 data1;
+ data1.a = 5;
+ data1.b = 6;
+ tree.add(tree.createInterval(2, 4, data1));
+ ASSERT_TRUE(tree.checkInvariants());
+}
+
+TEST(PODIntervalTreeTest, TestQueryingOfComplexUserData)
+{
+ PODIntervalTree<float, UserData1> tree;
+ UserData1 data1;
+ data1.a = 5;
+ data1.b = 6;
+ tree.add(tree.createInterval(2, 4, data1));
+ ASSERT_TRUE(tree.checkInvariants());
+ Vector<PODInterval<float, UserData1> > overlaps = tree.allOverlaps(tree.createInterval(3, 5, data1));
+ EXPECT_EQ(1U, overlaps.size());
+ EXPECT_EQ(5, overlaps[0].data().a);
+ EXPECT_EQ(6, overlaps[0].data().b);
+}
+
+namespace {
+
+class EndpointType1 {
+public:
+ explicit EndpointType1(int value)
+ : m_value(value) { }
+
+ int value() const { return m_value; }
+
+ bool operator<(const EndpointType1& other) const { return m_value < other.m_value; }
+ bool operator==(const EndpointType1& other) const { return m_value == other.m_value; }
+
+private:
+ int m_value;
+ // These operators should not be called by the interval tree.
+ bool operator>(const EndpointType1& other);
+ bool operator<=(const EndpointType1& other);
+ bool operator>=(const EndpointType1& other);
+ bool operator!=(const EndpointType1& other);
+};
+
+inline String valueToString(const EndpointType1& value)
+{
+ return String("[EndpointType1 value=") + String::number(value.value()) + "]";
+}
+
+} // anonymous namespace
+
+TEST(PODIntervalTreeTest, TestTreeDoesNotRequireMostOperators)
+{
+ PODIntervalTree<EndpointType1> tree;
+ tree.add(tree.createInterval(EndpointType1(1), EndpointType1(2)));
+ ASSERT_TRUE(tree.checkInvariants());
+}
+
+// Uncomment to debug a failure of the insertion and deletion test.
+// #define DEBUG_INSERTION_AND_DELETION_TEST
+
+namespace {
+
+void InsertionAndDeletionTest(int32_t seed, int treeSize)
+{
+ initRandom(seed);
+ int maximumValue = treeSize;
+ // Build the tree
+ PODIntervalTree<int> tree;
+ Vector<PODInterval<int> > addedElements;
+ Vector<PODInterval<int> > removedElements;
+ for (int i = 0; i < treeSize; i++) {
+ int left = nextRandom(maximumValue);
+ int length = nextRandom(maximumValue);
+ PODInterval<int> interval(left, left + length);
+ tree.add(interval);
+#ifdef DEBUG_INSERTION_AND_DELETION_TEST
+ LOG_ERROR("*** Adding element %s", valueToString(interval).ascii().data());
+#endif
+ addedElements.append(interval);
+ }
+ // Churn the tree's contents.
+ // First remove half of the elements in random order.
+ for (int i = 0; i < treeSize / 2; i++) {
+ int index = nextRandom(addedElements.size());
+#ifdef DEBUG_INSERTION_AND_DELETION_TEST
+ LOG_ERROR("*** Removing element %s", valueToString(addedElements[index]).ascii().data());
+#endif
+ ASSERT_TRUE(tree.contains(addedElements[index])) << "Test failed for seed " << seed;
+ tree.remove(addedElements[index]);
+ removedElements.append(addedElements[index]);
+ addedElements.remove(index);
+ ASSERT_TRUE(tree.checkInvariants()) << "Test failed for seed " << seed;
+ }
+ // Now randomly add or remove elements.
+ for (int i = 0; i < 2 * treeSize; i++) {
+ bool add = false;
+ if (!addedElements.size())
+ add = true;
+ else if (!removedElements.size())
+ add = false;
+ else
+ add = (nextRandom(2) == 1);
+ if (add) {
+ int index = nextRandom(removedElements.size());
+#ifdef DEBUG_INSERTION_AND_DELETION_TEST
+ LOG_ERROR("*** Adding element %s", valueToString(removedElements[index]).ascii().data());
+#endif
+ tree.add(removedElements[index]);
+ addedElements.append(removedElements[index]);
+ removedElements.remove(index);
+ } else {
+ int index = nextRandom(addedElements.size());
+#ifdef DEBUG_INSERTION_AND_DELETION_TEST
+ LOG_ERROR("*** Removing element %s", valueToString(addedElements[index]).ascii().data());
+#endif
+ ASSERT_TRUE(tree.contains(addedElements[index])) << "Test failed for seed " << seed;
+ ASSERT_TRUE(tree.remove(addedElements[index])) << "Test failed for seed " << seed;
+ removedElements.append(addedElements[index]);
+ addedElements.remove(index);
+ }
+ ASSERT_TRUE(tree.checkInvariants()) << "Test failed for seed " << seed;
+ }
+}
+
+} // anonymous namespace
+
+TEST(PODIntervalTreeTest, RandomDeletionAndInsertionRegressionTest1)
+{
+ InsertionAndDeletionTest(13972, 100);
+}
+
+TEST(PODIntervalTreeTest, RandomDeletionAndInsertionRegressionTest2)
+{
+ InsertionAndDeletionTest(1283382113, 10);
+}
+
+TEST(PODIntervalTreeTest, RandomDeletionAndInsertionRegressionTest3)
+{
+ // This is the sequence of insertions and deletions that triggered
+ // the failure in RandomDeletionAndInsertionRegressionTest2.
+ PODIntervalTree<int> tree;
+ tree.add(tree.createInterval(0, 5));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(tree.createInterval(4, 5));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(tree.createInterval(8, 9));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(tree.createInterval(1, 4));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(tree.createInterval(3, 5));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(tree.createInterval(4, 12));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(tree.createInterval(0, 2));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(tree.createInterval(0, 2));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(tree.createInterval(9, 13));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(tree.createInterval(0, 1));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.remove(tree.createInterval(0, 2));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.remove(tree.createInterval(9, 13));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.remove(tree.createInterval(0, 2));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.remove(tree.createInterval(0, 1));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.remove(tree.createInterval(4, 5));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.remove(tree.createInterval(4, 12));
+ ASSERT_TRUE(tree.checkInvariants());
+}
+
+TEST(PODIntervalTreeTest, RandomDeletionAndInsertionRegressionTest4)
+{
+ // Even further reduced test case for RandomDeletionAndInsertionRegressionTest3.
+ PODIntervalTree<int> tree;
+ tree.add(tree.createInterval(0, 5));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(tree.createInterval(8, 9));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(tree.createInterval(1, 4));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(tree.createInterval(3, 5));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(tree.createInterval(4, 12));
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.remove(tree.createInterval(4, 12));
+ ASSERT_TRUE(tree.checkInvariants());
+}
+
+TEST(PODIntervalTreeTest, TestRandomDeletionAndInsertion)
+{
+ InsertionAndDeletionTest(generateSeed(), 1000);
+}
+
+} // namespace WebCore
diff --git a/WebKit/chromium/tests/PODRedBlackTreeTest.cpp b/WebKit/chromium/tests/PODRedBlackTreeTest.cpp
new file mode 100644
index 0000000..0cc10e7
--- /dev/null
+++ b/WebKit/chromium/tests/PODRedBlackTreeTest.cpp
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Tests for the red-black tree class.
+
+#include "config.h"
+
+#include "PODRedBlackTree.h"
+
+#include "ArenaTestHelpers.h"
+#include "TreeTestHelpers.h"
+#include <gtest/gtest.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+using ArenaTestHelpers::TrackedAllocator;
+using TreeTestHelpers::generateSeed;
+using TreeTestHelpers::initRandom;
+using TreeTestHelpers::nextRandom;
+
+TEST(PODRedBlackTreeTest, TestTreeAllocatesFromArena)
+{
+ RefPtr<TrackedAllocator> allocator = TrackedAllocator::create();
+ {
+ RefPtr<PODArena> arena = PODArena::create(allocator);
+ PODRedBlackTree<int> tree(arena);
+ int numAdditions = 2 * PODArena::DefaultChunkSize / sizeof(int);
+ for (int i = 0; i < numAdditions; ++i)
+ tree.add(i);
+ EXPECT_GT(allocator->numRegions(), 1);
+ }
+ EXPECT_EQ(allocator->numRegions(), 0);
+}
+
+TEST(PODRedBlackTreeTest, TestSingleElementInsertion)
+{
+ PODRedBlackTree<int> tree;
+ tree.add(5);
+ ASSERT_TRUE(tree.checkInvariants());
+ EXPECT_TRUE(tree.contains(5));
+}
+
+TEST(PODRedBlackTreeTest, TestMultipleElementInsertion)
+{
+ PODRedBlackTree<int> tree;
+ tree.add(4);
+ ASSERT_TRUE(tree.checkInvariants());
+ EXPECT_TRUE(tree.contains(4));
+ tree.add(3);
+ ASSERT_TRUE(tree.checkInvariants());
+ EXPECT_TRUE(tree.contains(3));
+ tree.add(5);
+ ASSERT_TRUE(tree.checkInvariants());
+ EXPECT_TRUE(tree.contains(5));
+ EXPECT_TRUE(tree.contains(4));
+ EXPECT_TRUE(tree.contains(3));
+}
+
+TEST(PODRedBlackTreeTest, TestDuplicateElementInsertion)
+{
+ PODRedBlackTree<int> tree;
+ tree.add(3);
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(3);
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(3);
+ ASSERT_TRUE(tree.checkInvariants());
+ EXPECT_EQ(3, tree.size());
+ EXPECT_TRUE(tree.contains(3));
+}
+
+TEST(PODRedBlackTreeTest, TestSingleElementInsertionAndDeletion)
+{
+ PODRedBlackTree<int> tree;
+ tree.add(5);
+ ASSERT_TRUE(tree.checkInvariants());
+ EXPECT_TRUE(tree.contains(5));
+ tree.remove(5);
+ ASSERT_TRUE(tree.checkInvariants());
+ EXPECT_FALSE(tree.contains(5));
+}
+
+TEST(PODRedBlackTreeTest, TestMultipleElementInsertionAndDeletion)
+{
+ PODRedBlackTree<int> tree;
+ tree.add(4);
+ ASSERT_TRUE(tree.checkInvariants());
+ EXPECT_TRUE(tree.contains(4));
+ tree.add(3);
+ ASSERT_TRUE(tree.checkInvariants());
+ EXPECT_TRUE(tree.contains(3));
+ tree.add(5);
+ ASSERT_TRUE(tree.checkInvariants());
+ EXPECT_TRUE(tree.contains(5));
+ EXPECT_TRUE(tree.contains(4));
+ EXPECT_TRUE(tree.contains(3));
+ tree.remove(4);
+ ASSERT_TRUE(tree.checkInvariants());
+ EXPECT_TRUE(tree.contains(3));
+ EXPECT_FALSE(tree.contains(4));
+ EXPECT_TRUE(tree.contains(5));
+ tree.remove(5);
+ ASSERT_TRUE(tree.checkInvariants());
+ EXPECT_TRUE(tree.contains(3));
+ EXPECT_FALSE(tree.contains(4));
+ EXPECT_FALSE(tree.contains(5));
+ EXPECT_EQ(1, tree.size());
+}
+
+TEST(PODRedBlackTreeTest, TestDuplicateElementInsertionAndDeletion)
+{
+ PODRedBlackTree<int> tree;
+ tree.add(3);
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(3);
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(3);
+ ASSERT_TRUE(tree.checkInvariants());
+ EXPECT_EQ(3, tree.size());
+ EXPECT_TRUE(tree.contains(3));
+ tree.remove(3);
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.remove(3);
+ ASSERT_TRUE(tree.checkInvariants());
+ EXPECT_EQ(1, tree.size());
+ EXPECT_TRUE(tree.contains(3));
+ tree.remove(3);
+ ASSERT_TRUE(tree.checkInvariants());
+ EXPECT_EQ(0, tree.size());
+ EXPECT_FALSE(tree.contains(3));
+}
+
+TEST(PODRedBlackTreeTest, FailingInsertionRegressionTest1)
+{
+ // These numbers came from a previously-failing randomized test run.
+ PODRedBlackTree<int> tree;
+ tree.add(5113);
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(4517);
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(3373);
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(9307);
+ ASSERT_TRUE(tree.checkInvariants());
+ tree.add(7077);
+ ASSERT_TRUE(tree.checkInvariants());
+}
+
+namespace {
+void InsertionAndDeletionTest(const int32_t seed, const int treeSize)
+{
+ initRandom(seed);
+ const int maximumValue = treeSize;
+ // Build the tree.
+ PODRedBlackTree<int> tree;
+ Vector<int> values;
+ for (int i = 0; i < treeSize; i++) {
+ int value = nextRandom(maximumValue);
+ tree.add(value);
+ ASSERT_TRUE(tree.checkInvariants()) << "Test failed for seed " << seed;
+ values.append(value);
+ }
+ // Churn the tree's contents.
+ for (int i = 0; i < treeSize; i++) {
+ // Pick a random value to remove.
+ int index = nextRandom(treeSize);
+ int value = values[index];
+ // Remove this value.
+ tree.remove(value);
+ ASSERT_TRUE(tree.checkInvariants()) << "Test failed for seed " << seed;
+ // Replace it with a new one.
+ value = nextRandom(maximumValue);
+ values[index] = value;
+ tree.add(value);
+ ASSERT_TRUE(tree.checkInvariants()) << "Test failed for seed " << seed;
+ }
+}
+} // anonymous namespace
+
+TEST(PODRedBlackTreeTest, RandomDeletionAndInsertionRegressionTest1)
+{
+ InsertionAndDeletionTest(12311, 100);
+}
+
+TEST(PODRedBlackTreeTest, TestRandomDeletionAndInsertion)
+{
+ InsertionAndDeletionTest(generateSeed(), 100);
+}
+
+} // namespace WebCore
diff --git a/WebKit/chromium/tests/TreeTestHelpers.cpp b/WebKit/chromium/tests/TreeTestHelpers.cpp
new file mode 100644
index 0000000..103b871
--- /dev/null
+++ b/WebKit/chromium/tests/TreeTestHelpers.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "TreeTestHelpers.h"
+
+#include <cstdlib>
+#include <wtf/CurrentTime.h>
+
+namespace WebCore {
+namespace TreeTestHelpers {
+
+int32_t generateSeed()
+{
+ // A seed of 1 has the special behavior of resetting the random
+ // number generator. Assume that if we call this routine that we
+ // don't want this behavior.
+ int32_t seed;
+ do {
+ seed = static_cast<int32_t>(currentTime());
+ } while (seed <= 1);
+ return seed;
+}
+
+void initRandom(const int32_t seed)
+{
+ srand(seed);
+}
+
+int32_t nextRandom(const int32_t maximumValue)
+{
+ // rand_r is not available on Windows
+ return rand() % maximumValue;
+}
+
+} // namespace TreeTestHelpers
+} // namespace WebCore
diff --git a/WebKit/chromium/tests/TreeTestHelpers.h b/WebKit/chromium/tests/TreeTestHelpers.h
new file mode 100644
index 0000000..af07b2a
--- /dev/null
+++ b/WebKit/chromium/tests/TreeTestHelpers.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Simple pseudorandom number generator helper functions, used by the
+// red-black and interval tree tests.
+//
+// These are **not** thread safe!
+
+#ifndef TreeTestHelpers_h
+#define TreeTestHelpers_h
+
+#include <stdint.h>
+
+namespace WebCore {
+namespace TreeTestHelpers {
+
+// Generates a seed value to be passed to initRandom().
+int32_t generateSeed();
+
+// Initializes the pseudo-random number generator with a specific seed.
+void initRandom(const int32_t seed);
+
+// Produces the next pseudo-random number in the sequence, in the
+// range from [0..maximumValue). Negative numbers are not allowed and will
+// produce undefined results.
+int32_t nextRandom(const int32_t maximumValue);
+
+} // namespace TreeTestHelpers
+} // namespace WebCore
+
+#endif // TreeTestHelpers_h