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