diff options
Diffstat (limited to 'core/fxcrt/retain_ptr_unittest.cpp')
-rw-r--r-- | core/fxcrt/retain_ptr_unittest.cpp | 297 |
1 files changed, 254 insertions, 43 deletions
diff --git a/core/fxcrt/retain_ptr_unittest.cpp b/core/fxcrt/retain_ptr_unittest.cpp index 47277df63..b381e78d0 100644 --- a/core/fxcrt/retain_ptr_unittest.cpp +++ b/core/fxcrt/retain_ptr_unittest.cpp @@ -1,23 +1,52 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2016 The PDFium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "core/fxcrt/retain_ptr.h" +#include <functional> +#include <set> #include <utility> #include <vector> #include "testing/gtest/include/gtest/gtest.h" #include "testing/pseudo_retainable.h" +#include "third_party/base/containers/contains.h" + +namespace { + +template <typename T, typename C = std::less<T>> +class NoLinearSearchSet : public std::set<T, C> { + public: + typename std::set<T, C>::iterator begin() noexcept = delete; + typename std::set<T, C>::const_iterator cbegin() const noexcept = delete; +}; + +} // namespace namespace fxcrt { +namespace { + +template <typename T, typename C = std::less<T>> +class NoLinearSearchSet : public std::set<T, C> { + public: + typename std::set<T, C>::iterator begin() noexcept = delete; + typename std::set<T, C>::const_iterator cbegin() const noexcept = delete; +}; + +} // namespace -TEST(RetainPtr, Null) { +TEST(RetainPtr, DefaultCtor) { RetainPtr<PseudoRetainable> ptr; - EXPECT_EQ(nullptr, ptr.Get()); + EXPECT_FALSE(ptr.Get()); } -TEST(RetainPtr, Normal) { +TEST(RetainPtr, NullptrCtor) { + RetainPtr<PseudoRetainable> ptr(nullptr); + EXPECT_FALSE(ptr.Get()); +} + +TEST(RetainPtr, RawCtor) { PseudoRetainable obj; { RetainPtr<PseudoRetainable> ptr(&obj); @@ -51,7 +80,143 @@ TEST(RetainPtr, MoveCtor) { RetainPtr<PseudoRetainable> ptr1(&obj); { RetainPtr<PseudoRetainable> ptr2(std::move(ptr1)); - EXPECT_EQ(nullptr, ptr1.Get()); + EXPECT_FALSE(ptr1.Get()); + EXPECT_EQ(&obj, ptr2.Get()); + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(0, obj.release_count()); + } + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); + } + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); +} + +TEST(RetainPtr, CopyConversionCtor) { + PseudoRetainable obj; + { + RetainPtr<PseudoRetainable> ptr1(&obj); + { + RetainPtr<const PseudoRetainable> ptr2(ptr1); + EXPECT_EQ(2, obj.retain_count()); + EXPECT_EQ(0, obj.release_count()); + } + EXPECT_EQ(2, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); + } + EXPECT_EQ(2, obj.retain_count()); + EXPECT_EQ(2, obj.release_count()); +} + +TEST(RetainPtr, MoveConversionCtor) { + PseudoRetainable obj; + { + RetainPtr<PseudoRetainable> ptr1(&obj); + { + RetainPtr<const PseudoRetainable> ptr2(std::move(ptr1)); + EXPECT_FALSE(ptr1.Get()); + EXPECT_EQ(&obj, ptr2.Get()); + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(0, obj.release_count()); + } + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); + } + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); +} + +TEST(RetainPtr, NullptrAssign) { + PseudoRetainable obj; + RetainPtr<PseudoRetainable> ptr(&obj); + ptr = nullptr; + EXPECT_FALSE(ptr); +} + +TEST(RetainPtr, RawAssign) { + PseudoRetainable obj; + RetainPtr<PseudoRetainable> ptr; + ptr = pdfium::WrapRetain(&obj); + EXPECT_EQ(&obj, ptr); +} + +TEST(RetainPtr, CopyAssign) { + PseudoRetainable obj; + { + RetainPtr<PseudoRetainable> ptr(&obj); + { + RetainPtr<PseudoRetainable> ptr2; + ptr2 = ptr; + EXPECT_EQ(2, obj.retain_count()); + EXPECT_EQ(0, obj.release_count()); + } + { + // Test assignment from wrapped underlying type. + RetainPtr<PseudoRetainable> ptr2; + ptr2 = pdfium::WrapRetain(ptr.Get()); + EXPECT_EQ(3, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); + } + EXPECT_EQ(3, obj.retain_count()); + EXPECT_EQ(2, obj.release_count()); + } + EXPECT_EQ(3, obj.retain_count()); + EXPECT_EQ(3, obj.release_count()); +} + +TEST(RetainPtr, MoveAssign) { + PseudoRetainable obj; + { + RetainPtr<PseudoRetainable> ptr1(&obj); + { + RetainPtr<PseudoRetainable> ptr2; + EXPECT_EQ(&obj, ptr1.Get()); + EXPECT_FALSE(ptr2.Get()); + ptr2 = std::move(ptr1); + EXPECT_FALSE(ptr1.Get()); + EXPECT_EQ(&obj, ptr2.Get()); + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(0, obj.release_count()); + } + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); + } + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); +} + +TEST(RetainPtr, CopyConvertAssign) { + PseudoRetainable obj; + { + RetainPtr<PseudoRetainable> ptr(&obj); + { + RetainPtr<const PseudoRetainable> ptr2; + ptr2 = ptr; + EXPECT_EQ(2, obj.retain_count()); + EXPECT_EQ(0, obj.release_count()); + } + { + // Test assignment from wrapped underlying type. + RetainPtr<const PseudoRetainable> ptr2; + ptr2 = pdfium::WrapRetain(ptr.Get()); + EXPECT_EQ(3, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); + } + EXPECT_EQ(3, obj.retain_count()); + EXPECT_EQ(2, obj.release_count()); + } + EXPECT_EQ(3, obj.retain_count()); + EXPECT_EQ(3, obj.release_count()); +} + +TEST(RetainPtr, MoveConvertAssign) { + PseudoRetainable obj; + { + RetainPtr<PseudoRetainable> ptr1(&obj); + { + RetainPtr<const PseudoRetainable> ptr2; + ptr2 = std::move(ptr1); + EXPECT_FALSE(ptr1); EXPECT_EQ(&obj, ptr2.Get()); EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(0, obj.release_count()); @@ -63,6 +228,15 @@ TEST(RetainPtr, MoveCtor) { EXPECT_EQ(1, obj.release_count()); } +TEST(RetainPtr, AmbiguousExpression) { + class A : public Retainable {}; + class B : public A {}; + + // Test passes if it compiles without error. + RetainPtr<A> var = (0) ? pdfium::MakeRetain<A>() : pdfium::MakeRetain<B>(); + EXPECT_TRUE(var); +} + TEST(RetainPtr, ResetNull) { PseudoRetainable obj; { @@ -156,44 +330,6 @@ TEST(RetainPtr, SwapNull) { EXPECT_EQ(1, obj1.release_count()); } -TEST(RetainPtr, Assign) { - PseudoRetainable obj; - { - RetainPtr<PseudoRetainable> ptr(&obj); - { - RetainPtr<PseudoRetainable> ptr2; - ptr2 = ptr; - EXPECT_EQ(2, obj.retain_count()); - EXPECT_EQ(0, obj.release_count()); - } - EXPECT_EQ(2, obj.retain_count()); - EXPECT_EQ(1, obj.release_count()); - } - EXPECT_EQ(2, obj.retain_count()); - EXPECT_EQ(2, obj.release_count()); -} - -TEST(RetainPtr, MoveAssign) { - PseudoRetainable obj; - { - RetainPtr<PseudoRetainable> ptr1(&obj); - { - RetainPtr<PseudoRetainable> ptr2; - EXPECT_EQ(&obj, ptr1.Get()); - EXPECT_EQ(nullptr, ptr2.Get()); - ptr2 = std::move(ptr1); - EXPECT_EQ(nullptr, ptr1.Get()); - EXPECT_EQ(&obj, ptr2.Get()); - EXPECT_EQ(1, obj.retain_count()); - EXPECT_EQ(0, obj.release_count()); - } - EXPECT_EQ(1, obj.retain_count()); - EXPECT_EQ(1, obj.release_count()); - } - EXPECT_EQ(1, obj.retain_count()); - EXPECT_EQ(1, obj.release_count()); -} - TEST(RetainPtr, Equals) { PseudoRetainable obj1; PseudoRetainable obj2; @@ -309,4 +445,79 @@ TEST(RetainPtr, VectorMove) { EXPECT_EQ(1, obj.release_count()); } +TEST(RetainPtr, SetContains) { + // Makes sure pdfium::Contains() works the same way with raw pointers and + // RetainPtrs for containers that use find(). + PseudoRetainable obj1; + PseudoRetainable obj2; + RetainPtr<PseudoRetainable> ptr1(&obj1); + RetainPtr<PseudoRetainable> ptr2(&obj2); + RetainPtr<const PseudoRetainable> const_ptr1(&obj1); + RetainPtr<const PseudoRetainable> const_ptr2(&obj2); + NoLinearSearchSet<RetainPtr<const PseudoRetainable>, std::less<>> the_set; + + // Intially, two smart pointers to each object. + EXPECT_EQ(2, obj1.retain_count()); + EXPECT_EQ(0, obj1.release_count()); + EXPECT_EQ(2, obj2.retain_count()); + EXPECT_EQ(0, obj2.release_count()); + + // Passed by const-ref, increment on copy into set's data structure. + the_set.insert(const_ptr1); + EXPECT_EQ(3, obj1.retain_count()); + EXPECT_EQ(0, obj1.release_count()); + EXPECT_EQ(2, obj2.retain_count()); + EXPECT_EQ(0, obj2.release_count()); + + // None of the following should cause any churn. + EXPECT_NE(the_set.end(), the_set.find(&obj1)); + EXPECT_EQ(the_set.end(), the_set.find(&obj2)); + EXPECT_TRUE(pdfium::Contains(the_set, &obj1)); + EXPECT_FALSE(pdfium::Contains(the_set, &obj2)); + EXPECT_EQ(3, obj1.retain_count()); + EXPECT_EQ(0, obj1.release_count()); + EXPECT_EQ(2, obj2.retain_count()); + EXPECT_EQ(0, obj2.release_count()); + + EXPECT_NE(the_set.end(), the_set.find(const_ptr1)); + EXPECT_EQ(the_set.end(), the_set.find(const_ptr2)); + EXPECT_TRUE(pdfium::Contains(the_set, const_ptr1)); + EXPECT_FALSE(pdfium::Contains(the_set, const_ptr2)); + EXPECT_EQ(3, obj1.retain_count()); + EXPECT_EQ(0, obj1.release_count()); + EXPECT_EQ(2, obj2.retain_count()); + EXPECT_EQ(0, obj2.release_count()); + + // These involve const-removing conversions which seem to churn. + EXPECT_NE(the_set.end(), the_set.find(ptr1)); + EXPECT_EQ(the_set.end(), the_set.find(ptr2)); + EXPECT_TRUE(pdfium::Contains(the_set, ptr1)); + EXPECT_FALSE(pdfium::Contains(the_set, ptr2)); + EXPECT_EQ(5, obj1.retain_count()); + EXPECT_EQ(2, obj1.release_count()); + EXPECT_EQ(4, obj2.retain_count()); + EXPECT_EQ(2, obj2.release_count()); +} + +TEST(RetainPtr, VectorContains) { + // Makes sure pdfium::Contains() works the same way with raw pointers and + // RetainPtrs. for containers that use begin()/end(). + PseudoRetainable obj1; + PseudoRetainable obj2; + std::vector<const PseudoRetainable*> vec; + vec.push_back(&obj1); + EXPECT_TRUE(pdfium::Contains(vec, &obj1)); + EXPECT_FALSE(pdfium::Contains(vec, &obj2)); + + RetainPtr<PseudoRetainable> ptr1(&obj1); + RetainPtr<PseudoRetainable> ptr2(&obj2); + EXPECT_TRUE(pdfium::Contains(vec, ptr1)); + EXPECT_FALSE(pdfium::Contains(vec, ptr2)); + + RetainPtr<const PseudoRetainable> const_ptr1(&obj1); + RetainPtr<const PseudoRetainable> const_ptr2(&obj2); + EXPECT_TRUE(pdfium::Contains(vec, const_ptr1)); + EXPECT_FALSE(pdfium::Contains(vec, const_ptr2)); +} + } // namespace fxcrt |