// Exercise some basic codepaths ensuring registration order and // destruction order happen as expected, that instances are created // when expected, etc etc. TEST(Singleton, BasicUsage) { SingletonVault vault; EXPECT_EQ(vault.registeredSingletonCount(), 0); Singleton<Watchdog> watchdog_singleton(nullptr, nullptr, &vault); EXPECT_EQ(vault.registeredSingletonCount(), 1); Singleton<ChildWatchdog> child_watchdog_singleton(nullptr, nullptr, &vault); EXPECT_EQ(vault.registeredSingletonCount(), 2); vault.registrationComplete(); Watchdog* s1 = Singleton<Watchdog>::get(&vault); EXPECT_NE(s1, nullptr); Watchdog* s2 = Singleton<Watchdog>::get(&vault); EXPECT_NE(s2, nullptr); EXPECT_EQ(s1, s2); auto s3 = Singleton<ChildWatchdog>::get(&vault); EXPECT_NE(s3, nullptr); EXPECT_NE(s2, s3); EXPECT_EQ(vault.registeredSingletonCount(), 2); EXPECT_EQ(vault.livingSingletonCount(), 2); vault.destroyInstances(); EXPECT_EQ(vault.registeredSingletonCount(), 2); EXPECT_EQ(vault.livingSingletonCount(), 0); }
TEST(Singleton, SharedPtrUsage) { SingletonVault vault; EXPECT_EQ(vault.registeredSingletonCount(), 0); Singleton<Watchdog> watchdog_singleton(nullptr, nullptr, &vault); EXPECT_EQ(vault.registeredSingletonCount(), 1); Singleton<ChildWatchdog> child_watchdog_singleton(nullptr, nullptr, &vault); EXPECT_EQ(vault.registeredSingletonCount(), 2); vault.registrationComplete(); Watchdog* s1 = Singleton<Watchdog>::get(&vault); EXPECT_NE(s1, nullptr); Watchdog* s2 = Singleton<Watchdog>::get(&vault); EXPECT_NE(s2, nullptr); EXPECT_EQ(s1, s2); auto weak_s1 = Singleton<Watchdog>::get_weak(&vault); auto shared_s1 = weak_s1.lock(); EXPECT_EQ(shared_s1.get(), s1); EXPECT_EQ(shared_s1.use_count(), 2); LOG(ERROR) << "The following log message regarding ref counts is expected"; vault.destroyInstances(); EXPECT_EQ(vault.registeredSingletonCount(), 2); EXPECT_EQ(vault.livingSingletonCount(), 0); EXPECT_EQ(shared_s1.use_count(), 1); EXPECT_EQ(shared_s1.get(), s1); auto locked_s1 = weak_s1.lock(); EXPECT_EQ(locked_s1.get(), s1); EXPECT_EQ(shared_s1.use_count(), 2); locked_s1.reset(); EXPECT_EQ(shared_s1.use_count(), 1); // Track serial number rather than pointer since the memory could be // re-used when we create new_s1. auto old_serial = shared_s1->serial_number; shared_s1.reset(); locked_s1 = weak_s1.lock(); EXPECT_TRUE(weak_s1.expired()); Watchdog* new_s1 = Singleton<Watchdog>::get(&vault); EXPECT_NE(new_s1->serial_number, old_serial); }