1 // Copyright 2010 Google Inc.
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 /// \param unused_size The amount of memory to allocate, in bytes.
59 ///
60 /// \return Nothing; this always fails the test case.
61 void*
operator new(const size_t UTILS_UNUSED_PARAM (size))62 operator new(const size_t UTILS_UNUSED_PARAM(size))
63 {
64 ATF_FAIL("New called but should have been new[]");
65 return new int(5);
66 }
67
68 /// Obtains memory for a new instance and increments m_nblocks.
69 ///
70 /// \param size The amount of memory to allocate, in bytes.
71 ///
72 /// \return A pointer to the allocated memory.
73 ///
74 /// \throw std::bad_alloc If the memory cannot be allocated.
75 void*
operator new[](const size_t size)76 operator new[](const size_t size)
77 {
78 void* mem = ::operator new(size);
79 m_nblocks++;
80 std::cout << "Allocated 'test_array' object " << mem << "\n";
81 return mem;
82 }
83
84 /// Captures invalid calls to delete on an array.
85 ///
86 /// \param unused_mem The pointer to the memory to be deleted.
87 ///
88 /// \return Nothing; this always fails the test case.
89 void
operator delete(void * UTILS_UNUSED_PARAM (mem))90 operator delete(void* UTILS_UNUSED_PARAM(mem))
91 {
92 ATF_FAIL("Delete called but should have been delete[]");
93 }
94
95 /// Deletes a previously allocated array and decrements m_nblocks.
96 ///
97 /// \param mem The pointer to the memory to be deleted.
98 void
operator delete[](void * mem)99 operator delete[](void* mem)
100 {
101 std::cout << "Releasing 'test_array' object " << mem << "\n";
102 if (m_nblocks == 0)
103 ATF_FAIL("Unbalanced delete[]");
104 m_nblocks--;
105 ::operator delete(mem);
106 }
107 };
108
109
110 ssize_t test_array::m_nblocks = 0;
111
112
113 } // anonymous namespace
114
115
116 ATF_TEST_CASE(scope);
ATF_TEST_CASE_HEAD(scope)117 ATF_TEST_CASE_HEAD(scope)
118 {
119 set_md_var("descr", "Tests the automatic scope handling in the "
120 "auto_array smart pointer class");
121 }
ATF_TEST_CASE_BODY(scope)122 ATF_TEST_CASE_BODY(scope)
123 {
124 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
125 {
126 auto_array< test_array > t(new test_array[10]);
127 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
128 }
129 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
130 }
131
132
133 ATF_TEST_CASE(copy);
ATF_TEST_CASE_HEAD(copy)134 ATF_TEST_CASE_HEAD(copy)
135 {
136 set_md_var("descr", "Tests the auto_array smart pointer class' copy "
137 "constructor");
138 }
ATF_TEST_CASE_BODY(copy)139 ATF_TEST_CASE_BODY(copy)
140 {
141 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
142 {
143 auto_array< test_array > t1(new test_array[10]);
144 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
145
146 {
147 auto_array< test_array > t2(t1);
148 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
149 }
150 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
151 }
152 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
153 }
154
155
156 ATF_TEST_CASE(copy_ref);
ATF_TEST_CASE_HEAD(copy_ref)157 ATF_TEST_CASE_HEAD(copy_ref)
158 {
159 set_md_var("descr", "Tests the auto_array smart pointer class' copy "
160 "constructor through the auxiliary ref object");
161 }
ATF_TEST_CASE_BODY(copy_ref)162 ATF_TEST_CASE_BODY(copy_ref)
163 {
164 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
165 {
166 auto_array< test_array > t1(new test_array[10]);
167 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
168
169 {
170 auto_array< test_array > t2 = t1;
171 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
172 }
173 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
174 }
175 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
176 }
177
178
179 ATF_TEST_CASE(get);
ATF_TEST_CASE_HEAD(get)180 ATF_TEST_CASE_HEAD(get)
181 {
182 set_md_var("descr", "Tests the auto_array smart pointer class' get "
183 "method");
184 }
ATF_TEST_CASE_BODY(get)185 ATF_TEST_CASE_BODY(get)
186 {
187 test_array* ta = new test_array[10];
188 auto_array< test_array > t(ta);
189 ATF_REQUIRE_EQ(t.get(), ta);
190 }
191
192
193 ATF_TEST_CASE(release);
ATF_TEST_CASE_HEAD(release)194 ATF_TEST_CASE_HEAD(release)
195 {
196 set_md_var("descr", "Tests the auto_array smart pointer class' release "
197 "method");
198 }
ATF_TEST_CASE_BODY(release)199 ATF_TEST_CASE_BODY(release)
200 {
201 test_array* ta1 = new test_array[10];
202 {
203 auto_array< test_array > t(ta1);
204 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
205 test_array* ta2 = t.release();
206 ATF_REQUIRE_EQ(ta2, ta1);
207 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
208 }
209 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
210 delete [] ta1;
211 }
212
213
214 ATF_TEST_CASE(reset);
ATF_TEST_CASE_HEAD(reset)215 ATF_TEST_CASE_HEAD(reset)
216 {
217 set_md_var("descr", "Tests the auto_array smart pointer class' reset "
218 "method");
219 }
ATF_TEST_CASE_BODY(reset)220 ATF_TEST_CASE_BODY(reset)
221 {
222 test_array* ta1 = new test_array[10];
223 test_array* ta2 = new test_array[10];
224 ATF_REQUIRE_EQ(test_array::m_nblocks, 2);
225
226 {
227 auto_array< test_array > t(ta1);
228 ATF_REQUIRE_EQ(test_array::m_nblocks, 2);
229 t.reset(ta2);
230 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
231 t.reset();
232 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
233 }
234 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
235 }
236
237
238 ATF_TEST_CASE(assign);
ATF_TEST_CASE_HEAD(assign)239 ATF_TEST_CASE_HEAD(assign)
240 {
241 set_md_var("descr", "Tests the auto_array smart pointer class' "
242 "assignment operator");
243 }
ATF_TEST_CASE_BODY(assign)244 ATF_TEST_CASE_BODY(assign)
245 {
246 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
247 {
248 auto_array< test_array > t1(new test_array[10]);
249 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
250
251 {
252 auto_array< test_array > t2;
253 t2 = t1;
254 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
255 }
256 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
257 }
258 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
259 }
260
261
262 ATF_TEST_CASE(assign_ref);
ATF_TEST_CASE_HEAD(assign_ref)263 ATF_TEST_CASE_HEAD(assign_ref)
264 {
265 set_md_var("descr", "Tests the auto_array smart pointer class' "
266 "assignment operator through the auxiliary ref "
267 "object");
268 }
ATF_TEST_CASE_BODY(assign_ref)269 ATF_TEST_CASE_BODY(assign_ref)
270 {
271 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
272 {
273 auto_array< test_array > t1(new test_array[10]);
274 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
275
276 {
277 auto_array< test_array > t2;
278 t2 = t1;
279 ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
280 }
281 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
282 }
283 ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
284 }
285
286
287 ATF_TEST_CASE(access);
ATF_TEST_CASE_HEAD(access)288 ATF_TEST_CASE_HEAD(access)
289 {
290 set_md_var("descr", "Tests the auto_array smart pointer class' access "
291 "operator");
292 }
ATF_TEST_CASE_BODY(access)293 ATF_TEST_CASE_BODY(access)
294 {
295 auto_array< test_array > t(new test_array[10]);
296
297 for (int i = 0; i < 10; i++)
298 t[i].m_value = i * 2;
299
300 for (int i = 0; i < 10; i++)
301 ATF_REQUIRE_EQ(t[i].m_value, i * 2);
302 }
303
304
ATF_INIT_TEST_CASES(tcs)305 ATF_INIT_TEST_CASES(tcs)
306 {
307 ATF_ADD_TEST_CASE(tcs, scope);
308 ATF_ADD_TEST_CASE(tcs, copy);
309 ATF_ADD_TEST_CASE(tcs, copy_ref);
310 ATF_ADD_TEST_CASE(tcs, get);
311 ATF_ADD_TEST_CASE(tcs, release);
312 ATF_ADD_TEST_CASE(tcs, reset);
313 ATF_ADD_TEST_CASE(tcs, assign);
314 ATF_ADD_TEST_CASE(tcs, assign_ref);
315 ATF_ADD_TEST_CASE(tcs, access);
316 }
317