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