1/*
2 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "gtest/gtest.h"
12
13#include "map_wrapper.h"
14
15using ::webrtc::MapWrapper;
16using ::webrtc::MapItem;
17
18const int kNumberOfElements = 10;
19
20int* ItemPointer(MapItem* item) {
21    if (item == NULL) {
22        return NULL;
23    }
24    return reinterpret_cast<int*>(item->GetItem());
25}
26
27bool DeleteItemContent(MapItem* item) {
28    if(item == NULL) {
29        return false;
30    }
31    int* value_ptr = ItemPointer(item);
32    delete value_ptr;
33    return true;
34}
35
36int ItemValue(MapItem* item) {
37    if (item == NULL) {
38        return -1;
39    }
40    const int* value_ptr = ItemPointer(item);
41    if (value_ptr == 0) {
42        return -1;
43    }
44    return *value_ptr;
45}
46
47void PrintToConsole(const char* message, bool supress) {
48    if (supress) {
49        return;
50    }
51    printf("%s", message);
52}
53
54bool CreateAscendingMap(MapWrapper* ascending_map) {
55    int* insert_value = NULL;
56    for (int i = 0; i < kNumberOfElements; ++i) {
57        insert_value = new int;
58        if (insert_value == NULL) {
59            return false;
60        }
61        *insert_value = i;
62        if (0 != ascending_map->Insert(
63                     i,
64                     reinterpret_cast<void*>(insert_value))) {
65            return false;
66        }
67    }
68    return true;
69}
70
71bool ClearMap(MapWrapper* clear_map) {
72    bool success = true;
73    while (clear_map->Size() != 0) {
74        MapItem* remove_item = clear_map->First();
75        if (remove_item == NULL) {
76            return false;
77        }
78        if (!DeleteItemContent(remove_item)) {
79            success = false;
80        }
81        if (clear_map->Erase(remove_item) != 0) {
82            return false;
83        }
84    }
85    return success;
86}
87
88void PrintMapItem(MapItem* item, bool supress) {
89    const int id = item->GetId();
90    const int value = ItemValue(item);
91    char print_buffer[16];
92    sprintf(print_buffer, "(%3i,%3i) ", id, value);
93    PrintToConsole(print_buffer, supress);
94}
95
96// Succeeds only if all the items were printed.
97bool PrintMap(const MapWrapper& print_map, bool supress) {
98    const int elements_to_print = print_map.Size();
99    int elements_printed = 0;
100    MapItem* item = print_map.First();
101    PrintToConsole("[", supress);
102    while (item != NULL) {
103        PrintMapItem(item, supress);
104        ++elements_printed;
105        item = print_map.Next(item);
106    }
107    PrintToConsole("]\n", supress);
108    return elements_printed == elements_to_print;
109}
110
111// Succeeds only if all the items were printed.
112bool ReversePrintMap(const MapWrapper& print_map, bool supress) {
113    const int elements_to_print = print_map.Size();
114    int elements_printed = 0;
115    MapItem* item = print_map.Last();
116    PrintToConsole("[", supress);
117    while (item != NULL) {
118        PrintMapItem(item, supress);
119        ++elements_printed;
120        item = print_map.Previous(item);
121    }
122    PrintToConsole("]\n", supress);
123    return elements_printed == elements_to_print;
124}
125
126// Returns true if the map items contain the same item.
127bool CompareItems(MapItem* lhs_item, MapItem* rhs_item) {
128    if ((lhs_item == NULL) || (rhs_item == NULL)) {
129        return false;
130    }
131    if (lhs_item->GetId() != rhs_item->GetId()) {
132        return false;
133    }
134    return lhs_item->GetItem() == rhs_item->GetItem();
135}
136
137// Returns true if the map contains the same items.
138bool CompareMaps(const MapWrapper& lhs, const MapWrapper& rhs) {
139    const int map_size = lhs.Size();
140    if (map_size != rhs.Size()) {
141        return false;
142    }
143    int item_count = 0;
144    MapItem* lhs_item = lhs.First();
145    while (lhs_item != NULL) {
146        MapItem* rhs_item = rhs.Find(lhs_item->GetId());
147        if (rhs_item == NULL) {
148            return false;
149        }
150        if (!CompareItems(lhs_item, rhs_item)) {
151            return false;
152        }
153        ++item_count;
154        lhs_item = lhs.Next(lhs_item);
155    }
156    return item_count == map_size;
157}
158
159class MapWrapperTest : public ::testing::Test {
160protected:
161    virtual void SetUp() {
162        ASSERT_TRUE(CreateAscendingMap(&ascending_map_));
163    }
164
165    virtual void TearDown() {
166        EXPECT_TRUE(ClearMap(&ascending_map_));
167    }
168    MapWrapper ascending_map_;
169};
170
171TEST_F(MapWrapperTest,RemoveTest) {
172    // Erase using int id
173    { // Create local scope to avoid accidental re-use
174        MapItem* item_first = ascending_map_.First();
175        ASSERT_FALSE(item_first == NULL);
176        const int first_value_id = item_first->GetId();
177        const int first_value = ItemValue(item_first);
178        EXPECT_TRUE(first_value == 0);
179        EXPECT_EQ(first_value_id,first_value);
180        EXPECT_FALSE(NULL == ascending_map_.Find(first_value_id));
181        EXPECT_TRUE(DeleteItemContent(item_first));
182        ascending_map_.Erase(first_value_id);
183        EXPECT_TRUE(NULL == ascending_map_.Find(first_value_id));
184        EXPECT_EQ(kNumberOfElements-1,ascending_map_.Size());
185    }
186
187    // Erase using MapItem* item
188    MapItem* item_last = ascending_map_.Last();
189    ASSERT_FALSE(item_last == NULL);
190    const int last_value_id = item_last->GetId();
191    const int last_value = ItemValue(item_last);
192    EXPECT_TRUE(last_value == kNumberOfElements - 1);
193    EXPECT_EQ(last_value_id, last_value);
194    EXPECT_FALSE(NULL == ascending_map_.Find(last_value_id));
195    EXPECT_TRUE(DeleteItemContent(item_last));
196    ascending_map_.Erase(last_value_id);
197    EXPECT_TRUE(NULL == ascending_map_.Find(last_value_id));
198    EXPECT_EQ(kNumberOfElements-2,ascending_map_.Size());
199}
200
201TEST_F(MapWrapperTest, PrintTest) {
202    const bool supress = true; // Don't spam the console
203
204    EXPECT_TRUE(PrintMap(ascending_map_, supress));
205    EXPECT_TRUE(ReversePrintMap(ascending_map_, supress));
206}
207
208TEST_F(MapWrapperTest, CopyTest) {
209    MapWrapper compare_map;
210    ASSERT_TRUE(CreateAscendingMap(&compare_map));
211    const int map_size = compare_map.Size();
212    ASSERT_EQ(ascending_map_.Size(), map_size);
213    // CompareMaps compare the pointers not value of the pointers.
214    // (the values are the same since both are ascending maps).
215    EXPECT_FALSE(CompareMaps(compare_map,ascending_map_));
216
217    int copy_count = 0;
218    MapItem* ascend_item = ascending_map_.First();
219    while (ascend_item != NULL) {
220        MapItem* compare_item = compare_map.Find(ascend_item->GetId());
221        ASSERT_FALSE(compare_item == NULL);
222        DeleteItemContent(compare_item);
223        compare_item->SetItem(ascend_item->GetItem());
224        ascend_item = ascending_map_.Next(ascend_item);
225        ++copy_count;
226    }
227    EXPECT_TRUE(CompareMaps(compare_map,ascending_map_));
228    while (compare_map.Erase(compare_map.First()) == 0) {
229    }
230    EXPECT_EQ(map_size, copy_count);
231}
232