source: mainline/uspace/lib/cpp/src/__bits/test/memory.cpp@ 8624d1f

Last change on this file since 8624d1f was b57ba05, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 3 years ago

Update headers in C++ files

  • Property mode set to 100644
File size: 11.6 KB
Line 
1/*
2 * SPDX-FileCopyrightText: 2018 Jaroslav Jindrak
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <__bits/test/mock.hpp>
8#include <__bits/test/tests.hpp>
9#include <initializer_list>
10#include <memory>
11#include <type_traits>
12#include <utility>
13
14namespace std::test
15{
16 namespace aux
17 {
18 struct dummy_pointer1
19 {
20 using element_type = int;
21 using difference_type = bool;
22
23 template<class U>
24 using rebind = unsigned;
25
26 int tag{};
27
28 static dummy_pointer1 pointer_to(element_type& x)
29 {
30 dummy_pointer1 res;
31 res.tag = x;
32 return res;
33 }
34 };
35
36 template<class T, class... Args>
37 struct dummy_pointer2
38 {
39 using element_type = signed char;
40 using difference_type = unsigned char;
41 };
42
43 struct dummy_allocator1
44 {
45 using value_type = int;
46 };
47
48 struct dummy_allocator2
49 {
50 using value_type = int;
51 using pointer = char*;
52 using const_pointer = const void*;
53 using void_pointer = bool*;
54 using const_void_pointer = volatile bool*;
55 using difference_type = short;
56 using size_type = long;
57
58 using propagate_on_container_copy_assignment = std::true_type;
59 using propagate_on_container_move_assignment = std::true_type;
60 using propagate_on_container_swap = std::true_type;
61 using is_always_equal = std::true_type;
62 };
63 }
64
65 bool memory_test::run(bool report)
66 {
67 report_ = report;
68 start();
69
70 test_unique_ptr();
71 test_shared_ptr();
72 test_weak_ptr();
73 test_allocators();
74 test_pointers();
75
76 return end();
77 }
78
79 const char* memory_test::name()
80 {
81 return "memory";
82 }
83
84 void memory_test::test_unique_ptr()
85 {
86 mock::clear();
87 {
88 auto ptr = std::make_unique<mock>();
89 test_eq("unique_ptr get() when non-null", (ptr.get() != nullptr), true);
90 test_eq("unique_ptr operator bool when non-null", (bool)ptr, true);
91 }
92 test_eq("unique_ptr make_unique", mock::constructor_calls, 1U);
93 test_eq("unique_ptr out of scope", mock::destructor_calls, 1U);
94
95 mock::clear();
96 {
97 auto ptr = std::make_unique<mock>();
98 delete ptr.release();
99 }
100 test_eq("unique_ptr release", mock::destructor_calls, 1U);
101
102 mock::clear();
103 {
104 auto ptr = std::make_unique<mock>();
105 ptr.reset(new mock{});
106 }
107 test_eq("unique_ptr reset", mock::destructor_calls, 2U);
108
109 mock::clear();
110 {
111 std::unique_ptr<mock> ptr1{};
112 test_eq("unique_ptr get() when null", ptr1.get(), nullptr);
113 test_eq("unique_ptr operator bool when null", (bool)ptr1, false);
114 {
115 auto ptr2 = std::make_unique<mock>();
116 ptr1 = std::move(ptr2);
117 }
118 test_eq("unique_ptr move pt1", mock::destructor_calls, 0U);
119 }
120 test_eq("unique_ptr move pt2", mock::destructor_calls, 1U);
121
122 mock::clear();
123 {
124 auto ptr = std::make_unique<mock[]>(10U);
125 test_eq("unique_ptr make_unique array version", mock::constructor_calls, 10U);
126
127 new(&ptr[5]) mock{};
128 test_eq("placement new into the array", mock::constructor_calls, 11U);
129 test_eq("original not destroyed during placement new", mock::destructor_calls, 0U);
130 }
131 test_eq("unique_ptr array out of scope", mock::destructor_calls, 10U);
132 }
133
134 void memory_test::test_shared_ptr()
135 {
136 mock::clear();
137 {
138 auto ptr1 = std::make_shared<mock>();
139 test_eq("shared_ptr make_shared", mock::constructor_calls, 1U);
140 test_eq("shared_ptr unique", ptr1.unique(), true);
141 {
142 auto ptr2 = ptr1;
143 test_eq("shared_ptr copy pt1", ptr1.use_count(), 2L);
144 test_eq("shared_ptr copy pt2", ptr2.use_count(), 2L);
145 test_eq("shared_ptr copy no constructor call", mock::copy_constructor_calls, 0U);
146 test_eq("shared_ptr not unique", ptr1.unique(), false);
147
148 auto ptr3 = std::move(ptr2);
149 test_eq("shared_ptr move pt1", ptr1.use_count(), 2L);
150 test_eq("shared_ptr move pt2", ptr3.use_count(), 2L);
151 test_eq("shared_ptr move pt3", ptr2.use_count(), 0L);
152
153 test_eq("shared_ptr move origin empty", (bool)ptr2, false);
154 }
155 test_eq("shared_ptr copy out of scope", mock::destructor_calls, 0U);
156 }
157 test_eq("shared_ptr original out of scope", mock::destructor_calls, 1U);
158 }
159
160 void memory_test::test_weak_ptr()
161 {
162 mock::clear();
163 {
164 std::weak_ptr<mock> wptr1{};
165 {
166 auto ptr1 = std::make_shared<mock>();
167 wptr1 = ptr1;
168 {
169 std::weak_ptr<mock> wptr2 = ptr1;
170 test_eq("weak_ptr shares use count", wptr2.use_count(), 1L);
171 test_eq("weak_ptr not expired", wptr2.expired(), false);
172
173 auto ptr2 = wptr2.lock();
174 test_eq("locked ptr increases use count", ptr1.use_count(), 2L);
175 }
176 }
177 test_eq("weak_ptr expired after all shared_ptrs die", wptr1.expired(), true);
178 test_eq("shared object destroyed while weak_ptr exists", mock::destructor_calls, 1U);
179 }
180 }
181
182 void memory_test::test_allocators()
183 {
184 using dummy_traits1 = std::allocator_traits<aux::dummy_allocator1>;
185 using dummy_traits2 = std::allocator_traits<aux::dummy_allocator2>;
186
187 /**
188 * First dummy allocator doesn't provide
189 * anything except for the mandatory value_type,
190 * so we get all the defaults here.
191 */
192 test(
193 "allocator traits default for pointer",
194 std::is_same_v<typename dummy_traits1::pointer, int*>
195 );
196 test(
197 "allocator traits default for const_pointer",
198 std::is_same_v<typename dummy_traits1::const_pointer, const int*>
199 );
200 test(
201 "allocator traits default for void_pointer",
202 std::is_same_v<typename dummy_traits1::void_pointer, void*>
203 );
204 test(
205 "allocator traits default for const_void_pointer",
206 std::is_same_v<typename dummy_traits1::const_void_pointer, const void*>
207 );
208 test(
209 "allocator traits default for difference_type",
210 std::is_same_v<typename dummy_traits1::difference_type, ptrdiff_t>
211 );
212 test(
213 "allocator traits default for size_type",
214 std::is_same_v<typename dummy_traits1::size_type, std::make_unsigned_t<ptrdiff_t>>
215 );
216 test(
217 "allocator traits default for copy propagate",
218 std::is_same_v<typename dummy_traits1::propagate_on_container_copy_assignment, std::false_type>
219 );
220 test(
221 "allocator traits default for move propagate",
222 std::is_same_v<typename dummy_traits1::propagate_on_container_move_assignment, std::false_type>
223 );
224 test(
225 "allocator traits default for swap propagate",
226 std::is_same_v<typename dummy_traits1::propagate_on_container_swap, std::false_type>
227 );
228 test(
229 "allocator traits default for is_always_equal",
230 std::is_same_v<typename dummy_traits1::is_always_equal, typename std::is_empty<aux::dummy_allocator1>::type>
231 );
232
233 /**
234 * Second dummy allocator provides all typedefs, so
235 * the the traits just use identity.
236 */
237 test(
238 "allocator traits given pointer",
239 std::is_same_v<typename dummy_traits2::pointer, char*>
240 );
241 test(
242 "allocator traits given const_pointer",
243 std::is_same_v<typename dummy_traits2::const_pointer, const void*>
244 );
245 test(
246 "allocator traits given void_pointer",
247 std::is_same_v<typename dummy_traits2::void_pointer, bool*>
248 );
249 test(
250 "allocator traits given const_void_pointer",
251 std::is_same_v<typename dummy_traits2::const_void_pointer, volatile bool*>
252 );
253 test(
254 "allocator traits given difference_type",
255 std::is_same_v<typename dummy_traits2::difference_type, short>
256 );
257 test(
258 "allocator traits given size_type",
259 std::is_same_v<typename dummy_traits2::size_type, long>
260 );
261 test(
262 "allocator traits given copy propagate",
263 std::is_same_v<typename dummy_traits2::propagate_on_container_copy_assignment, std::true_type>
264 );
265 test(
266 "allocator traits given move propagate",
267 std::is_same_v<typename dummy_traits2::propagate_on_container_move_assignment, std::true_type>
268 );
269 test(
270 "allocator traits given swap propagate",
271 std::is_same_v<typename dummy_traits2::propagate_on_container_swap, std::true_type>
272 );
273 test(
274 "allocator traits given is_always_equal",
275 std::is_same_v<typename dummy_traits2::is_always_equal, std::true_type>
276 );
277 }
278
279 void memory_test::test_pointers()
280 {
281 using dummy_traits1 = std::pointer_traits<aux::dummy_pointer1>;
282 using dummy_traits2 = std::pointer_traits<aux::dummy_pointer2<int, char>>;
283 using int_traits = std::pointer_traits<int*>;
284
285 test(
286 "pointer traits pointer pt1",
287 std::is_same_v<typename dummy_traits1::pointer, aux::dummy_pointer1>
288 );
289 test(
290 "pointer traits element_type pt1",
291 std::is_same_v<typename dummy_traits1::element_type, int>
292 );
293 test(
294 "pointer traits difference_type pt1",
295 std::is_same_v<typename dummy_traits1::difference_type, bool>
296 );
297 test(
298 "pointer traits rebind pt1",
299 std::is_same_v<typename dummy_traits1::template rebind<long>, unsigned>
300 );
301
302 test(
303 "pointer traits pointer pt2",
304 std::is_same_v<typename dummy_traits2::pointer, aux::dummy_pointer2<int, char>>
305 );
306 test(
307 "pointer traits element_type pt2",
308 std::is_same_v<typename dummy_traits2::element_type, signed char>
309 );
310 test(
311 "pointer traits difference_type pt2",
312 std::is_same_v<typename dummy_traits2::difference_type, unsigned char>
313 );
314 test(
315 "pointer traits rebind pt2",
316 std::is_same_v<typename dummy_traits2::template rebind<long>, aux::dummy_pointer2<long, char>>
317 );
318
319 test(
320 "pointer traits pointer pt3",
321 std::is_same_v<typename int_traits::pointer, int*>
322 );
323 test(
324 "pointer traits element_type pt3",
325 std::is_same_v<typename int_traits::element_type, int>
326 );
327 test(
328 "pointer traits difference_type pt3",
329 std::is_same_v<typename int_traits::difference_type, ptrdiff_t>
330 );
331 test(
332 "pointer traits rebind pt3",
333 std::is_same_v<typename int_traits::rebind<char>, char*>
334 );
335
336 int x{10};
337 test_eq("pointer_traits<Ptr>::pointer_to", dummy_traits1::pointer_to(x).tag, 10);
338 test_eq("pointer_traits<T*>::pointer_to", int_traits::pointer_to(x), &x);
339 }
340}
Note: See TracBrowser for help on using the repository browser.