OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include <sstream> | |
12 #include <string> | |
13 #include <utility> | |
14 #include <vector> | |
15 | |
16 #include "webrtc/base/gunit.h" | |
17 #include "webrtc/base/maybe.h" | |
18 | |
19 namespace rtc { | |
20 | |
21 namespace { | |
22 | |
23 // Class whose instances logs various method calls (constructor, destructor, | |
24 // etc.). Each instance has a unique ID (a simple global sequence number) and | |
25 // an origin ID. When a copy is made, the new object gets a fresh ID but copies | |
26 // the origin ID from the original. When a new Logger is created from scratch, | |
27 // it gets a fresh ID, and the origin ID is the same as the ID (default | |
28 // constructor) or given as an argument (explicit constructor). | |
29 class Logger { | |
30 public: | |
31 Logger() : id_(next_id_++), origin_(id_) { Log("default constructor"); } | |
32 explicit Logger(int origin) : id_(next_id_++), origin_(origin) { | |
33 Log("explicit constructor"); | |
34 } | |
35 Logger(const Logger& other) : id_(next_id_++), origin_(other.origin_) { | |
36 LogFrom("copy constructor", other); | |
37 } | |
38 Logger(Logger&& other) : id_(next_id_++), origin_(other.origin_) { | |
39 LogFrom("move constructor", other); | |
40 } | |
41 ~Logger() { Log("destructor"); } | |
42 Logger& operator=(const Logger& other) { | |
43 origin_ = other.origin_; | |
44 LogFrom("operator= copy", other); | |
45 return *this; | |
46 } | |
47 Logger& operator=(Logger&& other) { | |
48 origin_ = other.origin_; | |
49 LogFrom("operator= move", other); | |
50 return *this; | |
51 } | |
52 friend void swap(Logger& a, Logger& b) { | |
53 using std::swap; | |
54 swap(a.origin_, b.origin_); | |
55 Log2("swap", a, b); | |
56 } | |
57 friend bool operator==(const Logger& a, const Logger& b) { | |
58 Log2("operator==", a, b); | |
59 return a.origin_ == b.origin_; | |
60 } | |
61 friend bool operator!=(const Logger& a, const Logger& b) { | |
62 Log2("operator!=", a, b); | |
63 return a.origin_ != b.origin_; | |
64 } | |
65 void Foo() { Log("Foo()"); } | |
66 void Foo() const { Log("Foo() const"); } | |
67 static rtc::scoped_ptr<std::vector<std::string>> Setup() { | |
68 auto s = rtc_make_scoped_ptr(new std::vector<std::string>); | |
69 Logger::log_ = s.get(); | |
70 Logger::next_id_ = 0; | |
71 return s; | |
72 } | |
73 | |
74 private: | |
75 int id_; | |
76 int origin_; | |
77 static std::vector<std::string>* log_; | |
78 static int next_id_; | |
79 void Log(const char* msg) const { | |
80 std::ostringstream oss; | |
81 oss << id_ << ':' << origin_ << ". " << msg; | |
82 log_->push_back(oss.str()); | |
83 } | |
84 void LogFrom(const char* msg, const Logger& other) const { | |
85 std::ostringstream oss; | |
86 oss << id_ << ':' << origin_ << ". " << msg << " (from " << other.id_ << ':' | |
87 << other.origin_ << ")"; | |
88 log_->push_back(oss.str()); | |
89 } | |
90 static void Log2(const char* msg, const Logger& a, const Logger& b) { | |
91 std::ostringstream oss; | |
92 oss << msg << ' ' << a.id_ << ':' << a.origin_ << ", " << b.id_ << ':' | |
93 << b.origin_; | |
94 log_->push_back(oss.str()); | |
95 } | |
96 }; | |
97 | |
98 std::vector<std::string>* Logger::log_ = nullptr; | |
99 int Logger::next_id_ = 0; | |
100 | |
101 // Append all the other args to the vector pointed to by the first arg. | |
102 template <typename T> | |
103 void VectorAppend(std::vector<T>* v) {} | |
104 template <typename T, typename... Ts> | |
105 void VectorAppend(std::vector<T>* v, const T& e, Ts... es) { | |
106 v->push_back(e); | |
107 VectorAppend(v, es...); | |
108 } | |
109 | |
110 // Create a vector of strings. Because we're not allowed to use | |
111 // std::initializer_list. | |
112 template <typename... Ts> | |
113 std::vector<std::string> V(Ts... es) { | |
114 std::vector<std::string> strings; | |
115 VectorAppend(&strings, static_cast<std::string>(es)...); | |
116 return strings; | |
117 } | |
118 | |
119 } // namespace | |
120 | |
121 TEST(MaybeTest, TestConstructDefault) { | |
122 auto log = Logger::Setup(); | |
123 { | |
124 Maybe<Logger> x; | |
125 EXPECT_FALSE(x); | |
126 } | |
127 EXPECT_EQ(V("0:0. default constructor", "0:0. destructor"), *log); | |
128 } | |
129 | |
130 TEST(MaybeTest, TestConstructCopyEmpty) { | |
131 auto log = Logger::Setup(); | |
132 { | |
133 Maybe<Logger> x; | |
134 EXPECT_FALSE(x); | |
135 auto y = x; | |
136 EXPECT_FALSE(y); | |
137 } | |
138 EXPECT_EQ(V("0:0. default constructor", "1:0. copy constructor (from 0:0)", | |
139 "1:0. destructor", "0:0. destructor"), | |
140 *log); | |
141 } | |
142 | |
143 TEST(MaybeTest, TestConstructCopyFull) { | |
144 auto log = Logger::Setup(); | |
145 { | |
146 Logger a; | |
147 Maybe<Logger> x(a); | |
148 EXPECT_TRUE(x); | |
149 log->push_back("---"); | |
150 auto y = x; | |
151 EXPECT_TRUE(y); | |
152 log->push_back("---"); | |
153 } | |
154 EXPECT_EQ(V("0:0. default constructor", "1:0. copy constructor (from 0:0)", | |
155 "---", "2:0. copy constructor (from 1:0)", "---", | |
156 "2:0. destructor", "1:0. destructor", "0:0. destructor"), | |
157 *log); | |
158 } | |
159 | |
160 TEST(MaybeTest, TestConstructMoveEmpty) { | |
161 auto log = Logger::Setup(); | |
162 { | |
163 Maybe<Logger> x; | |
164 EXPECT_FALSE(x); | |
165 auto y = static_cast<Maybe<Logger>&&>(x); | |
166 EXPECT_FALSE(y); | |
167 } | |
168 EXPECT_EQ(V("0:0. default constructor", "1:0. move constructor (from 0:0)", | |
169 "1:0. destructor", "0:0. destructor"), | |
170 *log); | |
171 } | |
172 | |
173 TEST(MaybeTest, TestConstructMoveFull) { | |
174 auto log = Logger::Setup(); | |
175 { | |
176 Maybe<Logger> x(Logger(17)); | |
177 EXPECT_TRUE(x); | |
178 log->push_back("---"); | |
179 auto y = static_cast<Maybe<Logger>&&>(x); | |
180 EXPECT_TRUE(x); | |
181 EXPECT_TRUE(y); | |
182 log->push_back("---"); | |
183 } | |
184 EXPECT_EQ( | |
185 V("0:17. explicit constructor", "1:17. move constructor (from 0:17)", | |
186 "0:17. destructor", "---", "2:17. move constructor (from 1:17)", "---", | |
187 "2:17. destructor", "1:17. destructor"), | |
188 *log); | |
189 } | |
190 | |
191 TEST(MaybeTest, TestCopyAssignToEmptyFromEmpty) { | |
192 auto log = Logger::Setup(); | |
193 { | |
194 Maybe<Logger> x, y; | |
195 x = y; | |
196 } | |
197 EXPECT_EQ( | |
198 V("0:0. default constructor", "1:1. default constructor", | |
199 "0:1. operator= copy (from 1:1)", "1:1. destructor", "0:1. destructor"), | |
200 *log); | |
201 } | |
202 | |
203 TEST(MaybeTest, TestCopyAssignToFullFromEmpty) { | |
204 auto log = Logger::Setup(); | |
205 { | |
206 Maybe<Logger> x(Logger(17)); | |
207 Maybe<Logger> y; | |
208 log->push_back("---"); | |
209 x = y; | |
210 log->push_back("---"); | |
211 } | |
212 EXPECT_EQ( | |
213 V("0:17. explicit constructor", "1:17. move constructor (from 0:17)", | |
214 "0:17. destructor", "2:2. default constructor", "---", | |
215 "1:2. operator= copy (from 2:2)", "---", "2:2. destructor", | |
216 "1:2. destructor"), | |
217 *log); | |
218 } | |
219 | |
220 TEST(MaybeTest, TestCopyAssignToEmptyFromFull) { | |
221 auto log = Logger::Setup(); | |
222 { | |
223 Maybe<Logger> x; | |
224 Maybe<Logger> y(Logger(17)); | |
225 log->push_back("---"); | |
226 x = y; | |
227 log->push_back("---"); | |
228 } | |
229 EXPECT_EQ(V("0:0. default constructor", "1:17. explicit constructor", | |
230 "2:17. move constructor (from 1:17)", "1:17. destructor", "---", | |
231 "0:17. operator= copy (from 2:17)", "---", "2:17. destructor", | |
232 "0:17. destructor"), | |
233 *log); | |
234 } | |
235 | |
236 TEST(MaybeTest, TestCopyAssignToFullFromFull) { | |
237 auto log = Logger::Setup(); | |
238 { | |
239 Maybe<Logger> x(Logger(17)); | |
240 Maybe<Logger> y(Logger(42)); | |
241 log->push_back("---"); | |
242 x = y; | |
243 log->push_back("---"); | |
244 } | |
245 EXPECT_EQ( | |
246 V("0:17. explicit constructor", "1:17. move constructor (from 0:17)", | |
247 "0:17. destructor", "2:42. explicit constructor", | |
248 "3:42. move constructor (from 2:42)", "2:42. destructor", "---", | |
249 "1:42. operator= copy (from 3:42)", "---", "3:42. destructor", | |
250 "1:42. destructor"), | |
251 *log); | |
252 } | |
253 | |
254 TEST(MaybeTest, TestCopyAssignToEmptyFromT) { | |
255 auto log = Logger::Setup(); | |
256 { | |
257 Maybe<Logger> x; | |
258 Logger y(17); | |
259 log->push_back("---"); | |
260 x = rtc::Maybe<Logger>(y); | |
261 log->push_back("---"); | |
262 } | |
263 EXPECT_EQ(V("0:0. default constructor", "1:17. explicit constructor", "---", | |
264 "2:17. copy constructor (from 1:17)", | |
265 "0:17. operator= move (from 2:17)", "2:17. destructor", "---", | |
266 "1:17. destructor", "0:17. destructor"), | |
267 *log); | |
268 } | |
269 | |
270 TEST(MaybeTest, TestCopyAssignToFullFromT) { | |
271 auto log = Logger::Setup(); | |
272 { | |
273 Maybe<Logger> x(Logger(17)); | |
274 Logger y(42); | |
275 log->push_back("---"); | |
276 x = rtc::Maybe<Logger>(y); | |
277 log->push_back("---"); | |
278 } | |
279 EXPECT_EQ( | |
280 V("0:17. explicit constructor", "1:17. move constructor (from 0:17)", | |
281 "0:17. destructor", "2:42. explicit constructor", "---", | |
282 "3:42. copy constructor (from 2:42)", | |
283 "1:42. operator= move (from 3:42)", "3:42. destructor", "---", | |
284 "2:42. destructor", "1:42. destructor"), | |
285 *log); | |
286 } | |
287 | |
288 TEST(MaybeTest, TestMoveAssignToEmptyFromEmpty) { | |
289 auto log = Logger::Setup(); | |
290 { | |
291 Maybe<Logger> x, y; | |
292 x = static_cast<Maybe<Logger>&&>(y); | |
293 } | |
294 EXPECT_EQ( | |
295 V("0:0. default constructor", "1:1. default constructor", | |
296 "0:1. operator= move (from 1:1)", "1:1. destructor", "0:1. destructor"), | |
297 *log); | |
298 } | |
299 | |
300 TEST(MaybeTest, TestMoveAssignToFullFromEmpty) { | |
301 auto log = Logger::Setup(); | |
302 { | |
303 Maybe<Logger> x(Logger(17)); | |
304 Maybe<Logger> y; | |
305 log->push_back("---"); | |
306 x = static_cast<Maybe<Logger>&&>(y); | |
307 log->push_back("---"); | |
308 } | |
309 EXPECT_EQ( | |
310 V("0:17. explicit constructor", "1:17. move constructor (from 0:17)", | |
311 "0:17. destructor", "2:2. default constructor", "---", | |
312 "1:2. operator= move (from 2:2)", "---", "2:2. destructor", | |
313 "1:2. destructor"), | |
314 *log); | |
315 } | |
316 | |
317 TEST(MaybeTest, TestMoveAssignToEmptyFromFull) { | |
318 auto log = Logger::Setup(); | |
319 { | |
320 Maybe<Logger> x; | |
321 Maybe<Logger> y(Logger(17)); | |
322 log->push_back("---"); | |
323 x = static_cast<Maybe<Logger>&&>(y); | |
324 log->push_back("---"); | |
325 } | |
326 EXPECT_EQ(V("0:0. default constructor", "1:17. explicit constructor", | |
327 "2:17. move constructor (from 1:17)", "1:17. destructor", "---", | |
328 "0:17. operator= move (from 2:17)", "---", "2:17. destructor", | |
329 "0:17. destructor"), | |
330 *log); | |
331 } | |
332 | |
333 TEST(MaybeTest, TestMoveAssignToFullFromFull) { | |
334 auto log = Logger::Setup(); | |
335 { | |
336 Maybe<Logger> x(Logger(17)); | |
337 Maybe<Logger> y(Logger(42)); | |
338 log->push_back("---"); | |
339 x = static_cast<Maybe<Logger>&&>(y); | |
340 log->push_back("---"); | |
341 } | |
342 EXPECT_EQ( | |
343 V("0:17. explicit constructor", "1:17. move constructor (from 0:17)", | |
344 "0:17. destructor", "2:42. explicit constructor", | |
345 "3:42. move constructor (from 2:42)", "2:42. destructor", "---", | |
346 "1:42. operator= move (from 3:42)", "---", "3:42. destructor", | |
347 "1:42. destructor"), | |
348 *log); | |
349 } | |
350 | |
351 TEST(MaybeTest, TestMoveAssignToEmptyFromT) { | |
352 auto log = Logger::Setup(); | |
353 { | |
354 Maybe<Logger> x; | |
355 Logger y(17); | |
356 log->push_back("---"); | |
357 x = rtc::Maybe<Logger>(static_cast<Logger&&>(y)); | |
358 log->push_back("---"); | |
359 } | |
360 EXPECT_EQ(V("0:0. default constructor", "1:17. explicit constructor", "---", | |
361 "2:17. move constructor (from 1:17)", | |
362 "0:17. operator= move (from 2:17)", "2:17. destructor", "---", | |
363 "1:17. destructor", "0:17. destructor"), | |
364 *log); | |
365 } | |
366 | |
367 TEST(MaybeTest, TestMoveAssignToFullFromT) { | |
368 auto log = Logger::Setup(); | |
369 { | |
370 Maybe<Logger> x(Logger(17)); | |
371 Logger y(42); | |
372 log->push_back("---"); | |
373 x = rtc::Maybe<Logger>(static_cast<Logger&&>(y)); | |
374 log->push_back("---"); | |
375 } | |
376 EXPECT_EQ( | |
377 V("0:17. explicit constructor", "1:17. move constructor (from 0:17)", | |
378 "0:17. destructor", "2:42. explicit constructor", "---", | |
379 "3:42. move constructor (from 2:42)", | |
380 "1:42. operator= move (from 3:42)", "3:42. destructor", "---", | |
381 "2:42. destructor", "1:42. destructor"), | |
382 *log); | |
383 } | |
384 | |
385 TEST(MaybeTest, TestDereference) { | |
386 auto log = Logger::Setup(); | |
387 { | |
388 Maybe<Logger> x(Logger(42)); | |
389 const auto& y = x; | |
390 log->push_back("---"); | |
391 x->Foo(); | |
392 y->Foo(); | |
393 static_cast<Maybe<Logger>&&>(x)->Foo(); | |
394 static_cast<const Maybe<Logger>&&>(y)->Foo(); | |
395 log->push_back("---"); | |
396 (*x).Foo(); | |
397 (*y).Foo(); | |
398 (*static_cast<Maybe<Logger>&&>(x)).Foo(); | |
399 (*static_cast<const Maybe<Logger>&&>(y)).Foo(); | |
400 log->push_back("---"); | |
401 } | |
402 EXPECT_EQ(V("0:42. explicit constructor", | |
403 "1:42. move constructor (from 0:42)", "0:42. destructor", "---", | |
404 "1:42. Foo()", "1:42. Foo() const", "1:42. Foo()", | |
405 "1:42. Foo() const", "---", "1:42. Foo()", "1:42. Foo() const", | |
406 "1:42. Foo()", "1:42. Foo() const", "---", "1:42. destructor"), | |
407 *log); | |
408 } | |
409 | |
410 TEST(MaybeTest, TestDereferenceWithDefault) { | |
411 auto log = Logger::Setup(); | |
412 { | |
413 const Logger a(17), b(42); | |
414 Maybe<Logger> x(a); | |
415 Maybe<Logger> y; | |
416 log->push_back("-1-"); | |
417 EXPECT_EQ(a, x.value_or(Logger(42))); | |
418 log->push_back("-2-"); | |
419 EXPECT_EQ(b, y.value_or(Logger(42))); | |
420 log->push_back("-3-"); | |
421 EXPECT_EQ(a, Maybe<Logger>(Logger(17)).value_or(b)); | |
422 log->push_back("-4-"); | |
423 EXPECT_EQ(b, Maybe<Logger>().value_or(b)); | |
424 log->push_back("-5-"); | |
425 } | |
426 EXPECT_EQ( | |
427 V("0:17. explicit constructor", "1:42. explicit constructor", | |
428 "2:17. copy constructor (from 0:17)", "3:3. default constructor", "-1-", | |
429 "4:42. explicit constructor", "operator== 0:17, 2:17", | |
430 "4:42. destructor", "-2-", "5:42. explicit constructor", | |
431 "operator== 1:42, 5:42", "5:42. destructor", "-3-", | |
432 "6:17. explicit constructor", "7:17. move constructor (from 6:17)", | |
433 "operator== 0:17, 7:17", "7:17. destructor", "6:17. destructor", "-4-", | |
434 "8:8. default constructor", "operator== 1:42, 1:42", "8:8. destructor", | |
435 "-5-", "3:3. destructor", "2:17. destructor", "1:42. destructor", | |
436 "0:17. destructor"), | |
437 *log); | |
438 } | |
439 | |
440 TEST(MaybeTest, TestEquality) { | |
441 auto log = Logger::Setup(); | |
442 { | |
443 Logger a(17), b(42); | |
444 Maybe<Logger> ma1(a), ma2(a), mb(b), me1, me2; | |
445 log->push_back("---"); | |
446 EXPECT_EQ(ma1, ma1); | |
447 EXPECT_EQ(ma1, ma2); | |
448 EXPECT_NE(ma1, mb); | |
449 EXPECT_NE(ma1, me1); | |
450 EXPECT_EQ(me1, me1); | |
451 EXPECT_EQ(me1, me2); | |
452 log->push_back("---"); | |
453 } | |
454 EXPECT_EQ(V("0:17. explicit constructor", "1:42. explicit constructor", | |
455 "2:17. copy constructor (from 0:17)", | |
456 "3:17. copy constructor (from 0:17)", | |
457 "4:42. copy constructor (from 1:42)", "5:5. default constructor", | |
458 "6:6. default constructor", "---", "operator== 2:17, 2:17", | |
459 "operator== 2:17, 3:17", "operator!= 2:17, 4:42", "---", | |
460 "6:6. destructor", "5:5. destructor", "4:42. destructor", | |
461 "3:17. destructor", "2:17. destructor", "1:42. destructor", | |
462 "0:17. destructor"), | |
463 *log); | |
464 } | |
465 | |
466 TEST(MaybeTest, TestSwap) { | |
467 auto log = Logger::Setup(); | |
468 { | |
469 Logger a(17), b(42); | |
470 Maybe<Logger> x1(a), x2(b), y1(a), y2, z1, z2; | |
471 log->push_back("---"); | |
472 swap(x1, x2); // Swap full <-> full. | |
473 swap(y1, y2); // Swap full <-> empty. | |
474 swap(z1, z2); // Swap empty <-> empty. | |
475 log->push_back("---"); | |
476 } | |
477 EXPECT_EQ(V("0:17. explicit constructor", "1:42. explicit constructor", | |
478 "2:17. copy constructor (from 0:17)", | |
479 "3:42. copy constructor (from 1:42)", | |
480 "4:17. copy constructor (from 0:17)", "5:5. default constructor", | |
481 "6:6. default constructor", "7:7. default constructor", "---", | |
482 "swap 2:42, 3:17", "swap 4:5, 5:17", "swap 6:7, 7:6", "---", | |
483 "7:6. destructor", "6:7. destructor", "5:17. destructor", | |
484 "4:5. destructor", "3:17. destructor", "2:42. destructor", | |
485 "1:42. destructor", "0:17. destructor"), | |
486 *log); | |
487 } | |
488 | |
489 } // namespace rtc | |
OLD | NEW |