serial_runner_unittest.cc revision 3551c9c881056c480085172ff9840cab31610854
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. 4 5#include "base/bind.h" 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" 11 12namespace media { 13 14class SerialRunnerTest : public ::testing::Test { 15 public: 16 SerialRunnerTest() 17 : inside_start_(false), done_called_(false), done_status_(PIPELINE_OK) {} 18 virtual ~SerialRunnerTest() {} 19 20 void RunSerialRunner() { 21 message_loop_.PostTask(FROM_HERE, base::Bind( 22 &SerialRunnerTest::StartRunnerInternal, base::Unretained(this), 23 bound_fns_)); 24 message_loop_.RunUntilIdle(); 25 } 26 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), 33 status, 34 called_.size())); 35 called_.push_back(false); 36 } 37 38 // Push a bound function to the queue that will delete the SerialRunner, 39 // which should cancel all remaining queued work. 40 void PushCancellation() { 41 bound_fns_.Push(base::Bind(&SerialRunnerTest::CancelSerialRunner, 42 base::Unretained(this))); 43 } 44 45 // Queries final status of pushed functions and done callback. Valid only 46 // after calling RunSerialRunner(). 47 bool called(size_t index) { return called_[index]; } 48 bool done_called() { return done_called_; } 49 PipelineStatus done_status() { return done_status_; } 50 51 private: 52 void RunBoundFunction(PipelineStatus status, 53 size_t index, 54 const PipelineStatusCB& status_cb) { 55 EXPECT_FALSE(inside_start_) 56 << "Bound functions should not run on same stack as " 57 << "SerialRunner::Run()\n" << base::debug::StackTrace().ToString(); 58 59 called_[index] = true; 60 status_cb.Run(status); 61 } 62 63 void StartRunnerInternal(const SerialRunner::Queue& bound_fns) { 64 inside_start_ = true; 65 runner_ = SerialRunner::Run(bound_fns_, base::Bind( 66 &SerialRunnerTest::DoneCallback, base::Unretained(this))); 67 inside_start_ = false; 68 } 69 70 void DoneCallback(PipelineStatus status) { 71 EXPECT_FALSE(inside_start_) 72 << "Done callback should not run on same stack as SerialRunner::Run()\n" 73 << base::debug::StackTrace().ToString(); 74 75 done_called_ = true; 76 done_status_ = status; 77 message_loop_.QuitWhenIdle(); 78 } 79 80 void CancelSerialRunner(const PipelineStatusCB& status_cb) { 81 // Tasks run by |runner_| shouldn't reset it, hence we post a task to do so. 82 message_loop_.PostTask(FROM_HERE, base::Bind( 83 &SerialRunnerTest::ResetSerialRunner, base::Unretained(this))); 84 status_cb.Run(PIPELINE_OK); 85 } 86 87 void ResetSerialRunner() { 88 runner_.reset(); 89 } 90 91 base::MessageLoop message_loop_; 92 SerialRunner::Queue bound_fns_; 93 scoped_ptr<SerialRunner> runner_; 94 95 // Used to enforce calling stack guarantees of the API. 96 bool inside_start_; 97 98 // Tracks whether the i'th bound function was called. 99 std::vector<bool> called_; 100 101 // Tracks whether the final done callback was called + resulting status. 102 bool done_called_; 103 PipelineStatus done_status_; 104 105 DISALLOW_COPY_AND_ASSIGN(SerialRunnerTest); 106}; 107 108TEST_F(SerialRunnerTest, Empty) { 109 RunSerialRunner(); 110 111 EXPECT_TRUE(done_called()); 112 EXPECT_EQ(PIPELINE_OK, done_status()); 113} 114 115TEST_F(SerialRunnerTest, Single) { 116 PushBoundFunction(PIPELINE_OK); 117 RunSerialRunner(); 118 119 EXPECT_TRUE(called(0)); 120 EXPECT_TRUE(done_called()); 121 EXPECT_EQ(PIPELINE_OK, done_status()); 122} 123 124TEST_F(SerialRunnerTest, Single_Error) { 125 PushBoundFunction(PIPELINE_ERROR_ABORT); 126 RunSerialRunner(); 127 128 EXPECT_TRUE(called(0)); 129 EXPECT_TRUE(done_called()); 130 EXPECT_EQ(PIPELINE_ERROR_ABORT, done_status()); 131} 132 133TEST_F(SerialRunnerTest, Single_Cancel) { 134 PushBoundFunction(PIPELINE_OK); 135 PushCancellation(); 136 RunSerialRunner(); 137 138 EXPECT_TRUE(called(0)); 139 EXPECT_FALSE(done_called()); 140} 141 142TEST_F(SerialRunnerTest, Multiple) { 143 PushBoundFunction(PIPELINE_OK); 144 PushBoundFunction(PIPELINE_OK); 145 RunSerialRunner(); 146 147 EXPECT_TRUE(called(0)); 148 EXPECT_TRUE(called(1)); 149 EXPECT_TRUE(done_called()); 150 EXPECT_EQ(PIPELINE_OK, done_status()); 151} 152 153TEST_F(SerialRunnerTest, Multiple_Error) { 154 PushBoundFunction(PIPELINE_ERROR_ABORT); 155 PushBoundFunction(PIPELINE_OK); 156 RunSerialRunner(); 157 158 EXPECT_TRUE(called(0)); 159 EXPECT_FALSE(called(1)); // A bad status cancels remaining work. 160 EXPECT_TRUE(done_called()); 161 EXPECT_EQ(PIPELINE_ERROR_ABORT, done_status()); 162} 163 164TEST_F(SerialRunnerTest, Multiple_Cancel) { 165 PushBoundFunction(PIPELINE_OK); 166 PushCancellation(); 167 PushBoundFunction(PIPELINE_OK); 168 RunSerialRunner(); 169 170 EXPECT_TRUE(called(0)); 171 EXPECT_FALSE(called(1)); 172 EXPECT_FALSE(done_called()); 173} 174 175} // namespace media 176