- add sources.
[platform/framework/web/crosswalk.git] / src / base / threading / simple_thread_unittest.cc
1 // Copyright (c) 2012 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/atomic_sequence_num.h"
6 #include "base/strings/string_number_conversions.h"
7 #include "base/synchronization/waitable_event.h"
8 #include "base/threading/simple_thread.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10
11 namespace base {
12
13 namespace {
14
15 class SetIntRunner : public DelegateSimpleThread::Delegate {
16  public:
17   SetIntRunner(int* ptr, int val) : ptr_(ptr), val_(val) { }
18   virtual ~SetIntRunner() { }
19
20   virtual void Run() OVERRIDE {
21     *ptr_ = val_;
22   }
23
24  private:
25   int* ptr_;
26   int val_;
27 };
28
29 class WaitEventRunner : public DelegateSimpleThread::Delegate {
30  public:
31   explicit WaitEventRunner(WaitableEvent* event) : event_(event) { }
32   virtual ~WaitEventRunner() { }
33
34   virtual void Run() OVERRIDE {
35     EXPECT_FALSE(event_->IsSignaled());
36     event_->Signal();
37     EXPECT_TRUE(event_->IsSignaled());
38   }
39  private:
40   WaitableEvent* event_;
41 };
42
43 class SeqRunner : public DelegateSimpleThread::Delegate {
44  public:
45   explicit SeqRunner(AtomicSequenceNumber* seq) : seq_(seq) { }
46   virtual void Run() OVERRIDE {
47     seq_->GetNext();
48   }
49
50  private:
51   AtomicSequenceNumber* seq_;
52 };
53
54 // We count up on a sequence number, firing on the event when we've hit our
55 // expected amount, otherwise we wait on the event.  This will ensure that we
56 // have all threads outstanding until we hit our expected thread pool size.
57 class VerifyPoolRunner : public DelegateSimpleThread::Delegate {
58  public:
59   VerifyPoolRunner(AtomicSequenceNumber* seq,
60                    int total, WaitableEvent* event)
61       : seq_(seq), total_(total), event_(event) { }
62
63   virtual void Run() OVERRIDE {
64     if (seq_->GetNext() == total_) {
65       event_->Signal();
66     } else {
67       event_->Wait();
68     }
69   }
70
71  private:
72   AtomicSequenceNumber* seq_;
73   int total_;
74   WaitableEvent* event_;
75 };
76
77 }  // namespace
78
79 TEST(SimpleThreadTest, CreateAndJoin) {
80   int stack_int = 0;
81
82   SetIntRunner runner(&stack_int, 7);
83   EXPECT_EQ(0, stack_int);
84
85   DelegateSimpleThread thread(&runner, "int_setter");
86   EXPECT_FALSE(thread.HasBeenStarted());
87   EXPECT_FALSE(thread.HasBeenJoined());
88   EXPECT_EQ(0, stack_int);
89
90   thread.Start();
91   EXPECT_TRUE(thread.HasBeenStarted());
92   EXPECT_FALSE(thread.HasBeenJoined());
93
94   thread.Join();
95   EXPECT_TRUE(thread.HasBeenStarted());
96   EXPECT_TRUE(thread.HasBeenJoined());
97   EXPECT_EQ(7, stack_int);
98 }
99
100 TEST(SimpleThreadTest, WaitForEvent) {
101   // Create a thread, and wait for it to signal us.
102   WaitableEvent event(true, false);
103
104   WaitEventRunner runner(&event);
105   DelegateSimpleThread thread(&runner, "event_waiter");
106
107   EXPECT_FALSE(event.IsSignaled());
108   thread.Start();
109   event.Wait();
110   EXPECT_TRUE(event.IsSignaled());
111   thread.Join();
112 }
113
114 TEST(SimpleThreadTest, NamedWithOptions) {
115   WaitableEvent event(true, false);
116
117   WaitEventRunner runner(&event);
118   SimpleThread::Options options;
119   DelegateSimpleThread thread(&runner, "event_waiter", options);
120   EXPECT_EQ(thread.name_prefix(), "event_waiter");
121   EXPECT_FALSE(event.IsSignaled());
122
123   thread.Start();
124   EXPECT_EQ(thread.name_prefix(), "event_waiter");
125   EXPECT_EQ(thread.name(),
126             std::string("event_waiter/") + IntToString(thread.tid()));
127   event.Wait();
128
129   EXPECT_TRUE(event.IsSignaled());
130   thread.Join();
131
132   // We keep the name and tid, even after the thread is gone.
133   EXPECT_EQ(thread.name_prefix(), "event_waiter");
134   EXPECT_EQ(thread.name(),
135             std::string("event_waiter/") + IntToString(thread.tid()));
136 }
137
138 TEST(SimpleThreadTest, ThreadPool) {
139   AtomicSequenceNumber seq;
140   SeqRunner runner(&seq);
141   DelegateSimpleThreadPool pool("seq_runner", 10);
142
143   // Add work before we're running.
144   pool.AddWork(&runner, 300);
145
146   EXPECT_EQ(seq.GetNext(), 0);
147   pool.Start();
148
149   // Add work while we're running.
150   pool.AddWork(&runner, 300);
151
152   pool.JoinAll();
153
154   EXPECT_EQ(seq.GetNext(), 601);
155
156   // We can reuse our pool.  Verify that all 10 threads can actually run in
157   // parallel, so this test will only pass if there are actually 10 threads.
158   AtomicSequenceNumber seq2;
159   WaitableEvent event(true, false);
160   // Changing 9 to 10, for example, would cause us JoinAll() to never return.
161   VerifyPoolRunner verifier(&seq2, 9, &event);
162   pool.Start();
163
164   pool.AddWork(&verifier, 10);
165
166   pool.JoinAll();
167   EXPECT_EQ(seq2.GetNext(), 10);
168 }
169
170 }  // namespace base