blob: f3b93f80f6ff59e052148b151517377cfc645373 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2014 The Chromium Authors
[email protected]1f7d92af2014-05-29 20:10:362// 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 Cheng3d173ee2023-01-06 01:31:157#include "base/features.h"
sdefresneae5e2d22017-02-13 11:49:268#include "base/memory/ptr_util.h"
Keishi Hattori0e45c022021-11-27 09:25:529#include "base/memory/raw_ptr.h"
Daniel Cheng3d173ee2023-01-06 01:31:1510#include "base/test/scoped_feature_list.h"
[email protected]1f7d92af2014-05-29 20:10:3611#include "testing/gtest/include/gtest/gtest.h"
12
13namespace base {
14namespace {
15
Matt Muellere74f61772019-08-13 20:00:5916struct TestSupportsUserData : public SupportsUserData {
17 // Make ClearAllUserData public so tests can access it.
18 using SupportsUserData::ClearAllUserData;
19};
[email protected]1f7d92af2014-05-29 20:10:3620
21struct 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
dcheng56488182014-10-21 10:54:5127 ~UsesItself() override {
Ivan Kotenkova16212a52017-11-08 12:37:3328 EXPECT_EQ(nullptr, supports_user_data_->GetUserData(key_));
[email protected]1f7d92af2014-05-29 20:10:3629 }
30
Keishi Hattori0e45c022021-11-27 09:25:5231 raw_ptr<SupportsUserData> supports_user_data_;
32 raw_ptr<const void> key_;
[email protected]1f7d92af2014-05-29 20:10:3633};
34
Daniel Cheng3d173ee2023-01-06 01:31:1535class 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
50TEST_P(SupportsUserDataTest, ClearWorksRecursively) {
Tom Sepez9c198872023-01-05 22:10:3651 char key = 0; // Must outlive `supports_user_data`.
[email protected]1f7d92af2014-05-29 20:10:3652 TestSupportsUserData supports_user_data;
sdefresneae5e2d22017-02-13 11:49:2653 supports_user_data.SetUserData(
Jeremy Roman9532f252017-08-16 23:27:2454 &key, std::make_unique<UsesItself>(&supports_user_data, &key));
[email protected]1f7d92af2014-05-29 20:10:3655 // Destruction of supports_user_data runs the actual test.
56}
57
Matt Mueller39fc01f92019-08-10 02:24:0858struct TestData : public SupportsUserData::Data {};
59
Daniel Cheng3d173ee2023-01-06 01:31:1560TEST_P(SupportsUserDataTest, Movable) {
Matt Mueller39fc01f92019-08-10 02:24:0861 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 Cheng3d173ee2023-01-06 01:31:1576TEST_P(SupportsUserDataTest, ClearAllUserData) {
Matt Muellere74f61772019-08-13 20:00:5977 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 Liu055a3542023-04-02 17:21:1992TEST_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 Chengae276202023-04-12 04:03:34113class 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.
123TEST_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 Cheng3d173ee2023-01-06 01:31:15130INSTANTIATE_TEST_SUITE_P(All,
131 SupportsUserDataTest,
132 testing::Values(false, true));
133
[email protected]1f7d92af2014-05-29 20:10:36134} // namespace
135} // namespace base