/*
* 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));
// NOLINTNEXTLINE - checking underlying storage has been freed
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);
// NOLINTNEXTLINE - checking underlying storage has been freed
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
Messung V0.5 in Prozent C=90 H=95 G=92
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-06-29)
¤
*© Formatika GbR, Deutschland