Home | History | Annotate | Download | only in base
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "variant_map.h"
     18 #include "gtest/gtest.h"
     19 
     20 #define EXPECT_NULL(expected) EXPECT_EQ(reinterpret_cast<const void*>(expected), \
     21                                         static_cast<void*>(nullptr));
     22 
     23 namespace art {
     24 
     25 namespace {
     26 template <typename TValue>
     27 struct FruitMapKey : VariantMapKey<TValue> {
     28   FruitMapKey() {}
     29 };
     30 
     31 struct FruitMap : VariantMap<FruitMap, FruitMapKey> {
     32   // This 'using' line is necessary to inherit the variadic constructor.
     33   using VariantMap<FruitMap, FruitMapKey>::VariantMap;
     34 
     35   // Make the next '4' usages of Key slightly shorter to type.
     36   template <typename TValue>
     37   using Key = FruitMapKey<TValue>;
     38 
     39   static const Key<int> Apple;
     40   static const Key<double> Orange;
     41   static const Key<std::string> Label;
     42 };
     43 
     44 const FruitMap::Key<int> FruitMap::Apple;
     45 const FruitMap::Key<double> FruitMap::Orange;
     46 const FruitMap::Key<std::string> FruitMap::Label;
     47 }  // namespace
     48 
     49 TEST(VariantMaps, BasicReadWrite) {
     50   FruitMap fm;
     51 
     52   EXPECT_NULL(fm.Get(FruitMap::Apple));
     53   EXPECT_FALSE(fm.Exists(FruitMap::Apple));
     54   EXPECT_NULL(fm.Get(FruitMap::Orange));
     55   EXPECT_FALSE(fm.Exists(FruitMap::Orange));
     56 
     57   fm.Set(FruitMap::Apple, 1);
     58   EXPECT_NULL(fm.Get(FruitMap::Orange));
     59   EXPECT_EQ(1, *fm.Get(FruitMap::Apple));
     60   EXPECT_TRUE(fm.Exists(FruitMap::Apple));
     61 
     62   fm.Set(FruitMap::Apple, 5);
     63   EXPECT_NULL(fm.Get(FruitMap::Orange));
     64   EXPECT_EQ(5, *fm.Get(FruitMap::Apple));
     65   EXPECT_TRUE(fm.Exists(FruitMap::Apple));
     66 
     67   fm.Set(FruitMap::Orange, 555.0);
     68   EXPECT_EQ(5, *fm.Get(FruitMap::Apple));
     69   EXPECT_DOUBLE_EQ(555.0, *fm.Get(FruitMap::Orange));
     70   EXPECT_EQ(size_t(2), fm.Size());
     71 
     72   // Simple remove
     73   fm.Remove(FruitMap::Apple);
     74   EXPECT_FALSE(fm.Exists(FruitMap::Apple));
     75 
     76   fm.Clear();
     77   EXPECT_EQ(size_t(0), fm.Size());
     78   EXPECT_FALSE(fm.Exists(FruitMap::Orange));
     79 }
     80 
     81 TEST(VariantMaps, SetPreviousValue) {
     82   FruitMap fm;
     83 
     84   // Indirect remove by setting yourself again
     85   fm.Set(FruitMap::Label, std::string("hello_world"));
     86   auto* ptr = fm.Get(FruitMap::Label);
     87   ASSERT_TRUE(ptr != nullptr);
     88   *ptr = "foobar";
     89 
     90   // Set the value to the same exact pointer which we got out of the map.
     91   // This should cleanly 'just work' and not try to delete the value too early.
     92   fm.Set(FruitMap::Label, *ptr);
     93 
     94   auto* new_ptr = fm.Get(FruitMap::Label);
     95   ASSERT_TRUE(ptr != nullptr);
     96   EXPECT_EQ(std::string("foobar"), *new_ptr);
     97 }
     98 
     99 TEST(VariantMaps, RuleOfFive) {
    100   // Test empty constructor
    101   FruitMap fmEmpty;
    102   EXPECT_EQ(size_t(0), fmEmpty.Size());
    103 
    104   // Test empty constructor
    105   FruitMap fmFilled;
    106   fmFilled.Set(FruitMap::Apple, 1);
    107   fmFilled.Set(FruitMap::Orange, 555.0);
    108   EXPECT_EQ(size_t(2), fmFilled.Size());
    109 
    110   // Test copy constructor
    111   FruitMap fmEmptyCopy(fmEmpty);
    112   EXPECT_EQ(size_t(0), fmEmptyCopy.Size());
    113 
    114   // Test copy constructor
    115   FruitMap fmFilledCopy(fmFilled);
    116   EXPECT_EQ(size_t(2), fmFilledCopy.Size());
    117   EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmFilledCopy.Get(FruitMap::Apple));
    118   EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmFilledCopy.Get(FruitMap::Orange));
    119 
    120   // Test operator=
    121   FruitMap fmFilledCopy2;
    122   fmFilledCopy2 = fmFilled;
    123   EXPECT_EQ(size_t(2), fmFilledCopy2.Size());
    124   EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmFilledCopy2.Get(FruitMap::Apple));
    125   EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmFilledCopy2.Get(FruitMap::Orange));
    126 
    127   // Test move constructor
    128   FruitMap fmMoved(std::move(fmFilledCopy));
    129   EXPECT_EQ(size_t(0), fmFilledCopy.Size());
    130   EXPECT_EQ(size_t(2), fmMoved.Size());
    131   EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmMoved.Get(FruitMap::Apple));
    132   EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmMoved.Get(FruitMap::Orange));
    133 
    134   // Test operator= move
    135   FruitMap fmMoved2;
    136   fmMoved2.Set(FruitMap::Apple, 12345);  // This value will be clobbered after the move
    137 
    138   fmMoved2 = std::move(fmFilledCopy2);
    139   EXPECT_EQ(size_t(0), fmFilledCopy2.Size());
    140   EXPECT_EQ(size_t(2), fmMoved2.Size());
    141   EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmMoved2.Get(FruitMap::Apple));
    142   EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmMoved2.Get(FruitMap::Orange));
    143 }
    144 
    145 TEST(VariantMaps, VariadicConstructors) {
    146   // Variadic constructor, 1 kv/pair
    147   FruitMap fmApple(FruitMap::Apple, 12345);
    148   EXPECT_EQ(size_t(1), fmApple.Size());
    149   EXPECT_EQ(12345, *fmApple.Get(FruitMap::Apple));
    150 
    151   // Variadic constructor, 2 kv/pair
    152   FruitMap fmAppleAndOrange(FruitMap::Apple,   12345,
    153                             FruitMap::Orange,  100.0);
    154   EXPECT_EQ(size_t(2), fmAppleAndOrange.Size());
    155   EXPECT_EQ(12345, *fmAppleAndOrange.Get(FruitMap::Apple));
    156   EXPECT_DOUBLE_EQ(100.0, *fmAppleAndOrange.Get(FruitMap::Orange));
    157 }
    158 
    159 TEST(VariantMaps, ReleaseOrDefault) {
    160   FruitMap fmAppleAndOrange(FruitMap::Apple,   12345,
    161                             FruitMap::Orange,  100.0);
    162 
    163   int apple = fmAppleAndOrange.ReleaseOrDefault(FruitMap::Apple);
    164   EXPECT_EQ(12345, apple);
    165 
    166   // Releasing will also remove the Apple key.
    167   EXPECT_EQ(size_t(1), fmAppleAndOrange.Size());
    168 
    169   // Releasing again yields a default value.
    170   int apple2 = fmAppleAndOrange.ReleaseOrDefault(FruitMap::Apple);
    171   EXPECT_EQ(0, apple2);
    172 }
    173 
    174 TEST(VariantMaps, GetOrDefault) {
    175   FruitMap fm(FruitMap::Apple,   12345);
    176 
    177   // Apple gives the expected value we set.
    178   int apple = fm.GetOrDefault(FruitMap::Apple);
    179   EXPECT_EQ(12345, apple);
    180 
    181   // Map is still 1.
    182   EXPECT_EQ(size_t(1), fm.Size());
    183 
    184   // Orange gives back a default value, since it's not in the map.
    185   double orange = fm.GetOrDefault(FruitMap::Orange);
    186   EXPECT_DOUBLE_EQ(0.0, orange);
    187 }
    188 
    189 }  // namespace art
    190