2 * Copyright 2016 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <folly/Singleton.h>
20 #include <folly/io/async/EventBase.h>
21 #include <folly/test/SingletonTestStructs.h>
23 #include <glog/logging.h>
24 #include <gtest/gtest.h>
25 #include <boost/thread/barrier.hpp>
27 using namespace folly;
29 TEST(Singleton, MissingSingleton) {
30 EXPECT_DEATH([]() { auto u = Singleton<UnregisteredWatchdog>::try_get(); }(),
34 struct BasicUsageTag {};
35 template <typename T, typename Tag = detail::DefaultTag>
36 using SingletonBasicUsage = Singleton <T, Tag, BasicUsageTag>;
38 // Exercise some basic codepaths ensuring registration order and
39 // destruction order happen as expected, that instances are created
40 // when expected, etc etc.
41 TEST(Singleton, BasicUsage) {
42 auto& vault = *SingletonVault::singleton<BasicUsageTag>();
44 EXPECT_EQ(vault.registeredSingletonCount(), 0);
45 SingletonBasicUsage<Watchdog> watchdog_singleton;
46 EXPECT_EQ(vault.registeredSingletonCount(), 1);
48 SingletonBasicUsage<ChildWatchdog> child_watchdog_singleton;
49 EXPECT_EQ(vault.registeredSingletonCount(), 2);
51 vault.registrationComplete();
53 // limit a scope to release references so we can destroy them later
55 std::shared_ptr<Watchdog> s1 = SingletonBasicUsage<Watchdog>::try_get();
56 EXPECT_NE(s1, nullptr);
58 std::shared_ptr<Watchdog> s2 = SingletonBasicUsage<Watchdog>::try_get();
59 EXPECT_NE(s2, nullptr);
62 EXPECT_EQ(s1.get(), SingletonBasicUsage<Watchdog>::try_get_fast().get());
64 std::shared_ptr<ChildWatchdog> s3 =
65 SingletonBasicUsage<ChildWatchdog>::try_get();
66 EXPECT_NE(s3, nullptr);
69 EXPECT_EQ(vault.registeredSingletonCount(), 2);
70 EXPECT_EQ(vault.livingSingletonCount(), 2);
73 vault.destroyInstances();
74 EXPECT_EQ(vault.registeredSingletonCount(), 2);
75 EXPECT_EQ(vault.livingSingletonCount(), 0);
78 struct DirectUsageTag {};
79 template <typename T, typename Tag = detail::DefaultTag>
80 using SingletonDirectUsage = Singleton <T, Tag, DirectUsageTag>;
82 TEST(Singleton, DirectUsage) {
83 auto& vault = *SingletonVault::singleton<DirectUsageTag>();
85 EXPECT_EQ(vault.registeredSingletonCount(), 0);
87 // Verify we can get to the underlying singletons via directly using
88 // the singleton definition.
89 SingletonDirectUsage<Watchdog> watchdog;
91 SingletonDirectUsage<Watchdog, TestTag> named_watchdog;
92 EXPECT_EQ(vault.registeredSingletonCount(), 2);
93 vault.registrationComplete();
95 EXPECT_NE(watchdog.try_get(), nullptr);
96 EXPECT_EQ(watchdog.try_get(), SingletonDirectUsage<Watchdog>::try_get());
97 EXPECT_NE(watchdog.try_get(), named_watchdog.try_get());
98 EXPECT_EQ(watchdog.try_get()->livingWatchdogCount(), 2);
100 vault.destroyInstances();
103 struct NamedUsageTag {};
104 template <typename T, typename Tag = detail::DefaultTag>
105 using SingletonNamedUsage = Singleton <T, Tag, NamedUsageTag>;
107 TEST(Singleton, NamedUsage) {
108 auto& vault = *SingletonVault::singleton<NamedUsageTag>();
110 EXPECT_EQ(vault.registeredSingletonCount(), 0);
112 // Define two named Watchdog singletons and one unnamed singleton.
115 typedef detail::DefaultTag Watchdog3;
116 SingletonNamedUsage<Watchdog, Watchdog1> watchdog1_singleton;
117 EXPECT_EQ(vault.registeredSingletonCount(), 1);
118 SingletonNamedUsage<Watchdog, Watchdog2> watchdog2_singleton;
119 EXPECT_EQ(vault.registeredSingletonCount(), 2);
120 SingletonNamedUsage<Watchdog, Watchdog3> watchdog3_singleton;
121 EXPECT_EQ(vault.registeredSingletonCount(), 3);
123 vault.registrationComplete();
125 // Verify our three singletons are distinct and non-nullptr.
126 auto s1 = SingletonNamedUsage<Watchdog, Watchdog1>::try_get();
127 EXPECT_EQ(s1, watchdog1_singleton.try_get());
128 auto s2 = SingletonNamedUsage<Watchdog, Watchdog2>::try_get();
129 EXPECT_EQ(s2, watchdog2_singleton.try_get());
131 auto s3 = SingletonNamedUsage<Watchdog, Watchdog3>::try_get();
132 EXPECT_EQ(s3, watchdog3_singleton.try_get());
136 // Verify the "default" singleton is the same as the DefaultTag-tagged
138 auto s4 = SingletonNamedUsage<Watchdog>::try_get();
139 EXPECT_EQ(s4, watchdog3_singleton.try_get());
142 vault.destroyInstances();
145 struct NaughtyUsageTag {};
146 template <typename T, typename Tag = detail::DefaultTag>
147 using SingletonNaughtyUsage = Singleton <T, Tag, NaughtyUsageTag>;
148 struct NaughtyUsageTag2 {};
149 template <typename T, typename Tag = detail::DefaultTag>
150 using SingletonNaughtyUsage2 = Singleton <T, Tag, NaughtyUsageTag2>;
152 // Some pathological cases such as getting unregistered singletons,
153 // double registration, etc.
154 TEST(Singleton, NaughtyUsage) {
155 auto& vault = *SingletonVault::singleton<NaughtyUsageTag>();
157 vault.registrationComplete();
160 EXPECT_DEATH(Singleton<Watchdog>::try_get(), "");
161 EXPECT_DEATH(SingletonNaughtyUsage<Watchdog>::try_get(), "");
163 vault.destroyInstances();
165 auto& vault2 = *SingletonVault::singleton<NaughtyUsageTag2>();
167 EXPECT_DEATH(SingletonNaughtyUsage2<Watchdog>::try_get(), "");
168 SingletonNaughtyUsage2<Watchdog> watchdog_singleton;
170 // double registration
171 EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> watchdog_singleton; }(),
173 vault2.destroyInstances();
175 // double registration after destroy
176 EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> watchdog_singleton; }(),
180 struct SharedPtrUsageTag {};
181 template <typename T, typename Tag = detail::DefaultTag>
182 using SingletonSharedPtrUsage = Singleton <T, Tag, SharedPtrUsageTag>;
184 // TODO (anob): revisit this test
185 TEST(Singleton, SharedPtrUsage) {
186 struct WatchdogHolder {
189 LOG(ERROR) << "The following log message with stack trace is expected";
193 std::shared_ptr<Watchdog> watchdog;
196 auto& vault = *SingletonVault::singleton<SharedPtrUsageTag>();
198 EXPECT_EQ(vault.registeredSingletonCount(), 0);
199 SingletonSharedPtrUsage<Watchdog> watchdog_singleton;
200 EXPECT_EQ(vault.registeredSingletonCount(), 1);
202 SingletonSharedPtrUsage<ChildWatchdog> child_watchdog_singleton;
203 EXPECT_EQ(vault.registeredSingletonCount(), 2);
206 SingletonSharedPtrUsage<Watchdog, ATag> named_watchdog_singleton;
208 SingletonSharedPtrUsage<WatchdogHolder> watchdog_holder_singleton;
210 vault.registrationComplete();
212 // Initilize holder singleton first, so that it's the last one to be
214 watchdog_holder_singleton.try_get();
216 auto s1 = SingletonSharedPtrUsage<Watchdog>::try_get().get();
217 EXPECT_NE(s1, nullptr);
219 auto s2 = SingletonSharedPtrUsage<Watchdog>::try_get().get();
220 EXPECT_NE(s2, nullptr);
224 auto weak_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
226 auto shared_s1 = weak_s1.lock();
227 EXPECT_EQ(shared_s1.get(), s1);
228 EXPECT_EQ(shared_s1.use_count(), 2);
230 auto old_serial = shared_s1->serial_number;
234 SingletonSharedPtrUsage<Watchdog, ATag>::get_weak();
235 auto locked = named_weak_s1.lock();
236 EXPECT_NE(locked.get(), shared_s1.get());
239 // We should release externally locked shared_ptr, otherwise it will be
241 watchdog_holder_singleton.try_get()->watchdog = std::move(shared_s1);
243 LOG(ERROR) << "The following log message regarding shared_ptr is expected";
245 auto start_time = std::chrono::steady_clock::now();
246 vault.destroyInstances();
247 auto duration = std::chrono::steady_clock::now() - start_time;
248 EXPECT_TRUE(duration > std::chrono::seconds{4} &&
249 duration < std::chrono::seconds{6});
251 EXPECT_EQ(vault.registeredSingletonCount(), 4);
252 EXPECT_EQ(vault.livingSingletonCount(), 0);
254 EXPECT_TRUE(weak_s1.expired());
256 auto empty_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
257 EXPECT_FALSE(empty_s1.lock());
259 vault.reenableInstances();
262 // Singleton should be re-created only after reenableInstances() was called.
263 auto new_s1 = SingletonSharedPtrUsage<Watchdog>::try_get();
264 // Track serial number rather than pointer since the memory could be
265 // re-used when we create new_s1.
266 EXPECT_NE(new_s1->serial_number, old_serial);
269 auto new_s1_weak = SingletonSharedPtrUsage<Watchdog>::get_weak();
270 auto new_s1_shared = new_s1_weak.lock();
271 std::thread t([new_s1_shared]() mutable {
272 std::this_thread::sleep_for(std::chrono::seconds{2});
273 new_s1_shared.reset();
275 new_s1_shared.reset();
277 auto start_time = std::chrono::steady_clock::now();
278 vault.destroyInstances();
279 auto duration = std::chrono::steady_clock::now() - start_time;
280 EXPECT_TRUE(duration > std::chrono::seconds{1} &&
281 duration < std::chrono::seconds{3});
283 EXPECT_TRUE(new_s1_weak.expired());
287 // Some classes to test singleton dependencies. NeedySingleton has a
288 // dependency on NeededSingleton, which happens during its
291 template <typename T, typename Tag = detail::DefaultTag>
292 using SingletonNeedy = Singleton <T, Tag, NeedyTag>;
294 struct NeededSingleton {};
295 struct NeedySingleton {
297 auto unused = SingletonNeedy<NeededSingleton>::try_get();
298 EXPECT_NE(unused, nullptr);
302 // Ensure circular dependencies fail -- a singleton that needs itself, whoops.
303 struct SelfNeedyTag {};
304 template <typename T, typename Tag = detail::DefaultTag>
305 using SingletonSelfNeedy = Singleton <T, Tag, SelfNeedyTag>;
307 struct SelfNeedySingleton {
308 SelfNeedySingleton() {
309 auto unused = SingletonSelfNeedy<SelfNeedySingleton>::try_get();
310 EXPECT_NE(unused, nullptr);
314 TEST(Singleton, SingletonDependencies) {
315 SingletonNeedy<NeededSingleton> needed_singleton;
316 SingletonNeedy<NeedySingleton> needy_singleton;
317 auto& needy_vault = *SingletonVault::singleton<NeedyTag>();
319 needy_vault.registrationComplete();
321 EXPECT_EQ(needy_vault.registeredSingletonCount(), 2);
322 EXPECT_EQ(needy_vault.livingSingletonCount(), 0);
324 auto needy = SingletonNeedy<NeedySingleton>::try_get();
325 EXPECT_EQ(needy_vault.livingSingletonCount(), 2);
327 SingletonSelfNeedy<SelfNeedySingleton> self_needy_singleton;
328 auto& self_needy_vault = *SingletonVault::singleton<SelfNeedyTag>();
330 self_needy_vault.registrationComplete();
331 EXPECT_DEATH([]() { SingletonSelfNeedy<SelfNeedySingleton>::try_get(); }(),
335 // A test to ensure multiple threads contending on singleton creation
336 // properly wait for creation rather than thinking it is a circular
338 class Slowpoke : public Watchdog {
340 Slowpoke() { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
343 struct ConcurrencyTag {};
344 template <typename T, typename Tag = detail::DefaultTag>
345 using SingletonConcurrency = Singleton <T, Tag, ConcurrencyTag>;
347 TEST(Singleton, SingletonConcurrency) {
348 auto& vault = *SingletonVault::singleton<ConcurrencyTag>();
349 SingletonConcurrency<Slowpoke> slowpoke_singleton;
350 vault.registrationComplete();
352 std::mutex gatekeeper;
354 auto func = [&gatekeeper]() {
357 auto unused = SingletonConcurrency<Slowpoke>::try_get();
360 EXPECT_EQ(vault.livingSingletonCount(), 0);
361 std::vector<std::thread> threads;
362 for (int i = 0; i < 100; ++i) {
363 threads.emplace_back(func);
365 // If circular dependency checks fail, the unlock would trigger a
366 // crash. Instead, it succeeds, and we have exactly one living
369 for (auto& t : threads) {
372 EXPECT_EQ(vault.livingSingletonCount(), 1);
375 struct ErrorConstructor {
376 static size_t constructCount_;
378 if ((constructCount_++) == 0) {
379 throw std::runtime_error("first time fails");
383 size_t ErrorConstructor::constructCount_(0);
385 struct CreationErrorTag {};
386 template <typename T, typename Tag = detail::DefaultTag>
387 using SingletonCreationError = Singleton<T, Tag, CreationErrorTag>;
389 TEST(Singleton, SingletonCreationError) {
390 SingletonVault::singleton<CreationErrorTag>();
391 SingletonCreationError<ErrorConstructor> error_once_singleton;
393 // first time should error out
394 EXPECT_THROW(error_once_singleton.try_get(), std::runtime_error);
396 // second time it'll work fine
397 error_once_singleton.try_get();
401 struct ConcurrencyStressTag {};
402 template <typename T, typename Tag = detail::DefaultTag>
403 using SingletonConcurrencyStress = Singleton <T, Tag, ConcurrencyStressTag>;
405 TEST(Singleton, SingletonConcurrencyStress) {
406 auto& vault = *SingletonVault::singleton<ConcurrencyStressTag>();
407 SingletonConcurrencyStress<Slowpoke> slowpoke_singleton;
409 std::vector<std::thread> ts;
410 for (size_t i = 0; i < 100; ++i) {
411 ts.emplace_back([&]() {
412 slowpoke_singleton.try_get();
416 for (size_t i = 0; i < 100; ++i) {
417 std::chrono::milliseconds d(20);
419 std::this_thread::sleep_for(d);
420 vault.destroyInstances();
421 std::this_thread::sleep_for(d);
422 vault.destroyInstances();
431 struct EagerInitSyncTag {};
433 template <typename T, typename Tag = detail::DefaultTag>
434 using SingletonEagerInitSync = Singleton<T, Tag, EagerInitSyncTag>;
435 TEST(Singleton, SingletonEagerInitSync) {
436 auto& vault = *SingletonVault::singleton<EagerInitSyncTag>();
437 bool didEagerInit = false;
438 auto sing = SingletonEagerInitSync<std::string>(
439 [&] {didEagerInit = true; return new std::string("foo"); })
441 vault.registrationComplete();
442 EXPECT_FALSE(didEagerInit);
444 EXPECT_TRUE(didEagerInit);
445 sing.get_weak(); // (avoid compile error complaining about unused var 'sing')
449 struct EagerInitAsyncTag {};
451 template <typename T, typename Tag = detail::DefaultTag>
452 using SingletonEagerInitAsync = Singleton<T, Tag, EagerInitAsyncTag>;
453 TEST(Singleton, SingletonEagerInitAsync) {
454 auto& vault = *SingletonVault::singleton<EagerInitAsyncTag>();
455 bool didEagerInit = false;
456 auto sing = SingletonEagerInitAsync<std::string>(
457 [&] {didEagerInit = true; return new std::string("foo"); })
461 vault.registrationComplete();
462 EXPECT_FALSE(didEagerInit);
463 vault.doEagerInitVia(eb, &done);
466 EXPECT_TRUE(didEagerInit);
467 sing.get_weak(); // (avoid compile error complaining about unused var 'sing')
471 class TestEagerInitParallelExecutor : public folly::Executor {
473 explicit TestEagerInitParallelExecutor(const size_t threadCount) {
474 eventBases_.reserve(threadCount);
475 threads_.reserve(threadCount);
476 for (size_t i = 0; i < threadCount; i++) {
477 eventBases_.push_back(std::make_shared<folly::EventBase>());
478 auto eb = eventBases_.back();
479 threads_.emplace_back(std::make_shared<std::thread>(
480 [eb] { eb->loopForever(); }));
484 virtual ~TestEagerInitParallelExecutor() override {
485 for (auto eb : eventBases_) {
486 eb->runInEventBaseThread([eb] { eb->terminateLoopSoon(); });
488 for (auto thread : threads_) {
493 virtual void add(folly::Func func) override {
494 const auto index = (counter_ ++) % eventBases_.size();
495 eventBases_[index]->add(func);
499 std::vector<std::shared_ptr<folly::EventBase>> eventBases_;
500 std::vector<std::shared_ptr<std::thread>> threads_;
501 std::atomic<size_t> counter_ {0};
506 struct EagerInitParallelTag {};
508 template <typename T, typename Tag = detail::DefaultTag>
509 using SingletonEagerInitParallel = Singleton<T, Tag, EagerInitParallelTag>;
510 TEST(Singleton, SingletonEagerInitParallel) {
511 const static size_t kIters = 1000;
512 const static size_t kThreads = 20;
514 std::atomic<size_t> initCounter;
516 auto& vault = *SingletonVault::singleton<EagerInitParallelTag>();
518 auto sing = SingletonEagerInitParallel<std::string>(
519 [&] {++initCounter; return new std::string(""); })
522 for (size_t i = 0; i < kIters; i++) {
524 // clean up each time
525 vault.destroyInstances();
526 vault.reenableInstances();
529 initCounter.store(0);
532 std::vector<std::shared_ptr<std::thread>> threads;
533 boost::barrier barrier(kThreads);
534 TestEagerInitParallelExecutor exe(kThreads);
535 vault.registrationComplete();
537 EXPECT_EQ(0, initCounter.load());
539 for (size_t j = 0; j < kThreads; j++) {
540 threads.push_back(std::make_shared<std::thread>([&] {
542 vault.doEagerInitVia(exe);
546 for (auto thread : threads) {
551 EXPECT_EQ(1, initCounter.load());
553 sing.get_weak(); // (avoid compile error complaining about unused var)
558 template <typename T, typename Tag = detail::DefaultTag>
559 using SingletonMock = Singleton <T, Tag, MockTag>;
561 // Verify that existing Singleton's can be overridden
562 // using the make_mock functionality.
563 TEST(Singleton, MockTest) {
564 auto& vault = *SingletonVault::singleton<MockTag>();
566 SingletonMock<Watchdog> watchdog_singleton;
567 vault.registrationComplete();
569 // Registring singletons after registrationComplete called works
570 // with make_mock (but not with Singleton ctor).
571 EXPECT_EQ(vault.registeredSingletonCount(), 1);
572 int serial_count_first = SingletonMock<Watchdog>::try_get()->serial_number;
574 // Override existing mock using make_mock.
575 SingletonMock<Watchdog>::make_mock();
577 EXPECT_EQ(vault.registeredSingletonCount(), 1);
578 int serial_count_mock = SingletonMock<Watchdog>::try_get()->serial_number;
580 // If serial_count value is the same, then singleton was not replaced.
581 EXPECT_NE(serial_count_first, serial_count_mock);