1 /*
2 * Copyright (c) Facebook, Inc. and its affiliates.
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 <folly/detail/StaticSingletonManager.h>
18
19 #include <folly/lang/Keep.h>
20 #include <folly/portability/GTest.h>
21
22 namespace folly {
23 namespace detail {
24
check_doit()25 FOLLY_ATTR_WEAK void check_doit() {}
26
27 namespace {
28 template <bool Noexcept>
29 struct MayThrow {
MayThrowfolly::detail::__anon384fdae80111::MayThrow30 FOLLY_NOINLINE MayThrow() noexcept(Noexcept) { check_doit(); }
~MayThrowfolly::detail::__anon384fdae80111::MayThrow31 FOLLY_NOINLINE ~MayThrow() { check_doit(); }
32 };
33 } // namespace
34
check()35 extern "C" FOLLY_KEEP int* check() {
36 return &createGlobal<int, void>();
37 }
38
check_throw()39 extern "C" FOLLY_KEEP void* check_throw() {
40 return &createGlobal<MayThrow<false>, void>();
41 }
42
check_nothrow()43 extern "C" FOLLY_KEEP void* check_nothrow() {
44 return &createGlobal<MayThrow<true>, void>();
45 }
46
47 struct StaticSingletonManagerTest : public testing::Test {};
48
49 template <typename T>
50 struct Tag {};
51
52 template <int I>
53 using Int = std::integral_constant<int, I>;
54
TEST_F(StaticSingletonManagerTest,example_sans_rtti)55 TEST_F(StaticSingletonManagerTest, example_sans_rtti) {
56 using K = StaticSingletonManagerSansRtti;
57
58 using T = std::integral_constant<int, 3>;
59
60 auto& i = K::create<T, Tag<char>>();
61 EXPECT_EQ(T::value, i);
62
63 auto& j = K::create<T, Tag<char>>();
64 EXPECT_EQ(&i, &j);
65 EXPECT_EQ(T::value, j);
66
67 auto& k = K::create<T, Tag<char*>>();
68 EXPECT_NE(&i, &k);
69 EXPECT_EQ(T::value, k);
70
71 static K::ArgCreate<true> m_arg{tag<T, Tag<int>>};
72 auto& m = K::create<T>(m_arg);
73 EXPECT_NE(&i, &m);
74 EXPECT_EQ(T::value, m);
75 }
76
TEST_F(StaticSingletonManagerTest,example_with_rtti)77 TEST_F(StaticSingletonManagerTest, example_with_rtti) {
78 using K = StaticSingletonManagerWithRtti;
79
80 using T = std::integral_constant<int, 3>;
81
82 auto& i = K::create<T, Tag<char>>();
83 EXPECT_EQ(T::value, i);
84
85 auto& j = K::create<T, Tag<char>>();
86 EXPECT_EQ(&i, &j);
87 EXPECT_EQ(T::value, j);
88
89 auto& k = K::create<T, Tag<char*>>();
90 EXPECT_NE(&i, &k);
91 EXPECT_EQ(T::value, k);
92
93 static K::ArgCreate<true> m_arg{tag<T, Tag<int>>};
94 auto& m = K::create<T>(m_arg);
95 EXPECT_NE(&i, &m);
96 EXPECT_EQ(T::value, m);
97 }
98
TEST_F(StaticSingletonManagerTest,example)99 TEST_F(StaticSingletonManagerTest, example) {
100 using T = std::integral_constant<int, 3>;
101
102 auto& i = createGlobal<T, Tag<char>>();
103 EXPECT_EQ(T::value, i);
104
105 auto& j = createGlobal<T, Tag<char>>();
106 EXPECT_EQ(&i, &j);
107 EXPECT_EQ(T::value, j);
108
109 auto& k = createGlobal<T, Tag<char*>>();
110 EXPECT_NE(&i, &k);
111 EXPECT_EQ(T::value, k);
112 }
113
114 } // namespace detail
115 } // namespace folly
116