1//
2// Automated Testing Framework (atf)
3//
4// Copyright (c) 2007 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
30extern "C" {
31#include <sys/types.h>
32}
33
34#include <iostream>
35
36#include "atf-c/defs.h"
37
38#include "../macros.hpp"
39
40#include "auto_array.hpp"
41
42// ------------------------------------------------------------------------
43// Tests for the "auto_array" class.
44// ------------------------------------------------------------------------
45
46class test_array {
47public:
48    int m_value;
49
50    static ssize_t m_nblocks;
51
52    static
53    atf::auto_array< test_array >
54    do_copy(atf::auto_array< test_array >& ta)
55    {
56        return atf::auto_array< test_array >(ta);
57    }
58
59    void* operator new(size_t size ATF_DEFS_ATTRIBUTE_UNUSED)
60    {
61        ATF_FAIL("New called but should have been new[]");
62        return new int(5);
63    }
64
65    void* operator new[](size_t size)
66    {
67        m_nblocks++;
68        void* mem = ::operator new(size);
69        std::cout << "Allocated 'test_array' object " << mem << "\n";
70        return mem;
71    }
72
73    void operator delete(void* mem ATF_DEFS_ATTRIBUTE_UNUSED)
74    {
75        ATF_FAIL("Delete called but should have been delete[]");
76    }
77
78    void operator delete[](void* mem)
79    {
80        std::cout << "Releasing 'test_array' object " << mem << "\n";
81        if (m_nblocks == 0)
82            ATF_FAIL("Unbalanced delete[]");
83        m_nblocks--;
84        ::operator delete(mem);
85    }
86};
87
88ssize_t test_array::m_nblocks = 0;
89
90ATF_TEST_CASE(auto_array_scope);
91ATF_TEST_CASE_HEAD(auto_array_scope)
92{
93    set_md_var("descr", "Tests the automatic scope handling in the "
94               "auto_array smart pointer class");
95}
96ATF_TEST_CASE_BODY(auto_array_scope)
97{
98    using atf::auto_array;
99
100    ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
101    {
102        auto_array< test_array > t(new test_array[10]);
103        ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
104    }
105    ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
106}
107
108ATF_TEST_CASE(auto_array_copy);
109ATF_TEST_CASE_HEAD(auto_array_copy)
110{
111    set_md_var("descr", "Tests the auto_array smart pointer class' copy "
112               "constructor");
113}
114ATF_TEST_CASE_BODY(auto_array_copy)
115{
116    using atf::auto_array;
117
118    ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
119    {
120        auto_array< test_array > t1(new test_array[10]);
121        ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
122
123        {
124            auto_array< test_array > t2(t1);
125            ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
126        }
127        ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
128    }
129    ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
130}
131
132ATF_TEST_CASE(auto_array_copy_ref);
133ATF_TEST_CASE_HEAD(auto_array_copy_ref)
134{
135    set_md_var("descr", "Tests the auto_array smart pointer class' copy "
136               "constructor through the auxiliary auto_array_ref object");
137}
138ATF_TEST_CASE_BODY(auto_array_copy_ref)
139{
140    using atf::auto_array;
141
142    ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
143    {
144        auto_array< test_array > t1(new test_array[10]);
145        ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
146
147        {
148            auto_array< test_array > t2 = test_array::do_copy(t1);
149            ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
150        }
151        ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
152    }
153    ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
154}
155
156ATF_TEST_CASE(auto_array_get);
157ATF_TEST_CASE_HEAD(auto_array_get)
158{
159    set_md_var("descr", "Tests the auto_array smart pointer class' get "
160               "method");
161}
162ATF_TEST_CASE_BODY(auto_array_get)
163{
164    using atf::auto_array;
165
166    test_array* ta = new test_array[10];
167    auto_array< test_array > t(ta);
168    ATF_REQUIRE_EQ(t.get(), ta);
169}
170
171ATF_TEST_CASE(auto_array_release);
172ATF_TEST_CASE_HEAD(auto_array_release)
173{
174    set_md_var("descr", "Tests the auto_array smart pointer class' release "
175               "method");
176}
177ATF_TEST_CASE_BODY(auto_array_release)
178{
179    using atf::auto_array;
180
181    test_array* ta1 = new test_array[10];
182    {
183        auto_array< test_array > t(ta1);
184        ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
185        test_array* ta2 = t.release();
186        ATF_REQUIRE_EQ(ta2, ta1);
187        ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
188    }
189    ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
190    delete [] ta1;
191}
192
193ATF_TEST_CASE(auto_array_reset);
194ATF_TEST_CASE_HEAD(auto_array_reset)
195{
196    set_md_var("descr", "Tests the auto_array smart pointer class' reset "
197               "method");
198}
199ATF_TEST_CASE_BODY(auto_array_reset)
200{
201    using atf::auto_array;
202
203    test_array* ta1 = new test_array[10];
204    test_array* ta2 = new test_array[10];
205    ATF_REQUIRE_EQ(test_array::m_nblocks, 2);
206
207    {
208        auto_array< test_array > t(ta1);
209        ATF_REQUIRE_EQ(test_array::m_nblocks, 2);
210        t.reset(ta2);
211        ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
212        t.reset();
213        ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
214    }
215    ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
216}
217
218ATF_TEST_CASE(auto_array_assign);
219ATF_TEST_CASE_HEAD(auto_array_assign)
220{
221    set_md_var("descr", "Tests the auto_array smart pointer class' "
222               "assignment operator");
223}
224ATF_TEST_CASE_BODY(auto_array_assign)
225{
226    using atf::auto_array;
227
228    ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
229    {
230        auto_array< test_array > t1(new test_array[10]);
231        ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
232
233        {
234            auto_array< test_array > t2;
235            t2 = t1;
236            ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
237        }
238        ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
239    }
240    ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
241}
242
243ATF_TEST_CASE(auto_array_assign_ref);
244ATF_TEST_CASE_HEAD(auto_array_assign_ref)
245{
246    set_md_var("descr", "Tests the auto_array smart pointer class' "
247               "assignment operator through the auxiliary auto_array_ref "
248               "object");
249}
250ATF_TEST_CASE_BODY(auto_array_assign_ref)
251{
252    using atf::auto_array;
253
254    ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
255    {
256        auto_array< test_array > t1(new test_array[10]);
257        ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
258
259        {
260            auto_array< test_array > t2;
261            t2 = test_array::do_copy(t1);
262            ATF_REQUIRE_EQ(test_array::m_nblocks, 1);
263        }
264        ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
265    }
266    ATF_REQUIRE_EQ(test_array::m_nblocks, 0);
267}
268
269ATF_TEST_CASE(auto_array_access);
270ATF_TEST_CASE_HEAD(auto_array_access)
271{
272    set_md_var("descr", "Tests the auto_array smart pointer class' access "
273               "operator");
274}
275ATF_TEST_CASE_BODY(auto_array_access)
276{
277    using atf::auto_array;
278
279    auto_array< test_array > t(new test_array[10]);
280
281    for (int i = 0; i < 10; i++)
282        t[i].m_value = i * 2;
283
284    for (int i = 0; i < 10; i++)
285        ATF_REQUIRE_EQ(t[i].m_value, i * 2);
286}
287
288// ------------------------------------------------------------------------
289// Main.
290// ------------------------------------------------------------------------
291
292ATF_INIT_TEST_CASES(tcs)
293{
294    // Add the test for the "auto_array" class.
295    ATF_ADD_TEST_CASE(tcs, auto_array_scope);
296    ATF_ADD_TEST_CASE(tcs, auto_array_copy);
297    ATF_ADD_TEST_CASE(tcs, auto_array_copy_ref);
298    ATF_ADD_TEST_CASE(tcs, auto_array_get);
299    ATF_ADD_TEST_CASE(tcs, auto_array_release);
300    ATF_ADD_TEST_CASE(tcs, auto_array_reset);
301    ATF_ADD_TEST_CASE(tcs, auto_array_assign);
302    ATF_ADD_TEST_CASE(tcs, auto_array_assign_ref);
303    ATF_ADD_TEST_CASE(tcs, auto_array_access);
304}
305