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

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

cpp: moved type getters for allocator and pointer traits to a separate header, fully implemented pointer_traits and added pointer_traits tests

  • Property mode set to 100644
File size: 8.2 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 };
76 }
77
78 bool memory_test::run(bool report)
79 {
80 report_ = report;
81 start();
82
83 test_unique_ptr();
84 test_shared_ptr();
85 test_weak_ptr();
86 test_allocators();
87 test_pointers();
88
89 return end();
90 }
91
92 const char* memory_test::name()
93 {
94 return "memory";
95 }
96
97 void memory_test::test_unique_ptr()
98 {
99 mock::clear();
100 {
101 auto ptr = std::make_unique<mock>();
102 test_eq("unique_ptr get() when non-null", (ptr.get() != nullptr), true);
103 test_eq("unique_ptr operator bool when non-null", (bool)ptr, true);
104 }
105 test_eq("unique_ptr make_unique", mock::constructor_calls, 1U);
106 test_eq("unique_ptr out of scope", mock::destructor_calls, 1U);
107
108 mock::clear();
109 {
110 auto ptr = std::make_unique<mock>();
111 delete ptr.release();
112 }
113 test_eq("unique_ptr release", mock::destructor_calls, 1U);
114
115 mock::clear();
116 {
117 auto ptr = std::make_unique<mock>();
118 ptr.reset(new mock{});
119 }
120 test_eq("unique_ptr reset", mock::destructor_calls, 2U);
121
122 mock::clear();
123 {
124 std::unique_ptr<mock> ptr1{};
125 test_eq("unique_ptr get() when null", ptr1.get(), nullptr);
126 test_eq("unique_ptr operator bool when null", (bool)ptr1, false);
127 {
128 auto ptr2 = std::make_unique<mock>();
129 ptr1 = std::move(ptr2);
130 }
131 test_eq("unique_ptr move pt1", mock::destructor_calls, 0U);
132 }
133 test_eq("unique_ptr move pt2", mock::destructor_calls, 1U);
134
135 mock::clear();
136 {
137 auto ptr = std::make_unique<mock[]>(10U);
138 test_eq("unique_ptr make_unique array version", mock::constructor_calls, 10U);
139
140 new(&ptr[5]) mock{};
141 test_eq("placement new into the array", mock::constructor_calls, 11U);
142 test_eq("original not destroyed during placement new", mock::destructor_calls, 0U);
143 }
144 test_eq("unique_ptr array out of scope", mock::destructor_calls, 10U);
145 }
146
147 void memory_test::test_shared_ptr()
148 {
149 mock::clear();
150 {
151 auto ptr1 = std::make_shared<mock>();
152 test_eq("shared_ptr make_shared", mock::constructor_calls, 1U);
153 test_eq("shared_ptr unique", ptr1.unique(), true);
154 {
155 auto ptr2 = ptr1;
156 test_eq("shared_ptr copy pt1", ptr1.use_count(), 2L);
157 test_eq("shared_ptr copy pt2", ptr2.use_count(), 2L);
158 test_eq("shared_ptr copy no constructor call", mock::copy_constructor_calls, 0U);
159 test_eq("shared_ptr not unique", ptr1.unique(), false);
160
161 auto ptr3 = std::move(ptr2);
162 test_eq("shared_ptr move pt1", ptr1.use_count(), 2L);
163 test_eq("shared_ptr move pt2", ptr3.use_count(), 2L);
164 test_eq("shared_ptr move pt3", ptr2.use_count(), 0L);
165
166 test_eq("shared_ptr move origin empty", (bool)ptr2, false);
167 }
168 test_eq("shared_ptr copy out of scope", mock::destructor_calls, 0U);
169 }
170 test_eq("shared_ptr original out of scope", mock::destructor_calls, 1U);
171 }
172
173 void memory_test::test_weak_ptr()
174 {
175 mock::clear();
176 {
177 std::weak_ptr<mock> wptr1{};
178 {
179 auto ptr1 = std::make_shared<mock>();
180 wptr1 = ptr1;
181 {
182 std::weak_ptr<mock> wptr2 = ptr1;
183 test_eq("weak_ptr shares use count", wptr2.use_count(), 1L);
184 test_eq("weak_ptr not expired", wptr2.expired(), false);
185
186 auto ptr2 = wptr2.lock();
187 test_eq("locked ptr increases use count", ptr1.use_count(), 2L);
188 }
189 }
190 test_eq("weak_ptr expired after all shared_ptrs die", wptr1.expired(), true);
191 test_eq("shared object destroyed while weak_ptr exists", mock::destructor_calls, 1U);
192 }
193 }
194
195 void memory_test::test_allocators()
196 {
197 using dummy_traits1 = std::allocator_traits<aux::dummy_allocator1>;
198 using dummy_traits2 = std::allocator_traits<aux::dummy_allocator2>;
199
200 /* static_assert(std::is_same_v<typename dummy_traits1::pointer, int*>); */
201 /* static_assert(std::is_same_v<typename dummy_traits2::pointer, char*>); */
202 }
203
204 void memory_test::test_pointers()
205 {
206 using dummy_traits1 = std::pointer_traits<aux::dummy_pointer1>;
207 using dummy_traits2 = std::pointer_traits<aux::dummy_pointer2<int, char>>;
208 using int_traits = std::pointer_traits<int*>;
209
210 static_assert(std::is_same_v<typename dummy_traits1::pointer, aux::dummy_pointer1>);
211 static_assert(std::is_same_v<typename dummy_traits1::element_type, int>);
212 static_assert(std::is_same_v<typename dummy_traits1::difference_type, bool>);
213 static_assert(std::is_same_v<typename dummy_traits1::template rebind<long>, unsigned>);
214
215 int x{10};
216 test_eq("pointer_traits<Ptr>::pointer_to", dummy_traits1::pointer_to(x).tag, 10);
217
218 static_assert(std::is_same_v<typename dummy_traits2::pointer, aux::dummy_pointer2<int, char>>);
219 static_assert(std::is_same_v<typename dummy_traits2::element_type, signed char>);
220 static_assert(std::is_same_v<typename dummy_traits2::difference_type, unsigned char>);
221
222 static_assert(std::is_same_v<typename int_traits::pointer, int*>);
223 static_assert(std::is_same_v<typename int_traits::element_type, int>);
224 static_assert(std::is_same_v<typename int_traits::difference_type, ptrdiff_t>);
225 static_assert(std::is_same_v<typename int_traits::rebind<char>, char*>);
226 }
227}
Note: See TracBrowser for help on using the repository browser.