1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/types/optional_ref.h"
6
7 #include <cstddef>
8 #include <optional>
9 #include <type_traits>
10 #include <utility>
11
12 #include "base/test/gtest_util.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace base {
16
17 namespace {
18
19 // Construction from `std::nullptr_t` is disallowed; `std::nullopt` must be
20 // used to construct an empty `optional_ref`.
21 static_assert(!std::is_constructible_v<optional_ref<int>, std::nullptr_t>);
22
23 // No-compile asserts for various const -> mutable conversions.
24 static_assert(
25 !std::is_constructible_v<optional_ref<int>, const std::optional<int>&>);
26 static_assert(!std::is_constructible_v<optional_ref<int>, const int*>);
27 static_assert(!std::is_constructible_v<optional_ref<int>, const int&>);
28 static_assert(!std::is_constructible_v<optional_ref<int>, int&&>);
29 static_assert(!std::is_constructible_v<optional_ref<int>, const int>);
30 static_assert(
31 !std::is_constructible_v<optional_ref<int>, optional_ref<const int>>);
32
33 // No-compile asserts for implicit conversions.
34 static_assert(!std::is_constructible_v<optional_ref<bool>, int>);
35 static_assert(!std::is_constructible_v<optional_ref<bool>, const int&>);
36 static_assert(!std::is_constructible_v<optional_ref<bool>, int&>);
37 static_assert(!std::is_constructible_v<optional_ref<bool>, const int*>);
38 static_assert(!std::is_constructible_v<optional_ref<bool>, int*>);
39
40 class ImplicitInt {
41 public:
42 // NOLINTNEXTLINE(google-explicit-constructor)
ImplicitInt(int)43 ImplicitInt(int) {}
44 };
45
46 static_assert(!std::is_constructible_v<optional_ref<ImplicitInt>, int>);
47 static_assert(!std::is_constructible_v<optional_ref<ImplicitInt>, const int&>);
48 static_assert(!std::is_constructible_v<optional_ref<ImplicitInt>, int&>);
49 static_assert(!std::is_constructible_v<optional_ref<ImplicitInt>, const int*>);
50 static_assert(!std::is_constructible_v<optional_ref<ImplicitInt>, int*>);
51
52 class TestClass {
53 public:
ConstMethod() const54 void ConstMethod() const {}
MutableMethod()55 void MutableMethod() {}
56 };
57
TEST(OptionalRefTest,FromNullopt)58 TEST(OptionalRefTest, FromNullopt) {
59 [](optional_ref<const int> r) { EXPECT_FALSE(r.has_value()); }(std::nullopt);
60
61 [](optional_ref<int> r) { EXPECT_FALSE(r.has_value()); }(std::nullopt);
62 }
63
TEST(OptionalRefTest,FromConstEmptyOptional)64 TEST(OptionalRefTest, FromConstEmptyOptional) {
65 const std::optional<int> optional_int;
66
67 [](optional_ref<const int> r) { EXPECT_FALSE(r.has_value()); }(optional_int);
68
69 // Mutable case covered by static_assert test above.
70 }
71
TEST(OptionalRefTest,FromMutableEmptyOptional)72 TEST(OptionalRefTest, FromMutableEmptyOptional) {
73 std::optional<int> optional_int;
74
75 [](optional_ref<const int> r) { EXPECT_FALSE(r.has_value()); }(optional_int);
76
77 [](optional_ref<int> r) { EXPECT_FALSE(r.has_value()); }(optional_int);
78 }
79
TEST(OptionalRefTest,FromConstOptional)80 TEST(OptionalRefTest, FromConstOptional) {
81 const std::optional<int> optional_int(6);
82
83 [](optional_ref<const int> r) {
84 EXPECT_TRUE(r.has_value());
85 EXPECT_EQ(6, r.value());
86 }(optional_int);
87
88 // Mutable case covered by static_assert test above.
89 }
90
TEST(OptionalRefTest,FromMutableOptional)91 TEST(OptionalRefTest, FromMutableOptional) {
92 std::optional<int> optional_int(6);
93
94 [](optional_ref<const int> r) {
95 EXPECT_TRUE(r.has_value());
96 EXPECT_EQ(6, r.value());
97 }(optional_int);
98
99 [](optional_ref<int> r) {
100 EXPECT_TRUE(r.has_value());
101 EXPECT_EQ(6, r.value());
102 }(optional_int);
103 }
104
105 // The From*NullPointer tests intentionally avoid passing nullptr directly,
106 // which is explicitly disallowed to reduce ambiguity when constructing an empty
107 // `optional_ref`.
TEST(OptionalRefTest,FromConstNullPointer)108 TEST(OptionalRefTest, FromConstNullPointer) {
109 const int* ptr = nullptr;
110
111 [](optional_ref<const int> r) { EXPECT_FALSE(r.has_value()); }(ptr);
112
113 // Mutable case covered by static_assert test above.
114 }
115
TEST(OptionalRefTest,FromMutableNullPointer)116 TEST(OptionalRefTest, FromMutableNullPointer) {
117 int* ptr = nullptr;
118
119 [](optional_ref<const int> r) { EXPECT_FALSE(r.has_value()); }(ptr);
120
121 [](optional_ref<int> r) { EXPECT_FALSE(r.has_value()); }(ptr);
122 }
123
TEST(OptionalRefTest,FromConstPointer)124 TEST(OptionalRefTest, FromConstPointer) {
125 int value = 6;
126 const int* ptr = &value;
127
128 [](optional_ref<const int> r) {
129 EXPECT_TRUE(r.has_value());
130 EXPECT_EQ(6, r.value());
131 }(ptr);
132
133 // Mutable case covered by static_assert test above.
134 }
135
TEST(OptionalRefTest,FromPointer)136 TEST(OptionalRefTest, FromPointer) {
137 int value = 6;
138 int* ptr = &value;
139
140 [](optional_ref<const int> r) {
141 EXPECT_TRUE(r.has_value());
142 EXPECT_EQ(6, r.value());
143 }(ptr);
144
145 [](optional_ref<int> r) {
146 EXPECT_TRUE(r.has_value());
147 EXPECT_EQ(6, r.value());
148 }(ptr);
149 }
150
TEST(OptionalRefTest,FromConstRef)151 TEST(OptionalRefTest, FromConstRef) {
152 int value = 6;
153 const int& ref = value;
154
155 [](optional_ref<const int> r) {
156 EXPECT_TRUE(r.has_value());
157 EXPECT_EQ(6, r.value());
158 }(ref);
159
160 // Mutable case covered by static_assert test above.
161 }
162
TEST(OptionalRefTest,FromMutableRef)163 TEST(OptionalRefTest, FromMutableRef) {
164 int value = 6;
165 int& ref = value;
166
167 [](optional_ref<const int> r) {
168 EXPECT_TRUE(r.has_value());
169 EXPECT_EQ(6, r.value());
170 }(ref);
171
172 [](optional_ref<int> r) {
173 EXPECT_TRUE(r.has_value());
174 EXPECT_EQ(6, r.value());
175 }(ref);
176 }
177
TEST(OptionalRefTest,FromConstValue)178 TEST(OptionalRefTest, FromConstValue) {
179 const int value = 6;
180
181 [](optional_ref<const int> r) {
182 EXPECT_TRUE(r.has_value());
183 EXPECT_EQ(6, r.value());
184 }(value);
185
186 [](optional_ref<const int> r) {
187 EXPECT_TRUE(r.has_value());
188 EXPECT_EQ(6, r.value());
189 }(6);
190
191 // Mutable case covered by static_assert test above.
192 }
193
TEST(OptionalRefTest,FromMutableValue)194 TEST(OptionalRefTest, FromMutableValue) {
195 int value = 6;
196
197 [](optional_ref<const int> r) {
198 EXPECT_TRUE(r.has_value());
199 EXPECT_EQ(6, r.value());
200 }(value);
201
202 [](optional_ref<int> r) {
203 EXPECT_TRUE(r.has_value());
204 EXPECT_EQ(6, r.value());
205 }(value);
206 }
207
TEST(OptionalRefTest,FromMutableEmptyOptionalRefTest)208 TEST(OptionalRefTest, FromMutableEmptyOptionalRefTest) {
209 {
210 optional_ref<int> r1;
211 [](optional_ref<const int> r2) { EXPECT_FALSE(r2.has_value()); }(r1);
212 }
213
214 {
215 optional_ref<int> r1(std::nullopt);
216 [](optional_ref<int> r2) { EXPECT_FALSE(r2.has_value()); }(r1);
217 }
218 }
219
TEST(OptionalRefTest,FromMutableOptionalRefTest)220 TEST(OptionalRefTest, FromMutableOptionalRefTest) {
221 int value = 6;
222 optional_ref<int> r1(value);
223
224 [](optional_ref<const int> r2) {
225 EXPECT_TRUE(r2.has_value());
226 EXPECT_EQ(6, r2.value());
227 }(r1);
228
229 [](optional_ref<int> r2) {
230 EXPECT_TRUE(r2.has_value());
231 EXPECT_EQ(6, r2.value());
232 }(r1);
233 }
234
TEST(OptionalRefTest,FromCopyConstructorConst)235 TEST(OptionalRefTest, FromCopyConstructorConst) {
236 [](optional_ref<const int> r) {
237 EXPECT_FALSE(r.has_value());
238 }(optional_ref<const int>());
239
240 int value = 6;
241 optional_ref<const int> r1(value);
242 [](optional_ref<const int> r2) {
243 EXPECT_TRUE(r2.has_value());
244 EXPECT_EQ(6, r2.value());
245 }(r1);
246
247 // Mutable case covered by static_assert test above.
248 }
249
TEST(OptionalRefTest,FromCopyConstructorMutable)250 TEST(OptionalRefTest, FromCopyConstructorMutable) {
251 [](optional_ref<int> r) { EXPECT_FALSE(r.has_value()); }(optional_ref<int>());
252
253 int value = 6;
254 optional_ref<int> r1(value);
255 [](optional_ref<int> r2) {
256 EXPECT_TRUE(r2.has_value());
257 EXPECT_EQ(6, r2.value());
258 }(r1);
259 }
260
TEST(OptionalRefTest,Arrow)261 TEST(OptionalRefTest, Arrow) {
262 int uninitialized_value;
263
264 {
265 const optional_ref<const int> r(uninitialized_value);
266 static_assert(std::is_same_v<decltype(r.operator->()), const int*>);
267 EXPECT_EQ(&uninitialized_value, r.operator->());
268 }
269
270 {
271 optional_ref<const int> r(uninitialized_value);
272 static_assert(std::is_same_v<decltype(r.operator->()), const int*>);
273 EXPECT_EQ(&uninitialized_value, r.operator->());
274 }
275
276 {
277 const optional_ref<int> r(uninitialized_value);
278 static_assert(std::is_same_v<decltype(r.operator->()), int*>);
279 EXPECT_EQ(&uninitialized_value, r.operator->());
280 }
281
282 {
283 optional_ref<int> r(uninitialized_value);
284 static_assert(std::is_same_v<decltype(r.operator->()), int*>);
285 EXPECT_EQ(&uninitialized_value, r.operator->());
286 }
287 }
288
TEST(OptionalRefTest,Star)289 TEST(OptionalRefTest, Star) {
290 int uninitialized_value;
291
292 {
293 const optional_ref<const int> r(uninitialized_value);
294 static_assert(std::is_same_v<decltype(r.operator*()), const int&>);
295 EXPECT_EQ(&uninitialized_value, &r.operator*());
296 }
297
298 {
299 optional_ref<const int> r(uninitialized_value);
300 static_assert(std::is_same_v<decltype(r.operator*()), const int&>);
301 EXPECT_EQ(&uninitialized_value, &r.operator*());
302 }
303
304 {
305 const optional_ref<int> r(uninitialized_value);
306 static_assert(std::is_same_v<decltype(r.operator*()), int&>);
307 EXPECT_EQ(&uninitialized_value, &r.operator*());
308 }
309
310 {
311 optional_ref<int> r(uninitialized_value);
312 static_assert(std::is_same_v<decltype(r.operator*()), int&>);
313 EXPECT_EQ(&uninitialized_value, &r.operator*());
314 }
315 }
316
TEST(OptionalRefTest,Value)317 TEST(OptionalRefTest, Value) {
318 // has_value() and value() are generally covered by the construction tests.
319 // Make sure value() doesn't somehow break const-ness here.
320 {
321 const optional_ref<const int> r;
322 static_assert(std::is_same_v<decltype(r.value()), const int&>);
323 }
324
325 {
326 optional_ref<const int> r;
327 static_assert(std::is_same_v<decltype(r.value()), const int&>);
328 }
329
330 {
331 const optional_ref<int> r;
332 static_assert(std::is_same_v<decltype(r.value()), int&>);
333 }
334
335 {
336 optional_ref<int> r;
337 static_assert(std::is_same_v<decltype(r.value()), int&>);
338 }
339 }
340
TEST(OptionalRefTest,AsPtr)341 TEST(OptionalRefTest, AsPtr) {
342 optional_ref<int> r1;
343 EXPECT_EQ(nullptr, r1.as_ptr());
344
345 int uninitialized_value;
346 {
347 const optional_ref<const int> r(uninitialized_value);
348 static_assert(std::is_same_v<decltype(r.as_ptr()), const int*>);
349 EXPECT_EQ(&uninitialized_value, r.as_ptr());
350 }
351
352 {
353 optional_ref<const int> r(uninitialized_value);
354 static_assert(std::is_same_v<decltype(r.as_ptr()), const int*>);
355 EXPECT_EQ(&uninitialized_value, r.as_ptr());
356 }
357
358 {
359 const optional_ref<int> r(uninitialized_value);
360 static_assert(std::is_same_v<decltype(r.as_ptr()), int*>);
361 EXPECT_EQ(&uninitialized_value, r.as_ptr());
362 }
363
364 {
365 optional_ref<int> r(uninitialized_value);
366 static_assert(std::is_same_v<decltype(r.as_ptr()), int*>);
367 EXPECT_EQ(&uninitialized_value, r.as_ptr());
368 }
369 }
370
TEST(OptionalRefTest,CopyAsOptional)371 TEST(OptionalRefTest, CopyAsOptional) {
372 optional_ref<int> r1;
373 std::optional<int> o1 = r1.CopyAsOptional();
374 EXPECT_EQ(std::nullopt, o1);
375
376 int value = 6;
377 optional_ref<int> r2(value);
378 std::optional<int> o2 = r2.CopyAsOptional();
379 EXPECT_EQ(6, o2);
380 }
381
TEST(OptionalRefTest,EqualityComparisonWithNullOpt)382 TEST(OptionalRefTest, EqualityComparisonWithNullOpt) {
383 {
384 optional_ref<int> r;
385 EXPECT_EQ(r, std::nullopt);
386 EXPECT_EQ(std::nullopt, r);
387 }
388
389 {
390 int value = 5;
391 optional_ref<int> r(value);
392 EXPECT_NE(r, std::nullopt);
393 EXPECT_NE(std::nullopt, r);
394 }
395 }
396
TEST(OptionalRefDeathTest,ArrowOnEmpty)397 TEST(OptionalRefDeathTest, ArrowOnEmpty) {
398 [](optional_ref<const TestClass> r) {
399 EXPECT_CHECK_DEATH(r->ConstMethod());
400 }(std::nullopt);
401
402 [](optional_ref<TestClass> r) {
403 EXPECT_CHECK_DEATH(r->ConstMethod());
404 EXPECT_CHECK_DEATH(r->MutableMethod());
405 }(std::nullopt);
406 }
407
TEST(OptionalRefDeathTest,StarOnEmpty)408 TEST(OptionalRefDeathTest, StarOnEmpty) {
409 [](optional_ref<const TestClass> r) {
410 EXPECT_CHECK_DEATH((*r).ConstMethod());
411 }(std::nullopt);
412
413 [](optional_ref<TestClass> r) {
414 EXPECT_CHECK_DEATH((*r).ConstMethod());
415 EXPECT_CHECK_DEATH((*r).MutableMethod());
416 }(std::nullopt);
417 }
418
TEST(OptionalRefDeathTest,ValueOnEmpty)419 TEST(OptionalRefDeathTest, ValueOnEmpty) {
420 [](optional_ref<const TestClass> r) {
421 EXPECT_CHECK_DEATH(r.value());
422 }(std::nullopt);
423
424 [](optional_ref<TestClass> r) {
425 EXPECT_CHECK_DEATH(r.value());
426 }(std::nullopt);
427 }
428
TEST(OptionalRefTest,ClassTemplateArgumentDeduction)429 TEST(OptionalRefTest, ClassTemplateArgumentDeduction) {
430 static_assert(
431 std::is_same_v<decltype(optional_ref{int()}), optional_ref<const int>>);
432
433 {
434 const int i = 0;
435 static_assert(
436 std::is_same_v<decltype(optional_ref(i)), optional_ref<const int>>);
437 }
438
439 {
440 int i = 0;
441 static_assert(std::is_same_v<decltype(optional_ref(i)), optional_ref<int>>);
442 }
443
444 static_assert(std::is_same_v<decltype(optional_ref(std::optional<int>())),
445 optional_ref<const int>>);
446
447 {
448 const std::optional<int> o;
449 static_assert(
450 std::is_same_v<decltype(optional_ref(o)), optional_ref<const int>>);
451 }
452
453 {
454 std::optional<int> o;
455 static_assert(std::is_same_v<decltype(optional_ref(o)), optional_ref<int>>);
456 }
457
458 {
459 const int* p = nullptr;
460 static_assert(
461 std::is_same_v<decltype(optional_ref(p)), optional_ref<const int>>);
462 }
463
464 {
465 int* p = nullptr;
466 static_assert(std::is_same_v<decltype(optional_ref(p)), optional_ref<int>>);
467 }
468 }
469
470 } // namespace
471
472 } // namespace base
473