summaryrefslogtreecommitdiffstats
path: root/dom/quota/test/gtest/TestCheckedUnsafePtr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/quota/test/gtest/TestCheckedUnsafePtr.cpp')
-rw-r--r--dom/quota/test/gtest/TestCheckedUnsafePtr.cpp145
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);