1 /*
2  *  Copyright (c) 2016, Facebook, Inc.
3  *  All rights reserved.
4  *
5  *  This source code is licensed under the BSD-style license found in the
6  *  LICENSE file in the root directory of this source tree. An additional grant
7  *  of patent rights can be found in the PATENTS file in the same directory.
8  */
9 
10 #include <fatal/type/pointer_selector.h>
11 
12 #include <fatal/test/driver.h>
13 
14 #include <memory>
15 
16 namespace fatal {
17 
18 struct test_deleter {
19   template <typename T>
operator ()fatal::test_deleter20   void operator ()(T *p) const { delete p; }
21 };
22 
FATAL_TEST(pointer_selector,element_type)23 FATAL_TEST(pointer_selector, element_type) {
24   FATAL_EXPECT_SAME<
25     int,
26     pointer_selector<pointer_class::raw, int>::element_type
27   >();
28 
29   FATAL_EXPECT_SAME<
30     int const,
31     pointer_selector<pointer_class::raw, int const>::element_type
32   >();
33 
34   FATAL_EXPECT_SAME<
35     int,
36     pointer_selector<pointer_class::unique, int>::element_type
37   >();
38 
39   FATAL_EXPECT_SAME<
40     int const,
41     pointer_selector<pointer_class::unique, int const>::element_type
42   >();
43 
44   FATAL_EXPECT_SAME<
45     int,
46     pointer_selector<pointer_class::unique, int, test_deleter>::element_type
47   >();
48 
49   FATAL_EXPECT_SAME<
50     int const,
51     pointer_selector<
52       pointer_class::unique, int const, test_deleter
53     >::element_type
54   >();
55 
56   FATAL_EXPECT_SAME<
57     int,
58     pointer_selector<pointer_class::shared, int>::element_type
59   >();
60 
61   FATAL_EXPECT_SAME<
62     int const,
63     pointer_selector<pointer_class::shared, int const>::element_type
64   >();
65 }
66 
FATAL_TEST(pointer_selector,pointer)67 FATAL_TEST(pointer_selector, pointer) {
68   FATAL_EXPECT_SAME<
69     int *,
70     pointer_selector<pointer_class::raw, int>::pointer
71   >();
72 
73   FATAL_EXPECT_SAME<
74     int const *,
75     pointer_selector<pointer_class::raw, int const>::pointer
76   >();
77 
78   FATAL_EXPECT_SAME<
79     int *,
80     pointer_selector<pointer_class::unique, int>::pointer
81   >();
82 
83   FATAL_EXPECT_SAME<
84     int const *,
85     pointer_selector<pointer_class::unique, int const>::pointer
86   >();
87 
88   FATAL_EXPECT_SAME<
89     int *,
90     pointer_selector<pointer_class::unique, int, test_deleter>::pointer
91   >();
92 
93   FATAL_EXPECT_SAME<
94     int const *,
95     pointer_selector<pointer_class::unique, int const, test_deleter>::pointer
96   >();
97 
98   FATAL_EXPECT_SAME<
99     int *,
100     pointer_selector<pointer_class::shared, int>::pointer
101   >();
102 
103   FATAL_EXPECT_SAME<
104     int const *,
105     pointer_selector<pointer_class::shared, int const>::pointer
106   >();
107 }
108 
FATAL_TEST(pointer_selector,type)109 FATAL_TEST(pointer_selector, type) {
110   FATAL_EXPECT_SAME<
111     int *,
112     pointer_selector<pointer_class::raw, int>::type
113   >();
114 
115   FATAL_EXPECT_SAME<
116     int const *,
117     pointer_selector<pointer_class::raw, int const>::type
118   >();
119 
120   FATAL_EXPECT_SAME<
121     std::unique_ptr<int>,
122     pointer_selector<pointer_class::unique, int>::type
123   >();
124 
125   FATAL_EXPECT_SAME<
126     std::unique_ptr<int const>,
127     pointer_selector<pointer_class::unique, int const>::type
128   >();
129 
130   FATAL_EXPECT_SAME<
131     std::unique_ptr<int, test_deleter>,
132     pointer_selector<pointer_class::unique, int, test_deleter>::type
133   >();
134 
135   FATAL_EXPECT_SAME<
136     std::unique_ptr<int const, test_deleter>,
137     pointer_selector<pointer_class::unique, int const, test_deleter>::type
138   >();
139 
140   FATAL_EXPECT_SAME<
141     std::shared_ptr<int>,
142     pointer_selector<pointer_class::shared, int>::type
143   >();
144 
145   FATAL_EXPECT_SAME<
146     std::shared_ptr<int const>,
147     pointer_selector<pointer_class::shared, int const>::type
148   >();
149 }
150 
FATAL_TEST(pointer_selector,managed)151 FATAL_TEST(pointer_selector, managed) {
152   FATAL_EXPECT_FALSE((
153     pointer_selector<pointer_class::raw, int>::managed::value
154   ));
155   FATAL_EXPECT_FALSE((
156     pointer_selector<pointer_class::raw, int const>::managed::value
157   ));
158   FATAL_EXPECT_TRUE((
159     pointer_selector<pointer_class::unique, int>::managed::value
160   ));
161   FATAL_EXPECT_TRUE((
162     pointer_selector<pointer_class::unique, int const>::managed::value
163   ));
164   FATAL_EXPECT_TRUE((
165     pointer_selector<pointer_class::unique, int, test_deleter>::managed::value
166   ));
167   FATAL_EXPECT_TRUE((
168     pointer_selector<
169       pointer_class::unique, int const, test_deleter
170     >::managed::value
171   ));
172   FATAL_EXPECT_TRUE((
173     pointer_selector<pointer_class::shared, int>::managed::value
174   ));
175   FATAL_EXPECT_TRUE((
176     pointer_selector<pointer_class::shared, int const>::managed::value
177   ));
178 }
179 
180 struct pointer_selector_tester {
pointer_selector_testerfatal::pointer_selector_tester181   pointer_selector_tester(int &v_): v(v_) { v = 99; }
~pointer_selector_testerfatal::pointer_selector_tester182   ~pointer_selector_tester() { v = 55; }
183 
184 private:
185   int &v;
186 };
187 
FATAL_TEST(pointer_selector,make_get_destroy)188 FATAL_TEST(pointer_selector, make_get_destroy) {
189 # define TEST_IMPL(PtrClass, ...) \
190   do { \
191     value = 11; \
192     using selector = pointer_selector<pointer_class::PtrClass, __VA_ARGS__>; \
193     { \
194       auto p = selector::make(value); \
195       FATAL_ASSERT_NE(nullptr, selector::get(p)); \
196       FATAL_EXPECT_EQ(99, value); \
197       if (!selector::managed::value) { \
198         selector::destroy(p); \
199       } \
200     } \
201     FATAL_EXPECT_EQ(55, value); \
202     \
203     value = 22; \
204     auto p = selector::make(value); \
205     FATAL_ASSERT_NE(nullptr, selector::get(p)); \
206     FATAL_EXPECT_EQ(99, value); \
207     selector::destroy(p); \
208     if (selector::managed::value) { \
209       FATAL_EXPECT_EQ(nullptr, selector::get(p)); \
210     } \
211     FATAL_EXPECT_EQ(55, value); \
212   } while (false)
213 
214   int value = 0;
215 
216   TEST_IMPL(raw, pointer_selector_tester);
217   TEST_IMPL(unique, pointer_selector_tester);
218   TEST_IMPL(unique, pointer_selector_tester, test_deleter);
219   TEST_IMPL(shared, pointer_selector_tester);
220 
221 # undef TEST_IMPL
222 }
223 
FATAL_TEST(pointer_selector_t,sanity_check)224 FATAL_TEST(pointer_selector_t, sanity_check) {
225   FATAL_EXPECT_SAME<
226     int *,
227     pointer_selector_t<pointer_class::raw, int>
228   >();
229 
230   FATAL_EXPECT_SAME<
231     int const *,
232     pointer_selector_t<pointer_class::raw, int const>
233   >();
234 
235   FATAL_EXPECT_SAME<
236     std::unique_ptr<int>,
237     pointer_selector_t<pointer_class::unique, int>
238   >();
239 
240   FATAL_EXPECT_SAME<
241     std::unique_ptr<int const>,
242     pointer_selector_t<pointer_class::unique, int const>
243   >();
244 
245   FATAL_EXPECT_SAME<
246     std::unique_ptr<int, test_deleter>,
247     pointer_selector_t<pointer_class::unique, int, test_deleter>
248   >();
249 
250   FATAL_EXPECT_SAME<
251     std::unique_ptr<int const, test_deleter>,
252     pointer_selector_t<pointer_class::unique, int const, test_deleter>
253   >();
254 
255   FATAL_EXPECT_SAME<
256     std::shared_ptr<int>,
257     pointer_selector_t<pointer_class::shared, int>
258   >();
259 
260   FATAL_EXPECT_SAME<
261     std::shared_ptr<int const>,
262     pointer_selector_t<pointer_class::shared, int const>
263   >();
264 }
265 
FATAL_TEST(make_ptr,sanity_check)266 FATAL_TEST(make_ptr, sanity_check) {
267 # define TEST_IMPL(PtrClass, ...) \
268   do { \
269     value = 12; \
270     using selector = pointer_selector<pointer_class::PtrClass, __VA_ARGS__>; \
271     { \
272       auto p = make_ptr<pointer_class::PtrClass, __VA_ARGS__>(value); \
273       FATAL_ASSERT_NE(nullptr, selector::get(p)); \
274       FATAL_EXPECT_EQ(99, value); \
275       if (!selector::managed::value) { \
276         selector::destroy(p); \
277       } \
278     } \
279     FATAL_EXPECT_EQ(55, value); \
280     \
281     value = 22; \
282     auto p = make_ptr<pointer_class::PtrClass, __VA_ARGS__>(value); \
283     FATAL_ASSERT_NE(nullptr, selector::get(p)); \
284     FATAL_EXPECT_EQ(99, value); \
285     selector::destroy(p); \
286     if (selector::managed::value) { \
287       FATAL_EXPECT_EQ(nullptr, selector::get(p)); \
288     } \
289     FATAL_EXPECT_EQ(55, value); \
290   } while (false)
291 
292   int value = 0;
293 
294   TEST_IMPL(raw, pointer_selector_tester);
295   TEST_IMPL(unique, pointer_selector_tester);
296   TEST_IMPL(unique, pointer_selector_tester, test_deleter);
297   TEST_IMPL(shared, pointer_selector_tester);
298 
299 # undef TEST_IMPL
300 }
301 
302 } // namespace fatal {
303