diff options
Diffstat (limited to 'dom/quota/test/gtest/TestCheckedUnsafePtr.cpp')
-rw-r--r-- | dom/quota/test/gtest/TestCheckedUnsafePtr.cpp | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/dom/quota/test/gtest/TestCheckedUnsafePtr.cpp b/dom/quota/test/gtest/TestCheckedUnsafePtr.cpp new file mode 100644 index 0000000000..14abb6631d --- /dev/null +++ b/dom/quota/test/gtest/TestCheckedUnsafePtr.cpp @@ -0,0 +1,145 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/quota/CheckedUnsafePtr.h" + +#include "gtest/gtest.h" + +#include <memory> +#include <type_traits> +#include <utility> +#include "mozilla/fallible.h" + +using namespace mozilla; + +class NoCheckTestType + : public SupportsCheckedUnsafePtr<DoNotCheckCheckedUnsafePtrs> {}; + +#if __cplusplus < 202002L +static_assert(std::is_literal_type_v<CheckedUnsafePtr<NoCheckTestType>>); +#endif + +static_assert( + std::is_trivially_copy_constructible_v<CheckedUnsafePtr<NoCheckTestType>>); +static_assert( + std::is_trivially_copy_assignable_v<CheckedUnsafePtr<NoCheckTestType>>); +static_assert( + std::is_trivially_move_constructible_v<CheckedUnsafePtr<NoCheckTestType>>); +static_assert( + std::is_trivially_move_assignable_v<CheckedUnsafePtr<NoCheckTestType>>); + +class TestCheckingPolicy : public CheckCheckedUnsafePtrs<TestCheckingPolicy> { + protected: + explicit TestCheckingPolicy(bool& aPassedCheck) + : mPassedCheck(aPassedCheck) {} + + private: + friend class mozilla::CheckingPolicyAccess; + void NotifyCheckFailure() { mPassedCheck = false; } + + bool& mPassedCheck; +}; + +struct BasePointee : public SupportsCheckedUnsafePtr<TestCheckingPolicy> { + explicit BasePointee(bool& aCheckPassed) + : SupportsCheckedUnsafePtr<TestCheckingPolicy>(aCheckPassed) {} +}; + +struct DerivedPointee : public BasePointee { + using BasePointee::BasePointee; +}; + +class CheckedUnsafePtrTest : public ::testing::Test { + protected: + bool mPassedCheck = true; +}; + +TEST_F(CheckedUnsafePtrTest, PointeeWithNoCheckedUnsafePtrs) { + { DerivedPointee pointee{mPassedCheck}; } + ASSERT_TRUE(mPassedCheck); +} + +template <typename PointerType> +class TypedCheckedUnsafePtrTest : public CheckedUnsafePtrTest {}; + +TYPED_TEST_SUITE_P(TypedCheckedUnsafePtrTest); + +TYPED_TEST_P(TypedCheckedUnsafePtrTest, PointeeWithOneCheckedUnsafePtr) { + { + DerivedPointee pointee{this->mPassedCheck}; + CheckedUnsafePtr<TypeParam> ptr = &pointee; + } + ASSERT_TRUE(this->mPassedCheck); +} + +TYPED_TEST_P(TypedCheckedUnsafePtrTest, CheckedUnsafePtrCopyConstructed) { + { + DerivedPointee pointee{this->mPassedCheck}; + CheckedUnsafePtr<TypeParam> ptr1 = &pointee; + CheckedUnsafePtr<TypeParam> ptr2 = ptr1; + } + ASSERT_TRUE(this->mPassedCheck); +} + +TYPED_TEST_P(TypedCheckedUnsafePtrTest, CheckedUnsafePtrCopyAssigned) { + { + DerivedPointee pointee{this->mPassedCheck}; + CheckedUnsafePtr<TypeParam> ptr1 = &pointee; + CheckedUnsafePtr<TypeParam> ptr2; + ptr2 = ptr1; + } + ASSERT_TRUE(this->mPassedCheck); +} + +TYPED_TEST_P(TypedCheckedUnsafePtrTest, + PointeeWithOneDanglingCheckedUnsafePtr) { + [this]() -> CheckedUnsafePtr<TypeParam> { + DerivedPointee pointee{this->mPassedCheck}; + return &pointee; + }(); + ASSERT_FALSE(this->mPassedCheck); +} + +TYPED_TEST_P(TypedCheckedUnsafePtrTest, + PointeeWithOneCopiedDanglingCheckedUnsafePtr) { + const auto dangling1 = [this]() -> CheckedUnsafePtr<DerivedPointee> { + DerivedPointee pointee{this->mPassedCheck}; + return &pointee; + }(); + EXPECT_FALSE(this->mPassedCheck); + + // With AddressSanitizer we would hopefully detect if the copy constructor + // tries to add dangling2 to the now-gone pointee's unsafe pointer array. No + // promises though, since it might be optimized away. + CheckedUnsafePtr<TypeParam> dangling2{dangling1}; + ASSERT_TRUE(dangling2); +} + +TYPED_TEST_P(TypedCheckedUnsafePtrTest, + PointeeWithOneCopyAssignedDanglingCheckedUnsafePtr) { + const auto dangling1 = [this]() -> CheckedUnsafePtr<DerivedPointee> { + DerivedPointee pointee{this->mPassedCheck}; + return &pointee; + }(); + EXPECT_FALSE(this->mPassedCheck); + + // With AddressSanitizer we would hopefully detect if the assignment tries to + // add dangling2 to the now-gone pointee's unsafe pointer array. No promises + // though, since it might be optimized away. + CheckedUnsafePtr<TypeParam> dangling2; + dangling2 = dangling1; + ASSERT_TRUE(dangling2); +} + +REGISTER_TYPED_TEST_SUITE_P(TypedCheckedUnsafePtrTest, + PointeeWithOneCheckedUnsafePtr, + CheckedUnsafePtrCopyConstructed, + CheckedUnsafePtrCopyAssigned, + PointeeWithOneDanglingCheckedUnsafePtr, + PointeeWithOneCopiedDanglingCheckedUnsafePtr, + PointeeWithOneCopyAssignedDanglingCheckedUnsafePtr); + +using BothTypes = ::testing::Types<BasePointee, DerivedPointee>; +INSTANTIATE_TYPED_TEST_SUITE_P(InstantiationOf, TypedCheckedUnsafePtrTest, + BothTypes); |