• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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