1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2019 The Chromium Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
4*d9f75844SAndroid Build Coastguard Worker *
5*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
6*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
7*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
8*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
9*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
10*d9f75844SAndroid Build Coastguard Worker */
11*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/strong_alias.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <cstdint>
14*d9f75844SAndroid Build Coastguard Worker #include <map>
15*d9f75844SAndroid Build Coastguard Worker #include <memory>
16*d9f75844SAndroid Build Coastguard Worker #include <string>
17*d9f75844SAndroid Build Coastguard Worker #include <type_traits>
18*d9f75844SAndroid Build Coastguard Worker #include <utility>
19*d9f75844SAndroid Build Coastguard Worker
20*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/containers/flat_map.h"
21*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/gunit.h"
22*d9f75844SAndroid Build Coastguard Worker #include "test/gmock.h"
23*d9f75844SAndroid Build Coastguard Worker
24*d9f75844SAndroid Build Coastguard Worker // This is a copy of
25*d9f75844SAndroid Build Coastguard Worker // https://source.chromium.org/chromium/chromium/src/+/main:base/types/strong_alias_unittest.cc
26*d9f75844SAndroid Build Coastguard Worker // but adapted to use WebRTC's includes, remove unit tests that test the ostream
27*d9f75844SAndroid Build Coastguard Worker // operator (it's removed in this port) and other adaptations to pass lint.
28*d9f75844SAndroid Build Coastguard Worker
29*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
30*d9f75844SAndroid Build Coastguard Worker namespace {
31*d9f75844SAndroid Build Coastguard Worker
32*d9f75844SAndroid Build Coastguard Worker // For test correctnenss, it's important that these getters return lexically
33*d9f75844SAndroid Build Coastguard Worker // incrementing values as `index` grows.
34*d9f75844SAndroid Build Coastguard Worker template <typename T>
35*d9f75844SAndroid Build Coastguard Worker T GetExampleValue(int index);
36*d9f75844SAndroid Build Coastguard Worker
37*d9f75844SAndroid Build Coastguard Worker template <>
GetExampleValue(int index)38*d9f75844SAndroid Build Coastguard Worker int GetExampleValue<int>(int index) {
39*d9f75844SAndroid Build Coastguard Worker return 5 + index;
40*d9f75844SAndroid Build Coastguard Worker }
41*d9f75844SAndroid Build Coastguard Worker template <>
GetExampleValue(int index)42*d9f75844SAndroid Build Coastguard Worker uint64_t GetExampleValue<uint64_t>(int index) {
43*d9f75844SAndroid Build Coastguard Worker return 500U + index;
44*d9f75844SAndroid Build Coastguard Worker }
45*d9f75844SAndroid Build Coastguard Worker
46*d9f75844SAndroid Build Coastguard Worker template <>
GetExampleValue(int index)47*d9f75844SAndroid Build Coastguard Worker std::string GetExampleValue<std::string>(int index) {
48*d9f75844SAndroid Build Coastguard Worker return std::string('a', index);
49*d9f75844SAndroid Build Coastguard Worker }
50*d9f75844SAndroid Build Coastguard Worker
51*d9f75844SAndroid Build Coastguard Worker } // namespace
52*d9f75844SAndroid Build Coastguard Worker
53*d9f75844SAndroid Build Coastguard Worker template <typename T>
54*d9f75844SAndroid Build Coastguard Worker class StrongAliasTest : public ::testing::Test {};
55*d9f75844SAndroid Build Coastguard Worker
56*d9f75844SAndroid Build Coastguard Worker using TestedTypes = ::testing::Types<int, uint64_t, std::string>;
57*d9f75844SAndroid Build Coastguard Worker TYPED_TEST_SUITE(StrongAliasTest, TestedTypes);
58*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST(StrongAliasTest,ValueAccessesUnderlyingValue)59*d9f75844SAndroid Build Coastguard Worker TYPED_TEST(StrongAliasTest, ValueAccessesUnderlyingValue) {
60*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, TypeParam>;
61*d9f75844SAndroid Build Coastguard Worker
62*d9f75844SAndroid Build Coastguard Worker // Const value getter.
63*d9f75844SAndroid Build Coastguard Worker const FooAlias const_alias(GetExampleValue<TypeParam>(1));
64*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(GetExampleValue<TypeParam>(1), const_alias.value());
65*d9f75844SAndroid Build Coastguard Worker static_assert(std::is_const<typename std::remove_reference<decltype(
66*d9f75844SAndroid Build Coastguard Worker const_alias.value())>::type>::value,
67*d9f75844SAndroid Build Coastguard Worker "Reference returned by const value getter should be const.");
68*d9f75844SAndroid Build Coastguard Worker }
69*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST(StrongAliasTest,ExplicitConversionToUnderlyingValue)70*d9f75844SAndroid Build Coastguard Worker TYPED_TEST(StrongAliasTest, ExplicitConversionToUnderlyingValue) {
71*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, TypeParam>;
72*d9f75844SAndroid Build Coastguard Worker
73*d9f75844SAndroid Build Coastguard Worker const FooAlias const_alias(GetExampleValue<TypeParam>(1));
74*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(GetExampleValue<TypeParam>(1), static_cast<TypeParam>(const_alias));
75*d9f75844SAndroid Build Coastguard Worker }
76*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST(StrongAliasTest,CanBeCopyConstructed)77*d9f75844SAndroid Build Coastguard Worker TYPED_TEST(StrongAliasTest, CanBeCopyConstructed) {
78*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, TypeParam>;
79*d9f75844SAndroid Build Coastguard Worker FooAlias alias(GetExampleValue<TypeParam>(0));
80*d9f75844SAndroid Build Coastguard Worker FooAlias copy_constructed = alias;
81*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(copy_constructed, alias);
82*d9f75844SAndroid Build Coastguard Worker
83*d9f75844SAndroid Build Coastguard Worker FooAlias copy_assigned;
84*d9f75844SAndroid Build Coastguard Worker copy_assigned = alias;
85*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(copy_assigned, alias);
86*d9f75844SAndroid Build Coastguard Worker }
87*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST(StrongAliasTest,CanBeMoveConstructed)88*d9f75844SAndroid Build Coastguard Worker TYPED_TEST(StrongAliasTest, CanBeMoveConstructed) {
89*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, TypeParam>;
90*d9f75844SAndroid Build Coastguard Worker FooAlias alias(GetExampleValue<TypeParam>(0));
91*d9f75844SAndroid Build Coastguard Worker FooAlias move_constructed = std::move(alias);
92*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(move_constructed, FooAlias(GetExampleValue<TypeParam>(0)));
93*d9f75844SAndroid Build Coastguard Worker
94*d9f75844SAndroid Build Coastguard Worker FooAlias alias2(GetExampleValue<TypeParam>(2));
95*d9f75844SAndroid Build Coastguard Worker FooAlias move_assigned;
96*d9f75844SAndroid Build Coastguard Worker move_assigned = std::move(alias2);
97*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(move_assigned, FooAlias(GetExampleValue<TypeParam>(2)));
98*d9f75844SAndroid Build Coastguard Worker
99*d9f75844SAndroid Build Coastguard Worker // Check that FooAlias is nothrow move constructible. This matters for
100*d9f75844SAndroid Build Coastguard Worker // performance when used in std::vectors.
101*d9f75844SAndroid Build Coastguard Worker static_assert(std::is_nothrow_move_constructible<FooAlias>::value,
102*d9f75844SAndroid Build Coastguard Worker "Error: Alias is not nothow move constructible");
103*d9f75844SAndroid Build Coastguard Worker }
104*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST(StrongAliasTest,CanBeConstructedFromMoveOnlyType)105*d9f75844SAndroid Build Coastguard Worker TYPED_TEST(StrongAliasTest, CanBeConstructedFromMoveOnlyType) {
106*d9f75844SAndroid Build Coastguard Worker // Note, using a move-only unique_ptr to T:
107*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, std::unique_ptr<TypeParam>>;
108*d9f75844SAndroid Build Coastguard Worker
109*d9f75844SAndroid Build Coastguard Worker FooAlias a(std::make_unique<TypeParam>(GetExampleValue<TypeParam>(0)));
110*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(*a.value(), GetExampleValue<TypeParam>(0));
111*d9f75844SAndroid Build Coastguard Worker
112*d9f75844SAndroid Build Coastguard Worker auto bare_value = std::make_unique<TypeParam>(GetExampleValue<TypeParam>(1));
113*d9f75844SAndroid Build Coastguard Worker FooAlias b(std::move(bare_value));
114*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(*b.value(), GetExampleValue<TypeParam>(1));
115*d9f75844SAndroid Build Coastguard Worker }
116*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST(StrongAliasTest,MutableOperatorArrow)117*d9f75844SAndroid Build Coastguard Worker TYPED_TEST(StrongAliasTest, MutableOperatorArrow) {
118*d9f75844SAndroid Build Coastguard Worker // Note, using a move-only unique_ptr to T:
119*d9f75844SAndroid Build Coastguard Worker using Ptr = std::unique_ptr<TypeParam>;
120*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, Ptr>;
121*d9f75844SAndroid Build Coastguard Worker
122*d9f75844SAndroid Build Coastguard Worker FooAlias a(std::make_unique<TypeParam>());
123*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(a.value());
124*d9f75844SAndroid Build Coastguard Worker
125*d9f75844SAndroid Build Coastguard Worker // Check that `a` can be modified through the use of operator->.
126*d9f75844SAndroid Build Coastguard Worker a->reset();
127*d9f75844SAndroid Build Coastguard Worker
128*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(a.value());
129*d9f75844SAndroid Build Coastguard Worker }
130*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST(StrongAliasTest,MutableOperatorStar)131*d9f75844SAndroid Build Coastguard Worker TYPED_TEST(StrongAliasTest, MutableOperatorStar) {
132*d9f75844SAndroid Build Coastguard Worker // Note, using a move-only unique_ptr to T:
133*d9f75844SAndroid Build Coastguard Worker using Ptr = std::unique_ptr<TypeParam>;
134*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, Ptr>;
135*d9f75844SAndroid Build Coastguard Worker
136*d9f75844SAndroid Build Coastguard Worker FooAlias a(std::make_unique<TypeParam>());
137*d9f75844SAndroid Build Coastguard Worker FooAlias b(std::make_unique<TypeParam>());
138*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(*a);
139*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(*b);
140*d9f75844SAndroid Build Coastguard Worker
141*d9f75844SAndroid Build Coastguard Worker // Check that both the mutable l-value and r-value overloads work and we can
142*d9f75844SAndroid Build Coastguard Worker // move out of the aliases.
143*d9f75844SAndroid Build Coastguard Worker { Ptr ignore(*std::move(a)); }
144*d9f75844SAndroid Build Coastguard Worker { Ptr ignore(std::move(*b)); }
145*d9f75844SAndroid Build Coastguard Worker
146*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(a.value());
147*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(b.value());
148*d9f75844SAndroid Build Coastguard Worker }
149*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST(StrongAliasTest,MutableValue)150*d9f75844SAndroid Build Coastguard Worker TYPED_TEST(StrongAliasTest, MutableValue) {
151*d9f75844SAndroid Build Coastguard Worker // Note, using a move-only unique_ptr to T:
152*d9f75844SAndroid Build Coastguard Worker using Ptr = std::unique_ptr<TypeParam>;
153*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, Ptr>;
154*d9f75844SAndroid Build Coastguard Worker
155*d9f75844SAndroid Build Coastguard Worker FooAlias a(std::make_unique<TypeParam>());
156*d9f75844SAndroid Build Coastguard Worker FooAlias b(std::make_unique<TypeParam>());
157*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(a.value());
158*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(b.value());
159*d9f75844SAndroid Build Coastguard Worker
160*d9f75844SAndroid Build Coastguard Worker // Check that both the mutable l-value and r-value overloads work and we can
161*d9f75844SAndroid Build Coastguard Worker // move out of the aliases.
162*d9f75844SAndroid Build Coastguard Worker { Ptr ignore(std::move(a).value()); }
163*d9f75844SAndroid Build Coastguard Worker { Ptr ignore(std::move(b.value())); }
164*d9f75844SAndroid Build Coastguard Worker
165*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(a.value());
166*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(b.value());
167*d9f75844SAndroid Build Coastguard Worker }
168*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST(StrongAliasTest,SizeSameAsUnderlyingType)169*d9f75844SAndroid Build Coastguard Worker TYPED_TEST(StrongAliasTest, SizeSameAsUnderlyingType) {
170*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, TypeParam>;
171*d9f75844SAndroid Build Coastguard Worker static_assert(sizeof(FooAlias) == sizeof(TypeParam),
172*d9f75844SAndroid Build Coastguard Worker "StrongAlias should be as large as the underlying type.");
173*d9f75844SAndroid Build Coastguard Worker }
174*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST(StrongAliasTest,IsDefaultConstructible)175*d9f75844SAndroid Build Coastguard Worker TYPED_TEST(StrongAliasTest, IsDefaultConstructible) {
176*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, TypeParam>;
177*d9f75844SAndroid Build Coastguard Worker static_assert(std::is_default_constructible<FooAlias>::value,
178*d9f75844SAndroid Build Coastguard Worker "Should be possible to default-construct a StrongAlias.");
179*d9f75844SAndroid Build Coastguard Worker static_assert(
180*d9f75844SAndroid Build Coastguard Worker std::is_trivially_default_constructible<FooAlias>::value ==
181*d9f75844SAndroid Build Coastguard Worker std::is_trivially_default_constructible<TypeParam>::value,
182*d9f75844SAndroid Build Coastguard Worker "Should be possible to trivially default-construct a StrongAlias iff the "
183*d9f75844SAndroid Build Coastguard Worker "underlying type is trivially default constructible.");
184*d9f75844SAndroid Build Coastguard Worker }
185*d9f75844SAndroid Build Coastguard Worker
TEST(StrongAliasTest,TrivialTypeAliasIsStandardLayout)186*d9f75844SAndroid Build Coastguard Worker TEST(StrongAliasTest, TrivialTypeAliasIsStandardLayout) {
187*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, int>;
188*d9f75844SAndroid Build Coastguard Worker static_assert(std::is_standard_layout<FooAlias>::value,
189*d9f75844SAndroid Build Coastguard Worker "int-based alias should have standard layout. ");
190*d9f75844SAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<FooAlias>::value,
191*d9f75844SAndroid Build Coastguard Worker "int-based alias should be trivially copyable. ");
192*d9f75844SAndroid Build Coastguard Worker }
193*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST(StrongAliasTest,CannotBeCreatedFromDifferentAlias)194*d9f75844SAndroid Build Coastguard Worker TYPED_TEST(StrongAliasTest, CannotBeCreatedFromDifferentAlias) {
195*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, TypeParam>;
196*d9f75844SAndroid Build Coastguard Worker using BarAlias = StrongAlias<class BarTag, TypeParam>;
197*d9f75844SAndroid Build Coastguard Worker static_assert(!std::is_constructible<FooAlias, BarAlias>::value,
198*d9f75844SAndroid Build Coastguard Worker "Should be impossible to construct FooAlias from a BarAlias.");
199*d9f75844SAndroid Build Coastguard Worker static_assert(!std::is_convertible<BarAlias, FooAlias>::value,
200*d9f75844SAndroid Build Coastguard Worker "Should be impossible to convert a BarAlias into FooAlias.");
201*d9f75844SAndroid Build Coastguard Worker }
202*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST(StrongAliasTest,CannotBeImplicitlyConverterToUnderlyingValue)203*d9f75844SAndroid Build Coastguard Worker TYPED_TEST(StrongAliasTest, CannotBeImplicitlyConverterToUnderlyingValue) {
204*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, TypeParam>;
205*d9f75844SAndroid Build Coastguard Worker static_assert(!std::is_convertible<FooAlias, TypeParam>::value,
206*d9f75844SAndroid Build Coastguard Worker "Should be impossible to implicitly convert a StrongAlias into "
207*d9f75844SAndroid Build Coastguard Worker "an underlying type.");
208*d9f75844SAndroid Build Coastguard Worker }
209*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST(StrongAliasTest,ComparesEqualToSameValue)210*d9f75844SAndroid Build Coastguard Worker TYPED_TEST(StrongAliasTest, ComparesEqualToSameValue) {
211*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, TypeParam>;
212*d9f75844SAndroid Build Coastguard Worker // Comparison to self:
213*d9f75844SAndroid Build Coastguard Worker const FooAlias a = FooAlias(GetExampleValue<TypeParam>(0));
214*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(a, a);
215*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(a != a);
216*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(a >= a);
217*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(a <= a);
218*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(a > a);
219*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(a < a);
220*d9f75844SAndroid Build Coastguard Worker // Comparison to other equal object:
221*d9f75844SAndroid Build Coastguard Worker const FooAlias b = FooAlias(GetExampleValue<TypeParam>(0));
222*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(a, b);
223*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(a != b);
224*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(a >= b);
225*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(a <= b);
226*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(a > b);
227*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(a < b);
228*d9f75844SAndroid Build Coastguard Worker }
229*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST(StrongAliasTest,ComparesCorrectlyToDifferentValue)230*d9f75844SAndroid Build Coastguard Worker TYPED_TEST(StrongAliasTest, ComparesCorrectlyToDifferentValue) {
231*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, TypeParam>;
232*d9f75844SAndroid Build Coastguard Worker const FooAlias a = FooAlias(GetExampleValue<TypeParam>(0));
233*d9f75844SAndroid Build Coastguard Worker const FooAlias b = FooAlias(GetExampleValue<TypeParam>(1));
234*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(a, b);
235*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(a == b);
236*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(b >= a);
237*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(a <= b);
238*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(b > a);
239*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(a < b);
240*d9f75844SAndroid Build Coastguard Worker }
241*d9f75844SAndroid Build Coastguard Worker
TEST(StrongAliasTest,CanBeDerivedFrom)242*d9f75844SAndroid Build Coastguard Worker TEST(StrongAliasTest, CanBeDerivedFrom) {
243*d9f75844SAndroid Build Coastguard Worker // Aliases can be enriched by custom operations or validations if needed.
244*d9f75844SAndroid Build Coastguard Worker // Ideally, one could go from a 'using' declaration to a derived class to add
245*d9f75844SAndroid Build Coastguard Worker // those methods without the need to change any other code.
246*d9f75844SAndroid Build Coastguard Worker class CountryCode : public StrongAlias<CountryCode, std::string> {
247*d9f75844SAndroid Build Coastguard Worker public:
248*d9f75844SAndroid Build Coastguard Worker explicit CountryCode(const std::string& value)
249*d9f75844SAndroid Build Coastguard Worker : StrongAlias<CountryCode, std::string>::StrongAlias(value) {
250*d9f75844SAndroid Build Coastguard Worker if (value_.length() != 2) {
251*d9f75844SAndroid Build Coastguard Worker // Country code invalid!
252*d9f75844SAndroid Build Coastguard Worker value_.clear(); // is_null() will return true.
253*d9f75844SAndroid Build Coastguard Worker }
254*d9f75844SAndroid Build Coastguard Worker }
255*d9f75844SAndroid Build Coastguard Worker
256*d9f75844SAndroid Build Coastguard Worker bool is_null() const { return value_.empty(); }
257*d9f75844SAndroid Build Coastguard Worker };
258*d9f75844SAndroid Build Coastguard Worker
259*d9f75844SAndroid Build Coastguard Worker CountryCode valid("US");
260*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(valid.is_null());
261*d9f75844SAndroid Build Coastguard Worker
262*d9f75844SAndroid Build Coastguard Worker CountryCode invalid("United States");
263*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(invalid.is_null());
264*d9f75844SAndroid Build Coastguard Worker }
265*d9f75844SAndroid Build Coastguard Worker
TEST(StrongAliasTest,CanWrapComplexStructures)266*d9f75844SAndroid Build Coastguard Worker TEST(StrongAliasTest, CanWrapComplexStructures) {
267*d9f75844SAndroid Build Coastguard Worker // A pair of strings implements odering and can, in principle, be used as
268*d9f75844SAndroid Build Coastguard Worker // a base of StrongAlias.
269*d9f75844SAndroid Build Coastguard Worker using PairOfStrings = std::pair<std::string, std::string>;
270*d9f75844SAndroid Build Coastguard Worker using ComplexAlias = StrongAlias<class FooTag, PairOfStrings>;
271*d9f75844SAndroid Build Coastguard Worker
272*d9f75844SAndroid Build Coastguard Worker ComplexAlias a1{std::make_pair("aaa", "bbb")};
273*d9f75844SAndroid Build Coastguard Worker ComplexAlias a2{std::make_pair("ccc", "ddd")};
274*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(a1 < a2);
275*d9f75844SAndroid Build Coastguard Worker
276*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(a1.value() == PairOfStrings("aaa", "bbb"));
277*d9f75844SAndroid Build Coastguard Worker
278*d9f75844SAndroid Build Coastguard Worker // Note a caveat, an std::pair doesn't have an overload of operator<<, and it
279*d9f75844SAndroid Build Coastguard Worker // cannot be easily added since ADL rules would require it to be in the std
280*d9f75844SAndroid Build Coastguard Worker // namespace. So we can't print ComplexAlias.
281*d9f75844SAndroid Build Coastguard Worker }
282*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST(StrongAliasTest,CanBeKeysInFlatMap)283*d9f75844SAndroid Build Coastguard Worker TYPED_TEST(StrongAliasTest, CanBeKeysInFlatMap) {
284*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, TypeParam>;
285*d9f75844SAndroid Build Coastguard Worker webrtc::flat_map<FooAlias, std::string> map;
286*d9f75844SAndroid Build Coastguard Worker
287*d9f75844SAndroid Build Coastguard Worker FooAlias k1(GetExampleValue<TypeParam>(0));
288*d9f75844SAndroid Build Coastguard Worker FooAlias k2(GetExampleValue<TypeParam>(1));
289*d9f75844SAndroid Build Coastguard Worker
290*d9f75844SAndroid Build Coastguard Worker map[k1] = "value1";
291*d9f75844SAndroid Build Coastguard Worker map[k2] = "value2";
292*d9f75844SAndroid Build Coastguard Worker
293*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(map[k1], "value1");
294*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(map[k2], "value2");
295*d9f75844SAndroid Build Coastguard Worker }
296*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST(StrongAliasTest,CanBeKeysInStdMap)297*d9f75844SAndroid Build Coastguard Worker TYPED_TEST(StrongAliasTest, CanBeKeysInStdMap) {
298*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, TypeParam>;
299*d9f75844SAndroid Build Coastguard Worker std::map<FooAlias, std::string> map;
300*d9f75844SAndroid Build Coastguard Worker
301*d9f75844SAndroid Build Coastguard Worker FooAlias k1(GetExampleValue<TypeParam>(0));
302*d9f75844SAndroid Build Coastguard Worker FooAlias k2(GetExampleValue<TypeParam>(1));
303*d9f75844SAndroid Build Coastguard Worker
304*d9f75844SAndroid Build Coastguard Worker map[k1] = "value1";
305*d9f75844SAndroid Build Coastguard Worker map[k2] = "value2";
306*d9f75844SAndroid Build Coastguard Worker
307*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(map[k1], "value1");
308*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(map[k2], "value2");
309*d9f75844SAndroid Build Coastguard Worker }
310*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST(StrongAliasTest,CanDifferentiateOverloads)311*d9f75844SAndroid Build Coastguard Worker TYPED_TEST(StrongAliasTest, CanDifferentiateOverloads) {
312*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, TypeParam>;
313*d9f75844SAndroid Build Coastguard Worker using BarAlias = StrongAlias<class BarTag, TypeParam>;
314*d9f75844SAndroid Build Coastguard Worker class Scope {
315*d9f75844SAndroid Build Coastguard Worker public:
316*d9f75844SAndroid Build Coastguard Worker static std::string Overload(FooAlias) { return "FooAlias"; }
317*d9f75844SAndroid Build Coastguard Worker static std::string Overload(BarAlias) { return "BarAlias"; }
318*d9f75844SAndroid Build Coastguard Worker };
319*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ("FooAlias", Scope::Overload(FooAlias()));
320*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ("BarAlias", Scope::Overload(BarAlias()));
321*d9f75844SAndroid Build Coastguard Worker }
322*d9f75844SAndroid Build Coastguard Worker
TEST(StrongAliasTest,EnsureConstexpr)323*d9f75844SAndroid Build Coastguard Worker TEST(StrongAliasTest, EnsureConstexpr) {
324*d9f75844SAndroid Build Coastguard Worker using FooAlias = StrongAlias<class FooTag, int>;
325*d9f75844SAndroid Build Coastguard Worker
326*d9f75844SAndroid Build Coastguard Worker // Check constructors.
327*d9f75844SAndroid Build Coastguard Worker static constexpr FooAlias kZero{};
328*d9f75844SAndroid Build Coastguard Worker static constexpr FooAlias kOne(1);
329*d9f75844SAndroid Build Coastguard Worker
330*d9f75844SAndroid Build Coastguard Worker // Check operator*.
331*d9f75844SAndroid Build Coastguard Worker static_assert(*kZero == 0, "");
332*d9f75844SAndroid Build Coastguard Worker static_assert(*kOne == 1, "");
333*d9f75844SAndroid Build Coastguard Worker
334*d9f75844SAndroid Build Coastguard Worker // Check value().
335*d9f75844SAndroid Build Coastguard Worker static_assert(kZero.value() == 0, "");
336*d9f75844SAndroid Build Coastguard Worker static_assert(kOne.value() == 1, "");
337*d9f75844SAndroid Build Coastguard Worker
338*d9f75844SAndroid Build Coastguard Worker // Check explicit conversions to underlying type.
339*d9f75844SAndroid Build Coastguard Worker static_assert(static_cast<int>(kZero) == 0, "");
340*d9f75844SAndroid Build Coastguard Worker static_assert(static_cast<int>(kOne) == 1, "");
341*d9f75844SAndroid Build Coastguard Worker
342*d9f75844SAndroid Build Coastguard Worker // Check comparison operations.
343*d9f75844SAndroid Build Coastguard Worker static_assert(kZero == kZero, "");
344*d9f75844SAndroid Build Coastguard Worker static_assert(kZero != kOne, "");
345*d9f75844SAndroid Build Coastguard Worker static_assert(kZero < kOne, "");
346*d9f75844SAndroid Build Coastguard Worker static_assert(kZero <= kOne, "");
347*d9f75844SAndroid Build Coastguard Worker static_assert(kOne > kZero, "");
348*d9f75844SAndroid Build Coastguard Worker static_assert(kOne >= kZero, "");
349*d9f75844SAndroid Build Coastguard Worker }
350*d9f75844SAndroid Build Coastguard Worker
TEST(StrongAliasTest,BooleansAreEvaluatedAsBooleans)351*d9f75844SAndroid Build Coastguard Worker TEST(StrongAliasTest, BooleansAreEvaluatedAsBooleans) {
352*d9f75844SAndroid Build Coastguard Worker using BoolAlias = StrongAlias<class BoolTag, bool>;
353*d9f75844SAndroid Build Coastguard Worker
354*d9f75844SAndroid Build Coastguard Worker BoolAlias happy(true);
355*d9f75844SAndroid Build Coastguard Worker BoolAlias sad(false);
356*d9f75844SAndroid Build Coastguard Worker
357*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(happy);
358*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(sad);
359*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(*happy);
360*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(*sad);
361*d9f75844SAndroid Build Coastguard Worker }
362*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
363