1 // Copyright 2010 The Kyua Authors. 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 /// \return Nothing; this always fails the test case. 59 void* 60 operator new(const size_t /* size */) 61 { 62 ATF_FAIL("New called but should have been new[]"); 63 return new int(5); 64 } 65 66 /// Obtains memory for a new instance and increments m_nblocks. 67 /// 68 /// \param size The amount of memory to allocate, in bytes. 69 /// 70 /// \return A pointer to the allocated memory. 71 /// 72 /// \throw std::bad_alloc If the memory cannot be allocated. 73 void* 74 operator new[](const size_t size) 75 { 76 void* mem = ::operator new(size); 77 m_nblocks++; 78 std::cout << "Allocated 'test_array' object " << mem << "\n"; 79 return mem; 80 } 81 82 /// Captures invalid calls to delete on an array. 83 /// 84 /// \return Nothing; this always fails the test case. 85 void 86 operator delete(void* /* mem */) 87 { 88 ATF_FAIL("Delete called but should have been delete[]"); 89 } 90 91 /// Deletes a previously allocated array and decrements m_nblocks. 92 /// 93 /// \param mem The pointer to the memory to be deleted. 94 void 95 operator delete[](void* mem) 96 { 97 std::cout << "Releasing 'test_array' object " << mem << "\n"; 98 if (m_nblocks == 0) 99 ATF_FAIL("Unbalanced delete[]"); 100 m_nblocks--; 101 ::operator delete(mem); 102 } 103 }; 104 105 106 ssize_t test_array::m_nblocks = 0; 107 108 109 } // anonymous namespace 110 111 112 ATF_TEST_CASE(scope); 113 ATF_TEST_CASE_HEAD(scope) 114 { 115 set_md_var("descr", "Tests the automatic scope handling in the " 116 "auto_array smart pointer class"); 117 } 118 ATF_TEST_CASE_BODY(scope) 119 { 120 ATF_REQUIRE_EQ(test_array::m_nblocks, 0); 121 { 122 auto_array< test_array > t(new test_array[10]); 123 ATF_REQUIRE_EQ(test_array::m_nblocks, 1); 124 } 125 ATF_REQUIRE_EQ(test_array::m_nblocks, 0); 126 } 127 128 129 ATF_TEST_CASE(copy); 130 ATF_TEST_CASE_HEAD(copy) 131 { 132 set_md_var("descr", "Tests the auto_array smart pointer class' copy " 133 "constructor"); 134 } 135 ATF_TEST_CASE_BODY(copy) 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(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 151 152 ATF_TEST_CASE(copy_ref); 153 ATF_TEST_CASE_HEAD(copy_ref) 154 { 155 set_md_var("descr", "Tests the auto_array smart pointer class' copy " 156 "constructor through the auxiliary ref object"); 157 } 158 ATF_TEST_CASE_BODY(copy_ref) 159 { 160 ATF_REQUIRE_EQ(test_array::m_nblocks, 0); 161 { 162 auto_array< test_array > t1(new test_array[10]); 163 ATF_REQUIRE_EQ(test_array::m_nblocks, 1); 164 165 { 166 auto_array< test_array > t2 = t1; 167 ATF_REQUIRE_EQ(test_array::m_nblocks, 1); 168 } 169 ATF_REQUIRE_EQ(test_array::m_nblocks, 0); 170 } 171 ATF_REQUIRE_EQ(test_array::m_nblocks, 0); 172 } 173 174 175 ATF_TEST_CASE(get); 176 ATF_TEST_CASE_HEAD(get) 177 { 178 set_md_var("descr", "Tests the auto_array smart pointer class' get " 179 "method"); 180 } 181 ATF_TEST_CASE_BODY(get) 182 { 183 test_array* ta = new test_array[10]; 184 auto_array< test_array > t(ta); 185 ATF_REQUIRE_EQ(t.get(), ta); 186 } 187 188 189 ATF_TEST_CASE(release); 190 ATF_TEST_CASE_HEAD(release) 191 { 192 set_md_var("descr", "Tests the auto_array smart pointer class' release " 193 "method"); 194 } 195 ATF_TEST_CASE_BODY(release) 196 { 197 test_array* ta1 = new test_array[10]; 198 { 199 auto_array< test_array > t(ta1); 200 ATF_REQUIRE_EQ(test_array::m_nblocks, 1); 201 test_array* ta2 = t.release(); 202 ATF_REQUIRE_EQ(ta2, ta1); 203 ATF_REQUIRE_EQ(test_array::m_nblocks, 1); 204 } 205 ATF_REQUIRE_EQ(test_array::m_nblocks, 1); 206 delete [] ta1; 207 } 208 209 210 ATF_TEST_CASE(reset); 211 ATF_TEST_CASE_HEAD(reset) 212 { 213 set_md_var("descr", "Tests the auto_array smart pointer class' reset " 214 "method"); 215 } 216 ATF_TEST_CASE_BODY(reset) 217 { 218 test_array* ta1 = new test_array[10]; 219 test_array* ta2 = new test_array[10]; 220 ATF_REQUIRE_EQ(test_array::m_nblocks, 2); 221 222 { 223 auto_array< test_array > t(ta1); 224 ATF_REQUIRE_EQ(test_array::m_nblocks, 2); 225 t.reset(ta2); 226 ATF_REQUIRE_EQ(test_array::m_nblocks, 1); 227 t.reset(); 228 ATF_REQUIRE_EQ(test_array::m_nblocks, 0); 229 } 230 ATF_REQUIRE_EQ(test_array::m_nblocks, 0); 231 } 232 233 234 ATF_TEST_CASE(assign); 235 ATF_TEST_CASE_HEAD(assign) 236 { 237 set_md_var("descr", "Tests the auto_array smart pointer class' " 238 "assignment operator"); 239 } 240 ATF_TEST_CASE_BODY(assign) 241 { 242 ATF_REQUIRE_EQ(test_array::m_nblocks, 0); 243 { 244 auto_array< test_array > t1(new test_array[10]); 245 ATF_REQUIRE_EQ(test_array::m_nblocks, 1); 246 247 { 248 auto_array< test_array > t2; 249 t2 = t1; 250 ATF_REQUIRE_EQ(test_array::m_nblocks, 1); 251 } 252 ATF_REQUIRE_EQ(test_array::m_nblocks, 0); 253 } 254 ATF_REQUIRE_EQ(test_array::m_nblocks, 0); 255 } 256 257 258 ATF_TEST_CASE(assign_ref); 259 ATF_TEST_CASE_HEAD(assign_ref) 260 { 261 set_md_var("descr", "Tests the auto_array smart pointer class' " 262 "assignment operator through the auxiliary ref " 263 "object"); 264 } 265 ATF_TEST_CASE_BODY(assign_ref) 266 { 267 ATF_REQUIRE_EQ(test_array::m_nblocks, 0); 268 { 269 auto_array< test_array > t1(new test_array[10]); 270 ATF_REQUIRE_EQ(test_array::m_nblocks, 1); 271 272 { 273 auto_array< test_array > t2; 274 t2 = t1; 275 ATF_REQUIRE_EQ(test_array::m_nblocks, 1); 276 } 277 ATF_REQUIRE_EQ(test_array::m_nblocks, 0); 278 } 279 ATF_REQUIRE_EQ(test_array::m_nblocks, 0); 280 } 281 282 283 ATF_TEST_CASE(access); 284 ATF_TEST_CASE_HEAD(access) 285 { 286 set_md_var("descr", "Tests the auto_array smart pointer class' access " 287 "operator"); 288 } 289 ATF_TEST_CASE_BODY(access) 290 { 291 auto_array< test_array > t(new test_array[10]); 292 293 for (int i = 0; i < 10; i++) 294 t[i].m_value = i * 2; 295 296 for (int i = 0; i < 10; i++) 297 ATF_REQUIRE_EQ(t[i].m_value, i * 2); 298 } 299 300 301 ATF_INIT_TEST_CASES(tcs) 302 { 303 ATF_ADD_TEST_CASE(tcs, scope); 304 ATF_ADD_TEST_CASE(tcs, copy); 305 ATF_ADD_TEST_CASE(tcs, copy_ref); 306 ATF_ADD_TEST_CASE(tcs, get); 307 ATF_ADD_TEST_CASE(tcs, release); 308 ATF_ADD_TEST_CASE(tcs, reset); 309 ATF_ADD_TEST_CASE(tcs, assign); 310 ATF_ADD_TEST_CASE(tcs, assign_ref); 311 ATF_ADD_TEST_CASE(tcs, access); 312 } 313