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.
5 #include "base/sequence_checker_impl.h"
10 #include "base/compiler_specific.h"
11 #include "base/location.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/message_loop.h"
14 #include "base/sequenced_task_runner.h"
15 #include "base/threading/thread.h"
16 #include "testing/gtest/include/gtest/gtest.h"
22 // Implementation of SequencedTaskRunner that lets us control what
23 // RunsTasksOnCurrentThread() returns.
24 class FakeTaskRunner
: public SequencedTaskRunner
{
26 FakeTaskRunner() : runs_tasks_on_current_thread_(false) {}
28 void SetRunsTasksOnCurrentThread(bool runs_tasks_on_current_thread
) {
29 runs_tasks_on_current_thread_
= runs_tasks_on_current_thread
;
32 // SequencedTaskRunner implementation.
33 virtual bool PostDelayedTask(const tracked_objects::Location
& from_here
,
35 TimeDelta delay
) OVERRIDE
{
40 virtual bool PostNonNestableDelayedTask(
41 const tracked_objects::Location
& from_here
,
43 TimeDelta delay
) OVERRIDE
{
48 virtual bool RunsTasksOnCurrentThread() const OVERRIDE
{
49 return runs_tasks_on_current_thread_
;
53 virtual ~FakeTaskRunner() {}
56 bool runs_tasks_on_current_thread_
;
59 class SequenceCheckerImplTest
: public ::testing::Test
{
62 // Create a SequenceCheckerImpl with a SequencedTaskRunner and make
63 // sure that CalledOnValidSequence() returns what that SequencedTaskRunner
64 // returns for RunsTasksOnCurrentThread().
65 TEST_F(SequenceCheckerImplTest
, CalledOnValidSequenceNonNull
) {
66 const scoped_refptr
<FakeTaskRunner
> fake_sequenced_task_runner(
67 new FakeTaskRunner());
69 const SequenceCheckerImpl
sequence_checker_impl(fake_sequenced_task_runner
);
70 EXPECT_FALSE(sequence_checker_impl
.CalledOnValidSequence());
72 fake_sequenced_task_runner
->SetRunsTasksOnCurrentThread(true);
73 EXPECT_TRUE(sequence_checker_impl
.CalledOnValidSequence());
75 fake_sequenced_task_runner
->SetRunsTasksOnCurrentThread(false);
76 EXPECT_FALSE(sequence_checker_impl
.CalledOnValidSequence());
79 void ExpectCalledOnValidSequence(
80 const tracked_objects::Location
& location
,
81 const SequenceCheckerImpl
* sequence_checker_impl
,
82 bool expected_value
) {
83 EXPECT_EQ(expected_value
, sequence_checker_impl
->CalledOnValidSequence())
84 << location
.ToString();
87 // Create a SequenceCheckerImpl with no SequencedTaskRunner and make
88 // sure that CalledOnValidSequence() behaves like
89 // ThreadChecker::CalledOnValidThread().
90 TEST_F(SequenceCheckerImplTest
, CalledOnValidSequenceNull
) {
91 const SequenceCheckerImpl
sequence_checker_impl(NULL
);
92 EXPECT_TRUE(sequence_checker_impl
.CalledOnValidSequence());
95 Thread
thread("thread 1");
96 ASSERT_TRUE(thread
.Start());
97 thread
.message_loop()->PostTask(
98 FROM_HERE
, Bind(&ExpectCalledOnValidSequence
,
100 Unretained(&sequence_checker_impl
),
104 EXPECT_TRUE(sequence_checker_impl
.CalledOnValidSequence());
107 // Create a SequenceCheckerImpl with a SequencedTaskRunner and switch
108 // it to another one. CalledOnValidSequence() should return what its
109 // underlying SequencedTaskRunner returns for
110 // RunsTasksOnCurrentThread().
111 TEST_F(SequenceCheckerImplTest
, ChangeSequenceNonNull
) {
112 const scoped_refptr
<FakeTaskRunner
> fake_sequenced_task_runner1(
113 new FakeTaskRunner());
115 const scoped_refptr
<FakeTaskRunner
> fake_sequenced_task_runner2(
116 new FakeTaskRunner());
118 SequenceCheckerImpl
sequence_checker_impl(fake_sequenced_task_runner1
);
119 EXPECT_FALSE(sequence_checker_impl
.CalledOnValidSequence());
121 fake_sequenced_task_runner2
->SetRunsTasksOnCurrentThread(true);
122 EXPECT_FALSE(sequence_checker_impl
.CalledOnValidSequence());
124 sequence_checker_impl
.ChangeSequence(fake_sequenced_task_runner2
);
125 EXPECT_TRUE(sequence_checker_impl
.CalledOnValidSequence());
127 sequence_checker_impl
.ChangeSequence(fake_sequenced_task_runner1
);
128 EXPECT_FALSE(sequence_checker_impl
.CalledOnValidSequence());
131 // Create a SequenceCheckerImpl with a SequencedTaskRunner and switch
132 // it to a NULL one. CalledOnValidSequence() should then behave like
133 // ThreadChecker::CalledOnValidThread().
134 TEST_F(SequenceCheckerImplTest
, ChangeSequenceNull
) {
135 const scoped_refptr
<FakeTaskRunner
> fake_sequenced_task_runner(
136 new FakeTaskRunner());
138 SequenceCheckerImpl
sequence_checker_impl(fake_sequenced_task_runner
);
139 EXPECT_FALSE(sequence_checker_impl
.CalledOnValidSequence());
141 sequence_checker_impl
.ChangeSequence(NULL
);
142 // Binds to current thread.
143 EXPECT_TRUE(sequence_checker_impl
.CalledOnValidSequence());
145 Thread
thread("thread 1");
146 ASSERT_TRUE(thread
.Start());
147 thread
.message_loop()->PostTask(
148 FROM_HERE
, Bind(&ExpectCalledOnValidSequence
,
150 Unretained(&sequence_checker_impl
),
154 EXPECT_TRUE(sequence_checker_impl
.CalledOnValidSequence());
156 sequence_checker_impl
.ChangeSequence(NULL
);
157 // Binds to worker thread.
159 Thread
thread("thread 2");
160 ASSERT_TRUE(thread
.Start());
161 thread
.message_loop()->PostTask(
162 FROM_HERE
, Bind(&ExpectCalledOnValidSequence
,
164 Unretained(&sequence_checker_impl
),
167 EXPECT_FALSE(sequence_checker_impl
.CalledOnValidSequence());
170 // Create a SequenceCheckerImpl with the current thread's task runner
171 // and switch it to other task runners. CalledOnValidSequence() should
172 // return true only when it's on the correct thread.
173 TEST_F(SequenceCheckerImplTest
, MultipleThreads
) {
176 SequenceCheckerImpl
sequence_checker_impl(loop
.message_loop_proxy());
177 EXPECT_TRUE(sequence_checker_impl
.CalledOnValidSequence());
180 Thread
thread("thread 1");
181 ASSERT_TRUE(thread
.Start());
182 thread
.message_loop()->PostTask(
183 FROM_HERE
, Bind(&ExpectCalledOnValidSequence
,
185 Unretained(&sequence_checker_impl
),
187 thread
.message_loop()->PostTask(
188 FROM_HERE
, Bind(&SequenceCheckerImpl::ChangeSequence
,
189 Unretained(&sequence_checker_impl
),
190 thread
.message_loop_proxy()));
191 thread
.message_loop()->PostTask(
192 FROM_HERE
, Bind(&ExpectCalledOnValidSequence
,
194 Unretained(&sequence_checker_impl
),
198 EXPECT_FALSE(sequence_checker_impl
.CalledOnValidSequence());
200 sequence_checker_impl
.ChangeSequence(loop
.message_loop_proxy());
201 EXPECT_TRUE(sequence_checker_impl
.CalledOnValidSequence());
204 Thread
thread("thread 2");
205 ASSERT_TRUE(thread
.Start());
206 thread
.message_loop()->PostTask(
207 FROM_HERE
, Bind(&ExpectCalledOnValidSequence
,
209 Unretained(&sequence_checker_impl
),
213 EXPECT_TRUE(sequence_checker_impl
.CalledOnValidSequence());