1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
base / types / id_type_unittest.cc [blame]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/types/id_type.h"
#include <limits>
#include <unordered_map>
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
namespace {
class Foo;
using FooId = IdType<Foo, int, 0>;
// A type that uses both 0 and -1 as invalid values.
using MultipleInvalidId = IdType<class MultipleInvalid, int, 0, 1, -1>;
} // namespace
TEST(IdType, DefaultValueIsInvalid) {
FooId foo_id;
EXPECT_TRUE(foo_id.is_null());
MultipleInvalidId multi_id;
EXPECT_TRUE(multi_id.is_null());
}
TEST(IdType, NormalValueIsValid) {
FooId foo_id = FooId::FromUnsafeValue(123);
EXPECT_FALSE(foo_id.is_null());
MultipleInvalidId multi_id = MultipleInvalidId::FromUnsafeValue(123);
EXPECT_FALSE(multi_id.is_null());
}
TEST(IdType, ExtraInvalidValue) {
MultipleInvalidId multi_id = MultipleInvalidId::FromUnsafeValue(-1);
EXPECT_TRUE(multi_id.is_null());
}
TEST(IdType, Generator) {
FooId::Generator foo_id_generator;
for (int i = 1; i < 10; i++)
EXPECT_EQ(foo_id_generator.GenerateNextId(), FooId::FromUnsafeValue(i));
}
TEST(IdType, GeneratorWithNonZeroInvalidValue) {
using TestId = IdType<class TestIdTag, int, -1>;
TestId::Generator test_id_generator;
for (int i = 0; i < 10; i++)
EXPECT_EQ(test_id_generator.GenerateNextId(), TestId::FromUnsafeValue(i));
}
TEST(IdType, GeneratorWithBigUnsignedInvalidValue) {
using TestId =
IdType<class TestIdTag, uint32_t, std::numeric_limits<uint32_t>::max()>;
TestId::Generator test_id_generator;
for (int i = 0; i < 10; i++) {
TestId id = test_id_generator.GenerateNextId();
EXPECT_FALSE(id.is_null());
EXPECT_EQ(id, TestId::FromUnsafeValue(i));
}
}
TEST(IdType, GeneratorWithDifferentStartingValue) {
using TestId = IdType<class TestIdTag, int, -1, 1>;
TestId::Generator test_id_generator;
for (int i = 1; i < 10; i++)
EXPECT_EQ(test_id_generator.GenerateNextId(), TestId::FromUnsafeValue(i));
}
TEST(IdType, EnsureConstexpr) {
using TestId = IdType32<class TestTag>;
// Test constructors.
static constexpr TestId kZero;
static constexpr auto kOne = TestId::FromUnsafeValue(1);
// Test getting the underlying value.
static_assert(kZero.value() == 0, "");
static_assert(kOne.value() == 1, "");
static_assert(kZero.GetUnsafeValue() == 0, "");
static_assert(kOne.GetUnsafeValue() == 1, "");
static constexpr MultipleInvalidId kMultiZero;
static constexpr auto kMultiNegative = MultipleInvalidId::FromUnsafeValue(-1);
static constexpr auto kMultiOne = MultipleInvalidId::FromUnsafeValue(1);
// Test is_null().
static_assert(kZero.is_null(), "");
static_assert(!kOne.is_null(), "");
static_assert(kMultiZero.is_null(), "");
static_assert(kMultiNegative.is_null(), "");
static_assert(!kMultiOne.is_null(), "");
// Test operator bool.
static_assert(!kZero, "");
static_assert(kOne, "");
static_assert(!kMultiZero, "");
static_assert(!kMultiNegative, "");
static_assert(kMultiOne, "");
}
TEST(IdType, Map) {
struct TestObject {};
using TestId = IdType32<class MapTestTag>;
TestId::Generator id_generator;
std::unordered_map<TestId, TestObject> map;
TestObject obj[5];
for (auto& i : obj) {
map[id_generator.GenerateNextId()] = i;
}
}
class IdTypeSpecificValueTest : public ::testing::TestWithParam<int> {
protected:
FooId test_id() { return FooId::FromUnsafeValue(GetParam()); }
FooId other_id() {
if (GetParam() != std::numeric_limits<int>::max())
return FooId::FromUnsafeValue(GetParam() + 1);
else
return FooId::FromUnsafeValue(std::numeric_limits<int>::min());
}
};
TEST_P(IdTypeSpecificValueTest, UnsafeValueRoundtrips) {
int original_value = GetParam();
FooId id = FooId::FromUnsafeValue(original_value);
int final_value = id.GetUnsafeValue();
EXPECT_EQ(original_value, final_value);
}
INSTANTIATE_TEST_SUITE_P(All,
IdTypeSpecificValueTest,
::testing::Values(std::numeric_limits<int>::min(),
-1,
0,
1,
123,
std::numeric_limits<int>::max()));
} // namespace base