diff options
author | Lei Zhang <thestig@chromium.org> | 2015-09-22 21:53:22 -0700 |
---|---|---|
committer | Lei Zhang <thestig@chromium.org> | 2015-09-22 21:53:22 -0700 |
commit | 13fe8c9d74607610b3a535c7edf911eaa8711318 (patch) | |
tree | abfc392171d0ace3144035903f7d930c78a9c96c /third_party/base/nonstd_unique_ptr_unittest.cpp | |
parent | 0244d40daf39caf97f47de9982f4aac88c0c8644 (diff) | |
download | pdfium-13fe8c9d74607610b3a535c7edf911eaa8711318.tar.xz |
Merge to XFA: Change nonstd::unique_ptr to take a custom deleter.
Code is mostly stolen from Chromium's scoped_ptr.
- Add unit tests.
- Use this to fix a leak.
BUG=chromium:531408
TBR=tsepez@chromium.org
Review URL: https://codereview.chromium.org/1351383004 .
(cherry picked from commit cef2a9c51bee4b987fc813013d45dad6535a9a46)
Review URL: https://codereview.chromium.org/1358163003 .
Diffstat (limited to 'third_party/base/nonstd_unique_ptr_unittest.cpp')
-rw-r--r-- | third_party/base/nonstd_unique_ptr_unittest.cpp | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/third_party/base/nonstd_unique_ptr_unittest.cpp b/third_party/base/nonstd_unique_ptr_unittest.cpp index 49cc901fe2..2b120581f4 100644 --- a/third_party/base/nonstd_unique_ptr_unittest.cpp +++ b/third_party/base/nonstd_unique_ptr_unittest.cpp @@ -85,3 +85,306 @@ TEST(UniquePtrTest, MoveTest) { } EXPECT_EQ(0, constructed); } + +TEST(UniquePtrTest, UniquePtr) { + int constructed = 0; + + // Ensure size of unique_ptr<> doesn't increase unexpectedly. + static_assert(sizeof(int*) >= sizeof(unique_ptr<int>), + "unique_ptr_larger_than_raw_ptr"); + + { + unique_ptr<CtorDtorLogger> scoper(new CtorDtorLogger(&constructed)); + EXPECT_EQ(1, constructed); + EXPECT_TRUE(scoper.get()); + + EXPECT_EQ(10, scoper->SomeMeth(10)); + EXPECT_EQ(10, scoper.get()->SomeMeth(10)); + EXPECT_EQ(10, (*scoper).SomeMeth(10)); + } + EXPECT_EQ(0, constructed); + + // Test reset() and release() + { + unique_ptr<CtorDtorLogger> scoper(new CtorDtorLogger(&constructed)); + EXPECT_EQ(1, constructed); + EXPECT_TRUE(scoper.get()); + + scoper.reset(new CtorDtorLogger(&constructed)); + EXPECT_EQ(1, constructed); + EXPECT_TRUE(scoper.get()); + + scoper.reset(); + EXPECT_EQ(0, constructed); + EXPECT_FALSE(scoper.get()); + + scoper.reset(new CtorDtorLogger(&constructed)); + EXPECT_EQ(1, constructed); + EXPECT_TRUE(scoper.get()); + + CtorDtorLogger* take = scoper.release(); + EXPECT_EQ(1, constructed); + EXPECT_FALSE(scoper.get()); + delete take; + EXPECT_EQ(0, constructed); + + scoper.reset(new CtorDtorLogger(&constructed)); + EXPECT_EQ(1, constructed); + EXPECT_TRUE(scoper.get()); + } + EXPECT_EQ(0, constructed); + + // Test swap(), == and != + { + unique_ptr<CtorDtorLogger> scoper1; + unique_ptr<CtorDtorLogger> scoper2; + EXPECT_TRUE(scoper1 == scoper2.get()); + EXPECT_FALSE(scoper1 != scoper2.get()); + + CtorDtorLogger* logger = new CtorDtorLogger(&constructed); + scoper1.reset(logger); + EXPECT_EQ(logger, scoper1.get()); + EXPECT_FALSE(scoper2.get()); + EXPECT_FALSE(scoper1 == scoper2.get()); + EXPECT_TRUE(scoper1 != scoper2.get()); + + scoper2.swap(scoper1); + EXPECT_EQ(logger, scoper2.get()); + EXPECT_FALSE(scoper1.get()); + EXPECT_FALSE(scoper1 == scoper2.get()); + EXPECT_TRUE(scoper1 != scoper2.get()); + } + EXPECT_EQ(0, constructed); +} + +TEST(UniquePtrTest, UniquePtrWithArray) { + static const int kNumLoggers = 12; + + int constructed = 0; + + { + unique_ptr<CtorDtorLogger[]> scoper(new CtorDtorLogger[kNumLoggers]); + EXPECT_TRUE(scoper); + EXPECT_EQ(&scoper[0], scoper.get()); + for (int i = 0; i < kNumLoggers; ++i) { + scoper[i].SetPtr(&constructed); + } + EXPECT_EQ(12, constructed); + + EXPECT_EQ(10, scoper.get()->SomeMeth(10)); + EXPECT_EQ(10, scoper[2].SomeMeth(10)); + } + EXPECT_EQ(0, constructed); + + // Test reset() and release() + { + unique_ptr<CtorDtorLogger[]> scoper; + EXPECT_FALSE(scoper.get()); + EXPECT_FALSE(scoper.release()); + EXPECT_FALSE(scoper.get()); + scoper.reset(); + EXPECT_FALSE(scoper.get()); + + scoper.reset(new CtorDtorLogger[kNumLoggers]); + for (int i = 0; i < kNumLoggers; ++i) { + scoper[i].SetPtr(&constructed); + } + EXPECT_EQ(12, constructed); + scoper.reset(); + EXPECT_EQ(0, constructed); + + scoper.reset(new CtorDtorLogger[kNumLoggers]); + for (int i = 0; i < kNumLoggers; ++i) { + scoper[i].SetPtr(&constructed); + } + EXPECT_EQ(12, constructed); + CtorDtorLogger* ptr = scoper.release(); + EXPECT_EQ(12, constructed); + delete[] ptr; + EXPECT_EQ(0, constructed); + } + EXPECT_EQ(0, constructed); + + // Test swap(), ==, !=, and type-safe Boolean. + { + unique_ptr<CtorDtorLogger[]> scoper1; + unique_ptr<CtorDtorLogger[]> scoper2; + EXPECT_TRUE(scoper1 == scoper2.get()); + EXPECT_FALSE(scoper1 != scoper2.get()); + + CtorDtorLogger* loggers = new CtorDtorLogger[kNumLoggers]; + for (int i = 0; i < kNumLoggers; ++i) { + loggers[i].SetPtr(&constructed); + } + scoper1.reset(loggers); + EXPECT_TRUE(scoper1); + EXPECT_EQ(loggers, scoper1.get()); + EXPECT_FALSE(scoper2); + EXPECT_FALSE(scoper2.get()); + EXPECT_FALSE(scoper1 == scoper2.get()); + EXPECT_TRUE(scoper1 != scoper2.get()); + + scoper2.swap(scoper1); + EXPECT_EQ(loggers, scoper2.get()); + EXPECT_FALSE(scoper1.get()); + EXPECT_FALSE(scoper1 == scoper2.get()); + EXPECT_TRUE(scoper1 != scoper2.get()); + } + EXPECT_EQ(0, constructed); +} + +TEST(UniquePtrTest, ReturnTypeBehavior) { + int constructed = 0; + + // Test that we can return a unique_ptr. + { + CtorDtorLogger* logger = new CtorDtorLogger(&constructed); + unique_ptr<CtorDtorLogger> scoper(logger); + EXPECT_EQ(1, constructed); + } + EXPECT_EQ(0, constructed); + + // Test uncaught return type not leak. + { + CtorDtorLogger* logger = new CtorDtorLogger(&constructed); + unique_ptr<CtorDtorLogger> scoper(logger); + EXPECT_EQ(1, constructed); + } + EXPECT_EQ(0, constructed); + + // Call TestReturnOfType() so the compiler doesn't warn for an unused + // function. + { TestReturnOfType(&constructed); } + EXPECT_EQ(0, constructed); +} + +TEST(UniquePtrTest, CustomDeleter) { + double dummy_value; // Custom deleter never touches this value. + int deletes = 0; + int alternate_deletes = 0; + + // Normal delete support. + { + deletes = 0; + unique_ptr<double, CountingDeleter> scoper(&dummy_value, + CountingDeleter(&deletes)); + EXPECT_EQ(0, deletes); + EXPECT_TRUE(scoper.get()); + } + EXPECT_EQ(1, deletes); + + // Test reset() and release(). + deletes = 0; + { + unique_ptr<double, CountingDeleter> scoper(nullptr, + CountingDeleter(&deletes)); + EXPECT_FALSE(scoper.get()); + EXPECT_FALSE(scoper.release()); + EXPECT_FALSE(scoper.get()); + scoper.reset(); + EXPECT_FALSE(scoper.get()); + EXPECT_EQ(0, deletes); + + scoper.reset(&dummy_value); + scoper.reset(); + EXPECT_EQ(1, deletes); + + scoper.reset(&dummy_value); + EXPECT_EQ(&dummy_value, scoper.release()); + } + EXPECT_EQ(1, deletes); + + // Test get_deleter(). + deletes = 0; + alternate_deletes = 0; + { + unique_ptr<double, CountingDeleter> scoper(&dummy_value, + CountingDeleter(&deletes)); + // Call deleter manually. + EXPECT_EQ(0, deletes); + scoper.get_deleter()(&dummy_value); + EXPECT_EQ(1, deletes); + + // Deleter is still there after reset. + scoper.reset(); + EXPECT_EQ(2, deletes); + scoper.get_deleter()(&dummy_value); + EXPECT_EQ(3, deletes); + + // Deleter can be assigned into (matches C++11 unique_ptr<> spec). + scoper.get_deleter() = CountingDeleter(&alternate_deletes); + scoper.reset(&dummy_value); + EXPECT_EQ(0, alternate_deletes); + } + EXPECT_EQ(3, deletes); + EXPECT_EQ(1, alternate_deletes); + + // Test swap(), ==, !=, and type-safe Boolean. + { + unique_ptr<double, CountingDeleter> scoper1(nullptr, + CountingDeleter(&deletes)); + unique_ptr<double, CountingDeleter> scoper2(nullptr, + CountingDeleter(&deletes)); + EXPECT_TRUE(scoper1 == scoper2.get()); + EXPECT_FALSE(scoper1 != scoper2.get()); + + scoper1.reset(&dummy_value); + EXPECT_TRUE(scoper1); + EXPECT_EQ(&dummy_value, scoper1.get()); + EXPECT_FALSE(scoper2); + EXPECT_FALSE(scoper2.get()); + EXPECT_FALSE(scoper1 == scoper2.get()); + EXPECT_TRUE(scoper1 != scoper2.get()); + + scoper2.swap(scoper1); + EXPECT_EQ(&dummy_value, scoper2.get()); + EXPECT_FALSE(scoper1.get()); + EXPECT_FALSE(scoper1 == scoper2.get()); + EXPECT_TRUE(scoper1 != scoper2.get()); + } +} + +unique_ptr<int> NullIntReturn() { + return nullptr; +} + +TEST(UniquePtrTest, Nullptr) { + unique_ptr<int> scoper1(nullptr); + unique_ptr<int> scoper2(new int); + scoper2 = nullptr; + unique_ptr<int> scoper3(NullIntReturn()); + unique_ptr<int> scoper4 = NullIntReturn(); + EXPECT_EQ(nullptr, scoper1.get()); + EXPECT_EQ(nullptr, scoper2.get()); + EXPECT_EQ(nullptr, scoper3.get()); + EXPECT_EQ(nullptr, scoper4.get()); +} + +unique_ptr<int[]> NullIntArrayReturn() { + return nullptr; +} + +TEST(UniquePtrTest, NullptrArray) { + unique_ptr<int[]> scoper1(nullptr); + unique_ptr<int[]> scoper2(new int[3]); + scoper2 = nullptr; + unique_ptr<int[]> scoper3(NullIntArrayReturn()); + unique_ptr<int[]> scoper4 = NullIntArrayReturn(); + EXPECT_EQ(nullptr, scoper1.get()); + EXPECT_EQ(nullptr, scoper2.get()); + EXPECT_EQ(nullptr, scoper3.get()); + EXPECT_EQ(nullptr, scoper4.get()); +} + +// Logging a unique_ptr<T> to an ostream shouldn't convert it to a boolean +// value first. +TEST(ScopedPtrTest, LoggingDoesntConvertToBoolean) { + unique_ptr<int> x(new int); + std::stringstream s1; + s1 << x; + + std::stringstream s2; + s2 << x.get(); + + EXPECT_EQ(s2.str(), s1.str()); +} |