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/optional.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(OptionalTest, TestConstructDefault) { 122 auto log = Logger::Setup(); 123 { 124 Optional<Logger> x; 125 EXPECT_FALSE(x); 126 } 127 EXPECT_EQ(V("0:0. default constructor", "0:0. destructor"), *log); 128 } 129 130 TEST(OptionalTest, TestConstructCopyEmpty) { 131 auto log = Logger::Setup(); 132 { 133 Optional<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(OptionalTest, TestConstructCopyFull) { 144 auto log = Logger::Setup(); 145 { 146 Logger a; 147 Optional<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(OptionalTest, TestConstructMoveEmpty) { 161 auto log = Logger::Setup(); 162 { 163 Optional<Logger> x; 164 EXPECT_FALSE(x); 165 auto y = std::move(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(OptionalTest, TestConstructMoveFull) { 174 auto log = Logger::Setup(); 175 { 176 Optional<Logger> x(Logger(17)); 177 EXPECT_TRUE(x); 178 log->push_back("---"); 179 auto y = std::move(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(OptionalTest, TestCopyAssignToEmptyFromEmpty) { 192 auto log = Logger::Setup(); 193 { 194 Optional<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(OptionalTest, TestCopyAssignToFullFromEmpty) { 204 auto log = Logger::Setup(); 205 { 206 Optional<Logger> x(Logger(17)); 207 Optional<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(OptionalTest, TestCopyAssignToEmptyFromFull) { 221 auto log = Logger::Setup(); 222 { 223 Optional<Logger> x; 224 Optional<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(OptionalTest, TestCopyAssignToFullFromFull) { 237 auto log = Logger::Setup(); 238 { 239 Optional<Logger> x(Logger(17)); 240 Optional<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(OptionalTest, TestCopyAssignToEmptyFromT) { 255 auto log = Logger::Setup(); 256 { 257 Optional<Logger> x; 258 Logger y(17); 259 log->push_back("---"); 260 x = Optional<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(OptionalTest, TestCopyAssignToFullFromT) { 271 auto log = Logger::Setup(); 272 { 273 Optional<Logger> x(Logger(17)); 274 Logger y(42); 275 log->push_back("---"); 276 x = Optional<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(OptionalTest, TestMoveAssignToEmptyFromEmpty) { 289 auto log = Logger::Setup(); 290 { 291 Optional<Logger> x, y; 292 x = std::move(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(OptionalTest, TestMoveAssignToFullFromEmpty) { 301 auto log = Logger::Setup(); 302 { 303 Optional<Logger> x(Logger(17)); 304 Optional<Logger> y; 305 log->push_back("---"); 306 x = std::move(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(OptionalTest, TestMoveAssignToEmptyFromFull) { 318 auto log = Logger::Setup(); 319 { 320 Optional<Logger> x; 321 Optional<Logger> y(Logger(17)); 322 log->push_back("---"); 323 x = std::move(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(OptionalTest, TestMoveAssignToFullFromFull) { 334 auto log = Logger::Setup(); 335 { 336 Optional<Logger> x(Logger(17)); 337 Optional<Logger> y(Logger(42)); 338 log->push_back("---"); 339 x = std::move(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(OptionalTest, TestMoveAssignToEmptyFromT) { 352 auto log = Logger::Setup(); 353 { 354 Optional<Logger> x; 355 Logger y(17); 356 log->push_back("---"); 357 x = Optional<Logger>(std::move(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(OptionalTest, TestMoveAssignToFullFromT) { 368 auto log = Logger::Setup(); 369 { 370 Optional<Logger> x(Logger(17)); 371 Logger y(42); 372 log->push_back("---"); 373 x = Optional<Logger>(std::move(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(OptionalTest, TestDereference) { 386 auto log = Logger::Setup(); 387 { 388 Optional<Logger> x(Logger(42)); 389 const auto& y = x; 390 log->push_back("---"); 391 x->Foo(); 392 y->Foo(); 393 std::move(x)->Foo(); 394 std::move(y)->Foo(); 395 log->push_back("---"); 396 (*x).Foo(); 397 (*y).Foo(); 398 (*std::move(x)).Foo(); 399 (*std::move(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(OptionalTest, TestDereferenceWithDefault) { 411 auto log = Logger::Setup(); 412 { 413 const Logger a(17), b(42); 414 Optional<Logger> x(a); 415 Optional<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, Optional<Logger>(Logger(17)).value_or(b)); 422 log->push_back("-4-"); 423 EXPECT_EQ(b, Optional<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(OptionalTest, TestEquality) { 441 auto log = Logger::Setup(); 442 { 443 Logger a(17), b(42); 444 Optional<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(OptionalTest, TestSwap) { 467 auto log = Logger::Setup(); 468 { 469 Logger a(17), b(42); 470 Optional<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 490