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