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/portability/GMock.h>
24 #include <folly/portability/GTest.h>
25 #include <folly/test/SingletonTestStructs.h>
27 #include <glog/logging.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> w2; }(), "");
175 vault2.destroyInstances();
177 // double registration after destroy
178 EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> w3; }(), "");
181 struct SharedPtrUsageTag {};
182 template <typename T, typename Tag = detail::DefaultTag>
183 using SingletonSharedPtrUsage = Singleton <T, Tag, SharedPtrUsageTag>;
185 // TODO (anob): revisit this test
186 TEST(Singleton, SharedPtrUsage) {
187 struct WatchdogHolder {
190 LOG(ERROR) << "The following log message with stack trace is expected";
194 std::shared_ptr<Watchdog> watchdog;
197 auto& vault = *SingletonVault::singleton<SharedPtrUsageTag>();
199 EXPECT_EQ(vault.registeredSingletonCount(), 0);
200 SingletonSharedPtrUsage<Watchdog> watchdog_singleton;
201 EXPECT_EQ(vault.registeredSingletonCount(), 1);
203 SingletonSharedPtrUsage<ChildWatchdog> child_watchdog_singleton;
204 EXPECT_EQ(vault.registeredSingletonCount(), 2);
207 SingletonSharedPtrUsage<Watchdog, ATag> named_watchdog_singleton;
209 SingletonSharedPtrUsage<WatchdogHolder> watchdog_holder_singleton;
211 vault.registrationComplete();
213 // Initilize holder singleton first, so that it's the last one to be
215 watchdog_holder_singleton.try_get();
217 auto s1 = SingletonSharedPtrUsage<Watchdog>::try_get().get();
218 EXPECT_NE(s1, nullptr);
220 auto s2 = SingletonSharedPtrUsage<Watchdog>::try_get().get();
221 EXPECT_NE(s2, nullptr);
225 auto weak_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
227 auto shared_s1 = weak_s1.lock();
228 EXPECT_EQ(shared_s1.get(), s1);
229 EXPECT_EQ(shared_s1.use_count(), 2);
231 auto old_serial = shared_s1->serial_number;
235 SingletonSharedPtrUsage<Watchdog, ATag>::get_weak();
236 auto locked = named_weak_s1.lock();
237 EXPECT_NE(locked.get(), shared_s1.get());
240 // We should release externally locked shared_ptr, otherwise it will be
242 watchdog_holder_singleton.try_get()->watchdog = std::move(shared_s1);
244 LOG(ERROR) << "The following log message regarding shared_ptr is expected";
246 auto start_time = std::chrono::steady_clock::now();
247 vault.destroyInstances();
248 auto duration = std::chrono::steady_clock::now() - start_time;
249 EXPECT_TRUE(duration > std::chrono::seconds{4} &&
250 duration < std::chrono::seconds{6});
252 EXPECT_EQ(vault.registeredSingletonCount(), 4);
253 EXPECT_EQ(vault.livingSingletonCount(), 0);
255 EXPECT_TRUE(weak_s1.expired());
257 auto empty_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
258 EXPECT_FALSE(empty_s1.lock());
260 vault.reenableInstances();
263 // Singleton should be re-created only after reenableInstances() was called.
264 auto new_s1 = SingletonSharedPtrUsage<Watchdog>::try_get();
265 // Track serial number rather than pointer since the memory could be
266 // re-used when we create new_s1.
267 EXPECT_NE(new_s1->serial_number, old_serial);
270 auto new_s1_weak = SingletonSharedPtrUsage<Watchdog>::get_weak();
271 auto new_s1_shared = new_s1_weak.lock();
272 std::thread t([new_s1_shared]() mutable {
273 std::this_thread::sleep_for(std::chrono::seconds{2});
274 new_s1_shared.reset();
276 new_s1_shared.reset();
278 auto start_time = std::chrono::steady_clock::now();
279 vault.destroyInstances();
280 auto duration = std::chrono::steady_clock::now() - start_time;
281 EXPECT_TRUE(duration > std::chrono::seconds{1} &&
282 duration < std::chrono::seconds{3});
284 EXPECT_TRUE(new_s1_weak.expired());
288 // Some classes to test singleton dependencies. NeedySingleton has a
289 // dependency on NeededSingleton, which happens during its
292 template <typename T, typename Tag = detail::DefaultTag>
293 using SingletonNeedy = Singleton <T, Tag, NeedyTag>;
295 struct NeededSingleton {};
296 struct NeedySingleton {
298 auto unused = SingletonNeedy<NeededSingleton>::try_get();
299 EXPECT_NE(unused, nullptr);
303 // Ensure circular dependencies fail -- a singleton that needs itself, whoops.
304 struct SelfNeedyTag {};
305 template <typename T, typename Tag = detail::DefaultTag>
306 using SingletonSelfNeedy = Singleton <T, Tag, SelfNeedyTag>;
308 struct SelfNeedySingleton {
309 SelfNeedySingleton() {
310 auto unused = SingletonSelfNeedy<SelfNeedySingleton>::try_get();
311 EXPECT_NE(unused, nullptr);
315 TEST(Singleton, SingletonDependencies) {
316 SingletonNeedy<NeededSingleton> needed_singleton;
317 SingletonNeedy<NeedySingleton> needy_singleton;
318 auto& needy_vault = *SingletonVault::singleton<NeedyTag>();
320 needy_vault.registrationComplete();
322 EXPECT_EQ(needy_vault.registeredSingletonCount(), 2);
323 EXPECT_EQ(needy_vault.livingSingletonCount(), 0);
325 auto needy = SingletonNeedy<NeedySingleton>::try_get();
326 EXPECT_EQ(needy_vault.livingSingletonCount(), 2);
328 SingletonSelfNeedy<SelfNeedySingleton> self_needy_singleton;
329 auto& self_needy_vault = *SingletonVault::singleton<SelfNeedyTag>();
331 self_needy_vault.registrationComplete();
332 EXPECT_DEATH([]() { SingletonSelfNeedy<SelfNeedySingleton>::try_get(); }(),
336 // A test to ensure multiple threads contending on singleton creation
337 // properly wait for creation rather than thinking it is a circular
339 class Slowpoke : public Watchdog {
341 Slowpoke() { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
344 struct ConcurrencyTag {};
345 template <typename T, typename Tag = detail::DefaultTag>
346 using SingletonConcurrency = Singleton <T, Tag, ConcurrencyTag>;
348 TEST(Singleton, SingletonConcurrency) {
349 auto& vault = *SingletonVault::singleton<ConcurrencyTag>();
350 SingletonConcurrency<Slowpoke> slowpoke_singleton;
351 vault.registrationComplete();
353 std::mutex gatekeeper;
355 auto func = [&gatekeeper]() {
358 auto unused = SingletonConcurrency<Slowpoke>::try_get();
361 EXPECT_EQ(vault.livingSingletonCount(), 0);
362 std::vector<std::thread> threads;
363 for (int i = 0; i < 100; ++i) {
364 threads.emplace_back(func);
366 // If circular dependency checks fail, the unlock would trigger a
367 // crash. Instead, it succeeds, and we have exactly one living
370 for (auto& t : threads) {
373 EXPECT_EQ(vault.livingSingletonCount(), 1);
376 struct ErrorConstructor {
377 static size_t constructCount_;
379 if ((constructCount_++) == 0) {
380 throw std::runtime_error("first time fails");
384 size_t ErrorConstructor::constructCount_(0);
386 struct CreationErrorTag {};
387 template <typename T, typename Tag = detail::DefaultTag>
388 using SingletonCreationError = Singleton<T, Tag, CreationErrorTag>;
390 TEST(Singleton, SingletonCreationError) {
391 SingletonVault::singleton<CreationErrorTag>();
392 SingletonCreationError<ErrorConstructor> error_once_singleton;
394 // first time should error out
395 EXPECT_THROW(error_once_singleton.try_get(), std::runtime_error);
397 // second time it'll work fine
398 error_once_singleton.try_get();
402 struct ConcurrencyStressTag {};
403 template <typename T, typename Tag = detail::DefaultTag>
404 using SingletonConcurrencyStress = Singleton <T, Tag, ConcurrencyStressTag>;
406 TEST(Singleton, SingletonConcurrencyStress) {
407 auto& vault = *SingletonVault::singleton<ConcurrencyStressTag>();
408 SingletonConcurrencyStress<Slowpoke> slowpoke_singleton;
410 std::vector<std::thread> ts;
411 for (size_t i = 0; i < 100; ++i) {
412 ts.emplace_back([&]() {
413 slowpoke_singleton.try_get();
417 for (size_t i = 0; i < 100; ++i) {
418 std::chrono::milliseconds d(20);
420 std::this_thread::sleep_for(d);
421 vault.destroyInstances();
422 std::this_thread::sleep_for(d);
423 vault.destroyInstances();
432 struct EagerInitSyncTag {};
434 template <typename T, typename Tag = detail::DefaultTag>
435 using SingletonEagerInitSync = Singleton<T, Tag, EagerInitSyncTag>;
436 TEST(Singleton, SingletonEagerInitSync) {
437 auto& vault = *SingletonVault::singleton<EagerInitSyncTag>();
438 bool didEagerInit = false;
439 auto sing = SingletonEagerInitSync<std::string>(
440 [&] {didEagerInit = true; return new std::string("foo"); })
442 vault.registrationComplete();
443 EXPECT_FALSE(didEagerInit);
445 EXPECT_TRUE(didEagerInit);
446 sing.get_weak(); // (avoid compile error complaining about unused var 'sing')
450 struct EagerInitAsyncTag {};
452 template <typename T, typename Tag = detail::DefaultTag>
453 using SingletonEagerInitAsync = Singleton<T, Tag, EagerInitAsyncTag>;
454 TEST(Singleton, SingletonEagerInitAsync) {
455 auto& vault = *SingletonVault::singleton<EagerInitAsyncTag>();
456 bool didEagerInit = false;
457 auto sing = SingletonEagerInitAsync<std::string>(
458 [&] {didEagerInit = true; return new std::string("foo"); })
462 vault.registrationComplete();
463 EXPECT_FALSE(didEagerInit);
464 vault.doEagerInitVia(eb, &done);
467 EXPECT_TRUE(didEagerInit);
468 sing.get_weak(); // (avoid compile error complaining about unused var 'sing')
472 class TestEagerInitParallelExecutor : public folly::Executor {
474 explicit TestEagerInitParallelExecutor(const size_t threadCount) {
475 eventBases_.reserve(threadCount);
476 threads_.reserve(threadCount);
477 for (size_t i = 0; i < threadCount; i++) {
478 eventBases_.push_back(std::make_shared<folly::EventBase>());
479 auto eb = eventBases_.back();
480 threads_.emplace_back(std::make_shared<std::thread>(
481 [eb] { eb->loopForever(); }));
485 virtual ~TestEagerInitParallelExecutor() override {
486 for (auto eb : eventBases_) {
487 eb->runInEventBaseThread([eb] { eb->terminateLoopSoon(); });
489 for (auto thread : threads_) {
494 virtual void add(folly::Func func) override {
495 const auto index = (counter_ ++) % eventBases_.size();
496 eventBases_[index]->add(std::move(func));
500 std::vector<std::shared_ptr<folly::EventBase>> eventBases_;
501 std::vector<std::shared_ptr<std::thread>> threads_;
502 std::atomic<size_t> counter_ {0};
507 struct EagerInitParallelTag {};
509 template <typename T, typename Tag = detail::DefaultTag>
510 using SingletonEagerInitParallel = Singleton<T, Tag, EagerInitParallelTag>;
511 TEST(Singleton, SingletonEagerInitParallel) {
512 const static size_t kIters = 1000;
513 const static size_t kThreads = 20;
515 std::atomic<size_t> initCounter;
517 auto& vault = *SingletonVault::singleton<EagerInitParallelTag>();
519 auto sing = SingletonEagerInitParallel<std::string>(
520 [&] {++initCounter; return new std::string(""); })
523 for (size_t i = 0; i < kIters; i++) {
525 // clean up each time
526 vault.destroyInstances();
527 vault.reenableInstances();
530 initCounter.store(0);
533 std::vector<std::shared_ptr<std::thread>> threads;
534 boost::barrier barrier(kThreads);
535 TestEagerInitParallelExecutor exe(kThreads);
536 vault.registrationComplete();
538 EXPECT_EQ(0, initCounter.load());
540 for (size_t j = 0; j < kThreads; j++) {
541 threads.push_back(std::make_shared<std::thread>([&] {
543 vault.doEagerInitVia(exe);
547 for (auto thread : threads) {
552 EXPECT_EQ(1, initCounter.load());
554 sing.get_weak(); // (avoid compile error complaining about unused var)
559 template <typename T, typename Tag = detail::DefaultTag>
560 using SingletonMock = Singleton <T, Tag, MockTag>;
562 // Verify that existing Singleton's can be overridden
563 // using the make_mock functionality.
564 TEST(Singleton, MockTest) {
565 auto& vault = *SingletonVault::singleton<MockTag>();
567 SingletonMock<Watchdog> watchdog_singleton;
568 vault.registrationComplete();
570 // Registring singletons after registrationComplete called works
571 // with make_mock (but not with Singleton ctor).
572 EXPECT_EQ(vault.registeredSingletonCount(), 1);
573 int serial_count_first = SingletonMock<Watchdog>::try_get()->serial_number;
575 // Override existing mock using make_mock.
576 SingletonMock<Watchdog>::make_mock();
578 EXPECT_EQ(vault.registeredSingletonCount(), 1);
579 int serial_count_mock = SingletonMock<Watchdog>::try_get()->serial_number;
581 // If serial_count value is the same, then singleton was not replaced.
582 EXPECT_NE(serial_count_first, serial_count_mock);
584 // Override existing mock using make_mock one more time
585 SingletonMock<Watchdog>::make_mock();
587 EXPECT_EQ(vault.registeredSingletonCount(), 1);
588 int serial_count_mock2 = SingletonMock<Watchdog>::try_get()->serial_number;
590 // If serial_count value is the same, then singleton was not replaced.
591 EXPECT_NE(serial_count_first, serial_count_mock2);
592 EXPECT_NE(serial_count_mock, serial_count_mock2);
594 vault.destroyInstances();
597 TEST(Singleton, DoubleRegistrationLogging) {
598 const auto basename = "singleton_double_registration";
599 const auto sub = fs::executable_path().remove_filename() / basename;
601 std::vector<std::string>{sub.string()},
602 Subprocess::Options()
603 .stdin(Subprocess::CLOSE)
604 .stdout(Subprocess::CLOSE)
607 auto err = p.communicate("").second;
609 EXPECT_EQ(ProcessReturnCode::KILLED, res.state());
610 EXPECT_EQ(SIGABRT, res.killSignal());
611 EXPECT_THAT(err, testing::StartsWith("Double registration of singletons"));