blob: 8bd817c75bcda1d7d5b867b40bb5effc74fca445 [file] [log] [blame]
[email protected]e7b3a612012-01-05 02:18:181// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commitd7cae122008-07-26 21:49:384
[email protected]34b99632011-01-01 01:01:065#include "base/threading/thread.h"
[email protected]f93ff3f2010-04-14 20:41:346
7#include <vector>
8
[email protected]6e238ba2011-11-23 20:45:439#include "base/bind.h"
[email protected]495cad92013-07-18 08:12:4010#include "base/message_loop/message_loop.h"
[email protected]ee857512010-05-14 08:24:4211#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
initial.commitd7cae122008-07-26 21:49:3812#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1513#include "testing/platform_test.h"
initial.commitd7cae122008-07-26 21:49:3814
[email protected]4d9bdfaf2008-08-26 05:53:5715using base::Thread;
16
[email protected]6e683db2008-08-28 01:17:0217typedef PlatformTest ThreadTest;
18
initial.commitd7cae122008-07-26 21:49:3819namespace {
initial.commitd7cae122008-07-26 21:49:3820
[email protected]6e238ba2011-11-23 20:45:4321void ToggleValue(bool* value) {
22 ANNOTATE_BENIGN_RACE(value, "Test-only data race on boolean "
23 "in base/thread_unittest");
24 *value = !*value;
25}
initial.commitd7cae122008-07-26 21:49:3826
[email protected]cd636d82009-01-27 01:26:1627class SleepInsideInitThread : public Thread {
28 public:
[email protected]ded6e7e2011-09-27 14:11:4429 SleepInsideInitThread() : Thread("none") {
30 init_called_ = false;
31 ANNOTATE_BENIGN_RACE(
32 this, "Benign test-only data race on vptr - http://crbug.com/98219");
33 }
[email protected]d583c3a2011-11-02 15:31:5634 virtual ~SleepInsideInitThread() {
35 Stop();
36 }
[email protected]cd636d82009-01-27 01:26:1637
[email protected]44106182012-04-06 03:53:0238 virtual void Init() OVERRIDE {
[email protected]a1b75b942011-12-31 22:53:5139 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(500));
[email protected]cd636d82009-01-27 01:26:1640 init_called_ = true;
41 }
42 bool InitCalled() { return init_called_; }
43 private:
44 bool init_called_;
45};
46
[email protected]f93ff3f2010-04-14 20:41:3447enum ThreadEvent {
48 // Thread::Init() was called.
[email protected]569c7602011-03-03 20:40:3249 THREAD_EVENT_INIT = 0,
[email protected]f93ff3f2010-04-14 20:41:3450
51 // The MessageLoop for the thread was deleted.
52 THREAD_EVENT_MESSAGE_LOOP_DESTROYED,
53
54 // Thread::CleanUp() was called.
55 THREAD_EVENT_CLEANUP,
56
[email protected]569c7602011-03-03 20:40:3257 // Keep at end of list.
58 THREAD_NUM_EVENTS
[email protected]f93ff3f2010-04-14 20:41:3459};
60
61typedef std::vector<ThreadEvent> EventList;
62
63class CaptureToEventList : public Thread {
64 public:
65 // This Thread pushes events into the vector |event_list| to show
66 // the order they occured in. |event_list| must remain valid for the
67 // lifetime of this thread.
68 explicit CaptureToEventList(EventList* event_list)
[email protected]44106182012-04-06 03:53:0269 : Thread("none"),
70 event_list_(event_list) {
[email protected]f93ff3f2010-04-14 20:41:3471 }
72
73 virtual ~CaptureToEventList() {
[email protected]f93ff3f2010-04-14 20:41:3474 Stop();
75 }
76
[email protected]44106182012-04-06 03:53:0277 virtual void Init() OVERRIDE {
[email protected]f93ff3f2010-04-14 20:41:3478 event_list_->push_back(THREAD_EVENT_INIT);
79 }
80
[email protected]44106182012-04-06 03:53:0281 virtual void CleanUp() OVERRIDE {
[email protected]f93ff3f2010-04-14 20:41:3482 event_list_->push_back(THREAD_EVENT_CLEANUP);
83 }
84
[email protected]f93ff3f2010-04-14 20:41:3485 private:
86 EventList* event_list_;
87};
88
89// Observer that writes a value into |event_list| when a message loop has been
90// destroyed.
[email protected]9e7154122013-05-30 23:11:0491class CapturingDestructionObserver
92 : public base::MessageLoop::DestructionObserver {
[email protected]f93ff3f2010-04-14 20:41:3493 public:
94 // |event_list| must remain valid throughout the observer's lifetime.
95 explicit CapturingDestructionObserver(EventList* event_list)
96 : event_list_(event_list) {
97 }
98
99 // DestructionObserver implementation:
[email protected]44106182012-04-06 03:53:02100 virtual void WillDestroyCurrentMessageLoop() OVERRIDE {
[email protected]f93ff3f2010-04-14 20:41:34101 event_list_->push_back(THREAD_EVENT_MESSAGE_LOOP_DESTROYED);
102 event_list_ = NULL;
103 }
104
105 private:
106 EventList* event_list_;
107};
108
109// Task that adds a destruction observer to the current message loop.
[email protected]9e7154122013-05-30 23:11:04110void RegisterDestructionObserver(
111 base::MessageLoop::DestructionObserver* observer) {
112 base::MessageLoop::current()->AddDestructionObserver(observer);
[email protected]e7b3a612012-01-05 02:18:18113}
[email protected]f93ff3f2010-04-14 20:41:34114
[email protected]eff4aecb2008-08-12 18:37:35115} // namespace
116
[email protected]6e683db2008-08-28 01:17:02117TEST_F(ThreadTest, Restart) {
[email protected]eff4aecb2008-08-12 18:37:35118 Thread a("Restart");
119 a.Stop();
120 EXPECT_FALSE(a.message_loop());
[email protected]b026f4a2009-01-28 17:21:23121 EXPECT_FALSE(a.IsRunning());
[email protected]eff4aecb2008-08-12 18:37:35122 EXPECT_TRUE(a.Start());
initial.commitd7cae122008-07-26 21:49:38123 EXPECT_TRUE(a.message_loop());
[email protected]b026f4a2009-01-28 17:21:23124 EXPECT_TRUE(a.IsRunning());
initial.commitd7cae122008-07-26 21:49:38125 a.Stop();
126 EXPECT_FALSE(a.message_loop());
[email protected]b026f4a2009-01-28 17:21:23127 EXPECT_FALSE(a.IsRunning());
[email protected]eff4aecb2008-08-12 18:37:35128 EXPECT_TRUE(a.Start());
initial.commitd7cae122008-07-26 21:49:38129 EXPECT_TRUE(a.message_loop());
[email protected]b026f4a2009-01-28 17:21:23130 EXPECT_TRUE(a.IsRunning());
initial.commitd7cae122008-07-26 21:49:38131 a.Stop();
132 EXPECT_FALSE(a.message_loop());
[email protected]b026f4a2009-01-28 17:21:23133 EXPECT_FALSE(a.IsRunning());
[email protected]eff4aecb2008-08-12 18:37:35134 a.Stop();
135 EXPECT_FALSE(a.message_loop());
[email protected]b026f4a2009-01-28 17:21:23136 EXPECT_FALSE(a.IsRunning());
initial.commitd7cae122008-07-26 21:49:38137}
138
[email protected]6e683db2008-08-28 01:17:02139TEST_F(ThreadTest, StartWithOptions_StackSize) {
[email protected]eff4aecb2008-08-12 18:37:35140 Thread a("StartWithStackSize");
141 // Ensure that the thread can work with only 12 kb and still process a
142 // message.
[email protected]4d9bdfaf2008-08-26 05:53:57143 Thread::Options options;
144 options.stack_size = 12*1024;
145 EXPECT_TRUE(a.StartWithOptions(options));
initial.commitd7cae122008-07-26 21:49:38146 EXPECT_TRUE(a.message_loop());
[email protected]b026f4a2009-01-28 17:21:23147 EXPECT_TRUE(a.IsRunning());
initial.commitd7cae122008-07-26 21:49:38148
149 bool was_invoked = false;
[email protected]6e238ba2011-11-23 20:45:43150 a.message_loop()->PostTask(FROM_HERE, base::Bind(&ToggleValue, &was_invoked));
initial.commitd7cae122008-07-26 21:49:38151
152 // wait for the task to run (we could use a kernel event here
153 // instead to avoid busy waiting, but this is sufficient for
154 // testing purposes).
[email protected]eff4aecb2008-08-12 18:37:35155 for (int i = 100; i >= 0 && !was_invoked; --i) {
[email protected]a1b75b942011-12-31 22:53:51156 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
initial.commitd7cae122008-07-26 21:49:38157 }
158 EXPECT_TRUE(was_invoked);
159}
160
[email protected]6e683db2008-08-28 01:17:02161TEST_F(ThreadTest, TwoTasks) {
initial.commitd7cae122008-07-26 21:49:38162 bool was_invoked = false;
163 {
[email protected]eff4aecb2008-08-12 18:37:35164 Thread a("TwoTasks");
165 EXPECT_TRUE(a.Start());
initial.commitd7cae122008-07-26 21:49:38166 EXPECT_TRUE(a.message_loop());
167
168 // Test that all events are dispatched before the Thread object is
169 // destroyed. We do this by dispatching a sleep event before the
170 // event that will toggle our sentinel value.
[email protected]767842922011-12-30 01:04:36171 a.message_loop()->PostTask(
172 FROM_HERE,
[email protected]a1b75b942011-12-31 22:53:51173 base::Bind(
174 static_cast<void (*)(base::TimeDelta)>(
175 &base::PlatformThread::Sleep),
176 base::TimeDelta::FromMilliseconds(20)));
[email protected]6e238ba2011-11-23 20:45:43177 a.message_loop()->PostTask(FROM_HERE, base::Bind(&ToggleValue,
178 &was_invoked));
initial.commitd7cae122008-07-26 21:49:38179 }
180 EXPECT_TRUE(was_invoked);
181}
182
[email protected]6e683db2008-08-28 01:17:02183TEST_F(ThreadTest, StopSoon) {
[email protected]eff4aecb2008-08-12 18:37:35184 Thread a("StopSoon");
185 EXPECT_TRUE(a.Start());
186 EXPECT_TRUE(a.message_loop());
[email protected]b026f4a2009-01-28 17:21:23187 EXPECT_TRUE(a.IsRunning());
[email protected]eff4aecb2008-08-12 18:37:35188 a.StopSoon();
[email protected]eff4aecb2008-08-12 18:37:35189 a.StopSoon();
[email protected]98c74f82008-12-01 14:34:42190 a.Stop();
[email protected]eff4aecb2008-08-12 18:37:35191 EXPECT_FALSE(a.message_loop());
[email protected]b026f4a2009-01-28 17:21:23192 EXPECT_FALSE(a.IsRunning());
initial.commitd7cae122008-07-26 21:49:38193}
194
[email protected]6e683db2008-08-28 01:17:02195TEST_F(ThreadTest, ThreadName) {
[email protected]eff4aecb2008-08-12 18:37:35196 Thread a("ThreadName");
197 EXPECT_TRUE(a.Start());
198 EXPECT_EQ("ThreadName", a.thread_name());
initial.commitd7cae122008-07-26 21:49:38199}
[email protected]cd636d82009-01-27 01:26:16200
201// Make sure we can't use a thread between Start() and Init().
202TEST_F(ThreadTest, SleepInsideInit) {
203 SleepInsideInitThread t;
204 EXPECT_FALSE(t.InitCalled());
205 t.Start();
206 EXPECT_TRUE(t.InitCalled());
207}
[email protected]f93ff3f2010-04-14 20:41:34208
209// Make sure that the destruction sequence is:
210//
211// (1) Thread::CleanUp()
212// (2) MessageLoop::~MessageLoop()
213// MessageLoop::DestructionObservers called.
[email protected]f93ff3f2010-04-14 20:41:34214TEST_F(ThreadTest, CleanUp) {
215 EventList captured_events;
216 CapturingDestructionObserver loop_destruction_observer(&captured_events);
217
218 {
219 // Start a thread which writes its event into |captured_events|.
220 CaptureToEventList t(&captured_events);
221 EXPECT_TRUE(t.Start());
222 EXPECT_TRUE(t.message_loop());
223 EXPECT_TRUE(t.IsRunning());
224
225 // Register an observer that writes into |captured_events| once the
226 // thread's message loop is destroyed.
227 t.message_loop()->PostTask(
[email protected]e7b3a612012-01-05 02:18:18228 FROM_HERE, base::Bind(&RegisterDestructionObserver,
229 base::Unretained(&loop_destruction_observer)));
[email protected]f93ff3f2010-04-14 20:41:34230
231 // Upon leaving this scope, the thread is deleted.
232 }
233
234 // Check the order of events during shutdown.
[email protected]569c7602011-03-03 20:40:32235 ASSERT_EQ(static_cast<size_t>(THREAD_NUM_EVENTS), captured_events.size());
[email protected]f93ff3f2010-04-14 20:41:34236 EXPECT_EQ(THREAD_EVENT_INIT, captured_events[0]);
237 EXPECT_EQ(THREAD_EVENT_CLEANUP, captured_events[1]);
238 EXPECT_EQ(THREAD_EVENT_MESSAGE_LOOP_DESTROYED, captured_events[2]);
[email protected]f93ff3f2010-04-14 20:41:34239}