Home | History | Annotate | Download | only in base
      1 // Copyright 2012 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/stl_util.h"
      6 
      7 #include <deque>
      8 #include <forward_list>
      9 #include <functional>
     10 #include <iterator>
     11 #include <list>
     12 #include <map>
     13 #include <set>
     14 #include <string>
     15 #include <unordered_map>
     16 #include <unordered_set>
     17 #include <vector>
     18 
     19 #include "base/strings/string16.h"
     20 #include "base/strings/utf_string_conversions.h"
     21 #include "testing/gtest/include/gtest/gtest.h"
     22 
     23 namespace {
     24 
     25 // Used as test case to ensure the various base::STLXxx functions don't require
     26 // more than operators "<" and "==" on values stored in containers.
     27 class ComparableValue {
     28  public:
     29   explicit ComparableValue(int value) : value_(value) {}
     30 
     31   bool operator==(const ComparableValue& rhs) const {
     32     return value_ == rhs.value_;
     33   }
     34 
     35   bool operator<(const ComparableValue& rhs) const {
     36     return value_ < rhs.value_;
     37   }
     38 
     39  private:
     40   int value_;
     41 };
     42 
     43 template <typename Container>
     44 void RunEraseTest() {
     45   const std::pair<Container, Container> test_data[] = {
     46       {Container(), Container()}, {{1, 2, 3}, {1, 3}}, {{1, 2, 3, 2}, {1, 3}}};
     47 
     48   for (auto test_case : test_data) {
     49     base::Erase(test_case.first, 2);
     50     EXPECT_EQ(test_case.second, test_case.first);
     51   }
     52 }
     53 
     54 // This test is written for containers of std::pair<int, int> to support maps.
     55 template <typename Container>
     56 void RunEraseIfTest() {
     57   struct {
     58     Container input;
     59     Container erase_even;
     60     Container erase_odd;
     61   } test_data[] = {
     62       {Container(), Container(), Container()},
     63       {{{1, 1}, {2, 2}, {3, 3}}, {{1, 1}, {3, 3}}, {{2, 2}}},
     64       {{{1, 1}, {2, 2}, {3, 3}, {4, 4}}, {{1, 1}, {3, 3}}, {{2, 2}, {4, 4}}},
     65   };
     66 
     67   for (auto test_case : test_data) {
     68     base::EraseIf(test_case.input, [](const std::pair<int, int>& elem) {
     69       return !(elem.first & 1);
     70     });
     71     EXPECT_EQ(test_case.erase_even, test_case.input);
     72   }
     73 
     74   for (auto test_case : test_data) {
     75     base::EraseIf(test_case.input, [](const std::pair<int, int>& elem) {
     76       return elem.first & 1;
     77     });
     78     EXPECT_EQ(test_case.erase_odd, test_case.input);
     79   }
     80 }
     81 
     82 struct CustomIntHash {
     83   size_t operator()(int elem) const { return std::hash<int>()(elem) + 1; }
     84 };
     85 
     86 struct HashByFirst {
     87   size_t operator()(const std::pair<int, int>& elem) const {
     88     return std::hash<int>()(elem.first);
     89   }
     90 };
     91 
     92 }  // namespace
     93 
     94 namespace base {
     95 namespace {
     96 
     97 TEST(STLUtilTest, STLIsSorted) {
     98   {
     99     std::set<int> set;
    100     set.insert(24);
    101     set.insert(1);
    102     set.insert(12);
    103     EXPECT_TRUE(STLIsSorted(set));
    104   }
    105 
    106   {
    107     std::set<ComparableValue> set;
    108     set.insert(ComparableValue(24));
    109     set.insert(ComparableValue(1));
    110     set.insert(ComparableValue(12));
    111     EXPECT_TRUE(STLIsSorted(set));
    112   }
    113 
    114   {
    115     std::vector<int> vector;
    116     vector.push_back(1);
    117     vector.push_back(1);
    118     vector.push_back(4);
    119     vector.push_back(64);
    120     vector.push_back(12432);
    121     EXPECT_TRUE(STLIsSorted(vector));
    122     vector.back() = 1;
    123     EXPECT_FALSE(STLIsSorted(vector));
    124   }
    125 }
    126 
    127 TEST(STLUtilTest, STLSetDifference) {
    128   std::set<int> a1;
    129   a1.insert(1);
    130   a1.insert(2);
    131   a1.insert(3);
    132   a1.insert(4);
    133 
    134   std::set<int> a2;
    135   a2.insert(3);
    136   a2.insert(4);
    137   a2.insert(5);
    138   a2.insert(6);
    139   a2.insert(7);
    140 
    141   {
    142     std::set<int> difference;
    143     difference.insert(1);
    144     difference.insert(2);
    145     EXPECT_EQ(difference, STLSetDifference<std::set<int> >(a1, a2));
    146   }
    147 
    148   {
    149     std::set<int> difference;
    150     difference.insert(5);
    151     difference.insert(6);
    152     difference.insert(7);
    153     EXPECT_EQ(difference, STLSetDifference<std::set<int> >(a2, a1));
    154   }
    155 
    156   {
    157     std::vector<int> difference;
    158     difference.push_back(1);
    159     difference.push_back(2);
    160     EXPECT_EQ(difference, STLSetDifference<std::vector<int> >(a1, a2));
    161   }
    162 
    163   {
    164     std::vector<int> difference;
    165     difference.push_back(5);
    166     difference.push_back(6);
    167     difference.push_back(7);
    168     EXPECT_EQ(difference, STLSetDifference<std::vector<int> >(a2, a1));
    169   }
    170 }
    171 
    172 TEST(STLUtilTest, STLSetUnion) {
    173   std::set<int> a1;
    174   a1.insert(1);
    175   a1.insert(2);
    176   a1.insert(3);
    177   a1.insert(4);
    178 
    179   std::set<int> a2;
    180   a2.insert(3);
    181   a2.insert(4);
    182   a2.insert(5);
    183   a2.insert(6);
    184   a2.insert(7);
    185 
    186   {
    187     std::set<int> result;
    188     result.insert(1);
    189     result.insert(2);
    190     result.insert(3);
    191     result.insert(4);
    192     result.insert(5);
    193     result.insert(6);
    194     result.insert(7);
    195     EXPECT_EQ(result, STLSetUnion<std::set<int> >(a1, a2));
    196   }
    197 
    198   {
    199     std::set<int> result;
    200     result.insert(1);
    201     result.insert(2);
    202     result.insert(3);
    203     result.insert(4);
    204     result.insert(5);
    205     result.insert(6);
    206     result.insert(7);
    207     EXPECT_EQ(result, STLSetUnion<std::set<int> >(a2, a1));
    208   }
    209 
    210   {
    211     std::vector<int> result;
    212     result.push_back(1);
    213     result.push_back(2);
    214     result.push_back(3);
    215     result.push_back(4);
    216     result.push_back(5);
    217     result.push_back(6);
    218     result.push_back(7);
    219     EXPECT_EQ(result, STLSetUnion<std::vector<int> >(a1, a2));
    220   }
    221 
    222   {
    223     std::vector<int> result;
    224     result.push_back(1);
    225     result.push_back(2);
    226     result.push_back(3);
    227     result.push_back(4);
    228     result.push_back(5);
    229     result.push_back(6);
    230     result.push_back(7);
    231     EXPECT_EQ(result, STLSetUnion<std::vector<int> >(a2, a1));
    232   }
    233 }
    234 
    235 TEST(STLUtilTest, STLSetIntersection) {
    236   std::set<int> a1;
    237   a1.insert(1);
    238   a1.insert(2);
    239   a1.insert(3);
    240   a1.insert(4);
    241 
    242   std::set<int> a2;
    243   a2.insert(3);
    244   a2.insert(4);
    245   a2.insert(5);
    246   a2.insert(6);
    247   a2.insert(7);
    248 
    249   {
    250     std::set<int> result;
    251     result.insert(3);
    252     result.insert(4);
    253     EXPECT_EQ(result, STLSetIntersection<std::set<int> >(a1, a2));
    254   }
    255 
    256   {
    257     std::set<int> result;
    258     result.insert(3);
    259     result.insert(4);
    260     EXPECT_EQ(result, STLSetIntersection<std::set<int> >(a2, a1));
    261   }
    262 
    263   {
    264     std::vector<int> result;
    265     result.push_back(3);
    266     result.push_back(4);
    267     EXPECT_EQ(result, STLSetIntersection<std::vector<int> >(a1, a2));
    268   }
    269 
    270   {
    271     std::vector<int> result;
    272     result.push_back(3);
    273     result.push_back(4);
    274     EXPECT_EQ(result, STLSetIntersection<std::vector<int> >(a2, a1));
    275   }
    276 }
    277 
    278 TEST(STLUtilTest, STLIncludes) {
    279   std::set<int> a1;
    280   a1.insert(1);
    281   a1.insert(2);
    282   a1.insert(3);
    283   a1.insert(4);
    284 
    285   std::set<int> a2;
    286   a2.insert(3);
    287   a2.insert(4);
    288 
    289   std::set<int> a3;
    290   a3.insert(3);
    291   a3.insert(4);
    292   a3.insert(5);
    293 
    294   EXPECT_TRUE(STLIncludes<std::set<int> >(a1, a2));
    295   EXPECT_FALSE(STLIncludes<std::set<int> >(a1, a3));
    296   EXPECT_FALSE(STLIncludes<std::set<int> >(a2, a1));
    297   EXPECT_FALSE(STLIncludes<std::set<int> >(a2, a3));
    298   EXPECT_FALSE(STLIncludes<std::set<int> >(a3, a1));
    299   EXPECT_TRUE(STLIncludes<std::set<int> >(a3, a2));
    300 }
    301 
    302 TEST(StringAsArrayTest, Empty) {
    303   std::string empty;
    304   EXPECT_EQ(nullptr, string_as_array(&empty));
    305 }
    306 
    307 TEST(StringAsArrayTest, NullTerminated) {
    308   // If any std::string implementation is not null-terminated, this should
    309   // fail. All compilers we use return a null-terminated buffer, but please do
    310   // not rely on this fact in your code.
    311   std::string str("abcde");
    312   str.resize(3);
    313   EXPECT_STREQ("abc", string_as_array(&str));
    314 }
    315 
    316 TEST(StringAsArrayTest, WriteCopy) {
    317   // With a COW implementation, this test will fail if
    318   // string_as_array(&str) is implemented as
    319   // const_cast<char*>(str->data()).
    320   std::string s1("abc");
    321   const std::string s2(s1);
    322   string_as_array(&s1)[1] = 'x';
    323   EXPECT_EQ("axc", s1);
    324   EXPECT_EQ("abc", s2);
    325 }
    326 
    327 TEST(Erase, String) {
    328   const std::pair<std::string, std::string> test_data[] = {
    329       {"", ""}, {"abc", "bc"}, {"abca", "bc"},
    330   };
    331 
    332   for (auto test_case : test_data) {
    333     Erase(test_case.first, 'a');
    334     EXPECT_EQ(test_case.second, test_case.first);
    335   }
    336 
    337   for (auto test_case : test_data) {
    338     EraseIf(test_case.first, [](char elem) { return elem < 'b'; });
    339     EXPECT_EQ(test_case.second, test_case.first);
    340   }
    341 }
    342 
    343 TEST(Erase, String16) {
    344   std::pair<base::string16, base::string16> test_data[] = {
    345       {base::string16(), base::string16()},
    346       {UTF8ToUTF16("abc"), UTF8ToUTF16("bc")},
    347       {UTF8ToUTF16("abca"), UTF8ToUTF16("bc")},
    348   };
    349 
    350   const base::string16 letters = UTF8ToUTF16("ab");
    351   for (auto test_case : test_data) {
    352     Erase(test_case.first, letters[0]);
    353     EXPECT_EQ(test_case.second, test_case.first);
    354   }
    355 
    356   for (auto test_case : test_data) {
    357     EraseIf(test_case.first, [&](short elem) { return elem < letters[1]; });
    358     EXPECT_EQ(test_case.second, test_case.first);
    359   }
    360 }
    361 
    362 TEST(Erase, Deque) {
    363   RunEraseTest<std::deque<int>>();
    364   RunEraseIfTest<std::deque<std::pair<int, int>>>();
    365 }
    366 
    367 TEST(Erase, Vector) {
    368   RunEraseTest<std::vector<int>>();
    369   RunEraseIfTest<std::vector<std::pair<int, int>>>();
    370 }
    371 
    372 TEST(Erase, ForwardList) {
    373   RunEraseTest<std::forward_list<int>>();
    374   RunEraseIfTest<std::forward_list<std::pair<int, int>>>();
    375 }
    376 
    377 TEST(Erase, List) {
    378   RunEraseTest<std::list<int>>();
    379   RunEraseIfTest<std::list<std::pair<int, int>>>();
    380 }
    381 
    382 TEST(Erase, Map) {
    383   RunEraseIfTest<std::map<int, int>>();
    384   RunEraseIfTest<std::map<int, int, std::greater<int>>>();
    385 }
    386 
    387 TEST(Erase, Multimap) {
    388   RunEraseIfTest<std::multimap<int, int>>();
    389   RunEraseIfTest<std::multimap<int, int, std::greater<int>>>();
    390 }
    391 
    392 TEST(Erase, Set) {
    393   RunEraseIfTest<std::set<std::pair<int, int>>>();
    394   RunEraseIfTest<
    395       std::set<std::pair<int, int>, std::greater<std::pair<int, int>>>>();
    396 }
    397 
    398 TEST(Erase, Multiset) {
    399   RunEraseIfTest<std::multiset<std::pair<int, int>>>();
    400   RunEraseIfTest<
    401       std::multiset<std::pair<int, int>, std::greater<std::pair<int, int>>>>();
    402 }
    403 
    404 TEST(Erase, UnorderedMap) {
    405   RunEraseIfTest<std::unordered_map<int, int>>();
    406   RunEraseIfTest<std::unordered_map<int, int, CustomIntHash>>();
    407 }
    408 
    409 TEST(Erase, UnorderedMultimap) {
    410   RunEraseIfTest<std::unordered_multimap<int, int>>();
    411   RunEraseIfTest<std::unordered_multimap<int, int, CustomIntHash>>();
    412 }
    413 
    414 TEST(Erase, UnorderedSet) {
    415   RunEraseIfTest<std::unordered_set<std::pair<int, int>, HashByFirst>>();
    416 }
    417 
    418 TEST(Erase, UnorderedMultiset) {
    419   RunEraseIfTest<std::unordered_multiset<std::pair<int, int>, HashByFirst>>();
    420 }
    421 
    422 }  // namespace
    423 }  // namespace base
    424