/* * * Copyright (c) 2021 Project CHIP Authors * All rights reserved. * * 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 #include #include #include namespace { struct Simple { bool operator==(const Simple &) const { return true; } }; struct Pod { Pod(int v1, int v2) : m1(v1), m2(v2) {} bool operator==(const Pod & other) const { return m1 == other.m1 && m2 == other.m2; } int m1; int m2; }; struct Movable { Movable(int v1, int v2) : m1(v1), m2(v2) {} Movable(Movable &) = delete; Movable & operator=(Movable &) = delete; Movable(Movable &&) = default; Movable & operator=(Movable &&) = default; int m1; int m2; }; struct Count { Count() { ++created; } ~Count() { ++destroyed; } Count(const Count &) { ++created; } Count & operator=(Count &) = default; Count(Count &&) { ++created; } Count & operator=(Count &&) = default; static int created; static int destroyed; }; int Count::created = 0; int Count::destroyed = 0; using namespace chip; TEST(TestVariant, TestVariantSimple) { Variant v; EXPECT_FALSE(v.Valid()); v.Set(5, 10); EXPECT_TRUE(v.Valid()); EXPECT_TRUE(v.Is()); EXPECT_EQ(v.Get().m1, 5); EXPECT_EQ(v.Get().m2, 10); } TEST(TestVariant, TestVariantMovable) { Variant v; v.Set(); v.Set(Movable{ 5, 10 }); EXPECT_EQ(v.Get().m1, 5); EXPECT_EQ(v.Get().m2, 10); auto & m = v.Get(); EXPECT_EQ(m.m1, 5); EXPECT_EQ(m.m2, 10); v.Set(); } TEST(TestVariant, TestVariantCtorDtor) { { Variant v; EXPECT_EQ(Count::created, 0); v.Set(); EXPECT_EQ(Count::created, 0); v.Get(); EXPECT_EQ(Count::created, 0); } { Variant v; EXPECT_EQ(Count::created, 0); v.Set(); EXPECT_EQ(Count::created, 0); v.Set(); EXPECT_EQ(Count::created, 1); EXPECT_EQ(Count::destroyed, 0); v.Get(); EXPECT_EQ(Count::created, 1); EXPECT_EQ(Count::destroyed, 0); v.Set(); EXPECT_EQ(Count::created, 1); EXPECT_EQ(Count::destroyed, 1); v.Set(); EXPECT_EQ(Count::created, 2); EXPECT_EQ(Count::destroyed, 1); } EXPECT_EQ(Count::destroyed, 2); { Variant v1; v1.Set(); Variant v2(v1); } EXPECT_EQ(Count::created, 4); EXPECT_EQ(Count::destroyed, 4); { Variant v1; v1.Set(); Variant v2(std::move(v1)); } EXPECT_EQ(Count::created, 6); EXPECT_EQ(Count::destroyed, 6); { Variant v1, v2; v1.Set(); v2 = v1; } EXPECT_EQ(Count::created, 8); EXPECT_EQ(Count::destroyed, 8); { Variant v1, v2; v1.Set(); v2 = std::move(v1); } EXPECT_EQ(Count::created, 10); EXPECT_EQ(Count::destroyed, 10); } TEST(TestVariant, TestVariantCopy) { Variant v1; v1.Set(5, 10); Variant v2 = v1; EXPECT_TRUE(v1.Valid()); EXPECT_EQ(v1.Get().m1, 5); EXPECT_EQ(v1.Get().m2, 10); EXPECT_TRUE(v2.Valid()); EXPECT_EQ(v2.Get().m1, 5); EXPECT_EQ(v2.Get().m2, 10); } TEST(TestVariant, TestVariantMove) { Variant v1; v1.Set(5, 10); Variant v2 = std::move(v1); EXPECT_FALSE(v1.Valid()); // NOLINT(bugprone-use-after-move) EXPECT_TRUE(v2.Valid()); EXPECT_EQ(v2.Get().m1, 5); EXPECT_EQ(v2.Get().m2, 10); } TEST(TestVariant, TestVariantCopyAssign) { Variant v1; Variant v2; v1.Set(5, 10); v2 = v1; EXPECT_TRUE(v1.Valid()); EXPECT_EQ(v1.Get().m1, 5); EXPECT_EQ(v1.Get().m2, 10); EXPECT_TRUE(v2.Valid()); EXPECT_EQ(v2.Get().m1, 5); EXPECT_EQ(v2.Get().m2, 10); } TEST(TestVariant, TestVariantMoveAssign) { Variant v1; Variant v2; v1.Set(5, 10); v2 = std::move(v1); EXPECT_FALSE(v1.Valid()); // NOLINT(bugprone-use-after-move) EXPECT_TRUE(v2.Valid()); EXPECT_EQ(v2.Get().m1, 5); EXPECT_EQ(v2.Get().m2, 10); } TEST(TestVariant, TestVariantInPlace) { int i = 0; Variant> v1 = Variant>(InPlaceTemplate>, i); EXPECT_TRUE(v1.Valid()); EXPECT_TRUE(v1.Is>()); EXPECT_EQ(&v1.Get>().get(), &i); Variant> v2 = Variant>::Create>(i); EXPECT_TRUE(v2.Valid()); EXPECT_TRUE(v2.Is>()); EXPECT_EQ(&v2.Get>().get(), &i); } TEST(TestVariant, TestVariantCompare) { Variant v0; Variant v1; Variant v2; Variant v3; Variant v4; v1.Set(); v2.Set(5, 10); v3.Set(5, 10); v4.Set(5, 11); EXPECT_TRUE(v0 == v0); EXPECT_FALSE(v0 == v1); EXPECT_FALSE(v0 == v2); EXPECT_FALSE(v0 == v3); EXPECT_FALSE(v0 == v4); EXPECT_FALSE(v1 == v0); EXPECT_TRUE(v1 == v1); EXPECT_FALSE(v1 == v2); EXPECT_FALSE(v1 == v3); EXPECT_FALSE(v1 == v4); EXPECT_FALSE(v2 == v0); EXPECT_FALSE(v2 == v1); EXPECT_TRUE(v2 == v2); EXPECT_TRUE(v2 == v3); EXPECT_FALSE(v2 == v4); EXPECT_FALSE(v3 == v0); EXPECT_FALSE(v3 == v1); EXPECT_TRUE(v3 == v2); EXPECT_TRUE(v3 == v3); EXPECT_FALSE(v3 == v4); EXPECT_FALSE(v4 == v0); EXPECT_FALSE(v4 == v1); EXPECT_FALSE(v4 == v2); EXPECT_FALSE(v4 == v3); EXPECT_TRUE(v4 == v4); } } // namespace