source: mainline/uspace/lib/cpp/src/internal/test/memory.cpp@ f31ea60

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f31ea60 was f31ea60, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: added tests for allocator_traits typedefs

  • Property mode set to 100644
File size: 10.8 KB
Line 
1/*
2 * Copyright (c) 2018 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <initializer_list>
30#include <internal/test/mock.hpp>
31#include <internal/test/tests.hpp>
32#include <memory>
33#include <type_traits>
34#include <utility>
35
36namespace std::test
37{
38 namespace aux
39 {
40 struct dummy_pointer1
41 {
42 using element_type = int;
43 using difference_type = bool;
44
45 template<class U>
46 using rebind = unsigned;
47
48 int tag{};
49
50 static dummy_pointer1 pointer_to(element_type& x)
51 {
52 dummy_pointer1 res;
53 res.tag = x;
54 return res;
55 }
56 };
57
58 template<class T, class... Args>
59 struct dummy_pointer2
60 {
61 using element_type = signed char;
62 using difference_type = unsigned char;
63 };
64
65 struct dummy_allocator1
66 {
67 using value_type = int;
68 };
69
70 struct dummy_allocator2
71 {
72 using value_type = int;
73 using pointer = char*;
74 using const_pointer = const void*;
75 using void_pointer = bool*;
76 using const_void_pointer = volatile bool*;
77 using difference_type = short;
78 using size_type = long;
79
80 using propagate_on_container_copy_assignment = std::true_type;
81 using propagate_on_container_move_assignment = std::true_type;
82 using propagate_on_container_swap = std::true_type;
83 using is_always_equal = std::true_type;
84 };
85 }
86
87 bool memory_test::run(bool report)
88 {
89 report_ = report;
90 start();
91
92 test_unique_ptr();
93 test_shared_ptr();
94 test_weak_ptr();
95 test_allocators();
96 test_pointers();
97
98 return end();
99 }
100
101 const char* memory_test::name()
102 {
103 return "memory";
104 }
105
106 void memory_test::test_unique_ptr()
107 {
108 mock::clear();
109 {
110 auto ptr = std::make_unique<mock>();
111 test_eq("unique_ptr get() when non-null", (ptr.get() != nullptr), true);
112 test_eq("unique_ptr operator bool when non-null", (bool)ptr, true);
113 }
114 test_eq("unique_ptr make_unique", mock::constructor_calls, 1U);
115 test_eq("unique_ptr out of scope", mock::destructor_calls, 1U);
116
117 mock::clear();
118 {
119 auto ptr = std::make_unique<mock>();
120 delete ptr.release();
121 }
122 test_eq("unique_ptr release", mock::destructor_calls, 1U);
123
124 mock::clear();
125 {
126 auto ptr = std::make_unique<mock>();
127 ptr.reset(new mock{});
128 }
129 test_eq("unique_ptr reset", mock::destructor_calls, 2U);
130
131 mock::clear();
132 {
133 std::unique_ptr<mock> ptr1{};
134 test_eq("unique_ptr get() when null", ptr1.get(), nullptr);
135 test_eq("unique_ptr operator bool when null", (bool)ptr1, false);
136 {
137 auto ptr2 = std::make_unique<mock>();
138 ptr1 = std::move(ptr2);
139 }
140 test_eq("unique_ptr move pt1", mock::destructor_calls, 0U);
141 }
142 test_eq("unique_ptr move pt2", mock::destructor_calls, 1U);
143
144 mock::clear();
145 {
146 auto ptr = std::make_unique<mock[]>(10U);
147 test_eq("unique_ptr make_unique array version", mock::constructor_calls, 10U);
148
149 new(&ptr[5]) mock{};
150 test_eq("placement new into the array", mock::constructor_calls, 11U);
151 test_eq("original not destroyed during placement new", mock::destructor_calls, 0U);
152 }
153 test_eq("unique_ptr array out of scope", mock::destructor_calls, 10U);
154 }
155
156 void memory_test::test_shared_ptr()
157 {
158 mock::clear();
159 {
160 auto ptr1 = std::make_shared<mock>();
161 test_eq("shared_ptr make_shared", mock::constructor_calls, 1U);
162 test_eq("shared_ptr unique", ptr1.unique(), true);
163 {
164 auto ptr2 = ptr1;
165 test_eq("shared_ptr copy pt1", ptr1.use_count(), 2L);
166 test_eq("shared_ptr copy pt2", ptr2.use_count(), 2L);
167 test_eq("shared_ptr copy no constructor call", mock::copy_constructor_calls, 0U);
168 test_eq("shared_ptr not unique", ptr1.unique(), false);
169
170 auto ptr3 = std::move(ptr2);
171 test_eq("shared_ptr move pt1", ptr1.use_count(), 2L);
172 test_eq("shared_ptr move pt2", ptr3.use_count(), 2L);
173 test_eq("shared_ptr move pt3", ptr2.use_count(), 0L);
174
175 test_eq("shared_ptr move origin empty", (bool)ptr2, false);
176 }
177 test_eq("shared_ptr copy out of scope", mock::destructor_calls, 0U);
178 }
179 test_eq("shared_ptr original out of scope", mock::destructor_calls, 1U);
180 }
181
182 void memory_test::test_weak_ptr()
183 {
184 mock::clear();
185 {
186 std::weak_ptr<mock> wptr1{};
187 {
188 auto ptr1 = std::make_shared<mock>();
189 wptr1 = ptr1;
190 {
191 std::weak_ptr<mock> wptr2 = ptr1;
192 test_eq("weak_ptr shares use count", wptr2.use_count(), 1L);
193 test_eq("weak_ptr not expired", wptr2.expired(), false);
194
195 auto ptr2 = wptr2.lock();
196 test_eq("locked ptr increases use count", ptr1.use_count(), 2L);
197 }
198 }
199 test_eq("weak_ptr expired after all shared_ptrs die", wptr1.expired(), true);
200 test_eq("shared object destroyed while weak_ptr exists", mock::destructor_calls, 1U);
201 }
202 }
203
204 void memory_test::test_allocators()
205 {
206 using dummy_traits1 = std::allocator_traits<aux::dummy_allocator1>;
207 using dummy_traits2 = std::allocator_traits<aux::dummy_allocator2>;
208
209 /**
210 * First dummy allocator doesn't provide
211 * anything except for the mandatory value_type,
212 * so we get all the defaults here.
213 */
214 static_assert(std::is_same_v<typename dummy_traits1::pointer, int*>);
215 static_assert(std::is_same_v<typename dummy_traits1::const_pointer, const int*>);
216 static_assert(std::is_same_v<typename dummy_traits1::void_pointer, void*>);
217 static_assert(std::is_same_v<typename dummy_traits1::const_void_pointer, const void*>);
218 static_assert(std::is_same_v<typename dummy_traits1::difference_type, ptrdiff_t>);
219 static_assert(std::is_same_v<typename dummy_traits1::size_type, std::make_unsigned_t<ptrdiff_t>>);
220 static_assert(std::is_same_v<typename dummy_traits1::propagate_on_container_copy_assignment, std::false_type>);
221 static_assert(std::is_same_v<typename dummy_traits1::propagate_on_container_move_assignment, std::false_type>);
222 static_assert(std::is_same_v<typename dummy_traits1::propagate_on_container_swap, std::false_type>);
223 static_assert(std::is_same_v<typename dummy_traits1::is_always_equal, typename std::is_empty<aux::dummy_allocator1>::type>);
224
225 /**
226 * Second dummy allocator provides all typedefs, so
227 * the the traits just use identity.
228 */
229 static_assert(std::is_same_v<typename dummy_traits2::pointer, char*>);
230 static_assert(std::is_same_v<typename dummy_traits2::const_pointer, const void*>);
231 static_assert(std::is_same_v<typename dummy_traits2::void_pointer, bool*>);
232 static_assert(std::is_same_v<typename dummy_traits2::const_void_pointer, volatile bool*>);
233 static_assert(std::is_same_v<typename dummy_traits2::difference_type, short>);
234 static_assert(std::is_same_v<typename dummy_traits2::size_type, long>);
235 static_assert(std::is_same_v<typename dummy_traits2::propagate_on_container_copy_assignment, std::true_type>);
236 static_assert(std::is_same_v<typename dummy_traits2::propagate_on_container_move_assignment, std::true_type>);
237 static_assert(std::is_same_v<typename dummy_traits2::propagate_on_container_swap, std::true_type>);
238 static_assert(std::is_same_v<typename dummy_traits2::is_always_equal, std::true_type>);
239 }
240
241 void memory_test::test_pointers()
242 {
243 using dummy_traits1 = std::pointer_traits<aux::dummy_pointer1>;
244 using dummy_traits2 = std::pointer_traits<aux::dummy_pointer2<int, char>>;
245 using int_traits = std::pointer_traits<int*>;
246
247 static_assert(std::is_same_v<typename dummy_traits1::pointer, aux::dummy_pointer1>);
248 static_assert(std::is_same_v<typename dummy_traits1::element_type, int>);
249 static_assert(std::is_same_v<typename dummy_traits1::difference_type, bool>);
250 static_assert(std::is_same_v<typename dummy_traits1::template rebind<long>, unsigned>);
251
252 int x{10};
253 test_eq("pointer_traits<Ptr>::pointer_to", dummy_traits1::pointer_to(x).tag, 10);
254 test_eq("pointer_traits<T*>::pointer_to", int_traits::pointer_to(x), &x);
255
256 static_assert(std::is_same_v<typename dummy_traits2::pointer, aux::dummy_pointer2<int, char>>);
257 static_assert(std::is_same_v<typename dummy_traits2::element_type, signed char>);
258 static_assert(std::is_same_v<typename dummy_traits2::difference_type, unsigned char>);
259
260 static_assert(std::is_same_v<typename int_traits::pointer, int*>);
261 static_assert(std::is_same_v<typename int_traits::element_type, int>);
262 static_assert(std::is_same_v<typename int_traits::difference_type, ptrdiff_t>);
263 static_assert(std::is_same_v<typename int_traits::rebind<char>, char*>);
264 }
265}
Note: See TracBrowser for help on using the repository browser.