TestCheckedUnsafePtr.cpp (5257B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include <type_traits> 6 7 #include "gtest/gtest.h" 8 #include "mozilla/dom/quota/CheckedUnsafePtr.h" 9 10 using namespace mozilla; 11 12 class NoCheckTestType 13 : public SupportsCheckedUnsafePtr<DoNotCheckCheckedUnsafePtrs> {}; 14 15 #if __cplusplus < 202002L 16 static_assert(std::is_literal_type_v<CheckedUnsafePtr<NoCheckTestType>>); 17 #endif 18 19 static_assert( 20 std::is_trivially_copy_constructible_v<CheckedUnsafePtr<NoCheckTestType>>); 21 static_assert( 22 std::is_trivially_copy_assignable_v<CheckedUnsafePtr<NoCheckTestType>>); 23 static_assert( 24 std::is_trivially_move_constructible_v<CheckedUnsafePtr<NoCheckTestType>>); 25 static_assert( 26 std::is_trivially_move_assignable_v<CheckedUnsafePtr<NoCheckTestType>>); 27 28 class TestCheckingPolicy : public CheckCheckedUnsafePtrs<TestCheckingPolicy> { 29 protected: 30 explicit TestCheckingPolicy(bool& aPassedCheck) 31 : mPassedCheck(aPassedCheck) {} 32 33 private: 34 friend class mozilla::CheckingPolicyAccess; 35 void NotifyCheckFailure() { mPassedCheck = false; } 36 37 bool& mPassedCheck; 38 }; 39 40 struct BasePointee : public SupportsCheckedUnsafePtr<TestCheckingPolicy> { 41 explicit BasePointee(bool& aCheckPassed) 42 : SupportsCheckedUnsafePtr<TestCheckingPolicy>(aCheckPassed) {} 43 }; 44 45 struct DerivedPointee : public BasePointee { 46 using BasePointee::BasePointee; 47 }; 48 49 class CheckedUnsafePtrTest : public ::testing::Test { 50 protected: 51 bool mPassedCheck = true; 52 }; 53 54 TEST_F(CheckedUnsafePtrTest, PointeeWithNoCheckedUnsafePtrs) { 55 { 56 DerivedPointee pointee{mPassedCheck}; 57 } 58 ASSERT_TRUE(mPassedCheck); 59 } 60 61 template <typename PointerType> 62 class TypedCheckedUnsafePtrTest : public CheckedUnsafePtrTest {}; 63 64 TYPED_TEST_SUITE_P(TypedCheckedUnsafePtrTest); 65 66 TYPED_TEST_P(TypedCheckedUnsafePtrTest, PointeeWithOneCheckedUnsafePtr) { 67 { 68 DerivedPointee pointee{this->mPassedCheck}; 69 CheckedUnsafePtr<TypeParam> ptr = &pointee; 70 } 71 ASSERT_TRUE(this->mPassedCheck); 72 } 73 74 TYPED_TEST_P(TypedCheckedUnsafePtrTest, CheckedUnsafePtrCopyConstructed) { 75 { 76 DerivedPointee pointee{this->mPassedCheck}; 77 CheckedUnsafePtr<TypeParam> ptr1 = &pointee; 78 CheckedUnsafePtr<TypeParam> ptr2 = ptr1; 79 } 80 ASSERT_TRUE(this->mPassedCheck); 81 } 82 83 TYPED_TEST_P(TypedCheckedUnsafePtrTest, CheckedUnsafePtrCopyAssigned) { 84 { 85 DerivedPointee pointee{this->mPassedCheck}; 86 CheckedUnsafePtr<TypeParam> ptr1 = &pointee; 87 CheckedUnsafePtr<TypeParam> ptr2; 88 ptr2 = ptr1; 89 } 90 ASSERT_TRUE(this->mPassedCheck); 91 } 92 93 TYPED_TEST_P(TypedCheckedUnsafePtrTest, CheckedUnsafePtrNullptrAssigned) { 94 { 95 CheckedUnsafePtr<TypeParam> ptr = nullptr; 96 } 97 ASSERT_TRUE(this->mPassedCheck); 98 } 99 100 TYPED_TEST_P(TypedCheckedUnsafePtrTest, 101 CheckedUnsafePtrNullCheckedUnsafePtrAssigned) { 102 { 103 CheckedUnsafePtr<TypeParam> ptr1(nullptr); 104 CheckedUnsafePtr<TypeParam> ptr2; 105 ptr2 = ptr1; 106 } 107 ASSERT_TRUE(this->mPassedCheck); 108 } 109 110 TYPED_TEST_P(TypedCheckedUnsafePtrTest, 111 PointeeWithOneDanglingCheckedUnsafePtr) { 112 [this]() -> CheckedUnsafePtr<TypeParam> { 113 DerivedPointee pointee{this->mPassedCheck}; 114 return &pointee; 115 }(); 116 ASSERT_FALSE(this->mPassedCheck); 117 } 118 119 TYPED_TEST_P(TypedCheckedUnsafePtrTest, 120 PointeeWithOneCopiedDanglingCheckedUnsafePtr) { 121 const auto dangling1 = [this]() -> CheckedUnsafePtr<DerivedPointee> { 122 DerivedPointee pointee{this->mPassedCheck}; 123 return &pointee; 124 }(); 125 EXPECT_FALSE(this->mPassedCheck); 126 127 // With AddressSanitizer we would hopefully detect if the copy constructor 128 // tries to add dangling2 to the now-gone pointee's unsafe pointer array. No 129 // promises though, since it might be optimized away. 130 CheckedUnsafePtr<TypeParam> dangling2{dangling1}; 131 ASSERT_TRUE(dangling2); 132 } 133 134 TYPED_TEST_P(TypedCheckedUnsafePtrTest, 135 PointeeWithOneCopyAssignedDanglingCheckedUnsafePtr) { 136 const auto dangling1 = [this]() -> CheckedUnsafePtr<DerivedPointee> { 137 DerivedPointee pointee{this->mPassedCheck}; 138 return &pointee; 139 }(); 140 EXPECT_FALSE(this->mPassedCheck); 141 142 // With AddressSanitizer we would hopefully detect if the assignment tries to 143 // add dangling2 to the now-gone pointee's unsafe pointer array. No promises 144 // though, since it might be optimized away. 145 CheckedUnsafePtr<TypeParam> dangling2; 146 dangling2 = dangling1; 147 ASSERT_TRUE(dangling2); 148 } 149 150 REGISTER_TYPED_TEST_SUITE_P(TypedCheckedUnsafePtrTest, 151 PointeeWithOneCheckedUnsafePtr, 152 CheckedUnsafePtrCopyConstructed, 153 CheckedUnsafePtrCopyAssigned, 154 CheckedUnsafePtrNullptrAssigned, 155 CheckedUnsafePtrNullCheckedUnsafePtrAssigned, 156 PointeeWithOneDanglingCheckedUnsafePtr, 157 PointeeWithOneCopiedDanglingCheckedUnsafePtr, 158 PointeeWithOneCopyAssignedDanglingCheckedUnsafePtr); 159 160 using BothTypes = ::testing::Types<BasePointee, DerivedPointee>; 161 INSTANTIATE_TYPED_TEST_SUITE_P(InstantiationOf, TypedCheckedUnsafePtrTest, 162 BothTypes);