1 // Copyright (c) 2006-2008 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/dynamic_annotations.h"
6 #include "base/lock.h"
7 #include "base/message_loop.h"
8 #include "base/string_util.h"
9 #include "base/thread.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "testing/platform_test.h"
12
13 using base::Thread;
14
15 typedef PlatformTest ThreadTest;
16
17 namespace {
18
19 class ToggleValue : public Task {
20 public:
ToggleValue(bool * value)21 explicit ToggleValue(bool* value) : value_(value) {
22 ANNOTATE_BENIGN_RACE(value, "Test-only data race on boolean "
23 "in base/thread_unittest");
24 }
Run()25 virtual void Run() {
26 *value_ = !*value_;
27 }
28 private:
29 bool* value_;
30 };
31
32 class SleepSome : public Task {
33 public:
SleepSome(int msec)34 explicit SleepSome(int msec) : msec_(msec) {
35 }
Run()36 virtual void Run() {
37 PlatformThread::Sleep(msec_);
38 }
39 private:
40 int msec_;
41 };
42
43 class SleepInsideInitThread : public Thread {
44 public:
SleepInsideInitThread()45 SleepInsideInitThread() : Thread("none") { init_called_ = false; }
~SleepInsideInitThread()46 virtual ~SleepInsideInitThread() { }
47
Init()48 virtual void Init() {
49 PlatformThread::Sleep(500);
50 init_called_ = true;
51 }
InitCalled()52 bool InitCalled() { return init_called_; }
53 private:
54 bool init_called_;
55 };
56
57 } // namespace
58
TEST_F(ThreadTest,Restart)59 TEST_F(ThreadTest, Restart) {
60 Thread a("Restart");
61 a.Stop();
62 EXPECT_FALSE(a.message_loop());
63 EXPECT_FALSE(a.IsRunning());
64 EXPECT_TRUE(a.Start());
65 EXPECT_TRUE(a.message_loop());
66 EXPECT_TRUE(a.IsRunning());
67 a.Stop();
68 EXPECT_FALSE(a.message_loop());
69 EXPECT_FALSE(a.IsRunning());
70 EXPECT_TRUE(a.Start());
71 EXPECT_TRUE(a.message_loop());
72 EXPECT_TRUE(a.IsRunning());
73 a.Stop();
74 EXPECT_FALSE(a.message_loop());
75 EXPECT_FALSE(a.IsRunning());
76 a.Stop();
77 EXPECT_FALSE(a.message_loop());
78 EXPECT_FALSE(a.IsRunning());
79 }
80
TEST_F(ThreadTest,StartWithOptions_StackSize)81 TEST_F(ThreadTest, StartWithOptions_StackSize) {
82 Thread a("StartWithStackSize");
83 // Ensure that the thread can work with only 12 kb and still process a
84 // message.
85 Thread::Options options;
86 options.stack_size = 12*1024;
87 EXPECT_TRUE(a.StartWithOptions(options));
88 EXPECT_TRUE(a.message_loop());
89 EXPECT_TRUE(a.IsRunning());
90
91 bool was_invoked = false;
92 a.message_loop()->PostTask(FROM_HERE, new ToggleValue(&was_invoked));
93
94 // wait for the task to run (we could use a kernel event here
95 // instead to avoid busy waiting, but this is sufficient for
96 // testing purposes).
97 for (int i = 100; i >= 0 && !was_invoked; --i) {
98 PlatformThread::Sleep(10);
99 }
100 EXPECT_TRUE(was_invoked);
101 }
102
TEST_F(ThreadTest,TwoTasks)103 TEST_F(ThreadTest, TwoTasks) {
104 bool was_invoked = false;
105 {
106 Thread a("TwoTasks");
107 EXPECT_TRUE(a.Start());
108 EXPECT_TRUE(a.message_loop());
109
110 // Test that all events are dispatched before the Thread object is
111 // destroyed. We do this by dispatching a sleep event before the
112 // event that will toggle our sentinel value.
113 a.message_loop()->PostTask(FROM_HERE, new SleepSome(20));
114 a.message_loop()->PostTask(FROM_HERE, new ToggleValue(&was_invoked));
115 }
116 EXPECT_TRUE(was_invoked);
117 }
118
TEST_F(ThreadTest,StopSoon)119 TEST_F(ThreadTest, StopSoon) {
120 Thread a("StopSoon");
121 EXPECT_TRUE(a.Start());
122 EXPECT_TRUE(a.message_loop());
123 EXPECT_TRUE(a.IsRunning());
124 a.StopSoon();
125 a.StopSoon();
126 a.Stop();
127 EXPECT_FALSE(a.message_loop());
128 EXPECT_FALSE(a.IsRunning());
129 }
130
TEST_F(ThreadTest,ThreadName)131 TEST_F(ThreadTest, ThreadName) {
132 Thread a("ThreadName");
133 EXPECT_TRUE(a.Start());
134 EXPECT_EQ("ThreadName", a.thread_name());
135 }
136
137 // Make sure we can't use a thread between Start() and Init().
TEST_F(ThreadTest,SleepInsideInit)138 TEST_F(ThreadTest, SleepInsideInit) {
139 SleepInsideInitThread t;
140 EXPECT_FALSE(t.InitCalled());
141 t.Start();
142 EXPECT_TRUE(t.InitCalled());
143 }
144