auto_array_test.cpp revision 1.1.1.1
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
31extern "C" {
32#include <sys/types.h>
33}
34
35#include <iostream>
36
37#include <atf-c++.hpp>
38
39#include "utils/defs.hpp"
40
41using utils::auto_array;
42
43
44namespace {
45
46
47/// Mock class to capture calls to the new and delete operators.
48class test_array {
49public:
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
110ssize_t test_array::m_nblocks = 0;
111
112
113}  // anonymous namespace
114
115
116ATF_TEST_CASE(scope);
117ATF_TEST_CASE_HEAD(scope)
118{
119    set_md_var("descr", "Tests the automatic scope handling in the "
120               "auto_array smart pointer class");
121}
122ATF_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
133ATF_TEST_CASE(copy);
134ATF_TEST_CASE_HEAD(copy)
135{
136    set_md_var("descr", "Tests the auto_array smart pointer class' copy "
137               "constructor");
138}
139ATF_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
156ATF_TEST_CASE(copy_ref);
157ATF_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}
162ATF_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
179ATF_TEST_CASE(get);
180ATF_TEST_CASE_HEAD(get)
181{
182    set_md_var("descr", "Tests the auto_array smart pointer class' get "
183               "method");
184}
185ATF_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
193ATF_TEST_CASE(release);
194ATF_TEST_CASE_HEAD(release)
195{
196    set_md_var("descr", "Tests the auto_array smart pointer class' release "
197               "method");
198}
199ATF_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
214ATF_TEST_CASE(reset);
215ATF_TEST_CASE_HEAD(reset)
216{
217    set_md_var("descr", "Tests the auto_array smart pointer class' reset "
218               "method");
219}
220ATF_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
238ATF_TEST_CASE(assign);
239ATF_TEST_CASE_HEAD(assign)
240{
241    set_md_var("descr", "Tests the auto_array smart pointer class' "
242               "assignment operator");
243}
244ATF_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
262ATF_TEST_CASE(assign_ref);
263ATF_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}
269ATF_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
287ATF_TEST_CASE(access);
288ATF_TEST_CASE_HEAD(access)
289{
290    set_md_var("descr", "Tests the auto_array smart pointer class' access "
291               "operator");
292}
293ATF_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
305ATF_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