1 // Copyright 2017 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/threading/thread_restrictions.h"
6
7 #include <utility>
8
9 #include "base/compiler_specific.h"
10 #include "base/dcheck_is_on.h"
11 #include "base/debug/stack_trace.h"
12 #include "base/functional/bind.h"
13 #include "base/functional/callback.h"
14 #include "base/test/gtest_util.h"
15 #include "build/build_config.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace base {
19
20 namespace {
21
22 class ThreadRestrictionsTest : public testing::Test {
23 public:
24 ThreadRestrictionsTest() = default;
25
26 ThreadRestrictionsTest(const ThreadRestrictionsTest&) = delete;
27 ThreadRestrictionsTest& operator=(const ThreadRestrictionsTest&) = delete;
28
~ThreadRestrictionsTest()29 ~ThreadRestrictionsTest() override {
30 internal::ResetThreadRestrictionsForTesting();
31 }
32 };
33
34 } // namespace
35
TEST_F(ThreadRestrictionsTest,BlockingAllowedByDefault)36 TEST_F(ThreadRestrictionsTest, BlockingAllowedByDefault) {
37 internal::AssertBlockingAllowed();
38 }
39
TEST_F(ThreadRestrictionsTest,ScopedDisallowBlocking)40 TEST_F(ThreadRestrictionsTest, ScopedDisallowBlocking) {
41 {
42 ScopedDisallowBlocking scoped_disallow_blocking;
43 EXPECT_DCHECK_DEATH({ internal::AssertBlockingAllowed(); });
44 }
45 internal::AssertBlockingAllowed();
46 }
47
TEST_F(ThreadRestrictionsTest,ScopedAllowBlocking)48 TEST_F(ThreadRestrictionsTest, ScopedAllowBlocking) {
49 ScopedDisallowBlocking scoped_disallow_blocking;
50 {
51 ScopedAllowBlocking scoped_allow_blocking;
52 internal::AssertBlockingAllowed();
53 }
54 EXPECT_DCHECK_DEATH({ internal::AssertBlockingAllowed(); });
55 }
56
TEST_F(ThreadRestrictionsTest,ScopedAllowBlockingForTesting)57 TEST_F(ThreadRestrictionsTest, ScopedAllowBlockingForTesting) {
58 ScopedDisallowBlocking scoped_disallow_blocking;
59 {
60 ScopedAllowBlockingForTesting scoped_allow_blocking_for_testing;
61 internal::AssertBlockingAllowed();
62 }
63 EXPECT_DCHECK_DEATH({ internal::AssertBlockingAllowed(); });
64 }
65
TEST_F(ThreadRestrictionsTest,BaseSyncPrimitivesAllowedByDefault)66 TEST_F(ThreadRestrictionsTest, BaseSyncPrimitivesAllowedByDefault) {
67 internal::AssertBaseSyncPrimitivesAllowed();
68 }
69
TEST_F(ThreadRestrictionsTest,DisallowBaseSyncPrimitives)70 TEST_F(ThreadRestrictionsTest, DisallowBaseSyncPrimitives) {
71 DisallowBaseSyncPrimitives();
72 EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); });
73 }
74
TEST_F(ThreadRestrictionsTest,ScopedAllowBaseSyncPrimitives)75 TEST_F(ThreadRestrictionsTest, ScopedAllowBaseSyncPrimitives) {
76 DisallowBaseSyncPrimitives();
77 ScopedAllowBaseSyncPrimitives scoped_allow_base_sync_primitives;
78 internal::AssertBaseSyncPrimitivesAllowed();
79 }
80
TEST_F(ThreadRestrictionsTest,ScopedAllowBaseSyncPrimitivesResetsState)81 TEST_F(ThreadRestrictionsTest, ScopedAllowBaseSyncPrimitivesResetsState) {
82 DisallowBaseSyncPrimitives();
83 { ScopedAllowBaseSyncPrimitives scoped_allow_base_sync_primitives; }
84 EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); });
85 }
86
TEST_F(ThreadRestrictionsTest,ScopedAllowBaseSyncPrimitivesWithBlockingDisallowed)87 TEST_F(ThreadRestrictionsTest,
88 ScopedAllowBaseSyncPrimitivesWithBlockingDisallowed) {
89 ScopedDisallowBlocking scoped_disallow_blocking;
90 DisallowBaseSyncPrimitives();
91
92 // This should DCHECK because blocking is not allowed in this scope
93 // and OutsideBlockingScope is not passed to the constructor.
94 EXPECT_DCHECK_DEATH(
95 { ScopedAllowBaseSyncPrimitives scoped_allow_base_sync_primitives; });
96 }
97
TEST_F(ThreadRestrictionsTest,ScopedAllowBaseSyncPrimitivesOutsideBlockingScope)98 TEST_F(ThreadRestrictionsTest,
99 ScopedAllowBaseSyncPrimitivesOutsideBlockingScope) {
100 ScopedDisallowBlocking scoped_disallow_blocking;
101 DisallowBaseSyncPrimitives();
102 ScopedAllowBaseSyncPrimitivesOutsideBlockingScope
103 scoped_allow_base_sync_primitives;
104 internal::AssertBaseSyncPrimitivesAllowed();
105 }
106
TEST_F(ThreadRestrictionsTest,ScopedAllowBaseSyncPrimitivesOutsideBlockingScopeResetsState)107 TEST_F(ThreadRestrictionsTest,
108 ScopedAllowBaseSyncPrimitivesOutsideBlockingScopeResetsState) {
109 DisallowBaseSyncPrimitives();
110 {
111 ScopedAllowBaseSyncPrimitivesOutsideBlockingScope
112 scoped_allow_base_sync_primitives;
113 }
114 EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); });
115 }
116
TEST_F(ThreadRestrictionsTest,ScopedAllowBaseSyncPrimitivesForTesting)117 TEST_F(ThreadRestrictionsTest, ScopedAllowBaseSyncPrimitivesForTesting) {
118 DisallowBaseSyncPrimitives();
119 ScopedAllowBaseSyncPrimitivesForTesting
120 scoped_allow_base_sync_primitives_for_testing;
121 internal::AssertBaseSyncPrimitivesAllowed();
122 }
123
TEST_F(ThreadRestrictionsTest,ScopedAllowBaseSyncPrimitivesForTestingResetsState)124 TEST_F(ThreadRestrictionsTest,
125 ScopedAllowBaseSyncPrimitivesForTestingResetsState) {
126 DisallowBaseSyncPrimitives();
127 {
128 ScopedAllowBaseSyncPrimitivesForTesting
129 scoped_allow_base_sync_primitives_for_testing;
130 }
131 EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); });
132 }
133
TEST_F(ThreadRestrictionsTest,ScopedAllowBaseSyncPrimitivesForTestingWithBlockingDisallowed)134 TEST_F(ThreadRestrictionsTest,
135 ScopedAllowBaseSyncPrimitivesForTestingWithBlockingDisallowed) {
136 ScopedDisallowBlocking scoped_disallow_blocking;
137 DisallowBaseSyncPrimitives();
138 // This should not DCHECK.
139 ScopedAllowBaseSyncPrimitivesForTesting
140 scoped_allow_base_sync_primitives_for_testing;
141 }
142
TEST_F(ThreadRestrictionsTest,ScopedDisallowBaseSyncPrimitives)143 TEST_F(ThreadRestrictionsTest, ScopedDisallowBaseSyncPrimitives) {
144 {
145 ScopedDisallowBaseSyncPrimitives disallow_sync_primitives;
146 EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); });
147 }
148 internal::AssertBaseSyncPrimitivesAllowed();
149 }
150
TEST_F(ThreadRestrictionsTest,SingletonAllowedByDefault)151 TEST_F(ThreadRestrictionsTest, SingletonAllowedByDefault) {
152 internal::AssertSingletonAllowed();
153 }
154
TEST_F(ThreadRestrictionsTest,DisallowSingleton)155 TEST_F(ThreadRestrictionsTest, DisallowSingleton) {
156 DisallowSingleton();
157 EXPECT_DCHECK_DEATH({ internal::AssertSingletonAllowed(); });
158 }
159
TEST_F(ThreadRestrictionsTest,ScopedDisallowSingleton)160 TEST_F(ThreadRestrictionsTest, ScopedDisallowSingleton) {
161 {
162 ScopedDisallowSingleton disallow_sync_primitives;
163 EXPECT_DCHECK_DEATH({ internal::AssertSingletonAllowed(); });
164 }
165 internal::AssertSingletonAllowed();
166 }
167
TEST_F(ThreadRestrictionsTest,LongCPUWorkAllowedByDefault)168 TEST_F(ThreadRestrictionsTest, LongCPUWorkAllowedByDefault) {
169 AssertLongCPUWorkAllowed();
170 }
171
TEST_F(ThreadRestrictionsTest,DisallowUnresponsiveTasks)172 TEST_F(ThreadRestrictionsTest, DisallowUnresponsiveTasks) {
173 DisallowUnresponsiveTasks();
174 EXPECT_DCHECK_DEATH(internal::AssertBlockingAllowed());
175 EXPECT_DCHECK_DEATH(internal::AssertBaseSyncPrimitivesAllowed());
176 EXPECT_DCHECK_DEATH(AssertLongCPUWorkAllowed());
177 }
178
179 // thread_restriction_checks_and_has_death_tests
180 #if !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_ANDROID) && DCHECK_IS_ON() && \
181 defined(GTEST_HAS_DEATH_TEST)
182
TEST_F(ThreadRestrictionsTest,BlockingCheckEmitsStack)183 TEST_F(ThreadRestrictionsTest, BlockingCheckEmitsStack) {
184 debug::OverrideStackTraceOutputForTesting enable_stacks_in_death_tests(
185 debug::OverrideStackTraceOutputForTesting::Mode::kForceOutput);
186 ScopedDisallowBlocking scoped_disallow_blocking;
187 // The above ScopedDisallowBlocking should be on the blame list for who set
188 // the ban.
189 EXPECT_DEATH({ internal::AssertBlockingAllowed(); },
190 EXPENSIVE_DCHECKS_ARE_ON() &&
191 debug::StackTrace::WillSymbolizeToStreamForTesting()
192 ? "ScopedDisallowBlocking"
193 : "");
194 // And the stack should mention this test body as source.
195 EXPECT_DEATH({ internal::AssertBlockingAllowed(); },
196 EXPENSIVE_DCHECKS_ARE_ON() &&
197 debug::StackTrace::WillSymbolizeToStreamForTesting()
198 ? "BlockingCheckEmitsStack"
199 : "");
200 }
201
202 class TestCustomDisallow {
203 public:
TestCustomDisallow()204 NOINLINE TestCustomDisallow() { DisallowBlocking(); }
~TestCustomDisallow()205 NOINLINE ~TestCustomDisallow() { PermanentThreadAllowance::AllowBlocking(); }
206 };
207
TEST_F(ThreadRestrictionsTest,NestedAllowRestoresPreviousStack)208 TEST_F(ThreadRestrictionsTest, NestedAllowRestoresPreviousStack) {
209 debug::OverrideStackTraceOutputForTesting enable_stacks_in_death_tests(
210 debug::OverrideStackTraceOutputForTesting::Mode::kForceOutput);
211 TestCustomDisallow custom_disallow;
212 {
213 ScopedAllowBlocking scoped_allow;
214 internal::AssertBlockingAllowed();
215 }
216 // TestCustomDisallow should be back on the blame list (as opposed to
217 // ~ScopedAllowBlocking which is the last one to have changed the state but is
218 // no longer relevant).
219 EXPECT_DEATH({ internal::AssertBlockingAllowed(); },
220 EXPENSIVE_DCHECKS_ARE_ON() &&
221 debug::StackTrace::WillSymbolizeToStreamForTesting()
222 ? "TestCustomDisallow"
223 : "");
224 // And the stack should mention this test body as source.
225 EXPECT_DEATH({ internal::AssertBlockingAllowed(); },
226 EXPENSIVE_DCHECKS_ARE_ON() &&
227 debug::StackTrace::WillSymbolizeToStreamForTesting()
228 ? "NestedAllowRestoresPreviousStack"
229 : "");
230 }
231
232 #endif // thread_restriction_checks_and_has_death_tests
233
234 } // namespace base
235