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