1 // Copyright 2023 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_TEST_MEMORY_DANGLING_PTR_INSTRUMENTATION_H_ 6 #define BASE_TEST_MEMORY_DANGLING_PTR_INSTRUMENTATION_H_ 7 8 #include <cstdint> 9 #include <string_view> 10 11 #include "base/memory/raw_ptr.h" 12 #include "base/types/expected.h" 13 #include "partition_alloc/dangling_raw_ptr_checks.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 16 namespace base::test { 17 18 // It is difficult to configure malloc as partition_alloc in death test and 19 // enable BackupRefPtr. This can be used as an alternative. This replaces a 20 // crash by incrementing a set of counters. 21 // 22 // Usage: 23 // 24 // ```cpp 25 // TEST(DanglingTest, Basic) { 26 // auto instrumentation = test::DanglingPtrInstrumentation::Create(); 27 // if (!instrumentation.has_value()) { 28 // GTEST_SKIP() << instrumentation.error(); 29 // } 30 // 31 // [...] 32 // EXPECT_EQ(instrumentation->dangling_ptr_detected(), 0u); 33 // EXPECT_EQ(instrumentation->dangling_ptr_released(), 0u); 34 // } 35 // ``` 36 class DanglingPtrInstrumentation { 37 public: 38 // Returns the DanglingPtrInstrumentation or a reason why it can't be used, 39 // in which case the test should be skipped. 40 // 41 // This function should typically be called from the `testing::Test::SetUp()` 42 // override so that it can skip the test with `GTEST_SKIP()` on failure. 43 static base::expected<DanglingPtrInstrumentation, std::string_view> Create(); 44 45 ~DanglingPtrInstrumentation(); 46 DanglingPtrInstrumentation(const DanglingPtrInstrumentation&) = delete; 47 DanglingPtrInstrumentation(DanglingPtrInstrumentation&&); 48 DanglingPtrInstrumentation& operator=(const DanglingPtrInstrumentation&) = 49 delete; 50 DanglingPtrInstrumentation& operator=(DanglingPtrInstrumentation&&); 51 dangling_ptr_detected()52 size_t dangling_ptr_detected() { return dangling_ptr_detected_; } dangling_ptr_released()53 size_t dangling_ptr_released() { return dangling_ptr_released_; } 54 55 private: 56 static void IncreaseCountDetected(std::uintptr_t); 57 static void IncreaseCountReleased(std::uintptr_t); 58 static raw_ptr<DanglingPtrInstrumentation> g_observer; 59 60 DanglingPtrInstrumentation(); 61 62 void Register(); 63 void Unregister(); 64 65 size_t dangling_ptr_detected_ = 0; 66 size_t dangling_ptr_released_ = 0; 67 partition_alloc::DanglingRawPtrDetectedFn* old_detected_fn_ = nullptr; 68 partition_alloc::DanglingRawPtrReleasedFn* old_dereferenced_fn_ = nullptr; 69 }; 70 71 } // namespace base::test 72 73 #endif // BASE_TEST_MEMORY_DANGLING_PTR_INSTRUMENTATION_H_ 74