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   for (IDMap<TestObject>::const_iterator iter(&map);
     71        !iter.IsAtEnd(); iter.Advance()) {
     72     map.Remove(iter.GetCurrentKey());
     73   }
     74 }
     75 
     76 TEST_F(IDMapTest, IteratorRemainsValidWhenRemovingOtherElements) {
     77   IDMap<TestObject> map;
     78 
     79   const int kCount = 5;
     80   TestObject obj[kCount];
     81   int32 ids[kCount];
     82 
     83   for (int i = 0; i < kCount; i++)
     84     ids[i] = map.Add(&obj[i]);
     85 
     86   int counter = 0;
     87   for (IDMap<TestObject>::const_iterator iter(&map);
     88        !iter.IsAtEnd(); iter.Advance()) {
     89     switch (counter) {
     90       case 0:
     91         EXPECT_EQ(ids[0], iter.GetCurrentKey());
     92         EXPECT_EQ(&obj[0], iter.GetCurrentValue());
     93         map.Remove(ids[1]);
     94         break;
     95       case 1:
     96         EXPECT_EQ(ids[2], iter.GetCurrentKey());
     97         EXPECT_EQ(&obj[2], iter.GetCurrentValue());
     98         map.Remove(ids[3]);
     99         break;
    100       case 2:
    101         EXPECT_EQ(ids[4], iter.GetCurrentKey());
    102         EXPECT_EQ(&obj[4], iter.GetCurrentValue());
    103         map.Remove(ids[0]);
    104         break;
    105       default:
    106         FAIL() << "should not have that many elements";
    107         break;
    108     }
    109 
    110     counter++;
    111   }
    112 }
    113 
    114 TEST_F(IDMapTest, OwningPointersDeletesThemOnRemove) {
    115   const int kCount = 3;
    116 
    117   int external_del_count = 0;
    118   DestructorCounter* external_obj[kCount];
    119   int map_external_ids[kCount];
    120 
    121   int owned_del_count = 0;
    122   DestructorCounter* owned_obj[kCount];
    123   int map_owned_ids[kCount];
    124 
    125   IDMap<DestructorCounter> map_external;
    126   IDMap<DestructorCounter, IDMapOwnPointer> map_owned;
    127 
    128   for (int i = 0; i < kCount; ++i) {
    129     external_obj[i] = new DestructorCounter(&external_del_count);
    130     map_external_ids[i] = map_external.Add(external_obj[i]);
    131 
    132     owned_obj[i] = new DestructorCounter(&owned_del_count);
    133     map_owned_ids[i] = map_owned.Add(owned_obj[i]);
    134   }
    135 
    136   for (int i = 0; i < kCount; ++i) {
    137     EXPECT_EQ(external_del_count, 0);
    138     EXPECT_EQ(owned_del_count, i);
    139 
    140     map_external.Remove(map_external_ids[i]);
    141     map_owned.Remove(map_owned_ids[i]);
    142   }
    143 
    144   for (int i = 0; i < kCount; ++i) {
    145     delete external_obj[i];
    146   }
    147 
    148   EXPECT_EQ(external_del_count, kCount);
    149   EXPECT_EQ(owned_del_count, kCount);
    150 }
    151 
    152 TEST_F(IDMapTest, OwningPointersDeletesThemOnDestruct) {
    153   const int kCount = 3;
    154 
    155   int external_del_count = 0;
    156   DestructorCounter* external_obj[kCount];
    157   int map_external_ids[kCount];
    158 
    159   int owned_del_count = 0;
    160   DestructorCounter* owned_obj[kCount];
    161   int map_owned_ids[kCount];
    162 
    163   {
    164     IDMap<DestructorCounter> map_external;
    165     IDMap<DestructorCounter, IDMapOwnPointer> map_owned;
    166 
    167     for (int i = 0; i < kCount; ++i) {
    168       external_obj[i] = new DestructorCounter(&external_del_count);
    169       map_external_ids[i] = map_external.Add(external_obj[i]);
    170 
    171       owned_obj[i] = new DestructorCounter(&owned_del_count);
    172       map_owned_ids[i] = map_owned.Add(owned_obj[i]);
    173     }
    174   }
    175 
    176   EXPECT_EQ(external_del_count, 0);
    177 
    178   for (int i = 0; i < kCount; ++i) {
    179     delete external_obj[i];
    180   }
    181 
    182   EXPECT_EQ(external_del_count, kCount);
    183   EXPECT_EQ(owned_del_count, kCount);
    184 }
    185 
    186 }  // namespace
    187