xref: /aosp_15_r20/external/cronet/base/supports_user_data_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2014 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 #include "base/supports_user_data.h"
6 
7 #include "base/features.h"
8 #include "base/memory/ptr_util.h"
9 #include "base/memory/raw_ptr.h"
10 #include "base/memory/raw_ref.h"
11 #include "base/test/gtest_util.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 namespace base {
15 namespace {
16 
17 struct TestSupportsUserData : public SupportsUserData {
18   // Make ClearAllUserData public so tests can access it.
19   using SupportsUserData::ClearAllUserData;
20 };
21 
22 struct UsesItself : public SupportsUserData::Data {
UsesItselfbase::__anon16e841650111::UsesItself23   UsesItself(SupportsUserData* supports_user_data, const void* key)
24       : supports_user_data_(supports_user_data),
25         key_(key) {
26   }
27 
~UsesItselfbase::__anon16e841650111::UsesItself28   ~UsesItself() override {
29     EXPECT_EQ(nullptr, supports_user_data_->GetUserData(key_));
30   }
31 
32   raw_ptr<SupportsUserData> supports_user_data_;
33   raw_ptr<const void> key_;
34 };
35 
36 using SupportsUserDataTest = ::testing::Test;
37 
TEST_F(SupportsUserDataTest,ClearWorksRecursively)38 TEST_F(SupportsUserDataTest, ClearWorksRecursively) {
39   char key = 0;  // Must outlive `supports_user_data`.
40   TestSupportsUserData supports_user_data;
41   supports_user_data.SetUserData(
42       &key, std::make_unique<UsesItself>(&supports_user_data, &key));
43   // Destruction of supports_user_data runs the actual test.
44 }
45 
46 struct TestData : public SupportsUserData::Data {};
47 
TEST_F(SupportsUserDataTest,Movable)48 TEST_F(SupportsUserDataTest, Movable) {
49   TestSupportsUserData supports_user_data_1;
50   char key1 = 0;
51   supports_user_data_1.SetUserData(&key1, std::make_unique<TestData>());
52   void* data_1_ptr = supports_user_data_1.GetUserData(&key1);
53 
54   TestSupportsUserData supports_user_data_2;
55   char key2 = 0;
56   supports_user_data_2.SetUserData(&key2, std::make_unique<TestData>());
57 
58   supports_user_data_2 = std::move(supports_user_data_1);
59 
60   EXPECT_EQ(data_1_ptr, supports_user_data_2.GetUserData(&key1));
61   EXPECT_EQ(nullptr, supports_user_data_2.GetUserData(&key2));
62 }
63 
TEST_F(SupportsUserDataTest,ClearAllUserData)64 TEST_F(SupportsUserDataTest, ClearAllUserData) {
65   TestSupportsUserData supports_user_data;
66   char key1 = 0;
67   supports_user_data.SetUserData(&key1, std::make_unique<TestData>());
68   char key2 = 0;
69   supports_user_data.SetUserData(&key2, std::make_unique<TestData>());
70 
71   EXPECT_TRUE(supports_user_data.GetUserData(&key1));
72   EXPECT_TRUE(supports_user_data.GetUserData(&key2));
73 
74   supports_user_data.ClearAllUserData();
75 
76   EXPECT_FALSE(supports_user_data.GetUserData(&key1));
77   EXPECT_FALSE(supports_user_data.GetUserData(&key2));
78 }
79 
TEST_F(SupportsUserDataTest,TakeUserData)80 TEST_F(SupportsUserDataTest, TakeUserData) {
81   TestSupportsUserData supports_user_data;
82   char key1 = 0;
83   supports_user_data.SetUserData(&key1, std::make_unique<TestData>());
84 
85   TestSupportsUserData::Data* data1_ptr = supports_user_data.GetUserData(&key1);
86   EXPECT_NE(data1_ptr, nullptr);
87 
88   char wrong_key = 0;
89   EXPECT_FALSE(supports_user_data.TakeUserData(&wrong_key));
90 
91   EXPECT_EQ(supports_user_data.GetUserData(&key1), data1_ptr);
92 
93   std::unique_ptr<TestSupportsUserData::Data> data1 =
94       supports_user_data.TakeUserData(&key1);
95   EXPECT_EQ(data1.get(), data1_ptr);
96 
97   EXPECT_FALSE(supports_user_data.GetUserData(&key1));
98   EXPECT_FALSE(supports_user_data.TakeUserData(&key1));
99 }
100 
101 class DataOwnsSupportsUserData : public SupportsUserData::Data {
102  public:
supports_user_data()103   TestSupportsUserData* supports_user_data() { return &supports_user_data_; }
104 
105  private:
106   TestSupportsUserData supports_user_data_;
107 };
108 
109 // Tests that removing a `SupportsUserData::Data` that owns a `SupportsUserData`
110 // does not crash.
TEST_F(SupportsUserDataTest,ReentrantRemoveUserData)111 TEST_F(SupportsUserDataTest, ReentrantRemoveUserData) {
112   DataOwnsSupportsUserData* data = new DataOwnsSupportsUserData;
113   char key = 0;
114   data->supports_user_data()->SetUserData(&key, WrapUnique(data));
115   data->supports_user_data()->RemoveUserData(&key);
116 }
117 
TEST_F(SupportsUserDataTest,ReentrantSetUserDataDuringRemoval)118 TEST_F(SupportsUserDataTest, ReentrantSetUserDataDuringRemoval) {
119   static const char kKey = 0;
120 
121   class ProblematicSet : public SupportsUserData::Data {
122    public:
123     explicit ProblematicSet(const void* const key,
124                             TestSupportsUserData& supports_user_data)
125         : key_(key), supports_user_data_(supports_user_data) {}
126 
127     ~ProblematicSet() override {
128       supports_user_data_->SetUserData(
129           key_, std::make_unique<ProblematicSet>(key_, *supports_user_data_));
130     }
131 
132    private:
133     const raw_ptr<const void> key_;
134     raw_ref<TestSupportsUserData> supports_user_data_;
135   };
136   {
137     std::optional<TestSupportsUserData> supports_user_data;
138     supports_user_data.emplace();
139     // This awkward construction is required since death tests are typically
140     // implemented using `fork()`, so calling `SetUserData()` outside the
141     // `EXPECT_CHECK_DEATH()` macro will also crash the process that's trying to
142     // observe the crash.
143     EXPECT_CHECK_DEATH([&] {
144       supports_user_data->SetUserData(
145           &kKey, std::make_unique<ProblematicSet>(&kKey, *supports_user_data));
146       // Triggers the reentrant attempt to call `SetUserData()` during
147       // destruction.
148       supports_user_data.reset();
149     }());
150   }
151 }
152 
153 }  // namespace
154 }  // namespace base
155