You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
6.0 KiB
190 lines
6.0 KiB
/*
|
|
* Copyright (C) 2015 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "variant_map.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
#define EXPECT_NULL(expected) EXPECT_EQ(reinterpret_cast<const void*>(expected), \
|
|
static_cast<void*>(nullptr));
|
|
|
|
namespace art {
|
|
|
|
namespace {
|
|
template <typename TValue>
|
|
struct FruitMapKey : VariantMapKey<TValue> {
|
|
FruitMapKey() {}
|
|
};
|
|
|
|
struct FruitMap : VariantMap<FruitMap, FruitMapKey> {
|
|
// This 'using' line is necessary to inherit the variadic constructor.
|
|
using VariantMap<FruitMap, FruitMapKey>::VariantMap;
|
|
|
|
// Make the next '4' usages of Key slightly shorter to type.
|
|
template <typename TValue>
|
|
using Key = FruitMapKey<TValue>;
|
|
|
|
static const Key<int> Apple;
|
|
static const Key<double> Orange;
|
|
static const Key<std::string> Label;
|
|
};
|
|
|
|
const FruitMap::Key<int> FruitMap::Apple;
|
|
const FruitMap::Key<double> FruitMap::Orange;
|
|
const FruitMap::Key<std::string> FruitMap::Label;
|
|
} // namespace
|
|
|
|
TEST(VariantMaps, BasicReadWrite) {
|
|
FruitMap fm;
|
|
|
|
EXPECT_NULL(fm.Get(FruitMap::Apple));
|
|
EXPECT_FALSE(fm.Exists(FruitMap::Apple));
|
|
EXPECT_NULL(fm.Get(FruitMap::Orange));
|
|
EXPECT_FALSE(fm.Exists(FruitMap::Orange));
|
|
|
|
fm.Set(FruitMap::Apple, 1);
|
|
EXPECT_NULL(fm.Get(FruitMap::Orange));
|
|
EXPECT_EQ(1, *fm.Get(FruitMap::Apple));
|
|
EXPECT_TRUE(fm.Exists(FruitMap::Apple));
|
|
|
|
fm.Set(FruitMap::Apple, 5);
|
|
EXPECT_NULL(fm.Get(FruitMap::Orange));
|
|
EXPECT_EQ(5, *fm.Get(FruitMap::Apple));
|
|
EXPECT_TRUE(fm.Exists(FruitMap::Apple));
|
|
|
|
fm.Set(FruitMap::Orange, 555.0);
|
|
EXPECT_EQ(5, *fm.Get(FruitMap::Apple));
|
|
EXPECT_DOUBLE_EQ(555.0, *fm.Get(FruitMap::Orange));
|
|
EXPECT_EQ(size_t(2), fm.Size());
|
|
|
|
// Simple remove
|
|
fm.Remove(FruitMap::Apple);
|
|
EXPECT_FALSE(fm.Exists(FruitMap::Apple));
|
|
|
|
fm.Clear();
|
|
EXPECT_EQ(size_t(0), fm.Size());
|
|
EXPECT_FALSE(fm.Exists(FruitMap::Orange));
|
|
}
|
|
|
|
TEST(VariantMaps, SetPreviousValue) {
|
|
FruitMap fm;
|
|
|
|
// Indirect remove by setting yourself again
|
|
fm.Set(FruitMap::Label, std::string("hello_world"));
|
|
auto* ptr = fm.Get(FruitMap::Label);
|
|
ASSERT_TRUE(ptr != nullptr);
|
|
*ptr = "foobar";
|
|
|
|
// Set the value to the same exact pointer which we got out of the map.
|
|
// This should cleanly 'just work' and not try to delete the value too early.
|
|
fm.Set(FruitMap::Label, *ptr);
|
|
|
|
auto* new_ptr = fm.Get(FruitMap::Label);
|
|
ASSERT_TRUE(ptr != nullptr);
|
|
EXPECT_EQ(std::string("foobar"), *new_ptr);
|
|
}
|
|
|
|
TEST(VariantMaps, RuleOfFive) {
|
|
// Test empty constructor
|
|
FruitMap fmEmpty;
|
|
EXPECT_EQ(size_t(0), fmEmpty.Size());
|
|
|
|
// Test empty constructor
|
|
FruitMap fmFilled;
|
|
fmFilled.Set(FruitMap::Apple, 1);
|
|
fmFilled.Set(FruitMap::Orange, 555.0);
|
|
EXPECT_EQ(size_t(2), fmFilled.Size());
|
|
|
|
// Test copy constructor
|
|
FruitMap fmEmptyCopy(fmEmpty); // NOLINT
|
|
EXPECT_EQ(size_t(0), fmEmptyCopy.Size());
|
|
|
|
// Test copy constructor
|
|
FruitMap fmFilledCopy(fmFilled);
|
|
EXPECT_EQ(size_t(2), fmFilledCopy.Size());
|
|
EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmFilledCopy.Get(FruitMap::Apple));
|
|
EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmFilledCopy.Get(FruitMap::Orange));
|
|
|
|
// Test operator=
|
|
FruitMap fmFilledCopy2;
|
|
fmFilledCopy2 = fmFilled;
|
|
EXPECT_EQ(size_t(2), fmFilledCopy2.Size());
|
|
EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmFilledCopy2.Get(FruitMap::Apple));
|
|
EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmFilledCopy2.Get(FruitMap::Orange));
|
|
|
|
// Test move constructor
|
|
FruitMap fmMoved(std::move(fmFilledCopy));
|
|
EXPECT_EQ(size_t(0), fmFilledCopy.Size());
|
|
EXPECT_EQ(size_t(2), fmMoved.Size());
|
|
EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmMoved.Get(FruitMap::Apple));
|
|
EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmMoved.Get(FruitMap::Orange));
|
|
|
|
// Test operator= move
|
|
FruitMap fmMoved2;
|
|
fmMoved2.Set(FruitMap::Apple, 12345); // This value will be clobbered after the move
|
|
|
|
fmMoved2 = std::move(fmFilledCopy2);
|
|
EXPECT_EQ(size_t(0), fmFilledCopy2.Size());
|
|
EXPECT_EQ(size_t(2), fmMoved2.Size());
|
|
EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmMoved2.Get(FruitMap::Apple));
|
|
EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmMoved2.Get(FruitMap::Orange));
|
|
}
|
|
|
|
TEST(VariantMaps, VariadicConstructors) {
|
|
// Variadic constructor, 1 kv/pair
|
|
FruitMap fmApple(FruitMap::Apple, 12345);
|
|
EXPECT_EQ(size_t(1), fmApple.Size());
|
|
EXPECT_EQ(12345, *fmApple.Get(FruitMap::Apple));
|
|
|
|
// Variadic constructor, 2 kv/pair
|
|
FruitMap fmAppleAndOrange(FruitMap::Apple, 12345,
|
|
FruitMap::Orange, 100.0);
|
|
EXPECT_EQ(size_t(2), fmAppleAndOrange.Size());
|
|
EXPECT_EQ(12345, *fmAppleAndOrange.Get(FruitMap::Apple));
|
|
EXPECT_DOUBLE_EQ(100.0, *fmAppleAndOrange.Get(FruitMap::Orange));
|
|
}
|
|
|
|
TEST(VariantMaps, ReleaseOrDefault) {
|
|
FruitMap fmAppleAndOrange(FruitMap::Apple, 12345,
|
|
FruitMap::Orange, 100.0);
|
|
|
|
int apple = fmAppleAndOrange.ReleaseOrDefault(FruitMap::Apple);
|
|
EXPECT_EQ(12345, apple);
|
|
|
|
// Releasing will also remove the Apple key.
|
|
EXPECT_EQ(size_t(1), fmAppleAndOrange.Size());
|
|
|
|
// Releasing again yields a default value.
|
|
int apple2 = fmAppleAndOrange.ReleaseOrDefault(FruitMap::Apple);
|
|
EXPECT_EQ(0, apple2);
|
|
}
|
|
|
|
TEST(VariantMaps, GetOrDefault) {
|
|
FruitMap fm(FruitMap::Apple, 12345);
|
|
|
|
// Apple gives the expected value we set.
|
|
int apple = fm.GetOrDefault(FruitMap::Apple);
|
|
EXPECT_EQ(12345, apple);
|
|
|
|
// Map is still 1.
|
|
EXPECT_EQ(size_t(1), fm.Size());
|
|
|
|
// Orange gives back a default value, since it's not in the map.
|
|
double orange = fm.GetOrDefault(FruitMap::Orange);
|
|
EXPECT_DOUBLE_EQ(0.0, orange);
|
|
}
|
|
|
|
} // namespace art
|