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