1 // Copyright 2010 The Kyua Authors.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of Google Inc. nor the names of its contributors
14 // may be used to endorse or promote products derived from this software
15 // without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 #include "utils/auto_array.ipp"
30
31 extern "C" {
32 #include <sys/types.h>
33 }
34
35 #include <iostream>
36
37 #include <atf-c++.hpp>
38
39 #include "utils/defs.hpp"
40
41 using utils::auto_array;
42
43
44 namespace {
45
46
47 /// Mock class to capture calls to the new and delete operators.
48 class test_array {
49 public:
50 /// User-settable cookie to disambiguate instances of this class.
51 int m_value;
52
53 /// The current balance of existing test_array instances.
54 static ssize_t m_nblocks;
55
56 /// Captures invalid calls to new on an array.
57 ///
58 /// \return Nothing; this always fails the test case.
59 void*
operator new(const size_t)60 operator new(const size_t /* size */)
61 {
62 ATF_FAIL("New called but should have been new[]");
63 return new int(5);
64 }
65
66 /// Obtains memory for a new instance and increments m_nblocks.
67 ///
68 /// \param size The amount of memory to allocate, in bytes.
69 ///
70 /// \return A pointer to the allocated memory.
71 ///
72 /// \throw std::bad_alloc If the memory cannot be allocated.
73 void*
operator new[](const size_t size)74 operator new[](const size_t size)
75 {
76 void* mem = ::operator new(size);
77 m_nblocks++;
78 std::cout << "Allocated 'test_array' object " << mem << "\n";
79 return mem;
80 }
81
82 /// Captures invalid calls to delete on an array.
83 ///
84 /// \return Nothing; this always fails the test case.
85 void
operator delete(void *)86 operator delete(void* /* mem */)
87 {
88 ATF_FAIL("Delete called but should have been delete[]");
89 }
90
91 /// Deletes a previously allocated array and decrements m_nblocks.
92 ///
93 /// \param mem The pointer to the memory to be deleted.
94 void
operator delete[](void * mem)95 operator delete[](void* mem)
96 {
97 std::cout << "Releasing 'test_array' object " << mem << "\n";
98 if (m_nblocks == 0)
99 ATF_FAIL("Unbalanced delete[]");
100 m_nblocks--;
101 ::operator delete(mem);
102 }
103 };
104
105
106 ssize_t test_array::m_nblocks = 0;
107
108
109 } // anonymous namespace
110
111
112 ATF_TEST_CASE(scope);
ATF_TEST_CASE_HEAD(scope)113 ATF_TEST_CASE_HEAD(scope)
114 {
115 set_md_var("descr", "Tests the automatic scope handling in the "
116 "auto_array smart pointer class");
117 }
ATF_TEST_CASE_BODY(scope)118 ATF_TEST_CASE_BODY(scope)
119 {
120 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
121 {
122 auto_array< test_array > t(new test_array[10]);
123 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
124 }
125 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
126 }
127
128
129 ATF_TEST_CASE(copy);
ATF_TEST_CASE_HEAD(copy)130 ATF_TEST_CASE_HEAD(copy)
131 {
132 set_md_var("descr", "Tests the auto_array smart pointer class' copy "
133 "constructor");
134 }
ATF_TEST_CASE_BODY(copy)135 ATF_TEST_CASE_BODY(copy)
136 {
137 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
138 {
139 auto_array< test_array > t1(new test_array[10]);
140 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
141
142 {
143 auto_array< test_array > t2(t1);
144 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
145 }
146 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
147 }
148 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
149 }
150
151
152 ATF_TEST_CASE(copy_ref);
ATF_TEST_CASE_HEAD(copy_ref)153 ATF_TEST_CASE_HEAD(copy_ref)
154 {
155 set_md_var("descr", "Tests the auto_array smart pointer class' copy "
156 "constructor through the auxiliary ref object");
157 }
ATF_TEST_CASE_BODY(copy_ref)158 ATF_TEST_CASE_BODY(copy_ref)
159 {
160 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
161 {
162 auto_array< test_array > t1(new test_array[10]);
163 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
164
165 {
166 auto_array< test_array > t2 = t1;
167 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
168 }
169 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
170 }
171 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
172 }
173
174
175 ATF_TEST_CASE(get);
ATF_TEST_CASE_HEAD(get)176 ATF_TEST_CASE_HEAD(get)
177 {
178 set_md_var("descr", "Tests the auto_array smart pointer class' get "
179 "method");
180 }
ATF_TEST_CASE_BODY(get)181 ATF_TEST_CASE_BODY(get)
182 {
183 test_array* ta = new test_array[10];
184 auto_array< test_array > t(ta);
185 ATF_REQUIRE_EQ(t.get(), ta);
186 }
187
188
189 ATF_TEST_CASE(release);
ATF_TEST_CASE_HEAD(release)190 ATF_TEST_CASE_HEAD(release)
191 {
192 set_md_var("descr", "Tests the auto_array smart pointer class' release "
193 "method");
194 }
ATF_TEST_CASE_BODY(release)195 ATF_TEST_CASE_BODY(release)
196 {
197 test_array* ta1 = new test_array[10];
198 {
199 auto_array< test_array > t(ta1);
200 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
201 test_array* ta2 = t.release();
202 ATF_REQUIRE_EQ(ta2, ta1);
203 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
204 }
205 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
206 delete [] ta1;
207 }
208
209
210 ATF_TEST_CASE(reset);
ATF_TEST_CASE_HEAD(reset)211 ATF_TEST_CASE_HEAD(reset)
212 {
213 set_md_var("descr", "Tests the auto_array smart pointer class' reset "
214 "method");
215 }
ATF_TEST_CASE_BODY(reset)216 ATF_TEST_CASE_BODY(reset)
217 {
218 test_array* ta1 = new test_array[10];
219 test_array* ta2 = new test_array[10];
220 ATF_REQUIRE_EQ(test_array::m_nblocks, 2);
221
222 {
223 auto_array< test_array > t(ta1);
224 ATF_REQUIRE_EQ(test_array::m_nblocks, 2);
225 t.reset(ta2);
226 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
227 t.reset();
228 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
229 }
230 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
231 }
232
233
234 ATF_TEST_CASE(assign);
ATF_TEST_CASE_HEAD(assign)235 ATF_TEST_CASE_HEAD(assign)
236 {
237 set_md_var("descr", "Tests the auto_array smart pointer class' "
238 "assignment operator");
239 }
ATF_TEST_CASE_BODY(assign)240 ATF_TEST_CASE_BODY(assign)
241 {
242 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
243 {
244 auto_array< test_array > t1(new test_array[10]);
245 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
246
247 {
248 auto_array< test_array > t2;
249 t2 = t1;
250 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
251 }
252 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
253 }
254 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
255 }
256
257
258 ATF_TEST_CASE(assign_ref);
ATF_TEST_CASE_HEAD(assign_ref)259 ATF_TEST_CASE_HEAD(assign_ref)
260 {
261 set_md_var("descr", "Tests the auto_array smart pointer class' "
262 "assignment operator through the auxiliary ref "
263 "object");
264 }
ATF_TEST_CASE_BODY(assign_ref)265 ATF_TEST_CASE_BODY(assign_ref)
266 {
267 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
268 {
269 auto_array< test_array > t1(new test_array[10]);
270 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
271
272 {
273 auto_array< test_array > t2;
274 t2 = t1;
275 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
276 }
277 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
278 }
279 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
280 }
281
282
283 ATF_TEST_CASE(access);
ATF_TEST_CASE_HEAD(access)284 ATF_TEST_CASE_HEAD(access)
285 {
286 set_md_var("descr", "Tests the auto_array smart pointer class' access "
287 "operator");
288 }
ATF_TEST_CASE_BODY(access)289 ATF_TEST_CASE_BODY(access)
290 {
291 auto_array< test_array > t(new test_array[10]);
292
293 for (int i = 0; i < 10; i++)
294 t[i].m_value = i * 2;
295
296 for (int i = 0; i < 10; i++)
297 ATF_REQUIRE_EQ(t[i].m_value, i * 2);
298 }
299
300
ATF_INIT_TEST_CASES(tcs)301 ATF_INIT_TEST_CASES(tcs)
302 {
303 ATF_ADD_TEST_CASE(tcs, scope);
304 ATF_ADD_TEST_CASE(tcs, copy);
305 ATF_ADD_TEST_CASE(tcs, copy_ref);
306 ATF_ADD_TEST_CASE(tcs, get);
307 ATF_ADD_TEST_CASE(tcs, release);
308 ATF_ADD_TEST_CASE(tcs, reset);
309 ATF_ADD_TEST_CASE(tcs, assign);
310 ATF_ADD_TEST_CASE(tcs, assign_ref);
311 ATF_ADD_TEST_CASE(tcs, access);
312 }
313