1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
53f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "testing/gtest/include/gtest/gtest.h"
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "testing/platform_test.h"
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::Thread;
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef PlatformTest ThreadTest;
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ToggleValue : public Task {
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  explicit ToggleValue(bool* value) : value_(value) {
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ANNOTATE_BENIGN_RACE(value, "Test-only data race on boolean "
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         "in base/thread_unittest");
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void Run() {
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *value_ = !*value_;
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool* value_;
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass SleepSome : public Task {
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  explicit SleepSome(int msec) : msec_(msec) {
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void Run() {
383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    base::PlatformThread::Sleep(msec_);
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int msec_;
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass SleepInsideInitThread : public Thread {
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SleepInsideInitThread() : Thread("none") { init_called_ = false; }
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual ~SleepInsideInitThread() { }
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void Init() {
503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    base::PlatformThread::Sleep(500);
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    init_called_ = true;
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool InitCalled() { return init_called_; }
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool init_called_;
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum ThreadEvent {
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Thread::Init() was called.
60dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  THREAD_EVENT_INIT = 0,
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The MessageLoop for the thread was deleted.
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  THREAD_EVENT_MESSAGE_LOOP_DESTROYED,
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Thread::CleanUp() was called.
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  THREAD_EVENT_CLEANUP,
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Keep at end of list.
69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  THREAD_NUM_EVENTS
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef std::vector<ThreadEvent> EventList;
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass CaptureToEventList : public Thread {
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This Thread pushes events into the vector |event_list| to show
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the order they occured in. |event_list| must remain valid for the
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // lifetime of this thread.
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  explicit CaptureToEventList(EventList* event_list)
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : Thread("none"), event_list_(event_list) {
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual ~CaptureToEventList() {
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Must call Stop() manually to have our CleanUp() function called.
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Stop();
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void Init() {
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    event_list_->push_back(THREAD_EVENT_INIT);
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void CleanUp() {
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    event_list_->push_back(THREAD_EVENT_CLEANUP);
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EventList* event_list_;
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Observer that writes a value into |event_list| when a message loop has been
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// destroyed.
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass CapturingDestructionObserver : public MessageLoop::DestructionObserver {
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |event_list| must remain valid throughout the observer's lifetime.
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  explicit CapturingDestructionObserver(EventList* event_list)
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : event_list_(event_list) {
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // DestructionObserver implementation:
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void WillDestroyCurrentMessageLoop() {
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    event_list_->push_back(THREAD_EVENT_MESSAGE_LOOP_DESTROYED);
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    event_list_ = NULL;
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EventList* event_list_;
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Task that adds a destruction observer to the current message loop.
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass RegisterDestructionObserver : public Task {
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  explicit RegisterDestructionObserver(
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MessageLoop::DestructionObserver* observer)
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : observer_(observer) {
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void Run() {
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MessageLoop::current()->AddDestructionObserver(observer_);
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    observer_ = NULL;
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::DestructionObserver* observer_;
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(ThreadTest, Restart) {
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Thread a("Restart");
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  a.Stop();
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(a.message_loop());
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(a.IsRunning());
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(a.Start());
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(a.message_loop());
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(a.IsRunning());
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  a.Stop();
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(a.message_loop());
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(a.IsRunning());
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(a.Start());
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(a.message_loop());
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(a.IsRunning());
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  a.Stop();
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(a.message_loop());
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(a.IsRunning());
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  a.Stop();
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(a.message_loop());
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(a.IsRunning());
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(ThreadTest, StartWithOptions_StackSize) {
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Thread a("StartWithStackSize");
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Ensure that the thread can work with only 12 kb and still process a
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // message.
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Thread::Options options;
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  options.stack_size = 12*1024;
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(a.StartWithOptions(options));
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(a.message_loop());
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(a.IsRunning());
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool was_invoked = false;
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  a.message_loop()->PostTask(FROM_HERE, new ToggleValue(&was_invoked));
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // wait for the task to run (we could use a kernel event here
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // instead to avoid busy waiting, but this is sufficient for
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // testing purposes).
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 100; i >= 0 && !was_invoked; --i) {
1773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    base::PlatformThread::Sleep(10);
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(was_invoked);
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(ThreadTest, TwoTasks) {
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool was_invoked = false;
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  {
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Thread a("TwoTasks");
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(a.Start());
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(a.message_loop());
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Test that all events are dispatched before the Thread object is
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // destroyed.  We do this by dispatching a sleep event before the
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // event that will toggle our sentinel value.
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    a.message_loop()->PostTask(FROM_HERE, new SleepSome(20));
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    a.message_loop()->PostTask(FROM_HERE, new ToggleValue(&was_invoked));
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(was_invoked);
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(ThreadTest, StopSoon) {
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Thread a("StopSoon");
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(a.Start());
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(a.message_loop());
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(a.IsRunning());
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  a.StopSoon();
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  a.StopSoon();
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  a.Stop();
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(a.message_loop());
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(a.IsRunning());
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(ThreadTest, ThreadName) {
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Thread a("ThreadName");
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(a.Start());
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ("ThreadName", a.thread_name());
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Make sure we can't use a thread between Start() and Init().
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(ThreadTest, SleepInsideInit) {
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SleepInsideInitThread t;
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(t.InitCalled());
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  t.Start();
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(t.InitCalled());
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Make sure that the destruction sequence is:
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//  (1) Thread::CleanUp()
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//  (2) MessageLoop::~MessageLoop()
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//      MessageLoop::DestructionObservers called.
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(ThreadTest, CleanUp) {
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EventList captured_events;
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CapturingDestructionObserver loop_destruction_observer(&captured_events);
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Start a thread which writes its event into |captured_events|.
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CaptureToEventList t(&captured_events);
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(t.Start());
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(t.message_loop());
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(t.IsRunning());
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Register an observer that writes into |captured_events| once the
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // thread's message loop is destroyed.
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    t.message_loop()->PostTask(
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        FROM_HERE,
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new RegisterDestructionObserver(&loop_destruction_observer));
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Upon leaving this scope, the thread is deleted.
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Check the order of events during shutdown.
250dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_EQ(static_cast<size_t>(THREAD_NUM_EVENTS), captured_events.size());
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(THREAD_EVENT_INIT, captured_events[0]);
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(THREAD_EVENT_CLEANUP, captured_events[1]);
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(THREAD_EVENT_MESSAGE_LOOP_DESTROYED, captured_events[2]);
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
255