Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/id_map.h"
      6 
      7 #include "testing/gtest/include/gtest/gtest.h"
      8 
      9 namespace {
     10 
     11 class TestObject {
     12 };
     13 
     14 class DestructorCounter {
     15  public:
     16   explicit DestructorCounter(int* counter) : counter_(counter) {}
     17   ~DestructorCounter() { ++(*counter_); }
     18 
     19  private:
     20   int* counter_;
     21 };
     22 
     23 TEST(IDMapTest, Basic) {
     24   IDMap<TestObject> map;
     25   EXPECT_TRUE(map.IsEmpty());
     26   EXPECT_EQ(0U, map.size());
     27 
     28   TestObject obj1;
     29   TestObject obj2;
     30 
     31   int32 id1 = map.Add(&obj1);
     32   EXPECT_FALSE(map.IsEmpty());
     33   EXPECT_EQ(1U, map.size());
     34   EXPECT_EQ(&obj1, map.Lookup(id1));
     35 
     36   int32 id2 = map.Add(&obj2);
     37   EXPECT_FALSE(map.IsEmpty());
     38   EXPECT_EQ(2U, map.size());
     39 
     40   EXPECT_EQ(&obj1, map.Lookup(id1));
     41   EXPECT_EQ(&obj2, map.Lookup(id2));
     42 
     43   map.Remove(id1);
     44   EXPECT_FALSE(map.IsEmpty());
     45   EXPECT_EQ(1U, map.size());
     46 
     47   map.Remove(id2);
     48   EXPECT_TRUE(map.IsEmpty());
     49   EXPECT_EQ(0U, map.size());
     50 
     51   map.AddWithID(&obj1, 1);
     52   map.AddWithID(&obj2, 2);
     53   EXPECT_EQ(&obj1, map.Lookup(1));
     54   EXPECT_EQ(&obj2, map.Lookup(2));
     55 
     56   EXPECT_EQ(0, map.iteration_depth());
     57 }
     58 
     59 TEST(IDMapTest, IteratorRemainsValidWhenRemovingCurrentElement) {
     60   IDMap<TestObject> map;
     61 
     62   TestObject obj1;
     63   TestObject obj2;
     64   TestObject obj3;
     65 
     66   map.Add(&obj1);
     67   map.Add(&obj2);
     68   map.Add(&obj3);
     69 
     70   {
     71     IDMap<TestObject>::const_iterator iter(&map);
     72 
     73     EXPECT_EQ(1, map.iteration_depth());
     74 
     75     while (!iter.IsAtEnd()) {
     76       map.Remove(iter.GetCurrentKey());
     77       iter.Advance();
     78     }
     79 
     80     // Test that while an iterator is still in scope, we get the map emptiness
     81     // right (http://crbug.com/35571).
     82     EXPECT_TRUE(map.IsEmpty());
     83     EXPECT_EQ(0U, map.size());
     84   }
     85 
     86   EXPECT_TRUE(map.IsEmpty());
     87   EXPECT_EQ(0U, map.size());
     88 
     89   EXPECT_EQ(0, map.iteration_depth());
     90 }
     91 
     92 TEST(IDMapTest, IteratorRemainsValidWhenRemovingOtherElements) {
     93   IDMap<TestObject> map;
     94 
     95   const int kCount = 5;
     96   TestObject obj[kCount];
     97   int32 ids[kCount];
     98 
     99   for (int i = 0; i < kCount; i++)
    100     ids[i] = map.Add(&obj[i]);
    101 
    102   int counter = 0;
    103   for (IDMap<TestObject>::const_iterator iter(&map);
    104        !iter.IsAtEnd(); iter.Advance()) {
    105     EXPECT_EQ(1, map.iteration_depth());
    106 
    107     switch (counter) {
    108       case 0:
    109         EXPECT_EQ(ids[0], iter.GetCurrentKey());
    110         EXPECT_EQ(&obj[0], iter.GetCurrentValue());
    111         map.Remove(ids[1]);
    112         break;
    113       case 1:
    114         EXPECT_EQ(ids[2], iter.GetCurrentKey());
    115         EXPECT_EQ(&obj[2], iter.GetCurrentValue());
    116         map.Remove(ids[3]);
    117         break;
    118       case 2:
    119         EXPECT_EQ(ids[4], iter.GetCurrentKey());
    120         EXPECT_EQ(&obj[4], iter.GetCurrentValue());
    121         map.Remove(ids[0]);
    122         break;
    123       default:
    124         FAIL() << "should not have that many elements";
    125         break;
    126     }
    127 
    128     counter++;
    129   }
    130 
    131   EXPECT_EQ(0, map.iteration_depth());
    132 }
    133 
    134 TEST(IDMapTest, CopyIterator) {
    135   IDMap<TestObject> map;
    136 
    137   TestObject obj1;
    138   TestObject obj2;
    139   TestObject obj3;
    140 
    141   map.Add(&obj1);
    142   map.Add(&obj2);
    143   map.Add(&obj3);
    144 
    145   EXPECT_EQ(0, map.iteration_depth());
    146 
    147   {
    148     IDMap<TestObject>::const_iterator iter1(&map);
    149     EXPECT_EQ(1, map.iteration_depth());
    150 
    151     // Make sure that copying the iterator correctly increments
    152     // map's iteration depth.
    153     IDMap<TestObject>::const_iterator iter2(iter1);
    154     EXPECT_EQ(2, map.iteration_depth());
    155   }
    156 
    157   // Make sure after destroying all iterators the map's iteration depth
    158   // returns to initial state.
    159   EXPECT_EQ(0, map.iteration_depth());
    160 }
    161 
    162 TEST(IDMapTest, AssignIterator) {
    163   IDMap<TestObject> map;
    164 
    165   TestObject obj1;
    166   TestObject obj2;
    167   TestObject obj3;
    168 
    169   map.Add(&obj1);
    170   map.Add(&obj2);
    171   map.Add(&obj3);
    172 
    173   EXPECT_EQ(0, map.iteration_depth());
    174 
    175   {
    176     IDMap<TestObject>::const_iterator iter1(&map);
    177     EXPECT_EQ(1, map.iteration_depth());
    178 
    179     IDMap<TestObject>::const_iterator iter2(&map);
    180     EXPECT_EQ(2, map.iteration_depth());
    181 
    182     // Make sure that assigning the iterator correctly updates
    183     // map's iteration depth (-1 for destruction, +1 for assignment).
    184     EXPECT_EQ(2, map.iteration_depth());
    185   }
    186 
    187   // Make sure after destroying all iterators the map's iteration depth
    188   // returns to initial state.
    189   EXPECT_EQ(0, map.iteration_depth());
    190 }
    191 
    192 TEST(IDMapTest, IteratorRemainsValidWhenClearing) {
    193   IDMap<TestObject> map;
    194 
    195   const int kCount = 5;
    196   TestObject obj[kCount];
    197   int32 ids[kCount];
    198 
    199   for (int i = 0; i < kCount; i++)
    200     ids[i] = map.Add(&obj[i]);
    201 
    202   int counter = 0;
    203   for (IDMap<TestObject>::const_iterator iter(&map);
    204        !iter.IsAtEnd(); iter.Advance()) {
    205     switch (counter) {
    206       case 0:
    207         EXPECT_EQ(ids[0], iter.GetCurrentKey());
    208         EXPECT_EQ(&obj[0], iter.GetCurrentValue());
    209         break;
    210       case 1:
    211         EXPECT_EQ(ids[1], iter.GetCurrentKey());
    212         EXPECT_EQ(&obj[1], iter.GetCurrentValue());
    213         map.Clear();
    214         EXPECT_TRUE(map.IsEmpty());
    215         EXPECT_EQ(0U, map.size());
    216         break;
    217       default:
    218         FAIL() << "should not have that many elements";
    219         break;
    220     }
    221     counter++;
    222   }
    223 
    224   EXPECT_TRUE(map.IsEmpty());
    225   EXPECT_EQ(0U, map.size());
    226 }
    227 
    228 TEST(IDMapTest, OwningPointersDeletesThemOnRemove) {
    229   const int kCount = 3;
    230 
    231   int external_del_count = 0;
    232   DestructorCounter* external_obj[kCount];
    233   int map_external_ids[kCount];
    234 
    235   int owned_del_count = 0;
    236   DestructorCounter* owned_obj[kCount];
    237   int map_owned_ids[kCount];
    238 
    239   IDMap<DestructorCounter> map_external;
    240   IDMap<DestructorCounter, IDMapOwnPointer> map_owned;
    241 
    242   for (int i = 0; i < kCount; ++i) {
    243     external_obj[i] = new DestructorCounter(&external_del_count);
    244     map_external_ids[i] = map_external.Add(external_obj[i]);
    245 
    246     owned_obj[i] = new DestructorCounter(&owned_del_count);
    247     map_owned_ids[i] = map_owned.Add(owned_obj[i]);
    248   }
    249 
    250   for (int i = 0; i < kCount; ++i) {
    251     EXPECT_EQ(external_del_count, 0);
    252     EXPECT_EQ(owned_del_count, i);
    253 
    254     map_external.Remove(map_external_ids[i]);
    255     map_owned.Remove(map_owned_ids[i]);
    256   }
    257 
    258   for (int i = 0; i < kCount; ++i) {
    259     delete external_obj[i];
    260   }
    261 
    262   EXPECT_EQ(external_del_count, kCount);
    263   EXPECT_EQ(owned_del_count, kCount);
    264 }
    265 
    266 TEST(IDMapTest, OwningPointersDeletesThemOnClear) {
    267   const int kCount = 3;
    268 
    269   int external_del_count = 0;
    270   DestructorCounter* external_obj[kCount];
    271 
    272   int owned_del_count = 0;
    273   DestructorCounter* owned_obj[kCount];
    274 
    275   IDMap<DestructorCounter> map_external;
    276   IDMap<DestructorCounter, IDMapOwnPointer> map_owned;
    277 
    278   for (int i = 0; i < kCount; ++i) {
    279     external_obj[i] = new DestructorCounter(&external_del_count);
    280     map_external.Add(external_obj[i]);
    281 
    282     owned_obj[i] = new DestructorCounter(&owned_del_count);
    283     map_owned.Add(owned_obj[i]);
    284   }
    285 
    286   EXPECT_EQ(external_del_count, 0);
    287   EXPECT_EQ(owned_del_count, 0);
    288 
    289   map_external.Clear();
    290   map_owned.Clear();
    291 
    292   EXPECT_EQ(external_del_count, 0);
    293   EXPECT_EQ(owned_del_count, kCount);
    294 
    295   for (int i = 0; i < kCount; ++i) {
    296     delete external_obj[i];
    297   }
    298 
    299   EXPECT_EQ(external_del_count, kCount);
    300   EXPECT_EQ(owned_del_count, kCount);
    301 }
    302 
    303 TEST(IDMapTest, OwningPointersDeletesThemOnDestruct) {
    304   const int kCount = 3;
    305 
    306   int external_del_count = 0;
    307   DestructorCounter* external_obj[kCount];
    308 
    309   int owned_del_count = 0;
    310   DestructorCounter* owned_obj[kCount];
    311 
    312   {
    313     IDMap<DestructorCounter> map_external;
    314     IDMap<DestructorCounter, IDMapOwnPointer> map_owned;
    315 
    316     for (int i = 0; i < kCount; ++i) {
    317       external_obj[i] = new DestructorCounter(&external_del_count);
    318       map_external.Add(external_obj[i]);
    319 
    320       owned_obj[i] = new DestructorCounter(&owned_del_count);
    321       map_owned.Add(owned_obj[i]);
    322     }
    323   }
    324 
    325   EXPECT_EQ(external_del_count, 0);
    326 
    327   for (int i = 0; i < kCount; ++i) {
    328     delete external_obj[i];
    329   }
    330 
    331   EXPECT_EQ(external_del_count, kCount);
    332   EXPECT_EQ(owned_del_count, kCount);
    333 }
    334 
    335 }  // namespace
    336