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.
4
5 #include "base/threading/thread.h"
6
7 #include <stddef.h>
8
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "base/location.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/synchronization/waitable_event.h"
15 #include "build/build_config.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "testing/platform_test.h"
18
19 using base::Thread;
20
21 typedef PlatformTest ThreadTest;
22
23 namespace {
24
ToggleValue(bool * value)25 void ToggleValue(bool* value) {
26 *value = !*value;
27 }
28
29 class SleepInsideInitThread : public Thread {
30 public:
SleepInsideInitThread()31 SleepInsideInitThread() : Thread("none") {
32 init_called_ = false;
33 }
~SleepInsideInitThread()34 ~SleepInsideInitThread() override { Stop(); }
35
Init()36 void Init() override {
37 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(500));
38 init_called_ = true;
39 }
InitCalled()40 bool InitCalled() { return init_called_; }
41 private:
42 bool init_called_;
43 };
44
45 enum ThreadEvent {
46 // Thread::Init() was called.
47 THREAD_EVENT_INIT = 0,
48
49 // The MessageLoop for the thread was deleted.
50 THREAD_EVENT_MESSAGE_LOOP_DESTROYED,
51
52 // Thread::CleanUp() was called.
53 THREAD_EVENT_CLEANUP,
54
55 // Keep at end of list.
56 THREAD_NUM_EVENTS
57 };
58
59 typedef std::vector<ThreadEvent> EventList;
60
61 class CaptureToEventList : public Thread {
62 public:
63 // This Thread pushes events into the vector |event_list| to show
64 // the order they occured in. |event_list| must remain valid for the
65 // lifetime of this thread.
CaptureToEventList(EventList * event_list)66 explicit CaptureToEventList(EventList* event_list)
67 : Thread("none"),
68 event_list_(event_list) {
69 }
70
~CaptureToEventList()71 ~CaptureToEventList() override { Stop(); }
72
Init()73 void Init() override { event_list_->push_back(THREAD_EVENT_INIT); }
74
CleanUp()75 void CleanUp() override { event_list_->push_back(THREAD_EVENT_CLEANUP); }
76
77 private:
78 EventList* event_list_;
79 };
80
81 // Observer that writes a value into |event_list| when a message loop has been
82 // destroyed.
83 class CapturingDestructionObserver
84 : public base::MessageLoop::DestructionObserver {
85 public:
86 // |event_list| must remain valid throughout the observer's lifetime.
CapturingDestructionObserver(EventList * event_list)87 explicit CapturingDestructionObserver(EventList* event_list)
88 : event_list_(event_list) {
89 }
90
91 // DestructionObserver implementation:
WillDestroyCurrentMessageLoop()92 void WillDestroyCurrentMessageLoop() override {
93 event_list_->push_back(THREAD_EVENT_MESSAGE_LOOP_DESTROYED);
94 event_list_ = NULL;
95 }
96
97 private:
98 EventList* event_list_;
99 };
100
101 // Task that adds a destruction observer to the current message loop.
RegisterDestructionObserver(base::MessageLoop::DestructionObserver * observer)102 void RegisterDestructionObserver(
103 base::MessageLoop::DestructionObserver* observer) {
104 base::MessageLoop::current()->AddDestructionObserver(observer);
105 }
106
107 // Task that calls GetThreadId() of |thread|, stores the result into |id|, then
108 // signal |event|.
ReturnThreadId(base::Thread * thread,base::PlatformThreadId * id,base::WaitableEvent * event)109 void ReturnThreadId(base::Thread* thread,
110 base::PlatformThreadId* id,
111 base::WaitableEvent* event) {
112 *id = thread->GetThreadId();
113 event->Signal();
114 }
115
116 } // namespace
117
TEST_F(ThreadTest,Restart)118 TEST_F(ThreadTest, Restart) {
119 Thread a("Restart");
120 a.Stop();
121 EXPECT_FALSE(a.message_loop());
122 EXPECT_FALSE(a.IsRunning());
123 EXPECT_TRUE(a.Start());
124 EXPECT_TRUE(a.message_loop());
125 EXPECT_TRUE(a.IsRunning());
126 a.Stop();
127 EXPECT_FALSE(a.message_loop());
128 EXPECT_FALSE(a.IsRunning());
129 EXPECT_TRUE(a.Start());
130 EXPECT_TRUE(a.message_loop());
131 EXPECT_TRUE(a.IsRunning());
132 a.Stop();
133 EXPECT_FALSE(a.message_loop());
134 EXPECT_FALSE(a.IsRunning());
135 a.Stop();
136 EXPECT_FALSE(a.message_loop());
137 EXPECT_FALSE(a.IsRunning());
138 }
139
TEST_F(ThreadTest,StartWithOptions_StackSize)140 TEST_F(ThreadTest, StartWithOptions_StackSize) {
141 Thread a("StartWithStackSize");
142 // Ensure that the thread can work with only 12 kb and still process a
143 // message.
144 Thread::Options options;
145 #if defined(ADDRESS_SANITIZER)
146 // ASan bloats the stack variables and overflows the 12 kb stack.
147 options.stack_size = 24*1024;
148 #else
149 options.stack_size = 12*1024;
150 #endif
151 EXPECT_TRUE(a.StartWithOptions(options));
152 EXPECT_TRUE(a.message_loop());
153 EXPECT_TRUE(a.IsRunning());
154
155 bool was_invoked = false;
156 a.task_runner()->PostTask(FROM_HERE, base::Bind(&ToggleValue, &was_invoked));
157
158 // wait for the task to run (we could use a kernel event here
159 // instead to avoid busy waiting, but this is sufficient for
160 // testing purposes).
161 for (int i = 100; i >= 0 && !was_invoked; --i) {
162 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
163 }
164 EXPECT_TRUE(was_invoked);
165 }
166
TEST_F(ThreadTest,TwoTasks)167 TEST_F(ThreadTest, TwoTasks) {
168 bool was_invoked = false;
169 {
170 Thread a("TwoTasks");
171 EXPECT_TRUE(a.Start());
172 EXPECT_TRUE(a.message_loop());
173
174 // Test that all events are dispatched before the Thread object is
175 // destroyed. We do this by dispatching a sleep event before the
176 // event that will toggle our sentinel value.
177 a.task_runner()->PostTask(
178 FROM_HERE, base::Bind(static_cast<void (*)(base::TimeDelta)>(
179 &base::PlatformThread::Sleep),
180 base::TimeDelta::FromMilliseconds(20)));
181 a.task_runner()->PostTask(FROM_HERE,
182 base::Bind(&ToggleValue, &was_invoked));
183 }
184 EXPECT_TRUE(was_invoked);
185 }
186
TEST_F(ThreadTest,StopSoon)187 TEST_F(ThreadTest, StopSoon) {
188 Thread a("StopSoon");
189 EXPECT_TRUE(a.Start());
190 EXPECT_TRUE(a.message_loop());
191 EXPECT_TRUE(a.IsRunning());
192 a.StopSoon();
193 a.StopSoon();
194 a.Stop();
195 EXPECT_FALSE(a.message_loop());
196 EXPECT_FALSE(a.IsRunning());
197 }
198
TEST_F(ThreadTest,ThreadName)199 TEST_F(ThreadTest, ThreadName) {
200 Thread a("ThreadName");
201 EXPECT_TRUE(a.Start());
202 EXPECT_EQ("ThreadName", a.thread_name());
203 }
204
TEST_F(ThreadTest,ThreadId)205 TEST_F(ThreadTest, ThreadId) {
206 Thread a("ThreadId0");
207 Thread b("ThreadId1");
208 a.Start();
209 b.Start();
210
211 // Post a task that calls GetThreadId() on the created thread.
212 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
213 base::WaitableEvent::InitialState::NOT_SIGNALED);
214 base::PlatformThreadId id_from_new_thread;
215 a.task_runner()->PostTask(
216 FROM_HERE, base::Bind(ReturnThreadId, &a, &id_from_new_thread, &event));
217
218 // Call GetThreadId() on the current thread before calling event.Wait() so
219 // that this test can find a race issue with TSAN.
220 base::PlatformThreadId id_from_current_thread = a.GetThreadId();
221
222 // Check if GetThreadId() returns consistent value in both threads.
223 event.Wait();
224 EXPECT_EQ(id_from_current_thread, id_from_new_thread);
225
226 // A started thread should have a valid ID.
227 EXPECT_NE(base::kInvalidThreadId, a.GetThreadId());
228 EXPECT_NE(base::kInvalidThreadId, b.GetThreadId());
229
230 // Each thread should have a different thread ID.
231 EXPECT_NE(a.GetThreadId(), b.GetThreadId());
232 }
233
TEST_F(ThreadTest,ThreadIdWithRestart)234 TEST_F(ThreadTest, ThreadIdWithRestart) {
235 Thread a("ThreadIdWithRestart");
236 base::PlatformThreadId previous_id = base::kInvalidThreadId;
237
238 for (size_t i = 0; i < 16; ++i) {
239 EXPECT_TRUE(a.Start());
240 base::PlatformThreadId current_id = a.GetThreadId();
241 EXPECT_NE(previous_id, current_id);
242 previous_id = current_id;
243 a.Stop();
244 }
245 }
246
247 // Make sure Init() is called after Start() and before
248 // WaitUntilThreadInitialized() returns.
TEST_F(ThreadTest,SleepInsideInit)249 TEST_F(ThreadTest, SleepInsideInit) {
250 SleepInsideInitThread t;
251 EXPECT_FALSE(t.InitCalled());
252 t.StartAndWaitForTesting();
253 EXPECT_TRUE(t.InitCalled());
254 }
255
256 // Make sure that the destruction sequence is:
257 //
258 // (1) Thread::CleanUp()
259 // (2) MessageLoop::~MessageLoop()
260 // MessageLoop::DestructionObservers called.
TEST_F(ThreadTest,CleanUp)261 TEST_F(ThreadTest, CleanUp) {
262 EventList captured_events;
263 CapturingDestructionObserver loop_destruction_observer(&captured_events);
264
265 {
266 // Start a thread which writes its event into |captured_events|.
267 CaptureToEventList t(&captured_events);
268 EXPECT_TRUE(t.Start());
269 EXPECT_TRUE(t.message_loop());
270 EXPECT_TRUE(t.IsRunning());
271
272 // Register an observer that writes into |captured_events| once the
273 // thread's message loop is destroyed.
274 t.task_runner()->PostTask(
275 FROM_HERE, base::Bind(&RegisterDestructionObserver,
276 base::Unretained(&loop_destruction_observer)));
277
278 // Upon leaving this scope, the thread is deleted.
279 }
280
281 // Check the order of events during shutdown.
282 ASSERT_EQ(static_cast<size_t>(THREAD_NUM_EVENTS), captured_events.size());
283 EXPECT_EQ(THREAD_EVENT_INIT, captured_events[0]);
284 EXPECT_EQ(THREAD_EVENT_CLEANUP, captured_events[1]);
285 EXPECT_EQ(THREAD_EVENT_MESSAGE_LOOP_DESTROYED, captured_events[2]);
286 }
287
TEST_F(ThreadTest,ThreadNotStarted)288 TEST_F(ThreadTest, ThreadNotStarted) {
289 Thread a("Inert");
290 EXPECT_FALSE(a.task_runner());
291 }
292
TEST_F(ThreadTest,MultipleWaitUntilThreadStarted)293 TEST_F(ThreadTest, MultipleWaitUntilThreadStarted) {
294 Thread a("MultipleWaitUntilThreadStarted");
295 EXPECT_TRUE(a.Start());
296 // It's OK to call WaitUntilThreadStarted() multiple times.
297 EXPECT_TRUE(a.WaitUntilThreadStarted());
298 EXPECT_TRUE(a.WaitUntilThreadStarted());
299 }
300