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 23namespace art { 24 25namespace { 26template <typename TValue> 27struct FruitMapKey : VariantMapKey<TValue> { 28 FruitMapKey() {} 29}; 30 31struct 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 44const FruitMap::Key<int> FruitMap::Apple; 45const FruitMap::Key<double> FruitMap::Orange; 46const FruitMap::Key<std::string> FruitMap::Label; 47} // namespace 48 49TEST(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 81TEST(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 99TEST(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 145TEST(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 159TEST(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 174TEST(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