OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 PDFium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include <sstream> |
| 6 |
| 7 #include "testing/gtest/include/gtest/gtest.h" |
| 8 #include "../../../third_party/base/macros.h" |
| 9 #include "../../../third_party/base/nonstd_unique_ptr.h" |
| 10 |
| 11 using nonstd::unique_ptr; |
| 12 |
| 13 namespace { |
| 14 |
| 15 // Used to test depth subtyping. |
| 16 class ConDecLoggerParent { |
| 17 public: |
| 18 virtual ~ConDecLoggerParent() {} |
| 19 |
| 20 virtual void SetPtr(int* ptr) = 0; |
| 21 |
| 22 virtual int SomeMeth(int x) const = 0; |
| 23 }; |
| 24 |
| 25 class ConDecLogger : public ConDecLoggerParent { |
| 26 public: |
| 27 ConDecLogger() : ptr_(nullptr) {} |
| 28 explicit ConDecLogger(int* ptr) { SetPtr(ptr); } |
| 29 ~ConDecLogger() override { --*ptr_; } |
| 30 |
| 31 void SetPtr(int* ptr) override { |
| 32 ptr_ = ptr; |
| 33 ++*ptr_; |
| 34 } |
| 35 |
| 36 int SomeMeth(int x) const override { return x; } |
| 37 |
| 38 private: |
| 39 int* ptr_; |
| 40 |
| 41 // Disallow evil constructors. |
| 42 ConDecLogger(const ConDecLogger&) = delete; |
| 43 void operator=(const ConDecLogger&) = delete; |
| 44 }; |
| 45 |
| 46 struct CountingDeleter { |
| 47 explicit CountingDeleter(int* count) : count_(count) {} |
| 48 inline void operator()(double* ptr) const { (*count_)++; } |
| 49 int* count_; |
| 50 }; |
| 51 |
| 52 // Do not delete this function! It's existence is to test that you can |
| 53 // return a temporarily constructed version of the scoper. |
| 54 unique_ptr<ConDecLogger> TestReturnOfType(int* constructed) { |
| 55 return unique_ptr<ConDecLogger>(new ConDecLogger(constructed)); |
| 56 } |
| 57 |
| 58 } // namespace |
| 59 |
| 60 TEST(UniquePtrTest, UniquePtr) { |
| 61 int constructed = 0; |
| 62 |
| 63 // Ensure size of unique_ptr<> doesn't increase unexpectedly. |
| 64 static_assert(sizeof(int*) >= sizeof(unique_ptr<int>), |
| 65 "unique_ptr_larger_than_raw_ptr"); |
| 66 |
| 67 { |
| 68 unique_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed)); |
| 69 EXPECT_EQ(1, constructed); |
| 70 EXPECT_TRUE(scoper.get()); |
| 71 |
| 72 EXPECT_EQ(10, scoper->SomeMeth(10)); |
| 73 EXPECT_EQ(10, scoper.get()->SomeMeth(10)); |
| 74 EXPECT_EQ(10, (*scoper).SomeMeth(10)); |
| 75 } |
| 76 EXPECT_EQ(0, constructed); |
| 77 |
| 78 // Test reset() and release() |
| 79 { |
| 80 unique_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed)); |
| 81 EXPECT_EQ(1, constructed); |
| 82 EXPECT_TRUE(scoper.get()); |
| 83 |
| 84 scoper.reset(new ConDecLogger(&constructed)); |
| 85 EXPECT_EQ(1, constructed); |
| 86 EXPECT_TRUE(scoper.get()); |
| 87 |
| 88 scoper.reset(); |
| 89 EXPECT_EQ(0, constructed); |
| 90 EXPECT_FALSE(scoper.get()); |
| 91 |
| 92 scoper.reset(new ConDecLogger(&constructed)); |
| 93 EXPECT_EQ(1, constructed); |
| 94 EXPECT_TRUE(scoper.get()); |
| 95 |
| 96 ConDecLogger* take = scoper.release(); |
| 97 EXPECT_EQ(1, constructed); |
| 98 EXPECT_FALSE(scoper.get()); |
| 99 delete take; |
| 100 EXPECT_EQ(0, constructed); |
| 101 |
| 102 scoper.reset(new ConDecLogger(&constructed)); |
| 103 EXPECT_EQ(1, constructed); |
| 104 EXPECT_TRUE(scoper.get()); |
| 105 } |
| 106 EXPECT_EQ(0, constructed); |
| 107 |
| 108 // Test swap(), == and != |
| 109 { |
| 110 unique_ptr<ConDecLogger> scoper1; |
| 111 unique_ptr<ConDecLogger> scoper2; |
| 112 EXPECT_TRUE(scoper1 == scoper2.get()); |
| 113 EXPECT_FALSE(scoper1 != scoper2.get()); |
| 114 |
| 115 ConDecLogger* logger = new ConDecLogger(&constructed); |
| 116 scoper1.reset(logger); |
| 117 EXPECT_EQ(logger, scoper1.get()); |
| 118 EXPECT_FALSE(scoper2.get()); |
| 119 EXPECT_FALSE(scoper1 == scoper2.get()); |
| 120 EXPECT_TRUE(scoper1 != scoper2.get()); |
| 121 |
| 122 scoper2.swap(scoper1); |
| 123 EXPECT_EQ(logger, scoper2.get()); |
| 124 EXPECT_FALSE(scoper1.get()); |
| 125 EXPECT_FALSE(scoper1 == scoper2.get()); |
| 126 EXPECT_TRUE(scoper1 != scoper2.get()); |
| 127 } |
| 128 EXPECT_EQ(0, constructed); |
| 129 } |
| 130 |
| 131 TEST(UniquePtrTest, UniquePtrWithArray) { |
| 132 static const int kNumLoggers = 12; |
| 133 |
| 134 int constructed = 0; |
| 135 |
| 136 { |
| 137 unique_ptr<ConDecLogger[]> scoper(new ConDecLogger[kNumLoggers]); |
| 138 EXPECT_TRUE(scoper); |
| 139 EXPECT_EQ(&scoper[0], scoper.get()); |
| 140 for (int i = 0; i < kNumLoggers; ++i) { |
| 141 scoper[i].SetPtr(&constructed); |
| 142 } |
| 143 EXPECT_EQ(12, constructed); |
| 144 |
| 145 EXPECT_EQ(10, scoper.get()->SomeMeth(10)); |
| 146 EXPECT_EQ(10, scoper[2].SomeMeth(10)); |
| 147 } |
| 148 EXPECT_EQ(0, constructed); |
| 149 |
| 150 // Test reset() and release() |
| 151 { |
| 152 unique_ptr<ConDecLogger[]> scoper; |
| 153 EXPECT_FALSE(scoper.get()); |
| 154 EXPECT_FALSE(scoper.release()); |
| 155 EXPECT_FALSE(scoper.get()); |
| 156 scoper.reset(); |
| 157 EXPECT_FALSE(scoper.get()); |
| 158 |
| 159 scoper.reset(new ConDecLogger[kNumLoggers]); |
| 160 for (int i = 0; i < kNumLoggers; ++i) { |
| 161 scoper[i].SetPtr(&constructed); |
| 162 } |
| 163 EXPECT_EQ(12, constructed); |
| 164 scoper.reset(); |
| 165 EXPECT_EQ(0, constructed); |
| 166 |
| 167 scoper.reset(new ConDecLogger[kNumLoggers]); |
| 168 for (int i = 0; i < kNumLoggers; ++i) { |
| 169 scoper[i].SetPtr(&constructed); |
| 170 } |
| 171 EXPECT_EQ(12, constructed); |
| 172 ConDecLogger* ptr = scoper.release(); |
| 173 EXPECT_EQ(12, constructed); |
| 174 delete[] ptr; |
| 175 EXPECT_EQ(0, constructed); |
| 176 } |
| 177 EXPECT_EQ(0, constructed); |
| 178 |
| 179 // Test swap(), ==, !=, and type-safe Boolean. |
| 180 { |
| 181 unique_ptr<ConDecLogger[]> scoper1; |
| 182 unique_ptr<ConDecLogger[]> scoper2; |
| 183 EXPECT_TRUE(scoper1 == scoper2.get()); |
| 184 EXPECT_FALSE(scoper1 != scoper2.get()); |
| 185 |
| 186 ConDecLogger* loggers = new ConDecLogger[kNumLoggers]; |
| 187 for (int i = 0; i < kNumLoggers; ++i) { |
| 188 loggers[i].SetPtr(&constructed); |
| 189 } |
| 190 scoper1.reset(loggers); |
| 191 EXPECT_TRUE(scoper1); |
| 192 EXPECT_EQ(loggers, scoper1.get()); |
| 193 EXPECT_FALSE(scoper2); |
| 194 EXPECT_FALSE(scoper2.get()); |
| 195 EXPECT_FALSE(scoper1 == scoper2.get()); |
| 196 EXPECT_TRUE(scoper1 != scoper2.get()); |
| 197 |
| 198 scoper2.swap(scoper1); |
| 199 EXPECT_EQ(loggers, scoper2.get()); |
| 200 EXPECT_FALSE(scoper1.get()); |
| 201 EXPECT_FALSE(scoper1 == scoper2.get()); |
| 202 EXPECT_TRUE(scoper1 != scoper2.get()); |
| 203 } |
| 204 EXPECT_EQ(0, constructed); |
| 205 } |
| 206 |
| 207 TEST(UniquePtrTest, ReturnTypeBehavior) { |
| 208 int constructed = 0; |
| 209 |
| 210 // Test that we can return a unique_ptr. |
| 211 { |
| 212 ConDecLogger* logger = new ConDecLogger(&constructed); |
| 213 unique_ptr<ConDecLogger> scoper(logger); |
| 214 EXPECT_EQ(1, constructed); |
| 215 } |
| 216 EXPECT_EQ(0, constructed); |
| 217 |
| 218 // Test uncaught return type not leak. |
| 219 { |
| 220 ConDecLogger* logger = new ConDecLogger(&constructed); |
| 221 unique_ptr<ConDecLogger> scoper(logger); |
| 222 EXPECT_EQ(1, constructed); |
| 223 } |
| 224 EXPECT_EQ(0, constructed); |
| 225 |
| 226 // Call TestReturnOfType() so the compiler doesn't warn for an unused |
| 227 // function. |
| 228 { TestReturnOfType(&constructed); } |
| 229 EXPECT_EQ(0, constructed); |
| 230 } |
| 231 |
| 232 TEST(UniquePtrTest, CustomDeleter) { |
| 233 double dummy_value; // Custom deleter never touches this value. |
| 234 int deletes = 0; |
| 235 int alternate_deletes = 0; |
| 236 |
| 237 // Normal delete support. |
| 238 { |
| 239 deletes = 0; |
| 240 unique_ptr<double, CountingDeleter> scoper(&dummy_value, |
| 241 CountingDeleter(&deletes)); |
| 242 EXPECT_EQ(0, deletes); |
| 243 EXPECT_TRUE(scoper.get()); |
| 244 } |
| 245 EXPECT_EQ(1, deletes); |
| 246 |
| 247 // Test reset() and release(). |
| 248 deletes = 0; |
| 249 { |
| 250 unique_ptr<double, CountingDeleter> scoper(nullptr, |
| 251 CountingDeleter(&deletes)); |
| 252 EXPECT_FALSE(scoper.get()); |
| 253 EXPECT_FALSE(scoper.release()); |
| 254 EXPECT_FALSE(scoper.get()); |
| 255 scoper.reset(); |
| 256 EXPECT_FALSE(scoper.get()); |
| 257 EXPECT_EQ(0, deletes); |
| 258 |
| 259 scoper.reset(&dummy_value); |
| 260 scoper.reset(); |
| 261 EXPECT_EQ(1, deletes); |
| 262 |
| 263 scoper.reset(&dummy_value); |
| 264 EXPECT_EQ(&dummy_value, scoper.release()); |
| 265 } |
| 266 EXPECT_EQ(1, deletes); |
| 267 |
| 268 // Test get_deleter(). |
| 269 deletes = 0; |
| 270 alternate_deletes = 0; |
| 271 { |
| 272 unique_ptr<double, CountingDeleter> scoper(&dummy_value, |
| 273 CountingDeleter(&deletes)); |
| 274 // Call deleter manually. |
| 275 EXPECT_EQ(0, deletes); |
| 276 scoper.get_deleter()(&dummy_value); |
| 277 EXPECT_EQ(1, deletes); |
| 278 |
| 279 // Deleter is still there after reset. |
| 280 scoper.reset(); |
| 281 EXPECT_EQ(2, deletes); |
| 282 scoper.get_deleter()(&dummy_value); |
| 283 EXPECT_EQ(3, deletes); |
| 284 |
| 285 // Deleter can be assigned into (matches C++11 unique_ptr<> spec). |
| 286 scoper.get_deleter() = CountingDeleter(&alternate_deletes); |
| 287 scoper.reset(&dummy_value); |
| 288 EXPECT_EQ(0, alternate_deletes); |
| 289 } |
| 290 EXPECT_EQ(3, deletes); |
| 291 EXPECT_EQ(1, alternate_deletes); |
| 292 |
| 293 // Test swap(), ==, !=, and type-safe Boolean. |
| 294 { |
| 295 unique_ptr<double, CountingDeleter> scoper1(nullptr, |
| 296 CountingDeleter(&deletes)); |
| 297 unique_ptr<double, CountingDeleter> scoper2(nullptr, |
| 298 CountingDeleter(&deletes)); |
| 299 EXPECT_TRUE(scoper1 == scoper2.get()); |
| 300 EXPECT_FALSE(scoper1 != scoper2.get()); |
| 301 |
| 302 scoper1.reset(&dummy_value); |
| 303 EXPECT_TRUE(scoper1); |
| 304 EXPECT_EQ(&dummy_value, scoper1.get()); |
| 305 EXPECT_FALSE(scoper2); |
| 306 EXPECT_FALSE(scoper2.get()); |
| 307 EXPECT_FALSE(scoper1 == scoper2.get()); |
| 308 EXPECT_TRUE(scoper1 != scoper2.get()); |
| 309 |
| 310 scoper2.swap(scoper1); |
| 311 EXPECT_EQ(&dummy_value, scoper2.get()); |
| 312 EXPECT_FALSE(scoper1.get()); |
| 313 EXPECT_FALSE(scoper1 == scoper2.get()); |
| 314 EXPECT_TRUE(scoper1 != scoper2.get()); |
| 315 } |
| 316 } |
| 317 |
| 318 unique_ptr<int> NullIntReturn() { |
| 319 return nullptr; |
| 320 } |
| 321 |
| 322 TEST(UniquePtrTest, Nullptr) { |
| 323 unique_ptr<int> scoper1(nullptr); |
| 324 unique_ptr<int> scoper2(new int); |
| 325 scoper2 = nullptr; |
| 326 unique_ptr<int> scoper3(NullIntReturn()); |
| 327 unique_ptr<int> scoper4 = NullIntReturn(); |
| 328 EXPECT_EQ(nullptr, scoper1.get()); |
| 329 EXPECT_EQ(nullptr, scoper2.get()); |
| 330 EXPECT_EQ(nullptr, scoper3.get()); |
| 331 EXPECT_EQ(nullptr, scoper4.get()); |
| 332 } |
| 333 |
| 334 unique_ptr<int[]> NullIntArrayReturn() { |
| 335 return nullptr; |
| 336 } |
| 337 |
| 338 TEST(UniquePtrTest, NullptrArray) { |
| 339 unique_ptr<int[]> scoper1(nullptr); |
| 340 unique_ptr<int[]> scoper2(new int[3]); |
| 341 scoper2 = nullptr; |
| 342 unique_ptr<int[]> scoper3(NullIntArrayReturn()); |
| 343 unique_ptr<int[]> scoper4 = NullIntArrayReturn(); |
| 344 EXPECT_EQ(nullptr, scoper1.get()); |
| 345 EXPECT_EQ(nullptr, scoper2.get()); |
| 346 EXPECT_EQ(nullptr, scoper3.get()); |
| 347 EXPECT_EQ(nullptr, scoper4.get()); |
| 348 } |
| 349 |
| 350 // Logging a unique_ptr<T> to an ostream shouldn't convert it to a boolean |
| 351 // value first. |
| 352 TEST(ScopedPtrTest, LoggingDoesntConvertToBoolean) { |
| 353 unique_ptr<int> x(new int); |
| 354 std::stringstream s1; |
| 355 s1 << x; |
| 356 |
| 357 std::stringstream s2; |
| 358 s2 << x.get(); |
| 359 |
| 360 EXPECT_EQ(s2.str(), s1.str()); |
| 361 } |
OLD | NEW |