Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2010 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 // Tests for the interval tree class.
     27 
     28 #include "config.h"
     29 
     30 #include "PODIntervalTree.h"
     31 
     32 #include "Logging.h"
     33 #include "TreeTestHelpers.h"
     34 #include <gtest/gtest.h>
     35 #include <wtf/Vector.h>
     36 #include <wtf/text/WTFString.h>
     37 
     38 namespace WebCore {
     39 
     40 using TreeTestHelpers::generateSeed;
     41 using TreeTestHelpers::initRandom;
     42 using TreeTestHelpers::nextRandom;
     43 
     44 #ifndef NDEBUG
     45 template<>
     46 struct ValueToString<float> {
     47     static String string(const float& value) { return String::number(value); }
     48 };
     49 
     50 template<>
     51 struct ValueToString<void*> {
     52     static String string(void* const& value)
     53     {
     54         return String::format("0x%p", value);
     55     }
     56 };
     57 #endif
     58 
     59 TEST(PODIntervalTreeTest, TestInsertion)
     60 {
     61     PODIntervalTree<float> tree;
     62     tree.add(PODInterval<float>(2, 4));
     63     ASSERT_TRUE(tree.checkInvariants());
     64 }
     65 
     66 TEST(PODIntervalTreeTest, TestInsertionAndQuery)
     67 {
     68     PODIntervalTree<float> tree;
     69     tree.add(PODInterval<float>(2, 4));
     70     ASSERT_TRUE(tree.checkInvariants());
     71     Vector<PODInterval<float> > result = tree.allOverlaps(PODInterval<float>(1, 3));
     72     EXPECT_EQ(1U, result.size());
     73     EXPECT_EQ(2, result[0].low());
     74     EXPECT_EQ(4, result[0].high());
     75 }
     76 
     77 TEST(PODIntervalTreeTest, TestQueryAgainstZeroSizeInterval)
     78 {
     79     PODIntervalTree<float> tree;
     80     tree.add(PODInterval<float>(1, 2.5));
     81     tree.add(PODInterval<float>(3.5, 5));
     82     tree.add(PODInterval<float>(2, 4));
     83     ASSERT_TRUE(tree.checkInvariants());
     84     Vector<PODInterval<float> > result = tree.allOverlaps(PODInterval<float>(3, 3));
     85     EXPECT_EQ(1U, result.size());
     86     EXPECT_EQ(2, result[0].low());
     87     EXPECT_EQ(4, result[0].high());
     88 }
     89 
     90 #ifndef NDEBUG
     91 template<>
     92 struct ValueToString<int*> {
     93     static String string(int* const& value)
     94     {
     95         return String::format("0x%p", value);
     96     }
     97 };
     98 #endif
     99 
    100 TEST(PODIntervalTreeTest, TestDuplicateElementInsertion)
    101 {
    102     PODIntervalTree<float, int*> tree;
    103     int tmp1 = 1;
    104     int tmp2 = 2;
    105     typedef PODIntervalTree<float, int*>::IntervalType IntervalType;
    106     IntervalType interval1(1, 3, &tmp1);
    107     IntervalType interval2(1, 3, &tmp2);
    108     tree.add(interval1);
    109     tree.add(interval2);
    110     ASSERT_TRUE(tree.checkInvariants());
    111     EXPECT_TRUE(tree.contains(interval1));
    112     EXPECT_TRUE(tree.contains(interval2));
    113     EXPECT_TRUE(tree.remove(interval1));
    114     EXPECT_TRUE(tree.contains(interval2));
    115     EXPECT_FALSE(tree.contains(interval1));
    116     EXPECT_TRUE(tree.remove(interval2));
    117     EXPECT_EQ(0, tree.size());
    118 }
    119 
    120 namespace {
    121 
    122 struct UserData1 {
    123 public:
    124     UserData1()
    125         : a(0), b(1) { }
    126 
    127     float a;
    128     int b;
    129 };
    130 
    131 } // anonymous namespace
    132 
    133 #ifndef NDEBUG
    134 template<>
    135 struct ValueToString<UserData1> {
    136     static String string(const UserData1& value)
    137     {
    138         return String("[UserData1 a=") + String::number(value.a) + " b=" + String::number(value.b) + "]";
    139     }
    140 };
    141 #endif
    142 
    143 TEST(PODIntervalTreeTest, TestInsertionOfComplexUserData)
    144 {
    145     PODIntervalTree<float, UserData1> tree;
    146     UserData1 data1;
    147     data1.a = 5;
    148     data1.b = 6;
    149     tree.add(tree.createInterval(2, 4, data1));
    150     ASSERT_TRUE(tree.checkInvariants());
    151 }
    152 
    153 TEST(PODIntervalTreeTest, TestQueryingOfComplexUserData)
    154 {
    155     PODIntervalTree<float, UserData1> tree;
    156     UserData1 data1;
    157     data1.a = 5;
    158     data1.b = 6;
    159     tree.add(tree.createInterval(2, 4, data1));
    160     ASSERT_TRUE(tree.checkInvariants());
    161     Vector<PODInterval<float, UserData1> > overlaps = tree.allOverlaps(tree.createInterval(3, 5, data1));
    162     EXPECT_EQ(1U, overlaps.size());
    163     EXPECT_EQ(5, overlaps[0].data().a);
    164     EXPECT_EQ(6, overlaps[0].data().b);
    165 }
    166 
    167 namespace {
    168 
    169 class EndpointType1 {
    170 public:
    171     explicit EndpointType1(int value)
    172         : m_value(value) { }
    173 
    174     int value() const { return m_value; }
    175 
    176     bool operator<(const EndpointType1& other) const { return m_value < other.m_value; }
    177     bool operator==(const EndpointType1& other) const { return m_value == other.m_value; }
    178 
    179 private:
    180     int m_value;
    181     // These operators should not be called by the interval tree.
    182     bool operator>(const EndpointType1& other);
    183     bool operator<=(const EndpointType1& other);
    184     bool operator>=(const EndpointType1& other);
    185     bool operator!=(const EndpointType1& other);
    186 };
    187 
    188 } // anonymous namespace
    189 
    190 #ifndef NDEBUG
    191 template<>
    192 struct ValueToString<EndpointType1> {
    193     static String string(const EndpointType1& value)
    194     {
    195         return String("[EndpointType1 value=") + String::number(value.value()) + "]";
    196     }
    197 };
    198 #endif
    199 
    200 TEST(PODIntervalTreeTest, TestTreeDoesNotRequireMostOperators)
    201 {
    202     PODIntervalTree<EndpointType1> tree;
    203     tree.add(tree.createInterval(EndpointType1(1), EndpointType1(2)));
    204     ASSERT_TRUE(tree.checkInvariants());
    205 }
    206 
    207 // Uncomment to debug a failure of the insertion and deletion test. Won't work
    208 // in release builds.
    209 // #define DEBUG_INSERTION_AND_DELETION_TEST
    210 
    211 #ifndef NDEBUG
    212 template<>
    213 struct ValueToString<int> {
    214     static String string(const int& value) { return String::number(value); }
    215 };
    216 #endif
    217 
    218 namespace {
    219 
    220 void InsertionAndDeletionTest(int32_t seed, int treeSize)
    221 {
    222     initRandom(seed);
    223     int maximumValue = treeSize;
    224     // Build the tree
    225     PODIntervalTree<int> tree;
    226     Vector<PODInterval<int> > addedElements;
    227     Vector<PODInterval<int> > removedElements;
    228     for (int i = 0; i < treeSize; i++) {
    229         int left = nextRandom(maximumValue);
    230         int length = nextRandom(maximumValue);
    231         PODInterval<int> interval(left, left + length);
    232         tree.add(interval);
    233 #ifdef DEBUG_INSERTION_AND_DELETION_TEST
    234         LOG_ERROR("*** Adding element %s", ValueToString<PODInterval<int> >::string(interval).ascii().data());
    235 #endif
    236         addedElements.append(interval);
    237     }
    238     // Churn the tree's contents.
    239     // First remove half of the elements in random order.
    240     for (int i = 0; i < treeSize / 2; i++) {
    241         int index = nextRandom(addedElements.size());
    242 #ifdef DEBUG_INSERTION_AND_DELETION_TEST
    243         LOG_ERROR("*** Removing element %s", ValueToString<PODInterval<int> >::string(addedElements[index]).ascii().data());
    244 #endif
    245         ASSERT_TRUE(tree.contains(addedElements[index])) << "Test failed for seed " << seed;
    246         tree.remove(addedElements[index]);
    247         removedElements.append(addedElements[index]);
    248         addedElements.remove(index);
    249         ASSERT_TRUE(tree.checkInvariants()) << "Test failed for seed " << seed;
    250     }
    251     // Now randomly add or remove elements.
    252     for (int i = 0; i < 2 * treeSize; i++) {
    253         bool add = false;
    254         if (!addedElements.size())
    255             add = true;
    256         else if (!removedElements.size())
    257             add = false;
    258         else
    259             add = (nextRandom(2) == 1);
    260         if (add) {
    261             int index = nextRandom(removedElements.size());
    262 #ifdef DEBUG_INSERTION_AND_DELETION_TEST
    263             LOG_ERROR("*** Adding element %s", ValueToString<PODInterval<int> >::string(removedElements[index]).ascii().data());
    264 #endif
    265             tree.add(removedElements[index]);
    266             addedElements.append(removedElements[index]);
    267             removedElements.remove(index);
    268         } else {
    269             int index = nextRandom(addedElements.size());
    270 #ifdef DEBUG_INSERTION_AND_DELETION_TEST
    271             LOG_ERROR("*** Removing element %s", ValueToString<PODInterval<int> >::string(addedElements[index]).ascii().data());
    272 #endif
    273             ASSERT_TRUE(tree.contains(addedElements[index])) << "Test failed for seed " << seed;
    274             ASSERT_TRUE(tree.remove(addedElements[index])) << "Test failed for seed " << seed;
    275             removedElements.append(addedElements[index]);
    276             addedElements.remove(index);
    277         }
    278         ASSERT_TRUE(tree.checkInvariants()) << "Test failed for seed " << seed;
    279     }
    280 }
    281 
    282 } // anonymous namespace
    283 
    284 TEST(PODIntervalTreeTest, RandomDeletionAndInsertionRegressionTest1)
    285 {
    286     InsertionAndDeletionTest(13972, 100);
    287 }
    288 
    289 TEST(PODIntervalTreeTest, RandomDeletionAndInsertionRegressionTest2)
    290 {
    291     InsertionAndDeletionTest(1283382113, 10);
    292 }
    293 
    294 TEST(PODIntervalTreeTest, RandomDeletionAndInsertionRegressionTest3)
    295 {
    296     // This is the sequence of insertions and deletions that triggered
    297     // the failure in RandomDeletionAndInsertionRegressionTest2.
    298     PODIntervalTree<int> tree;
    299     tree.add(tree.createInterval(0, 5));
    300     ASSERT_TRUE(tree.checkInvariants());
    301     tree.add(tree.createInterval(4, 5));
    302     ASSERT_TRUE(tree.checkInvariants());
    303     tree.add(tree.createInterval(8, 9));
    304     ASSERT_TRUE(tree.checkInvariants());
    305     tree.add(tree.createInterval(1, 4));
    306     ASSERT_TRUE(tree.checkInvariants());
    307     tree.add(tree.createInterval(3, 5));
    308     ASSERT_TRUE(tree.checkInvariants());
    309     tree.add(tree.createInterval(4, 12));
    310     ASSERT_TRUE(tree.checkInvariants());
    311     tree.add(tree.createInterval(0, 2));
    312     ASSERT_TRUE(tree.checkInvariants());
    313     tree.add(tree.createInterval(0, 2));
    314     ASSERT_TRUE(tree.checkInvariants());
    315     tree.add(tree.createInterval(9, 13));
    316     ASSERT_TRUE(tree.checkInvariants());
    317     tree.add(tree.createInterval(0, 1));
    318     ASSERT_TRUE(tree.checkInvariants());
    319     tree.remove(tree.createInterval(0, 2));
    320     ASSERT_TRUE(tree.checkInvariants());
    321     tree.remove(tree.createInterval(9, 13));
    322     ASSERT_TRUE(tree.checkInvariants());
    323     tree.remove(tree.createInterval(0, 2));
    324     ASSERT_TRUE(tree.checkInvariants());
    325     tree.remove(tree.createInterval(0, 1));
    326     ASSERT_TRUE(tree.checkInvariants());
    327     tree.remove(tree.createInterval(4, 5));
    328     ASSERT_TRUE(tree.checkInvariants());
    329     tree.remove(tree.createInterval(4, 12));
    330     ASSERT_TRUE(tree.checkInvariants());
    331 }
    332 
    333 TEST(PODIntervalTreeTest, RandomDeletionAndInsertionRegressionTest4)
    334 {
    335     // Even further reduced test case for RandomDeletionAndInsertionRegressionTest3.
    336     PODIntervalTree<int> tree;
    337     tree.add(tree.createInterval(0, 5));
    338     ASSERT_TRUE(tree.checkInvariants());
    339     tree.add(tree.createInterval(8, 9));
    340     ASSERT_TRUE(tree.checkInvariants());
    341     tree.add(tree.createInterval(1, 4));
    342     ASSERT_TRUE(tree.checkInvariants());
    343     tree.add(tree.createInterval(3, 5));
    344     ASSERT_TRUE(tree.checkInvariants());
    345     tree.add(tree.createInterval(4, 12));
    346     ASSERT_TRUE(tree.checkInvariants());
    347     tree.remove(tree.createInterval(4, 12));
    348     ASSERT_TRUE(tree.checkInvariants());
    349 }
    350 
    351 TEST(PODIntervalTreeTest, TestRandomDeletionAndInsertion)
    352 {
    353     InsertionAndDeletionTest(generateSeed(), 1000);
    354 }
    355 
    356 } // namespace WebCore
    357