1 | /* |
2 | * Copyright (C) 2016-2017 Apple Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
19 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
20 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
21 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
22 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
23 | * THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #include "config.h" |
27 | |
28 | #include "RefLogger.h" |
29 | |
30 | #include <memory> |
31 | #include <string> |
32 | |
33 | #include <wtf/Expected.h> |
34 | #include <wtf/Unexpected.h> |
35 | #include <wtf/StdLibExtras.h> |
36 | #include <wtf/Ref.h> |
37 | |
38 | namespace std { |
39 | |
40 | template<typename T0, typename T1> std::ostream& operator<<(std::ostream& os, const std::pair<T0, T1>& p) |
41 | { |
42 | return os << '(' << p.first << ", " << p.second << ')'; |
43 | } |
44 | |
45 | namespace experimental { |
46 | inline namespace fundamentals_v3 { |
47 | |
48 | template<class E> std::ostream& operator<<(std::ostream& os, const Unexpected<E>& u) |
49 | { |
50 | return os << u.value(); |
51 | } |
52 | |
53 | template<class T, class E> std::ostream& operator<<(std::ostream& os, const Expected<T, E>& e) |
54 | { |
55 | if (e.has_value()) |
56 | return os << e.value(); |
57 | return os << e.error(); |
58 | } |
59 | |
60 | template<class E> std::ostream& operator<<(std::ostream& os, const Expected<void, E>& e) |
61 | { |
62 | if (e.has_value()) |
63 | return os << "" ; |
64 | return os << e.error(); |
65 | } |
66 | |
67 | }}} // namespace std::experimental::fundamentals_v3 |
68 | |
69 | |
70 | namespace TestWebKitAPI { |
71 | |
72 | constexpr const char* oops = "oops" ; |
73 | constexpr const char* foof = "foof" ; |
74 | |
75 | TEST(WTF_Expected, Unexpected) |
76 | { |
77 | { |
78 | auto u = Unexpected<int>(42); |
79 | EXPECT_EQ(u.value(), 42); |
80 | constexpr auto c = makeUnexpected(42); |
81 | EXPECT_EQ(c.value(), 42); |
82 | EXPECT_EQ(u, c); |
83 | EXPECT_FALSE(u != c); |
84 | } |
85 | { |
86 | auto c = makeUnexpected(oops); |
87 | EXPECT_EQ(c.value(), oops); |
88 | } |
89 | { |
90 | auto s = makeUnexpected(std::string(oops)); |
91 | EXPECT_EQ(s.value(), oops); |
92 | } |
93 | { |
94 | constexpr auto s0 = makeUnexpected(oops); |
95 | constexpr auto s1(s0); |
96 | EXPECT_EQ(s0, s1); |
97 | } |
98 | } |
99 | |
100 | struct foo { |
101 | int v; |
102 | foo(int v) |
103 | : v(v) |
104 | { } |
105 | ~foo() { } |
106 | bool operator==(const foo& y) const { return v == y.v; } |
107 | friend std::ostream& operator<<(std::ostream&, const foo&); |
108 | }; |
109 | std::ostream& operator<<(std::ostream& os, const foo& f) { return os << f.v; } |
110 | |
111 | TEST(WTF_Expected, expected) |
112 | { |
113 | typedef Expected<int, const char*> E; |
114 | typedef Expected<int, const void*> EV; |
115 | typedef Expected<foo, const char*> FooChar; |
116 | typedef Expected<foo, std::string> FooString; |
117 | { |
118 | auto e = E(); |
119 | EXPECT_TRUE(e.has_value()); |
120 | EXPECT_EQ(e.value(), 0); |
121 | EXPECT_EQ(e.value_or(3.14), 0); |
122 | } |
123 | { |
124 | constexpr E e; |
125 | EXPECT_TRUE(e.has_value()); |
126 | EXPECT_EQ(e.value(), 0); |
127 | EXPECT_EQ(e.value_or(3.14), 0); |
128 | } |
129 | { |
130 | auto e = E(42); |
131 | EXPECT_TRUE(e.has_value()); |
132 | EXPECT_EQ(e.value(), 42); |
133 | EXPECT_EQ(e.value_or(3.14), 42); |
134 | const auto e2(e); |
135 | EXPECT_TRUE(e2.has_value()); |
136 | EXPECT_EQ(e2.value(), 42); |
137 | EXPECT_EQ(e2.value_or(3.14), 42); |
138 | E e3; |
139 | e3 = e2; |
140 | EXPECT_TRUE(e3.has_value()); |
141 | EXPECT_EQ(e3.value(), 42); |
142 | EXPECT_EQ(e3.value_or(3.14), 42); |
143 | const E e4 = e2; |
144 | EXPECT_TRUE(e4.has_value()); |
145 | EXPECT_EQ(e4.value(), 42); |
146 | EXPECT_EQ(e4.value_or(3.14), 42); |
147 | } |
148 | { |
149 | constexpr E c(42); |
150 | EXPECT_TRUE(c.has_value()); |
151 | EXPECT_EQ(c.value(), 42); |
152 | EXPECT_EQ(c.value_or(3.14), 42); |
153 | constexpr const auto c2(c); |
154 | EXPECT_TRUE(c2.has_value()); |
155 | EXPECT_EQ(c2.value(), 42); |
156 | EXPECT_EQ(c2.value_or(3.14), 42); |
157 | } |
158 | { |
159 | auto u = E(makeUnexpected(oops)); |
160 | EXPECT_FALSE(u.has_value()); |
161 | EXPECT_EQ(u.error(), oops); |
162 | EXPECT_EQ(u.value_or(3.14), 3); |
163 | } |
164 | { |
165 | auto uv = EV(makeUnexpected(oops)); |
166 | EXPECT_FALSE(uv.has_value()); |
167 | EXPECT_EQ(uv.error(), oops); |
168 | EXPECT_EQ(uv.value_or(3.14), 3); |
169 | } |
170 | { |
171 | E e = makeUnexpected(oops); |
172 | EXPECT_FALSE(e.has_value()); |
173 | EXPECT_EQ(e.error(), oops); |
174 | EXPECT_EQ(e.value_or(3.14), 3); |
175 | } |
176 | { |
177 | auto e = FooChar(42); |
178 | EXPECT_EQ(e->v, 42); |
179 | EXPECT_EQ((*e).v, 42); |
180 | } |
181 | { |
182 | auto e0 = E(42); |
183 | auto e1 = E(1024); |
184 | swap(e0, e1); |
185 | EXPECT_EQ(e0.value(), 1024); |
186 | EXPECT_EQ(e1.value(), 42); |
187 | } |
188 | { |
189 | auto e0 = E(makeUnexpected(oops)); |
190 | auto e1 = E(makeUnexpected(foof)); |
191 | swap(e0, e1); |
192 | EXPECT_EQ(e0.error(), foof); |
193 | EXPECT_EQ(e1.error(), oops); |
194 | } |
195 | { |
196 | FooChar c(foo(42)); |
197 | EXPECT_EQ(c->v, 42); |
198 | EXPECT_EQ((*c).v, 42); |
199 | } |
200 | { |
201 | FooString s(foo(42)); |
202 | EXPECT_EQ(s->v, 42); |
203 | EXPECT_EQ((*s).v, 42); |
204 | const char* message = "very long failure string, for very bad failure cases" ; |
205 | FooString e0(makeUnexpected<std::string>(message)); |
206 | FooString e1(makeUnexpected<std::string>(message)); |
207 | FooString e2(makeUnexpected<std::string>(std::string())); |
208 | EXPECT_EQ(e0.error(), std::string(message)); |
209 | EXPECT_EQ(e0, e1); |
210 | EXPECT_NE(e0, e2); |
211 | FooString* e4 = new FooString(makeUnexpected<std::string>(message)); |
212 | FooString* e5 = new FooString(*e4); |
213 | EXPECT_EQ(e0, *e4); |
214 | delete e4; |
215 | EXPECT_EQ(e0, *e5); |
216 | delete e5; |
217 | } |
218 | } |
219 | |
220 | TEST(WTF_Expected, void) |
221 | { |
222 | typedef Expected<void, const char*> E; |
223 | typedef Expected<void, const void*> EV; |
224 | typedef Expected<void, std::string> String; |
225 | { |
226 | auto e = E(); |
227 | EXPECT_TRUE(e.has_value()); |
228 | const auto e2(e); |
229 | EXPECT_TRUE(e2.has_value()); |
230 | EXPECT_EQ(e, e2); |
231 | E e3; |
232 | e3 = e2; |
233 | EXPECT_TRUE(e3.has_value()); |
234 | EXPECT_EQ(e, e3); |
235 | } |
236 | { |
237 | constexpr E c; |
238 | EXPECT_TRUE(c.has_value()); |
239 | constexpr const auto c2(c); |
240 | EXPECT_TRUE(c2.has_value()); |
241 | EXPECT_EQ(c, c2); |
242 | } |
243 | { |
244 | auto u = E(makeUnexpected(oops)); |
245 | EXPECT_FALSE(u.has_value()); |
246 | EXPECT_EQ(u.error(), oops); |
247 | } |
248 | { |
249 | auto uv = EV(makeUnexpected(oops)); |
250 | EXPECT_FALSE(uv.has_value()); |
251 | EXPECT_EQ(uv.error(), oops); |
252 | } |
253 | { |
254 | E e = makeUnexpected(oops); |
255 | EXPECT_FALSE(e.has_value()); |
256 | EXPECT_EQ(e.error(), oops); |
257 | } |
258 | { |
259 | auto e0 = E(); |
260 | auto e1 = E(); |
261 | swap(e0, e1); |
262 | EXPECT_EQ(e0, e1); |
263 | } |
264 | { |
265 | auto e0 = E(makeUnexpected(oops)); |
266 | auto e1 = E(makeUnexpected(foof)); |
267 | swap(e0, e1); |
268 | EXPECT_EQ(e0.error(), foof); |
269 | EXPECT_EQ(e1.error(), oops); |
270 | } |
271 | { |
272 | const char* message = "very long failure string, for very bad failure cases" ; |
273 | String e0(makeUnexpected<std::string>(message)); |
274 | String e1(makeUnexpected<std::string>(message)); |
275 | String e2(makeUnexpected<std::string>(std::string())); |
276 | EXPECT_EQ(e0.error(), std::string(message)); |
277 | EXPECT_EQ(e0, e1); |
278 | EXPECT_NE(e0, e2); |
279 | String* e4 = new String(makeUnexpected<std::string>(message)); |
280 | String* e5 = new String(*e4); |
281 | EXPECT_EQ(e0, *e4); |
282 | delete e4; |
283 | EXPECT_EQ(e0, *e5); |
284 | delete e5; |
285 | } |
286 | { |
287 | typedef Expected<std::pair<int, int>, std::string> Et; |
288 | EXPECT_EQ(Et(std::in_place, 1, 2), Et(std::in_place, 1, 2)); |
289 | } |
290 | } |
291 | |
292 | template<typename T> |
293 | struct NonCopyable { |
294 | NonCopyable(NonCopyable&&) = default; |
295 | NonCopyable(const NonCopyable&) = delete; |
296 | NonCopyable& operator=(const NonCopyable&) = delete; |
297 | NonCopyable& operator=(NonCopyable&&) = default; |
298 | bool operator==(const NonCopyable<T>& other) const { return value == other.value; } |
299 | bool operator!=(const NonCopyable<T>& other) const { return value != other.value; } |
300 | T value; |
301 | }; |
302 | |
303 | TEST(WTF_Expected, comparison) |
304 | { |
305 | typedef Expected<int, const char*> Ex; |
306 | typedef Expected<int, int> Er; |
307 | |
308 | // Two Expected, no errors. |
309 | EXPECT_EQ(Ex(42), Ex(42)); |
310 | EXPECT_NE(Ex(42), Ex(1024)); |
311 | |
312 | EXPECT_FALSE(Ex(42) == Ex(1024)); |
313 | EXPECT_FALSE(Ex(42) != Ex(42)); |
314 | |
315 | // Two Expected, half errors. |
316 | EXPECT_FALSE(Ex(42) == Ex(makeUnexpected(oops))); |
317 | EXPECT_NE(Ex(42), Ex(makeUnexpected(oops))); |
318 | |
319 | EXPECT_FALSE(Ex(makeUnexpected(oops)) == Ex(42)); |
320 | EXPECT_NE(Ex(makeUnexpected(oops)), Ex(42)); |
321 | |
322 | // Two Expected, all errors. |
323 | EXPECT_EQ(Er(42), Er(42)); |
324 | EXPECT_NE(Er(42), Er(1024)); |
325 | |
326 | EXPECT_FALSE(Er(42) == Er(1024)); |
327 | EXPECT_FALSE(Er(42) != Er(42)); |
328 | |
329 | // One Expected, one value. |
330 | EXPECT_EQ(Ex(42), 42); |
331 | EXPECT_NE(Ex(42), 0); |
332 | |
333 | EXPECT_FALSE(Ex(42) == 0); |
334 | EXPECT_FALSE(Ex(42) != 42); |
335 | |
336 | EXPECT_EQ(42, Ex(42)); |
337 | EXPECT_NE(42, Ex(1024)); |
338 | |
339 | EXPECT_FALSE(42 == Ex(1024)); |
340 | EXPECT_FALSE(42 != Ex(42)); |
341 | |
342 | // One Expected, one unexpected. |
343 | EXPECT_FALSE(Ex(42) == makeUnexpected(oops)); |
344 | EXPECT_NE(Ex(42), makeUnexpected(oops)); |
345 | |
346 | EXPECT_FALSE(makeUnexpected(oops) == Ex(42)); |
347 | EXPECT_NE(makeUnexpected(oops), Ex(42)); |
348 | |
349 | NonCopyable<int> a { 5 }; |
350 | NonCopyable<int> b { 6 }; |
351 | Unexpected<NonCopyable<double>> c { makeUnexpected(NonCopyable<double> { 5.0 }) }; |
352 | Expected<NonCopyable<int>, NonCopyable<double>> d { NonCopyable<int> { 5 } }; |
353 | Expected<NonCopyable<int>, NonCopyable<double>> e { makeUnexpected(NonCopyable<double> { 5.0 }) }; |
354 | |
355 | EXPECT_TRUE(a != e); |
356 | EXPECT_TRUE(e != a); |
357 | EXPECT_FALSE(a == e); |
358 | EXPECT_FALSE(e == a); |
359 | |
360 | EXPECT_TRUE(b != e); |
361 | EXPECT_TRUE(e != b); |
362 | EXPECT_FALSE(b == e); |
363 | EXPECT_FALSE(e == b); |
364 | |
365 | EXPECT_TRUE(c != d); |
366 | EXPECT_TRUE(d != c); |
367 | EXPECT_FALSE(c == d); |
368 | EXPECT_FALSE(d == c); |
369 | |
370 | EXPECT_TRUE(c == e); |
371 | EXPECT_TRUE(e == c); |
372 | EXPECT_FALSE(c != e); |
373 | EXPECT_FALSE(e != c); |
374 | } |
375 | |
376 | struct NonTrivialDtor { |
377 | ~NonTrivialDtor() { ++count; } |
378 | static int count; |
379 | }; |
380 | int NonTrivialDtor::count = 0; |
381 | |
382 | TEST(WTF_Expected, destructors) |
383 | { |
384 | typedef Expected<NonTrivialDtor, const char*> NT; |
385 | typedef Expected<const char*, NonTrivialDtor> TN; |
386 | typedef Expected<NonTrivialDtor, NonTrivialDtor> NN; |
387 | typedef Expected<void, NonTrivialDtor> VN; |
388 | EXPECT_EQ(NonTrivialDtor::count, 0); |
389 | { NT nt; } |
390 | EXPECT_EQ(NonTrivialDtor::count, 1); |
391 | { NT nt = makeUnexpected(oops); } |
392 | EXPECT_EQ(NonTrivialDtor::count, 1); |
393 | { TN tn; } |
394 | EXPECT_EQ(NonTrivialDtor::count, 1); |
395 | { TN tn = makeUnexpected(NonTrivialDtor()); } |
396 | EXPECT_EQ(NonTrivialDtor::count, 4); |
397 | { NN nn; } |
398 | EXPECT_EQ(NonTrivialDtor::count, 5); |
399 | { NN nn = makeUnexpected(NonTrivialDtor()); } |
400 | EXPECT_EQ(NonTrivialDtor::count, 8); |
401 | { VN vn; } |
402 | EXPECT_EQ(NonTrivialDtor::count, 8); |
403 | { VN vn = makeUnexpected(NonTrivialDtor()); } |
404 | EXPECT_EQ(NonTrivialDtor::count, 11); |
405 | } |
406 | |
407 | static int snowflakes = 0; |
408 | static int melted = 0; |
409 | struct snowflake { |
410 | static void reset() { snowflakes = melted = 0; } |
411 | snowflake() { ++snowflakes; } |
412 | ~snowflake() { ++melted; } |
413 | }; |
414 | |
415 | TEST(WTF_Expected, unique_ptr) |
416 | { |
417 | // Unique snowflakes cannot be copied. |
418 | { |
419 | auto s = makeUnexpected(std::make_unique<snowflake>()); |
420 | EXPECT_EQ(snowflakes, 1); |
421 | EXPECT_EQ(melted, 0); |
422 | } |
423 | EXPECT_EQ(snowflakes, 1); |
424 | EXPECT_EQ(melted, 1); |
425 | snowflake::reset(); |
426 | |
427 | { |
428 | auto s = makeUnexpected(std::make_unique<snowflake>()); |
429 | Unexpected<std::unique_ptr<snowflake>> c(WTFMove(s)); |
430 | EXPECT_EQ(snowflakes, 1); |
431 | EXPECT_EQ(melted, 0); |
432 | } |
433 | EXPECT_EQ(snowflakes, 1); |
434 | EXPECT_EQ(melted, 1); |
435 | snowflake::reset(); |
436 | |
437 | auto plow = [] (std::unique_ptr<snowflake>&& s) |
438 | { |
439 | { |
440 | std::unique_ptr<snowflake> moved = WTFMove(s); |
441 | EXPECT_EQ(snowflakes, 1); |
442 | EXPECT_EQ(melted, 0); |
443 | } |
444 | EXPECT_EQ(snowflakes, 1); |
445 | EXPECT_EQ(melted, 1); |
446 | }; |
447 | |
448 | { |
449 | Expected<std::unique_ptr<snowflake>, int> s(std::make_unique<snowflake>()); |
450 | plow(WTFMove(s).value()); |
451 | } |
452 | EXPECT_EQ(snowflakes, 1); |
453 | EXPECT_EQ(melted, 1); |
454 | snowflake::reset(); |
455 | |
456 | { |
457 | Expected<int, std::unique_ptr<snowflake>> s(makeUnexpected(std::make_unique<snowflake>())); |
458 | plow(WTFMove(s).error()); |
459 | } |
460 | EXPECT_EQ(snowflakes, 1); |
461 | EXPECT_EQ(melted, 1); |
462 | snowflake::reset(); |
463 | |
464 | { |
465 | Expected<void, std::unique_ptr<snowflake>> s(makeUnexpected(std::make_unique<snowflake>())); |
466 | plow(WTFMove(s).error()); |
467 | } |
468 | EXPECT_EQ(snowflakes, 1); |
469 | EXPECT_EQ(melted, 1); |
470 | snowflake::reset(); |
471 | } |
472 | |
473 | TEST(WTF_Expected, Ref) |
474 | { |
475 | { |
476 | RefLogger a("a" ); |
477 | Expected<Ref<RefLogger>, int> expected = Ref<RefLogger>(a); |
478 | EXPECT_TRUE(expected.has_value()); |
479 | EXPECT_EQ(&a, expected.value().ptr()); |
480 | } |
481 | |
482 | ASSERT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
483 | |
484 | { |
485 | RefLogger a("a" ); |
486 | Expected<Ref<RefLogger>, int> expected = Expected<Ref<RefLogger>, int>(Ref<RefLogger>(a)); |
487 | EXPECT_TRUE(expected.has_value()); |
488 | EXPECT_EQ(&a, expected.value().ptr()); |
489 | } |
490 | |
491 | ASSERT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
492 | |
493 | { |
494 | RefLogger a("a" ); |
495 | Expected<int, Ref<RefLogger>> expected = makeUnexpected(Ref<RefLogger>(a)); |
496 | EXPECT_FALSE(expected.has_value()); |
497 | EXPECT_EQ(&a, expected.error().ptr()); |
498 | } |
499 | |
500 | ASSERT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
501 | |
502 | { |
503 | RefLogger a("a" ); |
504 | Expected<void, Ref<RefLogger>> expected = makeUnexpected(Ref<RefLogger>(a)); |
505 | EXPECT_FALSE(expected.has_value()); |
506 | EXPECT_EQ(&a, expected.error().ptr()); |
507 | } |
508 | |
509 | ASSERT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
510 | } |
511 | |
512 | class NeedsStdAddress { |
513 | public: |
514 | NeedsStdAddress(NeedsStdAddress&& other) |
515 | : m_ptr(WTFMove(other.m_ptr)) { } |
516 | NeedsStdAddress(int& other) |
517 | : m_ptr(&other) { } |
518 | int* operator&() { ASSERT_NOT_REACHED(); return nullptr; } |
519 | private: |
520 | std::unique_ptr<int> m_ptr; |
521 | }; |
522 | |
523 | TEST(WTF_Expected, Address) |
524 | { |
525 | NeedsStdAddress a(*new int(3)); |
526 | Expected<NeedsStdAddress, float> b(WTFMove(a)); |
527 | Expected<NeedsStdAddress, float> c(WTFMove(b)); |
528 | (void)c; |
529 | } |
530 | |
531 | } // namespace TestWebkitAPI |
532 | |