xref: /aosp_15_r20/external/webrtc/rtc_base/strong_alias_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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