Replace Singleton<T>::get() with Singleton<T>::try_get and make it obsolete
[folly.git] / folly / test / SingletonTest.cpp
1 /*
2  * Copyright 2015 Facebook, Inc.
3  *
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
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <thread>
18
19 #include <folly/Singleton.h>
20
21 #include <folly/Benchmark.h>
22
23 #include <glog/logging.h>
24 #include <gtest/gtest.h>
25
26 using namespace folly;
27
28 // A simple class that tracks how often instances of the class and
29 // subclasses are created, and the ordering.  Also tracks a global
30 // unique counter for each object.
31 std::atomic<size_t> global_counter(19770326);
32 struct Watchdog {
33   static std::vector<Watchdog*> creation_order;
34   Watchdog() : serial_number(++global_counter) {
35     creation_order.push_back(this);
36   }
37
38   ~Watchdog() {
39     if (creation_order.back() != this) {
40       throw std::out_of_range("Watchdog destruction order mismatch");
41     }
42     creation_order.pop_back();
43   }
44
45   const size_t serial_number;
46   size_t livingWatchdogCount() const { return creation_order.size(); }
47
48   Watchdog(const Watchdog&) = delete;
49   Watchdog& operator=(const Watchdog&) = delete;
50   Watchdog(Watchdog&&) noexcept = default;
51 };
52
53 std::vector<Watchdog*> Watchdog::creation_order;
54
55 // Some basic types we use for tracking.
56 struct ChildWatchdog : public Watchdog {};
57 struct GlobalWatchdog : public Watchdog {};
58 struct UnregisteredWatchdog : public Watchdog {};
59
60 namespace {
61 Singleton<GlobalWatchdog> global_watchdog;
62 }
63
64 // Test basic global usage (the default way singletons will generally
65 // be used).
66 TEST(Singleton, BasicGlobalUsage) {
67   EXPECT_EQ(Watchdog::creation_order.size(), 0);
68   EXPECT_EQ(SingletonVault::singleton()->registeredSingletonCount(), 1);
69   EXPECT_EQ(SingletonVault::singleton()->livingSingletonCount(), 0);
70
71   {
72     std::shared_ptr<GlobalWatchdog> wd1 = Singleton<GlobalWatchdog>::try_get();
73     EXPECT_NE(wd1, nullptr);
74     EXPECT_EQ(Watchdog::creation_order.size(), 1);
75     std::shared_ptr<GlobalWatchdog> wd2 = Singleton<GlobalWatchdog>::try_get();
76     EXPECT_NE(wd2, nullptr);
77     EXPECT_EQ(wd1.get(), wd2.get());
78     EXPECT_EQ(Watchdog::creation_order.size(), 1);
79   }
80
81   SingletonVault::singleton()->destroyInstances();
82   EXPECT_EQ(Watchdog::creation_order.size(), 0);
83 }
84
85 TEST(Singleton, MissingSingleton) {
86   EXPECT_DEATH([]() { auto u = Singleton<UnregisteredWatchdog>::try_get(); }(),
87       "");
88 }
89
90 struct BasicUsageTag {};
91 template <typename T, typename Tag = detail::DefaultTag>
92 using SingletonBasicUsage = Singleton <T, Tag, BasicUsageTag>;
93
94 // Exercise some basic codepaths ensuring registration order and
95 // destruction order happen as expected, that instances are created
96 // when expected, etc etc.
97 TEST(Singleton, BasicUsage) {
98   auto& vault = *SingletonVault::singleton<BasicUsageTag>();
99
100   EXPECT_EQ(vault.registeredSingletonCount(), 0);
101   SingletonBasicUsage<Watchdog> watchdog_singleton;
102   EXPECT_EQ(vault.registeredSingletonCount(), 1);
103
104   SingletonBasicUsage<ChildWatchdog> child_watchdog_singleton;
105   EXPECT_EQ(vault.registeredSingletonCount(), 2);
106
107   vault.registrationComplete();
108
109   // limit a scope to release references so we can destroy them later
110   {
111     std::shared_ptr<Watchdog> s1 = SingletonBasicUsage<Watchdog>::try_get();
112     EXPECT_NE(s1, nullptr);
113
114     std::shared_ptr<Watchdog> s2 = SingletonBasicUsage<Watchdog>::try_get();
115     EXPECT_NE(s2, nullptr);
116
117     EXPECT_EQ(s1, s2);
118
119     std::shared_ptr<ChildWatchdog> s3 =
120       SingletonBasicUsage<ChildWatchdog>::try_get();
121     EXPECT_NE(s3, nullptr);
122     EXPECT_NE(s2, s3);
123
124     EXPECT_EQ(vault.registeredSingletonCount(), 2);
125     EXPECT_EQ(vault.livingSingletonCount(), 2);
126   }
127
128   vault.destroyInstances();
129   EXPECT_EQ(vault.registeredSingletonCount(), 2);
130   EXPECT_EQ(vault.livingSingletonCount(), 0);
131 }
132
133 struct DirectUsageTag {};
134 template <typename T, typename Tag = detail::DefaultTag>
135 using SingletonDirectUsage = Singleton <T, Tag, DirectUsageTag>;
136
137 TEST(Singleton, DirectUsage) {
138   auto& vault = *SingletonVault::singleton<DirectUsageTag>();
139
140   EXPECT_EQ(vault.registeredSingletonCount(), 0);
141
142   // Verify we can get to the underlying singletons via directly using
143   // the singleton definition.
144   SingletonDirectUsage<Watchdog> watchdog;
145   struct TestTag {};
146   SingletonDirectUsage<Watchdog, TestTag> named_watchdog;
147   EXPECT_EQ(vault.registeredSingletonCount(), 2);
148   vault.registrationComplete();
149
150   EXPECT_NE(watchdog.try_get(), nullptr);
151   EXPECT_EQ(watchdog.try_get(), SingletonDirectUsage<Watchdog>::try_get());
152   EXPECT_NE(watchdog.try_get(), named_watchdog.try_get());
153   EXPECT_EQ(watchdog.try_get()->livingWatchdogCount(), 2);
154
155   vault.destroyInstances();
156 }
157
158 struct NamedUsageTag {};
159 template <typename T, typename Tag = detail::DefaultTag>
160 using SingletonNamedUsage = Singleton <T, Tag, NamedUsageTag>;
161
162 TEST(Singleton, NamedUsage) {
163   auto& vault = *SingletonVault::singleton<NamedUsageTag>();
164
165   EXPECT_EQ(vault.registeredSingletonCount(), 0);
166
167   // Define two named Watchdog singletons and one unnamed singleton.
168   struct Watchdog1 {};
169   struct Watchdog2 {};
170   typedef detail::DefaultTag Watchdog3;
171   SingletonNamedUsage<Watchdog, Watchdog1> watchdog1_singleton;
172   EXPECT_EQ(vault.registeredSingletonCount(), 1);
173   SingletonNamedUsage<Watchdog, Watchdog2> watchdog2_singleton;
174   EXPECT_EQ(vault.registeredSingletonCount(), 2);
175   SingletonNamedUsage<Watchdog, Watchdog3> watchdog3_singleton;
176   EXPECT_EQ(vault.registeredSingletonCount(), 3);
177
178   vault.registrationComplete();
179   {
180     // Verify our three singletons are distinct and non-nullptr.
181     auto s1 = SingletonNamedUsage<Watchdog, Watchdog1>::try_get();
182     EXPECT_EQ(s1, watchdog1_singleton.try_get());
183     auto s2 = SingletonNamedUsage<Watchdog, Watchdog2>::try_get();
184     EXPECT_EQ(s2, watchdog2_singleton.try_get());
185     EXPECT_NE(s1, s2);
186     auto s3 = SingletonNamedUsage<Watchdog, Watchdog3>::try_get();
187     EXPECT_EQ(s3, watchdog3_singleton.try_get());
188     EXPECT_NE(s3, s1);
189     EXPECT_NE(s3, s2);
190
191     // Verify the "default" singleton is the same as the DefaultTag-tagged
192     // singleton.
193     auto s4 = SingletonNamedUsage<Watchdog>::try_get();
194     EXPECT_EQ(s4, watchdog3_singleton.try_get());
195   }
196
197   vault.destroyInstances();
198 }
199
200 struct NaughtyUsageTag {};
201 template <typename T, typename Tag = detail::DefaultTag>
202 using SingletonNaughtyUsage = Singleton <T, Tag, NaughtyUsageTag>;
203 struct NaughtyUsageTag2 {};
204 template <typename T, typename Tag = detail::DefaultTag>
205 using SingletonNaughtyUsage2 = Singleton <T, Tag, NaughtyUsageTag2>;
206
207 // Some pathological cases such as getting unregistered singletons,
208 // double registration, etc.
209 TEST(Singleton, NaughtyUsage) {
210   auto& vault = *SingletonVault::singleton<NaughtyUsageTag>();
211
212   vault.registrationComplete();
213
214   // Unregistered.
215   EXPECT_DEATH(Singleton<Watchdog>::try_get(), "");
216   EXPECT_DEATH(SingletonNaughtyUsage<Watchdog>::try_get(), "");
217
218   vault.destroyInstances();
219
220   auto& vault2 = *SingletonVault::singleton<NaughtyUsageTag2>();
221
222    EXPECT_DEATH(SingletonNaughtyUsage2<Watchdog>::try_get(), "");
223   SingletonNaughtyUsage2<Watchdog> watchdog_singleton;
224
225   // double registration
226   EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> watchdog_singleton; }(),
227                "");
228   vault2.destroyInstances();
229
230   // double registration after destroy
231   EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> watchdog_singleton; }(),
232                "");
233 }
234
235 struct SharedPtrUsageTag {};
236 template <typename T, typename Tag = detail::DefaultTag>
237 using SingletonSharedPtrUsage = Singleton <T, Tag, SharedPtrUsageTag>;
238
239 // TODO (anob): revisit this test
240 TEST(Singleton, SharedPtrUsage) {
241   struct WatchdogHolder {
242     ~WatchdogHolder() {
243       if (watchdog) {
244         LOG(ERROR) << "The following log message with stack trace is expected";
245       }
246     }
247
248     std::shared_ptr<Watchdog> watchdog;
249   };
250
251   auto& vault = *SingletonVault::singleton<SharedPtrUsageTag>();
252
253   EXPECT_EQ(vault.registeredSingletonCount(), 0);
254   SingletonSharedPtrUsage<Watchdog> watchdog_singleton;
255   EXPECT_EQ(vault.registeredSingletonCount(), 1);
256
257   SingletonSharedPtrUsage<ChildWatchdog> child_watchdog_singleton;
258   EXPECT_EQ(vault.registeredSingletonCount(), 2);
259
260   struct ATag {};
261   SingletonSharedPtrUsage<Watchdog, ATag> named_watchdog_singleton;
262
263   SingletonSharedPtrUsage<WatchdogHolder> watchdog_holder_singleton;
264
265   vault.registrationComplete();
266
267   // Initilize holder singleton first, so that it's the last one to be
268   // destroyed.
269   watchdog_holder_singleton.try_get();
270
271   auto s1 = SingletonSharedPtrUsage<Watchdog>::try_get().get();
272   EXPECT_NE(s1, nullptr);
273
274   auto s2 = SingletonSharedPtrUsage<Watchdog>::try_get().get();
275   EXPECT_NE(s2, nullptr);
276
277   EXPECT_EQ(s1, s2);
278
279   auto weak_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
280
281   auto shared_s1 = weak_s1.lock();
282   EXPECT_EQ(shared_s1.get(), s1);
283   EXPECT_EQ(shared_s1.use_count(), 2);
284
285   auto old_serial = shared_s1->serial_number;
286
287   {
288     auto named_weak_s1 =
289       SingletonSharedPtrUsage<Watchdog, ATag>::get_weak();
290     auto locked = named_weak_s1.lock();
291     EXPECT_NE(locked.get(), shared_s1.get());
292   }
293
294   // We should release externally locked shared_ptr, otherwise it will be
295   // considered a leak
296   watchdog_holder_singleton.try_get()->watchdog = std::move(shared_s1);
297
298   LOG(ERROR) << "The following log message regarding shared_ptr is expected";
299   {
300     auto start_time = std::chrono::steady_clock::now();
301     vault.destroyInstances();
302     auto duration = std::chrono::steady_clock::now() - start_time;
303     EXPECT_TRUE(duration > std::chrono::seconds{4} &&
304                 duration < std::chrono::seconds{6});
305   }
306   EXPECT_EQ(vault.registeredSingletonCount(), 4);
307   EXPECT_EQ(vault.livingSingletonCount(), 0);
308
309   EXPECT_TRUE(weak_s1.expired());
310
311   auto empty_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
312   EXPECT_FALSE(empty_s1.lock());
313
314   vault.reenableInstances();
315
316   {
317     // Singleton should be re-created only after reenableInstances() was called.
318     auto new_s1 = SingletonSharedPtrUsage<Watchdog>::try_get();
319     // Track serial number rather than pointer since the memory could be
320     // re-used when we create new_s1.
321     EXPECT_NE(new_s1->serial_number, old_serial);
322   }
323
324   auto new_s1_weak = SingletonSharedPtrUsage<Watchdog>::get_weak();
325   auto new_s1_shared = new_s1_weak.lock();
326   std::thread t([new_s1_shared]() mutable {
327       std::this_thread::sleep_for(std::chrono::seconds{2});
328       new_s1_shared.reset();
329     });
330   new_s1_shared.reset();
331   {
332     auto start_time = std::chrono::steady_clock::now();
333     vault.destroyInstances();
334     auto duration = std::chrono::steady_clock::now() - start_time;
335     EXPECT_TRUE(duration > std::chrono::seconds{1} &&
336                 duration < std::chrono::seconds{3});
337   }
338   EXPECT_TRUE(new_s1_weak.expired());
339   t.join();
340 }
341
342 // Some classes to test singleton dependencies.  NeedySingleton has a
343 // dependency on NeededSingleton, which happens during its
344 // construction.
345 struct NeedyTag {};
346 template <typename T, typename Tag = detail::DefaultTag>
347 using SingletonNeedy = Singleton <T, Tag, NeedyTag>;
348
349 struct NeededSingleton {};
350 struct NeedySingleton {
351   NeedySingleton() {
352     auto unused = SingletonNeedy<NeededSingleton>::try_get();
353     EXPECT_NE(unused, nullptr);
354   }
355 };
356
357 // Ensure circular dependencies fail -- a singleton that needs itself, whoops.
358 struct SelfNeedyTag {};
359 template <typename T, typename Tag = detail::DefaultTag>
360 using SingletonSelfNeedy = Singleton <T, Tag, SelfNeedyTag>;
361
362 struct SelfNeedySingleton {
363   SelfNeedySingleton() {
364     auto unused = SingletonSelfNeedy<SelfNeedySingleton>::try_get();
365     EXPECT_NE(unused, nullptr);
366   }
367 };
368
369 TEST(Singleton, SingletonDependencies) {
370   SingletonNeedy<NeededSingleton> needed_singleton;
371   SingletonNeedy<NeedySingleton> needy_singleton;
372   auto& needy_vault = *SingletonVault::singleton<NeedyTag>();
373
374   needy_vault.registrationComplete();
375
376   EXPECT_EQ(needy_vault.registeredSingletonCount(), 2);
377   EXPECT_EQ(needy_vault.livingSingletonCount(), 0);
378
379   auto needy = SingletonNeedy<NeedySingleton>::try_get();
380   EXPECT_EQ(needy_vault.livingSingletonCount(), 2);
381
382   SingletonSelfNeedy<SelfNeedySingleton> self_needy_singleton;
383   auto& self_needy_vault = *SingletonVault::singleton<SelfNeedyTag>();
384
385   self_needy_vault.registrationComplete();
386   EXPECT_DEATH([]() { SingletonSelfNeedy<SelfNeedySingleton>::try_get(); }(),
387       "");
388 }
389
390 // A test to ensure multiple threads contending on singleton creation
391 // properly wait for creation rather than thinking it is a circular
392 // dependency.
393 class Slowpoke : public Watchdog {
394  public:
395   Slowpoke() { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
396 };
397
398 struct ConcurrencyTag {};
399 template <typename T, typename Tag = detail::DefaultTag>
400 using SingletonConcurrency = Singleton <T, Tag, ConcurrencyTag>;
401
402 TEST(Singleton, SingletonConcurrency) {
403   auto& vault = *SingletonVault::singleton<ConcurrencyTag>();
404   SingletonConcurrency<Slowpoke> slowpoke_singleton;
405   vault.registrationComplete();
406
407   std::mutex gatekeeper;
408   gatekeeper.lock();
409   auto func = [&gatekeeper]() {
410     gatekeeper.lock();
411     gatekeeper.unlock();
412     auto unused = SingletonConcurrency<Slowpoke>::try_get();
413   };
414
415   EXPECT_EQ(vault.livingSingletonCount(), 0);
416   std::vector<std::thread> threads;
417   for (int i = 0; i < 100; ++i) {
418     threads.emplace_back(func);
419   }
420   // If circular dependency checks fail, the unlock would trigger a
421   // crash.  Instead, it succeeds, and we have exactly one living
422   // singleton.
423   gatekeeper.unlock();
424   for (auto& t : threads) {
425     t.join();
426   }
427   EXPECT_EQ(vault.livingSingletonCount(), 1);
428 }
429
430 struct ErrorConstructor {
431   static size_t constructCount_;
432   ErrorConstructor() {
433     if ((constructCount_++) == 0) {
434       throw std::runtime_error("first time fails");
435     }
436   }
437 };
438 size_t ErrorConstructor::constructCount_(0);
439
440 struct CreationErrorTag {};
441 template <typename T, typename Tag = detail::DefaultTag>
442 using SingletonCreationError = Singleton<T, Tag, CreationErrorTag>;
443
444 TEST(Singleton, SingletonCreationError) {
445   auto& vault = *SingletonVault::singleton<CreationErrorTag>();
446   SingletonCreationError<ErrorConstructor> error_once_singleton;
447
448   // first time should error out
449   EXPECT_THROW(error_once_singleton.get_weak().lock(), std::runtime_error);
450
451   // second time it'll work fine
452   error_once_singleton.get_weak().lock();
453   SUCCEED();
454 }
455
456 struct ConcurrencyStressTag {};
457 template <typename T, typename Tag = detail::DefaultTag>
458 using SingletonConcurrencyStress = Singleton <T, Tag, ConcurrencyStressTag>;
459
460 TEST(Singleton, SingletonConcurrencyStress) {
461   auto& vault = *SingletonVault::singleton<ConcurrencyStressTag>();
462   SingletonConcurrencyStress<Slowpoke> slowpoke_singleton;
463
464   std::vector<std::thread> ts;
465   for (size_t i = 0; i < 100; ++i) {
466     ts.emplace_back([&]() {
467         slowpoke_singleton.get_weak().lock();
468       });
469   }
470
471   for (size_t i = 0; i < 100; ++i) {
472     std::chrono::milliseconds d(20);
473
474     std::this_thread::sleep_for(d);
475     vault.destroyInstances();
476     std::this_thread::sleep_for(d);
477     vault.destroyInstances();
478   }
479
480   for (auto& t : ts) {
481     t.join();
482   }
483 }
484
485 // Benchmarking a normal singleton vs a Meyers singleton vs a Folly
486 // singleton.  Meyers are insanely fast, but (hopefully) Folly
487 // singletons are fast "enough."
488 int* getMeyersSingleton() {
489   static auto ret = new int(0);
490   return ret;
491 }
492
493 int normal_singleton_value = 0;
494 int* getNormalSingleton() {
495   doNotOptimizeAway(&normal_singleton_value);
496   return &normal_singleton_value;
497 }
498
499 struct MockTag {};
500 template <typename T, typename Tag = detail::DefaultTag>
501 using SingletonMock = Singleton <T, Tag, MockTag>;
502
503 // Verify that existing Singleton's can be overridden
504 // using the make_mock functionality.
505 TEST(Singleton, MockTest) {
506   auto& vault = *SingletonVault::singleton<MockTag>();
507
508   SingletonMock<Watchdog> watchdog_singleton;
509   vault.registrationComplete();
510
511   // Registring singletons after registrationComplete called works
512   // with make_mock (but not with Singleton ctor).
513   EXPECT_EQ(vault.registeredSingletonCount(), 1);
514   int serial_count_first = SingletonMock<Watchdog>::try_get()->serial_number;
515
516   // Override existing mock using make_mock.
517   SingletonMock<Watchdog>::make_mock();
518
519   EXPECT_EQ(vault.registeredSingletonCount(), 1);
520   int serial_count_mock = SingletonMock<Watchdog>::try_get()->serial_number;
521
522   // If serial_count value is the same, then singleton was not replaced.
523   EXPECT_NE(serial_count_first, serial_count_mock);
524 }
525
526 struct BenchmarkSingleton {
527   int val = 0;
528 };
529
530 BENCHMARK(NormalSingleton, n) {
531   for (size_t i = 0; i < n; ++i) {
532     doNotOptimizeAway(getNormalSingleton());
533   }
534 }
535
536 BENCHMARK_RELATIVE(MeyersSingleton, n) {
537   for (size_t i = 0; i < n; ++i) {
538     doNotOptimizeAway(getMeyersSingleton());
539   }
540 }
541
542 struct BenchmarkTag {};
543 template <typename T, typename Tag = detail::DefaultTag>
544 using SingletonBenchmark = Singleton <T, Tag, BenchmarkTag>;
545
546 struct GetTag{};
547 struct GetWeakTag{};
548
549 SingletonBenchmark<BenchmarkSingleton, GetTag> benchmark_singleton_get;
550 SingletonBenchmark<BenchmarkSingleton, GetWeakTag> benchmark_singleton_get_weak;
551
552 BENCHMARK_RELATIVE(FollySingleton, n) {
553   for (size_t i = 0; i < n; ++i) {
554     SingletonBenchmark<BenchmarkSingleton, GetTag>::try_get();
555   }
556 }
557
558 BENCHMARK_RELATIVE(FollySingletonWeak, n) {
559   for (size_t i = 0; i < n; ++i) {
560     SingletonBenchmark<BenchmarkSingleton, GetWeakTag>::get_weak();
561   }
562 }
563
564 int main(int argc, char* argv[]) {
565   testing::InitGoogleTest(&argc, argv);
566   google::InitGoogleLogging(argv[0]);
567   gflags::ParseCommandLineFlags(&argc, &argv, true);
568
569   SingletonVault::singleton()->registrationComplete();
570
571   auto ret = RUN_ALL_TESTS();
572   if (!ret) {
573     folly::runBenchmarksOnFlag();
574   }
575   return ret;
576 }