(wangle) fix after-delete assert
[folly.git] / folly / experimental / test / SingletonTest.cpp
1 /*
2  * Copyright 2014 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 // Exercise some basic codepaths ensuring registration order and
87 // destruction order happen as expected, that instances are created
88 // when expected, etc etc.
89 TEST(Singleton, BasicUsage) {
90   SingletonVault vault;
91
92   EXPECT_EQ(vault.registeredSingletonCount(), 0);
93   Singleton<Watchdog> watchdog_singleton(nullptr, nullptr, &vault);
94   EXPECT_EQ(vault.registeredSingletonCount(), 1);
95
96   Singleton<ChildWatchdog> child_watchdog_singleton(nullptr, nullptr, &vault);
97   EXPECT_EQ(vault.registeredSingletonCount(), 2);
98
99   vault.registrationComplete();
100
101   Watchdog* s1 = Singleton<Watchdog>::get(&vault);
102   EXPECT_NE(s1, nullptr);
103
104   Watchdog* s2 = Singleton<Watchdog>::get(&vault);
105   EXPECT_NE(s2, nullptr);
106
107   EXPECT_EQ(s1, s2);
108
109   auto s3 = Singleton<ChildWatchdog>::get(&vault);
110   EXPECT_NE(s3, nullptr);
111   EXPECT_NE(s2, s3);
112
113   EXPECT_EQ(vault.registeredSingletonCount(), 2);
114   EXPECT_EQ(vault.livingSingletonCount(), 2);
115
116   vault.destroyInstances();
117   EXPECT_EQ(vault.registeredSingletonCount(), 2);
118   EXPECT_EQ(vault.livingSingletonCount(), 0);
119 }
120
121 TEST(Singleton, DirectUsage) {
122   SingletonVault vault;
123
124   EXPECT_EQ(vault.registeredSingletonCount(), 0);
125
126   // Verify we can get to the underlying singletons via directly using
127   // the singleton definition.
128   Singleton<Watchdog> watchdog(nullptr, nullptr, &vault);
129   Singleton<Watchdog> named_watchdog("named", nullptr, nullptr, &vault);
130   EXPECT_EQ(vault.registeredSingletonCount(), 2);
131   vault.registrationComplete();
132
133   EXPECT_NE(watchdog.ptr(), nullptr);
134   EXPECT_EQ(watchdog.ptr(), Singleton<Watchdog>::get(&vault));
135   EXPECT_NE(watchdog.ptr(), named_watchdog.ptr());
136   EXPECT_EQ(watchdog->livingWatchdogCount(), 2);
137   EXPECT_EQ((*watchdog).livingWatchdogCount(), 2);
138 }
139
140 TEST(Singleton, NamedUsage) {
141   SingletonVault vault;
142
143   EXPECT_EQ(vault.registeredSingletonCount(), 0);
144
145   // Define two named Watchdog singletons and one unnamed singleton.
146   Singleton<Watchdog> watchdog1_singleton(
147       "watchdog1", nullptr, nullptr, &vault);
148   EXPECT_EQ(vault.registeredSingletonCount(), 1);
149   Singleton<Watchdog> watchdog2_singleton(
150       "watchdog2", nullptr, nullptr, &vault);
151   EXPECT_EQ(vault.registeredSingletonCount(), 2);
152   Singleton<Watchdog> watchdog3_singleton(nullptr, nullptr, &vault);
153   EXPECT_EQ(vault.registeredSingletonCount(), 3);
154
155   vault.registrationComplete();
156
157   // Verify our three singletons are distinct and non-nullptr.
158   Watchdog* s1 = Singleton<Watchdog>::get("watchdog1", &vault);
159   EXPECT_EQ(s1, watchdog1_singleton.ptr());
160   Watchdog* s2 = Singleton<Watchdog>::get("watchdog2", &vault);
161   EXPECT_EQ(s2, watchdog2_singleton.ptr());
162   EXPECT_NE(s1, s2);
163   Watchdog* s3 = Singleton<Watchdog>::get(&vault);
164   EXPECT_EQ(s3, watchdog3_singleton.ptr());
165   EXPECT_NE(s3, s1);
166   EXPECT_NE(s3, s2);
167
168   // Verify the "default" singleton is the same as the empty string
169   // singleton.
170   Watchdog* s4 = Singleton<Watchdog>::get("", &vault);
171   EXPECT_EQ(s4, watchdog3_singleton.ptr());
172 }
173
174 // Some pathological cases such as getting unregistered singletons,
175 // double registration, etc.
176 TEST(Singleton, NaughtyUsage) {
177   SingletonVault vault(SingletonVault::Type::Strict);
178   vault.registrationComplete();
179
180   // Unregistered.
181   EXPECT_THROW(Singleton<Watchdog>::get(), std::out_of_range);
182   EXPECT_THROW(Singleton<Watchdog>::get(&vault), std::out_of_range);
183
184   // Registring singletons after registrationComplete called.
185   EXPECT_THROW([&vault]() {
186                  Singleton<Watchdog> watchdog_singleton(
187                      nullptr, nullptr, &vault);
188                }(),
189                std::logic_error);
190
191   SingletonVault vault_2(SingletonVault::Type::Strict);
192   EXPECT_THROW(Singleton<Watchdog>::get(&vault_2), std::logic_error);
193   Singleton<Watchdog> watchdog_singleton(nullptr, nullptr, &vault_2);
194   // double registration
195   EXPECT_THROW([&vault_2]() {
196                  Singleton<Watchdog> watchdog_singleton(
197                      nullptr, nullptr, &vault_2);
198                }(),
199                std::logic_error);
200   vault_2.destroyInstances();
201   // double registration after destroy
202   EXPECT_THROW([&vault_2]() {
203                  Singleton<Watchdog> watchdog_singleton(
204                      nullptr, nullptr, &vault_2);
205                }(),
206                std::logic_error);
207 }
208
209 TEST(Singleton, SharedPtrUsage) {
210   SingletonVault vault;
211
212   EXPECT_EQ(vault.registeredSingletonCount(), 0);
213   Singleton<Watchdog> watchdog_singleton(nullptr, nullptr, &vault);
214   EXPECT_EQ(vault.registeredSingletonCount(), 1);
215
216   Singleton<ChildWatchdog> child_watchdog_singleton(nullptr, nullptr, &vault);
217   EXPECT_EQ(vault.registeredSingletonCount(), 2);
218
219   Singleton<Watchdog> named_watchdog_singleton(
220       "a_name", nullptr, nullptr, &vault);
221   vault.registrationComplete();
222
223   Watchdog* s1 = Singleton<Watchdog>::get(&vault);
224   EXPECT_NE(s1, nullptr);
225
226   Watchdog* s2 = Singleton<Watchdog>::get(&vault);
227   EXPECT_NE(s2, nullptr);
228
229   EXPECT_EQ(s1, s2);
230
231   auto weak_s1 = Singleton<Watchdog>::get_weak(&vault);
232   auto shared_s1 = weak_s1.lock();
233   EXPECT_EQ(shared_s1.get(), s1);
234   EXPECT_EQ(shared_s1.use_count(), 2);
235
236   {
237     auto named_weak_s1 = Singleton<Watchdog>::get_weak("a_name", &vault);
238     auto locked = named_weak_s1.lock();
239     EXPECT_NE(locked.get(), shared_s1.get());
240   }
241
242   LOG(ERROR) << "The following log message regarding ref counts is expected";
243   vault.destroyInstances();
244   EXPECT_EQ(vault.registeredSingletonCount(), 3);
245   EXPECT_EQ(vault.livingSingletonCount(), 0);
246
247   EXPECT_EQ(shared_s1.use_count(), 1);
248   EXPECT_EQ(shared_s1.get(), s1);
249
250   auto locked_s1 = weak_s1.lock();
251   EXPECT_EQ(locked_s1.get(), s1);
252   EXPECT_EQ(shared_s1.use_count(), 2);
253   locked_s1.reset();
254   EXPECT_EQ(shared_s1.use_count(), 1);
255
256   // Track serial number rather than pointer since the memory could be
257   // re-used when we create new_s1.
258   auto old_serial = shared_s1->serial_number;
259   shared_s1.reset();
260   locked_s1 = weak_s1.lock();
261   EXPECT_TRUE(weak_s1.expired());
262
263   auto empty_s1 = Singleton<Watchdog>::get_weak(&vault);
264   EXPECT_FALSE(empty_s1.lock());
265
266   vault.reenableInstances();
267
268   // Singleton should be re-created only after reenableInstances() was called.
269   Watchdog* new_s1 = Singleton<Watchdog>::get(&vault);
270   EXPECT_NE(new_s1->serial_number, old_serial);
271 }
272
273 // Some classes to test singleton dependencies.  NeedySingleton has a
274 // dependency on NeededSingleton, which happens during its
275 // construction.
276 SingletonVault needy_vault;
277
278 struct NeededSingleton {};
279 struct NeedySingleton {
280   NeedySingleton() {
281     auto unused = Singleton<NeededSingleton>::get(&needy_vault);
282     EXPECT_NE(unused, nullptr);
283   }
284 };
285
286 // Ensure circular dependencies fail -- a singleton that needs itself, whoops.
287 SingletonVault self_needy_vault;
288 struct SelfNeedySingleton {
289   SelfNeedySingleton() {
290     auto unused = Singleton<SelfNeedySingleton>::get(&self_needy_vault);
291     EXPECT_NE(unused, nullptr);
292   }
293 };
294
295 TEST(Singleton, SingletonDependencies) {
296   Singleton<NeededSingleton> needed_singleton(nullptr, nullptr, &needy_vault);
297   Singleton<NeedySingleton> needy_singleton(nullptr, nullptr, &needy_vault);
298   needy_vault.registrationComplete();
299
300   EXPECT_EQ(needy_vault.registeredSingletonCount(), 2);
301   EXPECT_EQ(needy_vault.livingSingletonCount(), 0);
302
303   auto needy = Singleton<NeedySingleton>::get(&needy_vault);
304   EXPECT_EQ(needy_vault.livingSingletonCount(), 2);
305
306   Singleton<SelfNeedySingleton> self_needy_singleton(
307       nullptr, nullptr, &self_needy_vault);
308   self_needy_vault.registrationComplete();
309   EXPECT_THROW([]() {
310                  Singleton<SelfNeedySingleton>::get(&self_needy_vault);
311                }(),
312                std::out_of_range);
313 }
314
315 // A test to ensure multiple threads contending on singleton creation
316 // properly wait for creation rather than thinking it is a circular
317 // dependency.
318 class Slowpoke {
319  public:
320   Slowpoke() { std::this_thread::sleep_for(std::chrono::seconds(1)); }
321 };
322
323 TEST(Singleton, SingletonConcurrency) {
324   SingletonVault vault;
325   Singleton<Slowpoke> slowpoke_singleton(nullptr, nullptr, &vault);
326   vault.registrationComplete();
327
328   std::mutex gatekeeper;
329   gatekeeper.lock();
330   auto func = [&vault, &gatekeeper]() {
331     gatekeeper.lock();
332     gatekeeper.unlock();
333     auto unused = Singleton<Slowpoke>::get(&vault);
334   };
335
336   EXPECT_EQ(vault.livingSingletonCount(), 0);
337   std::vector<std::thread> threads;
338   for (int i = 0; i < 100; ++i) {
339     threads.emplace_back(func);
340   }
341   // If circular dependency checks fail, the unlock would trigger a
342   // crash.  Instead, it succeeds, and we have exactly one living
343   // singleton.
344   gatekeeper.unlock();
345   for (auto& t : threads) {
346     t.join();
347   }
348   EXPECT_EQ(vault.livingSingletonCount(), 1);
349 }
350
351 // Benchmarking a normal singleton vs a Meyers singleton vs a Folly
352 // singleton.  Meyers are insanely fast, but (hopefully) Folly
353 // singletons are fast "enough."
354 int* getMeyersSingleton() {
355   static auto ret = new int(0);
356   return ret;
357 }
358
359 int normal_singleton_value = 0;
360 int* getNormalSingleton() {
361   doNotOptimizeAway(&normal_singleton_value);
362   return &normal_singleton_value;
363 }
364
365 struct BenchmarkSingleton {
366   int val = 0;
367 };
368
369 BENCHMARK(NormalSingleton, n) {
370   for (int i = 0; i < n; ++i) {
371     doNotOptimizeAway(getNormalSingleton());
372   }
373 }
374
375 BENCHMARK_RELATIVE(MeyersSingleton, n) {
376   for (int i = 0; i < n; ++i) {
377     doNotOptimizeAway(getMeyersSingleton());
378   }
379 }
380
381 BENCHMARK_RELATIVE(FollySingleton, n) {
382   SingletonVault benchmark_vault;
383   Singleton<BenchmarkSingleton> benchmark_singleton(
384       nullptr, nullptr, &benchmark_vault);
385   benchmark_vault.registrationComplete();
386
387   for (int i = 0; i < n; ++i) {
388     doNotOptimizeAway(Singleton<BenchmarkSingleton>::get(&benchmark_vault));
389   }
390 }
391
392 int main(int argc, char* argv[]) {
393   testing::InitGoogleTest(&argc, argv);
394   google::InitGoogleLogging(argv[0]);
395   google::ParseCommandLineFlags(&argc, &argv, true);
396
397   SingletonVault::singleton()->registrationComplete();
398
399   auto ret = RUN_ALL_TESTS();
400   if (!ret) {
401     folly::runBenchmarksOnFlag();
402   }
403   return ret;
404 }