Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2009 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 IDMapTest : public testing::Test {
     12 };
     13 
     14 class TestObject {
     15 };
     16 
     17 class DestructorCounter {
     18  public:
     19   explicit DestructorCounter(int* counter) : counter_(counter) {}
     20   ~DestructorCounter() { ++(*counter_); }
     21  private:
     22   int* counter_;
     23 };
     24 
     25 TEST_F(IDMapTest, Basic) {
     26   IDMap<TestObject> map;
     27   EXPECT_TRUE(map.IsEmpty());
     28   EXPECT_EQ(0U, map.size());
     29 
     30   TestObject obj1;
     31   TestObject obj2;
     32 
     33   int32 id1 = map.Add(&obj1);
     34   EXPECT_FALSE(map.IsEmpty());
     35   EXPECT_EQ(1U, map.size());
     36   EXPECT_EQ(&obj1, map.Lookup(id1));
     37 
     38   int32 id2 = map.Add(&obj2);
     39   EXPECT_FALSE(map.IsEmpty());
     40   EXPECT_EQ(2U, map.size());
     41 
     42   EXPECT_EQ(&obj1, map.Lookup(id1));
     43   EXPECT_EQ(&obj2, map.Lookup(id2));
     44 
     45   map.Remove(id1);
     46   EXPECT_FALSE(map.IsEmpty());
     47   EXPECT_EQ(1U, map.size());
     48 
     49   map.Remove(id2);
     50   EXPECT_TRUE(map.IsEmpty());
     51   EXPECT_EQ(0U, map.size());
     52 
     53   map.AddWithID(&obj1, 1);
     54   map.AddWithID(&obj2, 2);
     55   EXPECT_EQ(&obj1, map.Lookup(1));
     56   EXPECT_EQ(&obj2, map.Lookup(2));
     57 }
     58 
     59 TEST_F(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     while (!iter.IsAtEnd()) {
     73       map.Remove(iter.GetCurrentKey());
     74       iter.Advance();
     75     }
     76 
     77     // Test that while an iterator is still in scope, we get the map emptiness
     78     // right (http://crbug.com/35571).
     79     EXPECT_TRUE(map.IsEmpty());
     80     EXPECT_EQ(0U, map.size());
     81   }
     82 
     83   EXPECT_TRUE(map.IsEmpty());
     84   EXPECT_EQ(0U, map.size());
     85 }
     86 
     87 TEST_F(IDMapTest, IteratorRemainsValidWhenRemovingOtherElements) {
     88   IDMap<TestObject> map;
     89 
     90   const int kCount = 5;
     91   TestObject obj[kCount];
     92   int32 ids[kCount];
     93 
     94   for (int i = 0; i < kCount; i++)
     95     ids[i] = map.Add(&obj[i]);
     96 
     97   int counter = 0;
     98   for (IDMap<TestObject>::const_iterator iter(&map);
     99        !iter.IsAtEnd(); iter.Advance()) {
    100     switch (counter) {
    101       case 0:
    102         EXPECT_EQ(ids[0], iter.GetCurrentKey());
    103         EXPECT_EQ(&obj[0], iter.GetCurrentValue());
    104         map.Remove(ids[1]);
    105         break;
    106       case 1:
    107         EXPECT_EQ(ids[2], iter.GetCurrentKey());
    108         EXPECT_EQ(&obj[2], iter.GetCurrentValue());
    109         map.Remove(ids[3]);
    110         break;
    111       case 2:
    112         EXPECT_EQ(ids[4], iter.GetCurrentKey());
    113         EXPECT_EQ(&obj[4], iter.GetCurrentValue());
    114         map.Remove(ids[0]);
    115         break;
    116       default:
    117         FAIL() << "should not have that many elements";
    118         break;
    119     }
    120 
    121     counter++;
    122   }
    123 }
    124 
    125 TEST_F(IDMapTest, OwningPointersDeletesThemOnRemove) {
    126   const int kCount = 3;
    127 
    128   int external_del_count = 0;
    129   DestructorCounter* external_obj[kCount];
    130   int map_external_ids[kCount];
    131 
    132   int owned_del_count = 0;
    133   DestructorCounter* owned_obj[kCount];
    134   int map_owned_ids[kCount];
    135 
    136   IDMap<DestructorCounter> map_external;
    137   IDMap<DestructorCounter, IDMapOwnPointer> map_owned;
    138 
    139   for (int i = 0; i < kCount; ++i) {
    140     external_obj[i] = new DestructorCounter(&external_del_count);
    141     map_external_ids[i] = map_external.Add(external_obj[i]);
    142 
    143     owned_obj[i] = new DestructorCounter(&owned_del_count);
    144     map_owned_ids[i] = map_owned.Add(owned_obj[i]);
    145   }
    146 
    147   for (int i = 0; i < kCount; ++i) {
    148     EXPECT_EQ(external_del_count, 0);
    149     EXPECT_EQ(owned_del_count, i);
    150 
    151     map_external.Remove(map_external_ids[i]);
    152     map_owned.Remove(map_owned_ids[i]);
    153   }
    154 
    155   for (int i = 0; i < kCount; ++i) {
    156     delete external_obj[i];
    157   }
    158 
    159   EXPECT_EQ(external_del_count, kCount);
    160   EXPECT_EQ(owned_del_count, kCount);
    161 }
    162 
    163 TEST_F(IDMapTest, OwningPointersDeletesThemOnDestruct) {
    164   const int kCount = 3;
    165 
    166   int external_del_count = 0;
    167   DestructorCounter* external_obj[kCount];
    168   int map_external_ids[kCount];
    169 
    170   int owned_del_count = 0;
    171   DestructorCounter* owned_obj[kCount];
    172   int map_owned_ids[kCount];
    173 
    174   {
    175     IDMap<DestructorCounter> map_external;
    176     IDMap<DestructorCounter, IDMapOwnPointer> map_owned;
    177 
    178     for (int i = 0; i < kCount; ++i) {
    179       external_obj[i] = new DestructorCounter(&external_del_count);
    180       map_external_ids[i] = map_external.Add(external_obj[i]);
    181 
    182       owned_obj[i] = new DestructorCounter(&owned_del_count);
    183       map_owned_ids[i] = map_owned.Add(owned_obj[i]);
    184     }
    185   }
    186 
    187   EXPECT_EQ(external_del_count, 0);
    188 
    189   for (int i = 0; i < kCount; ++i) {
    190     delete external_obj[i];
    191   }
    192 
    193   EXPECT_EQ(external_del_count, kCount);
    194   EXPECT_EQ(owned_del_count, kCount);
    195 }
    196 
    197 }  // namespace
    198