15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 10ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/third_party/dynamic_annotations/dynamic_annotations.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/platform_test.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Thread; 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef PlatformTest ThreadTest; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ToggleValue(bool* value) { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ANNOTATE_BENIGN_RACE(value, "Test-only data race on boolean " 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "in base/thread_unittest"); 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *value = !*value; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SleepInsideInitThread : public Thread { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SleepInsideInitThread() : Thread("none") { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) init_called_ = false; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ANNOTATE_BENIGN_RACE( 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, "Benign test-only data race on vptr - http://crbug.com/98219"); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~SleepInsideInitThread() { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Stop(); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Init() OVERRIDE { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(500)); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) init_called_ = true; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool InitCalled() { return init_called_; } 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool init_called_; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum ThreadEvent { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Thread::Init() was called. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) THREAD_EVENT_INIT = 0, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The MessageLoop for the thread was deleted. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) THREAD_EVENT_MESSAGE_LOOP_DESTROYED, 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Thread::CleanUp() was called. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) THREAD_EVENT_CLEANUP, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Keep at end of list. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) THREAD_NUM_EVENTS 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::vector<ThreadEvent> EventList; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CaptureToEventList : public Thread { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This Thread pushes events into the vector |event_list| to show 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the order they occured in. |event_list| must remain valid for the 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // lifetime of this thread. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit CaptureToEventList(EventList* event_list) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : Thread("none"), 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_list_(event_list) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~CaptureToEventList() { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Stop(); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Init() OVERRIDE { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_list_->push_back(THREAD_EVENT_INIT); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void CleanUp() OVERRIDE { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_list_->push_back(THREAD_EVENT_CLEANUP); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EventList* event_list_; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Observer that writes a value into |event_list| when a message loop has been 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// destroyed. 91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class CapturingDestructionObserver 92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : public base::MessageLoop::DestructionObserver { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |event_list| must remain valid throughout the observer's lifetime. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit CapturingDestructionObserver(EventList* event_list) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : event_list_(event_list) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DestructionObserver implementation: 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void WillDestroyCurrentMessageLoop() OVERRIDE { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_list_->push_back(THREAD_EVENT_MESSAGE_LOOP_DESTROYED); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_list_ = NULL; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EventList* event_list_; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Task that adds a destruction observer to the current message loop. 110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void RegisterDestructionObserver( 111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::MessageLoop::DestructionObserver* observer) { 112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::MessageLoop::current()->AddDestructionObserver(observer); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ThreadTest, Restart) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Thread a("Restart"); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a.Stop(); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(a.message_loop()); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(a.IsRunning()); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(a.Start()); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(a.message_loop()); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(a.IsRunning()); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a.Stop(); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(a.message_loop()); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(a.IsRunning()); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(a.Start()); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(a.message_loop()); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(a.IsRunning()); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a.Stop(); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(a.message_loop()); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(a.IsRunning()); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a.Stop(); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(a.message_loop()); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(a.IsRunning()); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ThreadTest, StartWithOptions_StackSize) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Thread a("StartWithStackSize"); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure that the thread can work with only 12 kb and still process a 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // message. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Thread::Options options; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.stack_size = 12*1024; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(a.StartWithOptions(options)); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(a.message_loop()); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(a.IsRunning()); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool was_invoked = false; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a.message_loop()->PostTask(FROM_HERE, base::Bind(&ToggleValue, &was_invoked)); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // wait for the task to run (we could use a kernel event here 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instead to avoid busy waiting, but this is sufficient for 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // testing purposes). 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 100; i >= 0 && !was_invoked; --i) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(was_invoked); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ThreadTest, TwoTasks) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool was_invoked = false; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Thread a("TwoTasks"); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(a.Start()); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(a.message_loop()); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test that all events are dispatched before the Thread object is 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // destroyed. We do this by dispatching a sleep event before the 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // event that will toggle our sentinel value. 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a.message_loop()->PostTask( 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind( 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<void (*)(base::TimeDelta)>( 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &base::PlatformThread::Sleep), 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(20))); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a.message_loop()->PostTask(FROM_HERE, base::Bind(&ToggleValue, 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &was_invoked)); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(was_invoked); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ThreadTest, StopSoon) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Thread a("StopSoon"); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(a.Start()); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(a.message_loop()); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(a.IsRunning()); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a.StopSoon(); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a.StopSoon(); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a.Stop(); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(a.message_loop()); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(a.IsRunning()); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ThreadTest, ThreadName) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Thread a("ThreadName"); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(a.Start()); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ("ThreadName", a.thread_name()); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Make sure we can't use a thread between Start() and Init(). 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ThreadTest, SleepInsideInit) { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SleepInsideInitThread t; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(t.InitCalled()); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t.Start(); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(t.InitCalled()); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Make sure that the destruction sequence is: 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (1) Thread::CleanUp() 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (2) MessageLoop::~MessageLoop() 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MessageLoop::DestructionObservers called. 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ThreadTest, CleanUp) { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EventList captured_events; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CapturingDestructionObserver loop_destruction_observer(&captured_events); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start a thread which writes its event into |captured_events|. 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CaptureToEventList t(&captured_events); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(t.Start()); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(t.message_loop()); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(t.IsRunning()); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register an observer that writes into |captured_events| once the 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread's message loop is destroyed. 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t.message_loop()->PostTask( 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::Bind(&RegisterDestructionObserver, 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(&loop_destruction_observer))); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Upon leaving this scope, the thread is deleted. 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check the order of events during shutdown. 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(static_cast<size_t>(THREAD_NUM_EVENTS), captured_events.size()); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(THREAD_EVENT_INIT, captured_events[0]); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(THREAD_EVENT_CLEANUP, captured_events[1]); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(THREAD_EVENT_MESSAGE_LOOP_DESTROYED, captured_events[2]); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 240