Avi Drissman | e4622aa | 2022-09-08 20:36:06 | [diff] [blame] | 1 | // Copyright 2014 The Chromium Authors |
[email protected] | 1f7d92af | 2014-05-29 20:10:36 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "base/supports_user_data.h" |
| 6 | |
Daniel Cheng | 3d173ee | 2023-01-06 01:31:15 | [diff] [blame] | 7 | #include "base/features.h" |
sdefresne | ae5e2d2 | 2017-02-13 11:49:26 | [diff] [blame] | 8 | #include "base/memory/ptr_util.h" |
Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 9 | #include "base/memory/raw_ptr.h" |
Daniel Cheng | 3d173ee | 2023-01-06 01:31:15 | [diff] [blame] | 10 | #include "base/test/scoped_feature_list.h" |
[email protected] | 1f7d92af | 2014-05-29 20:10:36 | [diff] [blame] | 11 | #include "testing/gtest/include/gtest/gtest.h" |
| 12 | |
| 13 | namespace base { |
| 14 | namespace { |
| 15 | |
Matt Mueller | e74f6177 | 2019-08-13 20:00:59 | [diff] [blame] | 16 | struct TestSupportsUserData : public SupportsUserData { |
| 17 | // Make ClearAllUserData public so tests can access it. |
| 18 | using SupportsUserData::ClearAllUserData; |
| 19 | }; |
[email protected] | 1f7d92af | 2014-05-29 20:10:36 | [diff] [blame] | 20 | |
| 21 | struct UsesItself : public SupportsUserData::Data { |
| 22 | UsesItself(SupportsUserData* supports_user_data, const void* key) |
| 23 | : supports_user_data_(supports_user_data), |
| 24 | key_(key) { |
| 25 | } |
| 26 | |
dcheng | 5648818 | 2014-10-21 10:54:51 | [diff] [blame] | 27 | ~UsesItself() override { |
Ivan Kotenkov | a16212a5 | 2017-11-08 12:37:33 | [diff] [blame] | 28 | EXPECT_EQ(nullptr, supports_user_data_->GetUserData(key_)); |
[email protected] | 1f7d92af | 2014-05-29 20:10:36 | [diff] [blame] | 29 | } |
| 30 | |
Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 31 | raw_ptr<SupportsUserData> supports_user_data_; |
| 32 | raw_ptr<const void> key_; |
[email protected] | 1f7d92af | 2014-05-29 20:10:36 | [diff] [blame] | 33 | }; |
| 34 | |
Daniel Cheng | 3d173ee | 2023-01-06 01:31:15 | [diff] [blame] | 35 | class SupportsUserDataTest : public ::testing::TestWithParam<bool> { |
| 36 | public: |
| 37 | SupportsUserDataTest() { |
| 38 | if (GetParam()) { |
| 39 | scoped_features_.InitWithFeatures( |
| 40 | {features::kSupportsUserDataFlatHashMap}, {}); |
| 41 | } else { |
| 42 | scoped_features_.InitWithFeatures( |
| 43 | {}, {features::kSupportsUserDataFlatHashMap}); |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | base::test::ScopedFeatureList scoped_features_; |
| 48 | }; |
| 49 | |
| 50 | TEST_P(SupportsUserDataTest, ClearWorksRecursively) { |
Tom Sepez | 9c19887 | 2023-01-05 22:10:36 | [diff] [blame] | 51 | char key = 0; // Must outlive `supports_user_data`. |
[email protected] | 1f7d92af | 2014-05-29 20:10:36 | [diff] [blame] | 52 | TestSupportsUserData supports_user_data; |
sdefresne | ae5e2d2 | 2017-02-13 11:49:26 | [diff] [blame] | 53 | supports_user_data.SetUserData( |
Jeremy Roman | 9532f25 | 2017-08-16 23:27:24 | [diff] [blame] | 54 | &key, std::make_unique<UsesItself>(&supports_user_data, &key)); |
[email protected] | 1f7d92af | 2014-05-29 20:10:36 | [diff] [blame] | 55 | // Destruction of supports_user_data runs the actual test. |
| 56 | } |
| 57 | |
Matt Mueller | 39fc01f9 | 2019-08-10 02:24:08 | [diff] [blame] | 58 | struct TestData : public SupportsUserData::Data {}; |
| 59 | |
Daniel Cheng | 3d173ee | 2023-01-06 01:31:15 | [diff] [blame] | 60 | TEST_P(SupportsUserDataTest, Movable) { |
Matt Mueller | 39fc01f9 | 2019-08-10 02:24:08 | [diff] [blame] | 61 | TestSupportsUserData supports_user_data_1; |
| 62 | char key1 = 0; |
| 63 | supports_user_data_1.SetUserData(&key1, std::make_unique<TestData>()); |
| 64 | void* data_1_ptr = supports_user_data_1.GetUserData(&key1); |
| 65 | |
| 66 | TestSupportsUserData supports_user_data_2; |
| 67 | char key2 = 0; |
| 68 | supports_user_data_2.SetUserData(&key2, std::make_unique<TestData>()); |
| 69 | |
| 70 | supports_user_data_2 = std::move(supports_user_data_1); |
| 71 | |
| 72 | EXPECT_EQ(data_1_ptr, supports_user_data_2.GetUserData(&key1)); |
| 73 | EXPECT_EQ(nullptr, supports_user_data_2.GetUserData(&key2)); |
| 74 | } |
| 75 | |
Daniel Cheng | 3d173ee | 2023-01-06 01:31:15 | [diff] [blame] | 76 | TEST_P(SupportsUserDataTest, ClearAllUserData) { |
Matt Mueller | e74f6177 | 2019-08-13 20:00:59 | [diff] [blame] | 77 | TestSupportsUserData supports_user_data; |
| 78 | char key1 = 0; |
| 79 | supports_user_data.SetUserData(&key1, std::make_unique<TestData>()); |
| 80 | char key2 = 0; |
| 81 | supports_user_data.SetUserData(&key2, std::make_unique<TestData>()); |
| 82 | |
| 83 | EXPECT_TRUE(supports_user_data.GetUserData(&key1)); |
| 84 | EXPECT_TRUE(supports_user_data.GetUserData(&key2)); |
| 85 | |
| 86 | supports_user_data.ClearAllUserData(); |
| 87 | |
| 88 | EXPECT_FALSE(supports_user_data.GetUserData(&key1)); |
| 89 | EXPECT_FALSE(supports_user_data.GetUserData(&key2)); |
| 90 | } |
| 91 | |
William Liu | 055a354 | 2023-04-02 17:21:19 | [diff] [blame] | 92 | TEST_P(SupportsUserDataTest, TakeUserData) { |
| 93 | TestSupportsUserData supports_user_data; |
| 94 | char key1 = 0; |
| 95 | supports_user_data.SetUserData(&key1, std::make_unique<TestData>()); |
| 96 | |
| 97 | TestSupportsUserData::Data* data1_ptr = supports_user_data.GetUserData(&key1); |
| 98 | EXPECT_NE(data1_ptr, nullptr); |
| 99 | |
| 100 | char wrong_key = 0; |
| 101 | EXPECT_FALSE(supports_user_data.TakeUserData(&wrong_key)); |
| 102 | |
| 103 | EXPECT_EQ(supports_user_data.GetUserData(&key1), data1_ptr); |
| 104 | |
| 105 | std::unique_ptr<TestSupportsUserData::Data> data1 = |
| 106 | supports_user_data.TakeUserData(&key1); |
| 107 | EXPECT_EQ(data1.get(), data1_ptr); |
| 108 | |
| 109 | EXPECT_FALSE(supports_user_data.GetUserData(&key1)); |
| 110 | EXPECT_FALSE(supports_user_data.TakeUserData(&key1)); |
| 111 | } |
| 112 | |
Daniel Cheng | ae27620 | 2023-04-12 04:03:34 | [diff] [blame] | 113 | class DataOwnsSupportsUserData : public SupportsUserData::Data { |
| 114 | public: |
| 115 | TestSupportsUserData* supports_user_data() { return &supports_user_data_; } |
| 116 | |
| 117 | private: |
| 118 | TestSupportsUserData supports_user_data_; |
| 119 | }; |
| 120 | |
| 121 | // Tests that removing a `SupportsUserData::Data` that owns a `SupportsUserData` |
| 122 | // does not crash. |
| 123 | TEST_P(SupportsUserDataTest, ReentrantRemoveUserData) { |
| 124 | DataOwnsSupportsUserData* data = new DataOwnsSupportsUserData; |
| 125 | char key = 0; |
| 126 | data->supports_user_data()->SetUserData(&key, WrapUnique(data)); |
| 127 | data->supports_user_data()->RemoveUserData(&key); |
| 128 | } |
| 129 | |
Daniel Cheng | 3d173ee | 2023-01-06 01:31:15 | [diff] [blame] | 130 | INSTANTIATE_TEST_SUITE_P(All, |
| 131 | SupportsUserDataTest, |
| 132 | testing::Values(false, true)); |
| 133 | |
[email protected] | 1f7d92af | 2014-05-29 20:10:36 | [diff] [blame] | 134 | } // namespace |
| 135 | } // namespace base |