1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/compiler_specific.h"
6 #include "base/macros.h"
7 #include "base/synchronization/waitable_event.h"
8 #include "base/threading/platform_thread.h"
9 #include "testing/gtest/include/gtest/gtest.h"
17 // Trivial tests that thread runs and doesn't crash on create and join ---------
19 class TrivialThread
: public PlatformThread::Delegate
{
21 TrivialThread() : did_run_(false) {}
23 void ThreadMain() override
{ did_run_
= true; }
25 bool did_run() const { return did_run_
; }
30 DISALLOW_COPY_AND_ASSIGN(TrivialThread
);
33 TEST(PlatformThreadTest
, Trivial
) {
35 PlatformThreadHandle handle
;
37 ASSERT_FALSE(thread
.did_run());
38 ASSERT_TRUE(PlatformThread::Create(0, &thread
, &handle
));
39 PlatformThread::Join(handle
);
40 ASSERT_TRUE(thread
.did_run());
43 TEST(PlatformThreadTest
, TrivialTimesTen
) {
44 TrivialThread thread
[10];
45 PlatformThreadHandle handle
[arraysize(thread
)];
47 for (size_t n
= 0; n
< arraysize(thread
); n
++)
48 ASSERT_FALSE(thread
[n
].did_run());
49 for (size_t n
= 0; n
< arraysize(thread
); n
++)
50 ASSERT_TRUE(PlatformThread::Create(0, &thread
[n
], &handle
[n
]));
51 for (size_t n
= 0; n
< arraysize(thread
); n
++)
52 PlatformThread::Join(handle
[n
]);
53 for (size_t n
= 0; n
< arraysize(thread
); n
++)
54 ASSERT_TRUE(thread
[n
].did_run());
57 // Tests of basic thread functions ---------------------------------------------
59 class FunctionTestThread
: public PlatformThread::Delegate
{
62 : thread_id_(kInvalidThreadId
),
63 thread_started_(true, false),
64 terminate_thread_(true, false),
66 ~FunctionTestThread() override
{
67 EXPECT_TRUE(terminate_thread_
.IsSignaled())
68 << "Need to mark thread for termination and join the underlying thread "
69 << "before destroying a FunctionTestThread as it owns the "
70 << "WaitableEvent blocking the underlying thread's main.";
73 // Grabs |thread_id_|, signals |thread_started_|, and then waits for
74 // |terminate_thread_| to be signaled before exiting.
75 void ThreadMain() override
{
76 thread_id_
= PlatformThread::CurrentId();
77 EXPECT_NE(thread_id_
, kInvalidThreadId
);
79 // Make sure that the thread ID is the same across calls.
80 EXPECT_EQ(thread_id_
, PlatformThread::CurrentId());
82 thread_started_
.Signal();
84 terminate_thread_
.Wait();
89 PlatformThreadId
thread_id() const {
90 EXPECT_TRUE(thread_started_
.IsSignaled()) << "Thread ID still unknown";
94 bool IsRunning() const {
95 return thread_started_
.IsSignaled() && !done_
;
98 // Blocks until this thread is started.
99 void WaitForThreadStart() { thread_started_
.Wait(); }
101 // Mark this thread for termination (callers must then join this thread to be
102 // guaranteed of termination).
103 void MarkForTermination() { terminate_thread_
.Signal(); }
106 PlatformThreadId thread_id_
;
108 mutable WaitableEvent thread_started_
;
109 WaitableEvent terminate_thread_
;
112 DISALLOW_COPY_AND_ASSIGN(FunctionTestThread
);
115 TEST(PlatformThreadTest
, Function
) {
116 PlatformThreadId main_thread_id
= PlatformThread::CurrentId();
118 FunctionTestThread thread
;
119 PlatformThreadHandle handle
;
121 ASSERT_FALSE(thread
.IsRunning());
122 ASSERT_TRUE(PlatformThread::Create(0, &thread
, &handle
));
123 thread
.WaitForThreadStart();
124 ASSERT_TRUE(thread
.IsRunning());
125 EXPECT_NE(thread
.thread_id(), main_thread_id
);
127 thread
.MarkForTermination();
128 PlatformThread::Join(handle
);
129 ASSERT_FALSE(thread
.IsRunning());
131 // Make sure that the thread ID is the same across calls.
132 EXPECT_EQ(main_thread_id
, PlatformThread::CurrentId());
135 TEST(PlatformThreadTest
, FunctionTimesTen
) {
136 PlatformThreadId main_thread_id
= PlatformThread::CurrentId();
138 FunctionTestThread thread
[10];
139 PlatformThreadHandle handle
[arraysize(thread
)];
141 for (size_t n
= 0; n
< arraysize(thread
); n
++)
142 ASSERT_FALSE(thread
[n
].IsRunning());
144 for (size_t n
= 0; n
< arraysize(thread
); n
++)
145 ASSERT_TRUE(PlatformThread::Create(0, &thread
[n
], &handle
[n
]));
146 for (size_t n
= 0; n
< arraysize(thread
); n
++)
147 thread
[n
].WaitForThreadStart();
149 for (size_t n
= 0; n
< arraysize(thread
); n
++) {
150 ASSERT_TRUE(thread
[n
].IsRunning());
151 EXPECT_NE(thread
[n
].thread_id(), main_thread_id
);
153 // Make sure no two threads get the same ID.
154 for (size_t i
= 0; i
< n
; ++i
) {
155 EXPECT_NE(thread
[i
].thread_id(), thread
[n
].thread_id());
159 for (size_t n
= 0; n
< arraysize(thread
); n
++)
160 thread
[n
].MarkForTermination();
161 for (size_t n
= 0; n
< arraysize(thread
); n
++)
162 PlatformThread::Join(handle
[n
]);
163 for (size_t n
= 0; n
< arraysize(thread
); n
++)
164 ASSERT_FALSE(thread
[n
].IsRunning());
166 // Make sure that the thread ID is the same across calls.
167 EXPECT_EQ(main_thread_id
, PlatformThread::CurrentId());
172 const ThreadPriority kThreadPriorityTestValues
[] = {
173 // Disable non-normal priority toggling on POSIX as it appears to be broken
174 // (http://crbug.com/468793). This is prefered to disabling the tests altogether
175 // on POSIX as it at least provides coverage for running this code under
176 // "normal" priority.
177 #if !defined(OS_POSIX)
178 ThreadPriority::DISPLAY
,
179 ThreadPriority::REALTIME_AUDIO
,
180 // Keep BACKGROUND second to last to test backgrounding from other
182 ThreadPriority::BACKGROUND
,
183 #endif // !defined(OS_POSIX)
184 // Keep NORMAL last to test unbackgrounding.
185 ThreadPriority::NORMAL
190 // Test changing another thread's priority.
191 // NOTE: This test is partially disabled on POSIX, see note above and
192 // http://crbug.com/468793.
193 TEST(PlatformThreadTest
, ThreadPriorityOtherThread
) {
194 PlatformThreadHandle
current_handle(PlatformThread::CurrentHandle());
196 // Confirm that the current thread's priority is as expected.
197 EXPECT_EQ(ThreadPriority::NORMAL
,
198 PlatformThread::GetThreadPriority(current_handle
));
200 // Create a test thread.
201 FunctionTestThread thread
;
202 PlatformThreadHandle handle
;
203 ASSERT_TRUE(PlatformThread::Create(0, &thread
, &handle
));
204 thread
.WaitForThreadStart();
205 EXPECT_NE(thread
.thread_id(), kInvalidThreadId
);
206 EXPECT_NE(thread
.thread_id(), PlatformThread::CurrentId());
208 // New threads should get normal priority by default.
209 EXPECT_EQ(ThreadPriority::NORMAL
, PlatformThread::GetThreadPriority(handle
));
211 // Toggle each supported priority on the test thread and confirm it only
212 // affects it (and not the current thread).
213 for (size_t i
= 0; i
< arraysize(kThreadPriorityTestValues
); ++i
) {
216 // Alter and verify the test thread's priority.
217 PlatformThread::SetThreadPriority(handle
, kThreadPriorityTestValues
[i
]);
218 EXPECT_EQ(kThreadPriorityTestValues
[i
],
219 PlatformThread::GetThreadPriority(handle
));
221 // Make sure the current thread was otherwise unaffected.
222 EXPECT_EQ(ThreadPriority::NORMAL
,
223 PlatformThread::GetThreadPriority(current_handle
));
226 thread
.MarkForTermination();
227 PlatformThread::Join(handle
);
230 // Test changing the current thread's priority (which has different semantics on
232 // NOTE: This test is partially disabled on POSIX, see note above and
233 // http://crbug.com/468793.
234 TEST(PlatformThreadTest
, ThreadPriorityCurrentThread
) {
235 PlatformThreadHandle
current_handle(PlatformThread::CurrentHandle());
237 // Confirm that the current thread's priority is as expected.
238 EXPECT_EQ(ThreadPriority::NORMAL
,
239 PlatformThread::GetThreadPriority(current_handle
));
241 // Create a test thread for verification purposes only.
242 FunctionTestThread thread
;
243 PlatformThreadHandle handle
;
244 ASSERT_TRUE(PlatformThread::Create(0, &thread
, &handle
));
245 thread
.WaitForThreadStart();
246 EXPECT_NE(thread
.thread_id(), kInvalidThreadId
);
247 EXPECT_NE(thread
.thread_id(), PlatformThread::CurrentId());
249 // Confirm that the new thread's priority is as expected.
250 EXPECT_EQ(ThreadPriority::NORMAL
, PlatformThread::GetThreadPriority(handle
));
252 // Toggle each supported priority on the current thread and confirm it only
253 // affects it (and not the test thread).
254 for (size_t i
= 0; i
< arraysize(kThreadPriorityTestValues
); ++i
) {
257 // Alter and verify the current thread's priority.
258 PlatformThread::SetThreadPriority(current_handle
,
259 kThreadPriorityTestValues
[i
]);
260 EXPECT_EQ(kThreadPriorityTestValues
[i
],
261 PlatformThread::GetThreadPriority(current_handle
));
263 // Make sure the test thread was otherwise unaffected.
264 EXPECT_EQ(ThreadPriority::NORMAL
,
265 PlatformThread::GetThreadPriority(handle
));
268 // Restore current thread priority for follow-up tests.
269 PlatformThread::SetThreadPriority(current_handle
, ThreadPriority::NORMAL
);
271 thread
.MarkForTermination();
272 PlatformThread::Join(handle
);