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/Subprocess.h>
21 #include <folly/experimental/io/FsUtil.h>
22 #include <folly/io/async/EventBase.h>
23 #include <folly/test/SingletonTestStructs.h>
25 #include <glog/logging.h>
26 #include <gmock/gmock.h>
27 #include <gtest/gtest.h>
28 #include <boost/thread/barrier.hpp>
30 using namespace folly;
32 TEST(Singleton, MissingSingleton) {
33 EXPECT_DEATH([]() { auto u = Singleton<UnregisteredWatchdog>::try_get(); }(),
37 struct BasicUsageTag {};
38 template <typename T, typename Tag = detail::DefaultTag>
39 using SingletonBasicUsage = Singleton <T, Tag, BasicUsageTag>;
41 // Exercise some basic codepaths ensuring registration order and
42 // destruction order happen as expected, that instances are created
43 // when expected, etc etc.
44 TEST(Singleton, BasicUsage) {
45 auto& vault = *SingletonVault::singleton<BasicUsageTag>();
47 EXPECT_EQ(vault.registeredSingletonCount(), 0);
48 SingletonBasicUsage<Watchdog> watchdog_singleton;
49 EXPECT_EQ(vault.registeredSingletonCount(), 1);
51 SingletonBasicUsage<ChildWatchdog> child_watchdog_singleton;
52 EXPECT_EQ(vault.registeredSingletonCount(), 2);
54 vault.registrationComplete();
56 // limit a scope to release references so we can destroy them later
58 std::shared_ptr<Watchdog> s1 = SingletonBasicUsage<Watchdog>::try_get();
59 EXPECT_NE(s1, nullptr);
61 std::shared_ptr<Watchdog> s2 = SingletonBasicUsage<Watchdog>::try_get();
62 EXPECT_NE(s2, nullptr);
65 EXPECT_EQ(s1.get(), SingletonBasicUsage<Watchdog>::try_get_fast().get());
67 std::shared_ptr<ChildWatchdog> s3 =
68 SingletonBasicUsage<ChildWatchdog>::try_get();
69 EXPECT_NE(s3, nullptr);
72 EXPECT_EQ(vault.registeredSingletonCount(), 2);
73 EXPECT_EQ(vault.livingSingletonCount(), 2);
76 vault.destroyInstances();
77 EXPECT_EQ(vault.registeredSingletonCount(), 2);
78 EXPECT_EQ(vault.livingSingletonCount(), 0);
81 struct DirectUsageTag {};
82 template <typename T, typename Tag = detail::DefaultTag>
83 using SingletonDirectUsage = Singleton <T, Tag, DirectUsageTag>;
85 TEST(Singleton, DirectUsage) {
86 auto& vault = *SingletonVault::singleton<DirectUsageTag>();
88 EXPECT_EQ(vault.registeredSingletonCount(), 0);
90 // Verify we can get to the underlying singletons via directly using
91 // the singleton definition.
92 SingletonDirectUsage<Watchdog> watchdog;
94 SingletonDirectUsage<Watchdog, TestTag> named_watchdog;
95 EXPECT_EQ(vault.registeredSingletonCount(), 2);
96 vault.registrationComplete();
98 EXPECT_NE(watchdog.try_get(), nullptr);
99 EXPECT_EQ(watchdog.try_get(), SingletonDirectUsage<Watchdog>::try_get());
100 EXPECT_NE(watchdog.try_get(), named_watchdog.try_get());
101 EXPECT_EQ(watchdog.try_get()->livingWatchdogCount(), 2);
103 vault.destroyInstances();
106 struct NamedUsageTag {};
107 template <typename T, typename Tag = detail::DefaultTag>
108 using SingletonNamedUsage = Singleton <T, Tag, NamedUsageTag>;
110 TEST(Singleton, NamedUsage) {
111 auto& vault = *SingletonVault::singleton<NamedUsageTag>();
113 EXPECT_EQ(vault.registeredSingletonCount(), 0);
115 // Define two named Watchdog singletons and one unnamed singleton.
118 typedef detail::DefaultTag Watchdog3;
119 SingletonNamedUsage<Watchdog, Watchdog1> watchdog1_singleton;
120 EXPECT_EQ(vault.registeredSingletonCount(), 1);
121 SingletonNamedUsage<Watchdog, Watchdog2> watchdog2_singleton;
122 EXPECT_EQ(vault.registeredSingletonCount(), 2);
123 SingletonNamedUsage<Watchdog, Watchdog3> watchdog3_singleton;
124 EXPECT_EQ(vault.registeredSingletonCount(), 3);
126 vault.registrationComplete();
128 // Verify our three singletons are distinct and non-nullptr.
129 auto s1 = SingletonNamedUsage<Watchdog, Watchdog1>::try_get();
130 EXPECT_EQ(s1, watchdog1_singleton.try_get());
131 auto s2 = SingletonNamedUsage<Watchdog, Watchdog2>::try_get();
132 EXPECT_EQ(s2, watchdog2_singleton.try_get());
134 auto s3 = SingletonNamedUsage<Watchdog, Watchdog3>::try_get();
135 EXPECT_EQ(s3, watchdog3_singleton.try_get());
139 // Verify the "default" singleton is the same as the DefaultTag-tagged
141 auto s4 = SingletonNamedUsage<Watchdog>::try_get();
142 EXPECT_EQ(s4, watchdog3_singleton.try_get());
145 vault.destroyInstances();
148 struct NaughtyUsageTag {};
149 template <typename T, typename Tag = detail::DefaultTag>
150 using SingletonNaughtyUsage = Singleton <T, Tag, NaughtyUsageTag>;
151 struct NaughtyUsageTag2 {};
152 template <typename T, typename Tag = detail::DefaultTag>
153 using SingletonNaughtyUsage2 = Singleton <T, Tag, NaughtyUsageTag2>;
155 // Some pathological cases such as getting unregistered singletons,
156 // double registration, etc.
157 TEST(Singleton, NaughtyUsage) {
158 auto& vault = *SingletonVault::singleton<NaughtyUsageTag>();
160 vault.registrationComplete();
163 EXPECT_DEATH(Singleton<Watchdog>::try_get(), "");
164 EXPECT_DEATH(SingletonNaughtyUsage<Watchdog>::try_get(), "");
166 vault.destroyInstances();
168 auto& vault2 = *SingletonVault::singleton<NaughtyUsageTag2>();
170 EXPECT_DEATH(SingletonNaughtyUsage2<Watchdog>::try_get(), "");
171 SingletonNaughtyUsage2<Watchdog> watchdog_singleton;
173 // double registration
174 EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> watchdog_singleton; }(),
176 vault2.destroyInstances();
178 // double registration after destroy
179 EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> watchdog_singleton; }(),
183 struct SharedPtrUsageTag {};
184 template <typename T, typename Tag = detail::DefaultTag>
185 using SingletonSharedPtrUsage = Singleton <T, Tag, SharedPtrUsageTag>;
187 // TODO (anob): revisit this test
188 TEST(Singleton, SharedPtrUsage) {
189 struct WatchdogHolder {
192 LOG(ERROR) << "The following log message with stack trace is expected";
196 std::shared_ptr<Watchdog> watchdog;
199 auto& vault = *SingletonVault::singleton<SharedPtrUsageTag>();
201 EXPECT_EQ(vault.registeredSingletonCount(), 0);
202 SingletonSharedPtrUsage<Watchdog> watchdog_singleton;
203 EXPECT_EQ(vault.registeredSingletonCount(), 1);
205 SingletonSharedPtrUsage<ChildWatchdog> child_watchdog_singleton;
206 EXPECT_EQ(vault.registeredSingletonCount(), 2);
209 SingletonSharedPtrUsage<Watchdog, ATag> named_watchdog_singleton;
211 SingletonSharedPtrUsage<WatchdogHolder> watchdog_holder_singleton;
213 vault.registrationComplete();
215 // Initilize holder singleton first, so that it's the last one to be
217 watchdog_holder_singleton.try_get();
219 auto s1 = SingletonSharedPtrUsage<Watchdog>::try_get().get();
220 EXPECT_NE(s1, nullptr);
222 auto s2 = SingletonSharedPtrUsage<Watchdog>::try_get().get();
223 EXPECT_NE(s2, nullptr);
227 auto weak_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
229 auto shared_s1 = weak_s1.lock();
230 EXPECT_EQ(shared_s1.get(), s1);
231 EXPECT_EQ(shared_s1.use_count(), 2);
233 auto old_serial = shared_s1->serial_number;
237 SingletonSharedPtrUsage<Watchdog, ATag>::get_weak();
238 auto locked = named_weak_s1.lock();
239 EXPECT_NE(locked.get(), shared_s1.get());
242 // We should release externally locked shared_ptr, otherwise it will be
244 watchdog_holder_singleton.try_get()->watchdog = std::move(shared_s1);
246 LOG(ERROR) << "The following log message regarding shared_ptr is expected";
248 auto start_time = std::chrono::steady_clock::now();
249 vault.destroyInstances();
250 auto duration = std::chrono::steady_clock::now() - start_time;
251 EXPECT_TRUE(duration > std::chrono::seconds{4} &&
252 duration < std::chrono::seconds{6});
254 EXPECT_EQ(vault.registeredSingletonCount(), 4);
255 EXPECT_EQ(vault.livingSingletonCount(), 0);
257 EXPECT_TRUE(weak_s1.expired());
259 auto empty_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
260 EXPECT_FALSE(empty_s1.lock());
262 vault.reenableInstances();
265 // Singleton should be re-created only after reenableInstances() was called.
266 auto new_s1 = SingletonSharedPtrUsage<Watchdog>::try_get();
267 // Track serial number rather than pointer since the memory could be
268 // re-used when we create new_s1.
269 EXPECT_NE(new_s1->serial_number, old_serial);
272 auto new_s1_weak = SingletonSharedPtrUsage<Watchdog>::get_weak();
273 auto new_s1_shared = new_s1_weak.lock();
274 std::thread t([new_s1_shared]() mutable {
275 std::this_thread::sleep_for(std::chrono::seconds{2});
276 new_s1_shared.reset();
278 new_s1_shared.reset();
280 auto start_time = std::chrono::steady_clock::now();
281 vault.destroyInstances();
282 auto duration = std::chrono::steady_clock::now() - start_time;
283 EXPECT_TRUE(duration > std::chrono::seconds{1} &&
284 duration < std::chrono::seconds{3});
286 EXPECT_TRUE(new_s1_weak.expired());
290 // Some classes to test singleton dependencies. NeedySingleton has a
291 // dependency on NeededSingleton, which happens during its
294 template <typename T, typename Tag = detail::DefaultTag>
295 using SingletonNeedy = Singleton <T, Tag, NeedyTag>;
297 struct NeededSingleton {};
298 struct NeedySingleton {
300 auto unused = SingletonNeedy<NeededSingleton>::try_get();
301 EXPECT_NE(unused, nullptr);
305 // Ensure circular dependencies fail -- a singleton that needs itself, whoops.
306 struct SelfNeedyTag {};
307 template <typename T, typename Tag = detail::DefaultTag>
308 using SingletonSelfNeedy = Singleton <T, Tag, SelfNeedyTag>;
310 struct SelfNeedySingleton {
311 SelfNeedySingleton() {
312 auto unused = SingletonSelfNeedy<SelfNeedySingleton>::try_get();
313 EXPECT_NE(unused, nullptr);
317 TEST(Singleton, SingletonDependencies) {
318 SingletonNeedy<NeededSingleton> needed_singleton;
319 SingletonNeedy<NeedySingleton> needy_singleton;
320 auto& needy_vault = *SingletonVault::singleton<NeedyTag>();
322 needy_vault.registrationComplete();
324 EXPECT_EQ(needy_vault.registeredSingletonCount(), 2);
325 EXPECT_EQ(needy_vault.livingSingletonCount(), 0);
327 auto needy = SingletonNeedy<NeedySingleton>::try_get();
328 EXPECT_EQ(needy_vault.livingSingletonCount(), 2);
330 SingletonSelfNeedy<SelfNeedySingleton> self_needy_singleton;
331 auto& self_needy_vault = *SingletonVault::singleton<SelfNeedyTag>();
333 self_needy_vault.registrationComplete();
334 EXPECT_DEATH([]() { SingletonSelfNeedy<SelfNeedySingleton>::try_get(); }(),
338 // A test to ensure multiple threads contending on singleton creation
339 // properly wait for creation rather than thinking it is a circular
341 class Slowpoke : public Watchdog {
343 Slowpoke() { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
346 struct ConcurrencyTag {};
347 template <typename T, typename Tag = detail::DefaultTag>
348 using SingletonConcurrency = Singleton <T, Tag, ConcurrencyTag>;
350 TEST(Singleton, SingletonConcurrency) {
351 auto& vault = *SingletonVault::singleton<ConcurrencyTag>();
352 SingletonConcurrency<Slowpoke> slowpoke_singleton;
353 vault.registrationComplete();
355 std::mutex gatekeeper;
357 auto func = [&gatekeeper]() {
360 auto unused = SingletonConcurrency<Slowpoke>::try_get();
363 EXPECT_EQ(vault.livingSingletonCount(), 0);
364 std::vector<std::thread> threads;
365 for (int i = 0; i < 100; ++i) {
366 threads.emplace_back(func);
368 // If circular dependency checks fail, the unlock would trigger a
369 // crash. Instead, it succeeds, and we have exactly one living
372 for (auto& t : threads) {
375 EXPECT_EQ(vault.livingSingletonCount(), 1);
378 struct ErrorConstructor {
379 static size_t constructCount_;
381 if ((constructCount_++) == 0) {
382 throw std::runtime_error("first time fails");
386 size_t ErrorConstructor::constructCount_(0);
388 struct CreationErrorTag {};
389 template <typename T, typename Tag = detail::DefaultTag>
390 using SingletonCreationError = Singleton<T, Tag, CreationErrorTag>;
392 TEST(Singleton, SingletonCreationError) {
393 SingletonVault::singleton<CreationErrorTag>();
394 SingletonCreationError<ErrorConstructor> error_once_singleton;
396 // first time should error out
397 EXPECT_THROW(error_once_singleton.try_get(), std::runtime_error);
399 // second time it'll work fine
400 error_once_singleton.try_get();
404 struct ConcurrencyStressTag {};
405 template <typename T, typename Tag = detail::DefaultTag>
406 using SingletonConcurrencyStress = Singleton <T, Tag, ConcurrencyStressTag>;
408 TEST(Singleton, SingletonConcurrencyStress) {
409 auto& vault = *SingletonVault::singleton<ConcurrencyStressTag>();
410 SingletonConcurrencyStress<Slowpoke> slowpoke_singleton;
412 std::vector<std::thread> ts;
413 for (size_t i = 0; i < 100; ++i) {
414 ts.emplace_back([&]() {
415 slowpoke_singleton.try_get();
419 for (size_t i = 0; i < 100; ++i) {
420 std::chrono::milliseconds d(20);
422 std::this_thread::sleep_for(d);
423 vault.destroyInstances();
424 std::this_thread::sleep_for(d);
425 vault.destroyInstances();
434 struct EagerInitSyncTag {};
436 template <typename T, typename Tag = detail::DefaultTag>
437 using SingletonEagerInitSync = Singleton<T, Tag, EagerInitSyncTag>;
438 TEST(Singleton, SingletonEagerInitSync) {
439 auto& vault = *SingletonVault::singleton<EagerInitSyncTag>();
440 bool didEagerInit = false;
441 auto sing = SingletonEagerInitSync<std::string>(
442 [&] {didEagerInit = true; return new std::string("foo"); })
444 vault.registrationComplete();
445 EXPECT_FALSE(didEagerInit);
447 EXPECT_TRUE(didEagerInit);
448 sing.get_weak(); // (avoid compile error complaining about unused var 'sing')
452 struct EagerInitAsyncTag {};
454 template <typename T, typename Tag = detail::DefaultTag>
455 using SingletonEagerInitAsync = Singleton<T, Tag, EagerInitAsyncTag>;
456 TEST(Singleton, SingletonEagerInitAsync) {
457 auto& vault = *SingletonVault::singleton<EagerInitAsyncTag>();
458 bool didEagerInit = false;
459 auto sing = SingletonEagerInitAsync<std::string>(
460 [&] {didEagerInit = true; return new std::string("foo"); })
464 vault.registrationComplete();
465 EXPECT_FALSE(didEagerInit);
466 vault.doEagerInitVia(eb, &done);
469 EXPECT_TRUE(didEagerInit);
470 sing.get_weak(); // (avoid compile error complaining about unused var 'sing')
474 class TestEagerInitParallelExecutor : public folly::Executor {
476 explicit TestEagerInitParallelExecutor(const size_t threadCount) {
477 eventBases_.reserve(threadCount);
478 threads_.reserve(threadCount);
479 for (size_t i = 0; i < threadCount; i++) {
480 eventBases_.push_back(std::make_shared<folly::EventBase>());
481 auto eb = eventBases_.back();
482 threads_.emplace_back(std::make_shared<std::thread>(
483 [eb] { eb->loopForever(); }));
487 virtual ~TestEagerInitParallelExecutor() override {
488 for (auto eb : eventBases_) {
489 eb->runInEventBaseThread([eb] { eb->terminateLoopSoon(); });
491 for (auto thread : threads_) {
496 virtual void add(folly::Func func) override {
497 const auto index = (counter_ ++) % eventBases_.size();
498 eventBases_[index]->add(func);
502 std::vector<std::shared_ptr<folly::EventBase>> eventBases_;
503 std::vector<std::shared_ptr<std::thread>> threads_;
504 std::atomic<size_t> counter_ {0};
509 struct EagerInitParallelTag {};
511 template <typename T, typename Tag = detail::DefaultTag>
512 using SingletonEagerInitParallel = Singleton<T, Tag, EagerInitParallelTag>;
513 TEST(Singleton, SingletonEagerInitParallel) {
514 const static size_t kIters = 1000;
515 const static size_t kThreads = 20;
517 std::atomic<size_t> initCounter;
519 auto& vault = *SingletonVault::singleton<EagerInitParallelTag>();
521 auto sing = SingletonEagerInitParallel<std::string>(
522 [&] {++initCounter; return new std::string(""); })
525 for (size_t i = 0; i < kIters; i++) {
527 // clean up each time
528 vault.destroyInstances();
529 vault.reenableInstances();
532 initCounter.store(0);
535 std::vector<std::shared_ptr<std::thread>> threads;
536 boost::barrier barrier(kThreads);
537 TestEagerInitParallelExecutor exe(kThreads);
538 vault.registrationComplete();
540 EXPECT_EQ(0, initCounter.load());
542 for (size_t j = 0; j < kThreads; j++) {
543 threads.push_back(std::make_shared<std::thread>([&] {
545 vault.doEagerInitVia(exe);
549 for (auto thread : threads) {
554 EXPECT_EQ(1, initCounter.load());
556 sing.get_weak(); // (avoid compile error complaining about unused var)
561 template <typename T, typename Tag = detail::DefaultTag>
562 using SingletonMock = Singleton <T, Tag, MockTag>;
564 // Verify that existing Singleton's can be overridden
565 // using the make_mock functionality.
566 TEST(Singleton, MockTest) {
567 auto& vault = *SingletonVault::singleton<MockTag>();
569 SingletonMock<Watchdog> watchdog_singleton;
570 vault.registrationComplete();
572 // Registring singletons after registrationComplete called works
573 // with make_mock (but not with Singleton ctor).
574 EXPECT_EQ(vault.registeredSingletonCount(), 1);
575 int serial_count_first = SingletonMock<Watchdog>::try_get()->serial_number;
577 // Override existing mock using make_mock.
578 SingletonMock<Watchdog>::make_mock();
580 EXPECT_EQ(vault.registeredSingletonCount(), 1);
581 int serial_count_mock = SingletonMock<Watchdog>::try_get()->serial_number;
583 // If serial_count value is the same, then singleton was not replaced.
584 EXPECT_NE(serial_count_first, serial_count_mock);
586 // Override existing mock using make_mock one more time
587 SingletonMock<Watchdog>::make_mock();
589 EXPECT_EQ(vault.registeredSingletonCount(), 1);
590 int serial_count_mock2 = SingletonMock<Watchdog>::try_get()->serial_number;
592 // If serial_count value is the same, then singleton was not replaced.
593 EXPECT_NE(serial_count_first, serial_count_mock2);
594 EXPECT_NE(serial_count_mock, serial_count_mock2);
596 vault.destroyInstances();
599 TEST(Singleton, DoubleRegistrationLogging) {
600 const auto basename = "singleton_double_registration";
601 const auto sub = fs::executable_path().remove_filename() / basename;
603 std::vector<std::string>{sub.string()},
604 Subprocess::Options()
605 .stdin(Subprocess::CLOSE)
606 .stdout(Subprocess::CLOSE)
609 auto err = p.communicate("").second;
611 EXPECT_EQ(ProcessReturnCode::KILLED, res.state());
612 EXPECT_EQ(SIGABRT, res.killSignal());
613 EXPECT_THAT(err, testing::StartsWith("Double registration of singletons"));