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