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 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 /// \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 110 ssize_t test_array::m_nblocks = 0; 111 112 113 } // anonymous namespace 114 115 116 ATF_TEST_CASE(scope); 117 ATF_TEST_CASE_HEAD(scope) 118 { 119 set_md_var("descr", "Tests the automatic scope handling in the " 120 "auto_array smart pointer class"); 121 } 122 ATF_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 133 ATF_TEST_CASE(copy); 134 ATF_TEST_CASE_HEAD(copy) 135 { 136 set_md_var("descr", "Tests the auto_array smart pointer class' copy " 137 "constructor"); 138 } 139 ATF_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 156 ATF_TEST_CASE(copy_ref); 157 ATF_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 } 162 ATF_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 179 ATF_TEST_CASE(get); 180 ATF_TEST_CASE_HEAD(get) 181 { 182 set_md_var("descr", "Tests the auto_array smart pointer class' get " 183 "method"); 184 } 185 ATF_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 193 ATF_TEST_CASE(release); 194 ATF_TEST_CASE_HEAD(release) 195 { 196 set_md_var("descr", "Tests the auto_array smart pointer class' release " 197 "method"); 198 } 199 ATF_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 214 ATF_TEST_CASE(reset); 215 ATF_TEST_CASE_HEAD(reset) 216 { 217 set_md_var("descr", "Tests the auto_array smart pointer class' reset " 218 "method"); 219 } 220 ATF_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 238 ATF_TEST_CASE(assign); 239 ATF_TEST_CASE_HEAD(assign) 240 { 241 set_md_var("descr", "Tests the auto_array smart pointer class' " 242 "assignment operator"); 243 } 244 ATF_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 262 ATF_TEST_CASE(assign_ref); 263 ATF_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 } 269 ATF_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 287 ATF_TEST_CASE(access); 288 ATF_TEST_CASE_HEAD(access) 289 { 290 set_md_var("descr", "Tests the auto_array smart pointer class' access " 291 "operator"); 292 } 293 ATF_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 305 ATF_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