Home | History | Annotate | Download | only in cctest
      1 // Copyright 2008 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include <stdlib.h>
     29 
     30 #include "src/v8.h"
     31 #include "test/cctest/cctest.h"
     32 
     33 #include "src/base/hashmap.h"
     34 
     35 using namespace v8::internal;
     36 
     37 static bool DefaultMatchFun(void* a, void* b) {
     38   return a == b;
     39 }
     40 
     41 
     42 typedef uint32_t (*IntKeyHash)(uint32_t key);
     43 
     44 
     45 class IntSet {
     46  public:
     47   explicit IntSet(IntKeyHash hash) : hash_(hash), map_(DefaultMatchFun)  {}
     48 
     49   void Insert(int x) {
     50     CHECK_NE(0, x);  // 0 corresponds to (void*)NULL - illegal key value
     51     v8::base::HashMap::Entry* p =
     52         map_.LookupOrInsert(reinterpret_cast<void*>(x), hash_(x));
     53     CHECK(p != NULL);  // insert is set!
     54     CHECK_EQ(reinterpret_cast<void*>(x), p->key);
     55     // we don't care about p->value
     56   }
     57 
     58   void Remove(int x) {
     59     CHECK_NE(0, x);  // 0 corresponds to (void*)NULL - illegal key value
     60     map_.Remove(reinterpret_cast<void*>(x), hash_(x));
     61   }
     62 
     63   bool Present(int x) {
     64     v8::base::HashMap::Entry* p =
     65         map_.Lookup(reinterpret_cast<void*>(x), hash_(x));
     66     if (p != NULL) {
     67       CHECK_EQ(reinterpret_cast<void*>(x), p->key);
     68     }
     69     return p != NULL;
     70   }
     71 
     72   void Clear() {
     73     map_.Clear();
     74   }
     75 
     76   uint32_t occupancy() const {
     77     uint32_t count = 0;
     78     for (v8::base::HashMap::Entry* p = map_.Start(); p != NULL;
     79          p = map_.Next(p)) {
     80       count++;
     81     }
     82     CHECK_EQ(map_.occupancy(), static_cast<double>(count));
     83     return count;
     84   }
     85 
     86  private:
     87   IntKeyHash hash_;
     88   v8::base::HashMap map_;
     89 };
     90 
     91 
     92 static uint32_t Hash(uint32_t key)  { return 23; }
     93 static uint32_t CollisionHash(uint32_t key)  { return key & 0x3; }
     94 
     95 
     96 void TestSet(IntKeyHash hash, int size) {
     97   IntSet set(hash);
     98   CHECK_EQ(0u, set.occupancy());
     99 
    100   set.Insert(1);
    101   set.Insert(2);
    102   set.Insert(3);
    103   CHECK_EQ(3u, set.occupancy());
    104 
    105   set.Insert(2);
    106   set.Insert(3);
    107   CHECK_EQ(3u, set.occupancy());
    108 
    109   CHECK(set.Present(1));
    110   CHECK(set.Present(2));
    111   CHECK(set.Present(3));
    112   CHECK(!set.Present(4));
    113   CHECK_EQ(3u, set.occupancy());
    114 
    115   set.Remove(1);
    116   CHECK(!set.Present(1));
    117   CHECK(set.Present(2));
    118   CHECK(set.Present(3));
    119   CHECK_EQ(2u, set.occupancy());
    120 
    121   set.Remove(3);
    122   CHECK(!set.Present(1));
    123   CHECK(set.Present(2));
    124   CHECK(!set.Present(3));
    125   CHECK_EQ(1u, set.occupancy());
    126 
    127   set.Clear();
    128   CHECK_EQ(0u, set.occupancy());
    129 
    130   // Insert a long series of values.
    131   const int start = 453;
    132   const int factor = 13;
    133   const int offset = 7;
    134   const uint32_t n = size;
    135 
    136   int x = start;
    137   for (uint32_t i = 0; i < n; i++) {
    138     CHECK_EQ(i, static_cast<double>(set.occupancy()));
    139     set.Insert(x);
    140     x = x * factor + offset;
    141   }
    142   CHECK_EQ(n, static_cast<double>(set.occupancy()));
    143 
    144   // Verify the same sequence of values.
    145   x = start;
    146   for (uint32_t i = 0; i < n; i++) {
    147     CHECK(set.Present(x));
    148     x = x * factor + offset;
    149   }
    150   CHECK_EQ(n, static_cast<double>(set.occupancy()));
    151 
    152   // Remove all these values.
    153   x = start;
    154   for (uint32_t i = 0; i < n; i++) {
    155     CHECK_EQ(n - i, static_cast<double>(set.occupancy()));
    156     CHECK(set.Present(x));
    157     set.Remove(x);
    158     CHECK(!set.Present(x));
    159     x = x * factor + offset;
    160 
    161     // Verify the the expected values are still there.
    162     int y = start;
    163     for (uint32_t j = 0; j < n; j++) {
    164       if (j <= i) {
    165         CHECK(!set.Present(y));
    166       } else {
    167         CHECK(set.Present(y));
    168       }
    169       y = y * factor + offset;
    170     }
    171   }
    172   CHECK_EQ(0u, set.occupancy());
    173 }
    174 
    175 
    176 TEST(HashSet) {
    177   TestSet(Hash, 100);
    178   TestSet(CollisionHash, 50);
    179 }
    180