1 // Copyright 2013 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.
6 #include "base/debug/stack_trace.h"
7 #include "base/message_loop/message_loop.h"
8 #include "media/base/pipeline_status.h"
9 #include "media/base/serial_runner.h"
10 #include "testing/gtest/include/gtest/gtest.h"
14 class SerialRunnerTest
: public ::testing::Test
{
17 : inside_start_(false), done_called_(false), done_status_(PIPELINE_OK
) {}
18 ~SerialRunnerTest() override
{}
20 void RunSerialRunner() {
21 message_loop_
.PostTask(FROM_HERE
, base::Bind(
22 &SerialRunnerTest::StartRunnerInternal
, base::Unretained(this),
24 message_loop_
.RunUntilIdle();
27 // Pushes a bound function to the queue that will run its callback with
28 // |status|. called(i) returns whether the i'th bound function pushed to the
29 // queue was called while running the SerialRunner.
30 void PushBoundFunction(PipelineStatus status
) {
31 bound_fns_
.Push(base::Bind(&SerialRunnerTest::RunBoundFunction
,
32 base::Unretained(this),
35 called_
.push_back(false);
38 void PushBoundClosure() {
39 bound_fns_
.Push(base::Bind(&SerialRunnerTest::RunBoundClosure
,
40 base::Unretained(this),
42 called_
.push_back(false);
46 bound_fns_
.Push(base::Bind(&SerialRunnerTest::RunClosure
,
47 base::Unretained(this),
49 called_
.push_back(false);
52 // Push a bound function to the queue that will delete the SerialRunner,
53 // which should cancel all remaining queued work.
54 void PushCancellation() {
55 bound_fns_
.Push(base::Bind(&SerialRunnerTest::CancelSerialRunner
,
56 base::Unretained(this)));
59 // Queries final status of pushed functions and done callback. Valid only
60 // after calling RunSerialRunner().
61 bool called(size_t index
) { return called_
[index
]; }
62 bool done_called() { return done_called_
; }
63 PipelineStatus
done_status() { return done_status_
; }
66 void RunBoundFunction(PipelineStatus status
,
68 const PipelineStatusCB
& status_cb
) {
69 EXPECT_EQ(index
== 0u, inside_start_
)
70 << "First bound function should run on same stack as "
71 << "SerialRunner::Run() while all others should not\n"
72 << base::debug::StackTrace().ToString();
74 called_
[index
] = true;
75 status_cb
.Run(status
);
78 void RunBoundClosure(size_t index
,
79 const base::Closure
& done_cb
) {
80 EXPECT_EQ(index
== 0u, inside_start_
)
81 << "First bound function should run on same stack as "
82 << "SerialRunner::Run() while all others should not\n"
83 << base::debug::StackTrace().ToString();
85 called_
[index
] = true;
89 void RunClosure(size_t index
) {
90 EXPECT_EQ(index
== 0u, inside_start_
)
91 << "First bound function should run on same stack as "
92 << "SerialRunner::Run() while all others should not\n"
93 << base::debug::StackTrace().ToString();
95 called_
[index
] = true;
98 void StartRunnerInternal(const SerialRunner::Queue
& bound_fns
) {
100 runner_
= SerialRunner::Run(bound_fns_
, base::Bind(
101 &SerialRunnerTest::DoneCallback
, base::Unretained(this)));
102 inside_start_
= false;
105 void DoneCallback(PipelineStatus status
) {
106 EXPECT_FALSE(inside_start_
)
107 << "Done callback should not run on same stack as SerialRunner::Run()\n"
108 << base::debug::StackTrace().ToString();
111 done_status_
= status
;
112 message_loop_
.QuitWhenIdle();
115 void CancelSerialRunner(const PipelineStatusCB
& status_cb
) {
116 // Tasks run by |runner_| shouldn't reset it, hence we post a task to do so.
117 message_loop_
.PostTask(FROM_HERE
, base::Bind(
118 &SerialRunnerTest::ResetSerialRunner
, base::Unretained(this)));
119 status_cb
.Run(PIPELINE_OK
);
122 void ResetSerialRunner() {
126 base::MessageLoop message_loop_
;
127 SerialRunner::Queue bound_fns_
;
128 scoped_ptr
<SerialRunner
> runner_
;
130 // Used to enforce calling stack guarantees of the API.
133 // Tracks whether the i'th bound function was called.
134 std::vector
<bool> called_
;
136 // Tracks whether the final done callback was called + resulting status.
138 PipelineStatus done_status_
;
140 DISALLOW_COPY_AND_ASSIGN(SerialRunnerTest
);
143 TEST_F(SerialRunnerTest
, Empty
) {
146 EXPECT_TRUE(done_called());
147 EXPECT_EQ(PIPELINE_OK
, done_status());
150 TEST_F(SerialRunnerTest
, Single
) {
151 PushBoundFunction(PIPELINE_OK
);
154 EXPECT_TRUE(called(0));
155 EXPECT_TRUE(done_called());
156 EXPECT_EQ(PIPELINE_OK
, done_status());
159 TEST_F(SerialRunnerTest
, Single_Error
) {
160 PushBoundFunction(PIPELINE_ERROR_ABORT
);
163 EXPECT_TRUE(called(0));
164 EXPECT_TRUE(done_called());
165 EXPECT_EQ(PIPELINE_ERROR_ABORT
, done_status());
168 TEST_F(SerialRunnerTest
, Single_Cancel
) {
169 PushBoundFunction(PIPELINE_OK
);
173 EXPECT_TRUE(called(0));
174 EXPECT_FALSE(done_called());
177 TEST_F(SerialRunnerTest
, Multiple
) {
178 PushBoundFunction(PIPELINE_OK
);
179 PushBoundFunction(PIPELINE_OK
);
182 EXPECT_TRUE(called(0));
183 EXPECT_TRUE(called(1));
184 EXPECT_TRUE(done_called());
185 EXPECT_EQ(PIPELINE_OK
, done_status());
188 TEST_F(SerialRunnerTest
, Multiple_Error
) {
189 PushBoundFunction(PIPELINE_ERROR_ABORT
);
190 PushBoundFunction(PIPELINE_OK
);
193 EXPECT_TRUE(called(0));
194 EXPECT_FALSE(called(1)); // A bad status cancels remaining work.
195 EXPECT_TRUE(done_called());
196 EXPECT_EQ(PIPELINE_ERROR_ABORT
, done_status());
199 TEST_F(SerialRunnerTest
, Multiple_Cancel
) {
200 PushBoundFunction(PIPELINE_OK
);
202 PushBoundFunction(PIPELINE_OK
);
205 EXPECT_TRUE(called(0));
206 EXPECT_FALSE(called(1));
207 EXPECT_FALSE(done_called());
210 TEST_F(SerialRunnerTest
, BoundClosure
) {
214 EXPECT_TRUE(called(0));
215 EXPECT_TRUE(done_called());
216 EXPECT_EQ(PIPELINE_OK
, done_status());
219 TEST_F(SerialRunnerTest
, Closure
) {
223 EXPECT_TRUE(called(0));
224 EXPECT_TRUE(done_called());
225 EXPECT_EQ(PIPELINE_OK
, done_status());