Home | History | Annotate | Download | only in base
      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:
     21   explicit ToggleValue(bool* value) : value_(value) {
     22     ANNOTATE_BENIGN_RACE(value, "Test-only data race on boolean "
     23                          "in base/thread_unittest");
     24   }
     25   virtual void Run() {
     26     *value_ = !*value_;
     27   }
     28  private:
     29   bool* value_;
     30 };
     31 
     32 class SleepSome : public Task {
     33  public:
     34   explicit SleepSome(int msec) : msec_(msec) {
     35   }
     36   virtual void Run() {
     37     PlatformThread::Sleep(msec_);
     38   }
     39  private:
     40   int msec_;
     41 };
     42 
     43 class SleepInsideInitThread : public Thread {
     44  public:
     45   SleepInsideInitThread() : Thread("none") { init_called_ = false; }
     46   virtual ~SleepInsideInitThread() { }
     47 
     48   virtual void Init() {
     49     PlatformThread::Sleep(500);
     50     init_called_ = true;
     51   }
     52   bool InitCalled() { return init_called_; }
     53  private:
     54   bool init_called_;
     55 };
     56 
     57 }  // namespace
     58 
     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 
     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 
    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 
    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 
    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().
    138 TEST_F(ThreadTest, SleepInsideInit) {
    139   SleepInsideInitThread t;
    140   EXPECT_FALSE(t.InitCalled());
    141   t.Start();
    142   EXPECT_TRUE(t.InitCalled());
    143 }
    144