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 25 void ToggleValue(bool* value) { 26 *value = !*value; 27 } 28 29 class SleepInsideInitThread : public Thread { 30 public: 31 SleepInsideInitThread() : Thread("none") { 32 init_called_ = false; 33 } 34 ~SleepInsideInitThread() override { Stop(); } 35 36 void Init() override { 37 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(500)); 38 init_called_ = true; 39 } 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. 66 explicit CaptureToEventList(EventList* event_list) 67 : Thread("none"), 68 event_list_(event_list) { 69 } 70 71 ~CaptureToEventList() override { Stop(); } 72 73 void Init() override { event_list_->push_back(THREAD_EVENT_INIT); } 74 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. 87 explicit CapturingDestructionObserver(EventList* event_list) 88 : event_list_(event_list) { 89 } 90 91 // DestructionObserver implementation: 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. 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|. 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 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 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) && defined(OS_MACOSX) 146 // ASan bloats the stack variables and overflows the 12 kb stack on OSX. 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 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 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 199 TEST_F(ThreadTest, ThreadName) { 200 Thread a("ThreadName"); 201 EXPECT_TRUE(a.Start()); 202 EXPECT_EQ("ThreadName", a.thread_name()); 203 } 204 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(false, false); 213 base::PlatformThreadId id_from_new_thread; 214 a.task_runner()->PostTask( 215 FROM_HERE, base::Bind(ReturnThreadId, &a, &id_from_new_thread, &event)); 216 217 // Call GetThreadId() on the current thread before calling event.Wait() so 218 // that this test can find a race issue with TSAN. 219 base::PlatformThreadId id_from_current_thread = a.GetThreadId(); 220 221 // Check if GetThreadId() returns consistent value in both threads. 222 event.Wait(); 223 EXPECT_EQ(id_from_current_thread, id_from_new_thread); 224 225 // A started thread should have a valid ID. 226 EXPECT_NE(base::kInvalidThreadId, a.GetThreadId()); 227 EXPECT_NE(base::kInvalidThreadId, b.GetThreadId()); 228 229 // Each thread should have a different thread ID. 230 EXPECT_NE(a.GetThreadId(), b.GetThreadId()); 231 } 232 233 TEST_F(ThreadTest, ThreadIdWithRestart) { 234 Thread a("ThreadIdWithRestart"); 235 base::PlatformThreadId previous_id = base::kInvalidThreadId; 236 237 for (size_t i = 0; i < 16; ++i) { 238 EXPECT_TRUE(a.Start()); 239 base::PlatformThreadId current_id = a.GetThreadId(); 240 EXPECT_NE(previous_id, current_id); 241 previous_id = current_id; 242 a.Stop(); 243 } 244 } 245 246 // Make sure Init() is called after Start() and before 247 // WaitUntilThreadInitialized() returns. 248 TEST_F(ThreadTest, SleepInsideInit) { 249 SleepInsideInitThread t; 250 EXPECT_FALSE(t.InitCalled()); 251 t.StartAndWaitForTesting(); 252 EXPECT_TRUE(t.InitCalled()); 253 } 254 255 // Make sure that the destruction sequence is: 256 // 257 // (1) Thread::CleanUp() 258 // (2) MessageLoop::~MessageLoop() 259 // MessageLoop::DestructionObservers called. 260 TEST_F(ThreadTest, CleanUp) { 261 EventList captured_events; 262 CapturingDestructionObserver loop_destruction_observer(&captured_events); 263 264 { 265 // Start a thread which writes its event into |captured_events|. 266 CaptureToEventList t(&captured_events); 267 EXPECT_TRUE(t.Start()); 268 EXPECT_TRUE(t.message_loop()); 269 EXPECT_TRUE(t.IsRunning()); 270 271 // Register an observer that writes into |captured_events| once the 272 // thread's message loop is destroyed. 273 t.task_runner()->PostTask( 274 FROM_HERE, base::Bind(&RegisterDestructionObserver, 275 base::Unretained(&loop_destruction_observer))); 276 277 // Upon leaving this scope, the thread is deleted. 278 } 279 280 // Check the order of events during shutdown. 281 ASSERT_EQ(static_cast<size_t>(THREAD_NUM_EVENTS), captured_events.size()); 282 EXPECT_EQ(THREAD_EVENT_INIT, captured_events[0]); 283 EXPECT_EQ(THREAD_EVENT_CLEANUP, captured_events[1]); 284 EXPECT_EQ(THREAD_EVENT_MESSAGE_LOOP_DESTROYED, captured_events[2]); 285 } 286 287 TEST_F(ThreadTest, ThreadNotStarted) { 288 Thread a("Inert"); 289 EXPECT_EQ(nullptr, a.task_runner()); 290 } 291