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"
12 #include <sys/types.h>
20 // Trivial tests that thread runs and doesn't crash on create and join ---------
24 class TrivialThread
: public PlatformThread::Delegate
{
26 TrivialThread() : did_run_(false) {}
28 void ThreadMain() override
{ did_run_
= true; }
30 bool did_run() const { return did_run_
; }
35 DISALLOW_COPY_AND_ASSIGN(TrivialThread
);
40 TEST(PlatformThreadTest
, Trivial
) {
42 PlatformThreadHandle handle
;
44 ASSERT_FALSE(thread
.did_run());
45 ASSERT_TRUE(PlatformThread::Create(0, &thread
, &handle
));
46 PlatformThread::Join(handle
);
47 ASSERT_TRUE(thread
.did_run());
50 TEST(PlatformThreadTest
, TrivialTimesTen
) {
51 TrivialThread thread
[10];
52 PlatformThreadHandle handle
[arraysize(thread
)];
54 for (size_t n
= 0; n
< arraysize(thread
); n
++)
55 ASSERT_FALSE(thread
[n
].did_run());
56 for (size_t n
= 0; n
< arraysize(thread
); n
++)
57 ASSERT_TRUE(PlatformThread::Create(0, &thread
[n
], &handle
[n
]));
58 for (size_t n
= 0; n
< arraysize(thread
); n
++)
59 PlatformThread::Join(handle
[n
]);
60 for (size_t n
= 0; n
< arraysize(thread
); n
++)
61 ASSERT_TRUE(thread
[n
].did_run());
64 // Tests of basic thread functions ---------------------------------------------
68 class FunctionTestThread
: public PlatformThread::Delegate
{
71 : thread_id_(kInvalidThreadId
),
72 termination_ready_(true, false),
73 terminate_thread_(true, false),
75 ~FunctionTestThread() override
{
76 EXPECT_TRUE(terminate_thread_
.IsSignaled())
77 << "Need to mark thread for termination and join the underlying thread "
78 << "before destroying a FunctionTestThread as it owns the "
79 << "WaitableEvent blocking the underlying thread's main.";
82 // Grabs |thread_id_|, runs an optional test on that thread, signals
83 // |termination_ready_|, and then waits for |terminate_thread_| to be
84 // signaled before exiting.
85 void ThreadMain() override
{
86 thread_id_
= PlatformThread::CurrentId();
87 EXPECT_NE(thread_id_
, kInvalidThreadId
);
89 // Make sure that the thread ID is the same across calls.
90 EXPECT_EQ(thread_id_
, PlatformThread::CurrentId());
95 termination_ready_
.Signal();
96 terminate_thread_
.Wait();
101 PlatformThreadId
thread_id() const {
102 EXPECT_TRUE(termination_ready_
.IsSignaled()) << "Thread ID still unknown";
106 bool IsRunning() const {
107 return termination_ready_
.IsSignaled() && !done_
;
110 // Blocks until this thread is started and ready to be terminated.
111 void WaitForTerminationReady() { termination_ready_
.Wait(); }
113 // Marks this thread for termination (callers must then join this thread to be
114 // guaranteed of termination).
115 void MarkForTermination() { terminate_thread_
.Signal(); }
118 // Runs an optional test on the newly created thread.
119 virtual void RunTest() {}
121 PlatformThreadId thread_id_
;
123 mutable WaitableEvent termination_ready_
;
124 WaitableEvent terminate_thread_
;
127 DISALLOW_COPY_AND_ASSIGN(FunctionTestThread
);
132 TEST(PlatformThreadTest
, Function
) {
133 PlatformThreadId main_thread_id
= PlatformThread::CurrentId();
135 FunctionTestThread thread
;
136 PlatformThreadHandle handle
;
138 ASSERT_FALSE(thread
.IsRunning());
139 ASSERT_TRUE(PlatformThread::Create(0, &thread
, &handle
));
140 thread
.WaitForTerminationReady();
141 ASSERT_TRUE(thread
.IsRunning());
142 EXPECT_NE(thread
.thread_id(), main_thread_id
);
144 thread
.MarkForTermination();
145 PlatformThread::Join(handle
);
146 ASSERT_FALSE(thread
.IsRunning());
148 // Make sure that the thread ID is the same across calls.
149 EXPECT_EQ(main_thread_id
, PlatformThread::CurrentId());
152 TEST(PlatformThreadTest
, FunctionTimesTen
) {
153 PlatformThreadId main_thread_id
= PlatformThread::CurrentId();
155 FunctionTestThread thread
[10];
156 PlatformThreadHandle handle
[arraysize(thread
)];
158 for (size_t n
= 0; n
< arraysize(thread
); n
++)
159 ASSERT_FALSE(thread
[n
].IsRunning());
161 for (size_t n
= 0; n
< arraysize(thread
); n
++)
162 ASSERT_TRUE(PlatformThread::Create(0, &thread
[n
], &handle
[n
]));
163 for (size_t n
= 0; n
< arraysize(thread
); n
++)
164 thread
[n
].WaitForTerminationReady();
166 for (size_t n
= 0; n
< arraysize(thread
); n
++) {
167 ASSERT_TRUE(thread
[n
].IsRunning());
168 EXPECT_NE(thread
[n
].thread_id(), main_thread_id
);
170 // Make sure no two threads get the same ID.
171 for (size_t i
= 0; i
< n
; ++i
) {
172 EXPECT_NE(thread
[i
].thread_id(), thread
[n
].thread_id());
176 for (size_t n
= 0; n
< arraysize(thread
); n
++)
177 thread
[n
].MarkForTermination();
178 for (size_t n
= 0; n
< arraysize(thread
); n
++)
179 PlatformThread::Join(handle
[n
]);
180 for (size_t n
= 0; n
< arraysize(thread
); n
++)
181 ASSERT_FALSE(thread
[n
].IsRunning());
183 // Make sure that the thread ID is the same across calls.
184 EXPECT_EQ(main_thread_id
, PlatformThread::CurrentId());
189 const ThreadPriority kThreadPriorityTestValues
[] = {
190 // The order should be higher to lower to cover as much cases as possible on
191 // Linux trybots running without CAP_SYS_NICE permission.
192 #if !defined(OS_ANDROID)
193 // PlatformThread::GetCurrentThreadPriority() on Android does not support
194 // REALTIME_AUDIO case. See http://crbug.com/505474.
195 ThreadPriority::REALTIME_AUDIO
,
197 ThreadPriority::DISPLAY
,
198 // This redundant BACKGROUND priority is to test backgrounding from other
199 // priorities, and unbackgrounding.
200 ThreadPriority::BACKGROUND
,
201 ThreadPriority::NORMAL
,
202 ThreadPriority::BACKGROUND
};
204 bool IsBumpingPriorityAllowed() {
205 #if defined(OS_POSIX)
206 // Only root can raise thread priority on POSIX environment. On Linux, users
207 // who have CAP_SYS_NICE permission also can raise the thread priority, but
208 // libcap.so would be needed to check the capability.
209 return geteuid() == 0;
215 class ThreadPriorityTestThread
: public FunctionTestThread
{
217 ThreadPriorityTestThread() = default;
218 ~ThreadPriorityTestThread() override
= default;
221 void RunTest() override
{
222 // Confirm that the current thread's priority is as expected.
223 EXPECT_EQ(ThreadPriority::NORMAL
,
224 PlatformThread::GetCurrentThreadPriority());
226 // Toggle each supported priority on the current thread and confirm it
228 const bool bumping_priority_allowed
= IsBumpingPriorityAllowed();
229 for (size_t i
= 0; i
< arraysize(kThreadPriorityTestValues
); ++i
) {
231 if (!bumping_priority_allowed
&&
232 kThreadPriorityTestValues
[i
] >
233 PlatformThread::GetCurrentThreadPriority()) {
237 // Alter and verify the current thread's priority.
238 PlatformThread::SetCurrentThreadPriority(kThreadPriorityTestValues
[i
]);
239 EXPECT_EQ(kThreadPriorityTestValues
[i
],
240 PlatformThread::GetCurrentThreadPriority());
244 DISALLOW_COPY_AND_ASSIGN(ThreadPriorityTestThread
);
249 #if defined(OS_MACOSX)
250 // PlatformThread::GetCurrentThreadPriority() is not implemented on OS X.
251 #define MAYBE_ThreadPriorityCurrentThread DISABLED_ThreadPriorityCurrentThread
253 #define MAYBE_ThreadPriorityCurrentThread ThreadPriorityCurrentThread
256 // Test changing a created thread's priority (which has different semantics on
258 TEST(PlatformThreadTest
, MAYBE_ThreadPriorityCurrentThread
) {
259 ThreadPriorityTestThread thread
;
260 PlatformThreadHandle handle
;
262 ASSERT_FALSE(thread
.IsRunning());
263 ASSERT_TRUE(PlatformThread::Create(0, &thread
, &handle
));
264 thread
.WaitForTerminationReady();
265 ASSERT_TRUE(thread
.IsRunning());
267 thread
.MarkForTermination();
268 PlatformThread::Join(handle
);
269 ASSERT_FALSE(thread
.IsRunning());