xref: /netbsd-src/external/bsd/kyua-cli/dist/utils/auto_array_test.cpp (revision 76c7fc5f6b13ed0b1508e6b313e88e59977ed78e)
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*
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*
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
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
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);
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 }
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);
134 ATF_TEST_CASE_HEAD(copy)
135 {
136     set_md_var("descr", "Tests the auto_array smart pointer class' copy "
137                "constructor");
138 }
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);
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 }
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);
180 ATF_TEST_CASE_HEAD(get)
181 {
182     set_md_var("descr", "Tests the auto_array smart pointer class' get "
183                "method");
184 }
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);
194 ATF_TEST_CASE_HEAD(release)
195 {
196     set_md_var("descr", "Tests the auto_array smart pointer class' release "
197                "method");
198 }
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);
215 ATF_TEST_CASE_HEAD(reset)
216 {
217     set_md_var("descr", "Tests the auto_array smart pointer class' reset "
218                "method");
219 }
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);
239 ATF_TEST_CASE_HEAD(assign)
240 {
241     set_md_var("descr", "Tests the auto_array smart pointer class' "
242                "assignment operator");
243 }
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);
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 }
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);
288 ATF_TEST_CASE_HEAD(access)
289 {
290     set_md_var("descr", "Tests the auto_array smart pointer class' access "
291                "operator");
292 }
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 
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