diff options
author | Torne (Richard Coles) <torne@google.com> | 2013-08-23 16:39:15 +0100 |
---|---|---|
committer | Torne (Richard Coles) <torne@google.com> | 2013-08-23 16:39:15 +0100 |
commit | 3551c9c881056c480085172ff9840cab31610854 (patch) | |
tree | 23660320f5f4c279966609cf9da7491b96d10ca8 /media/base/serial_runner_unittest.cc | |
parent | 4e9d9adbbb6cf287125ca44a0823791a570472f5 (diff) | |
download | chromium_org-3551c9c881056c480085172ff9840cab31610854.tar.gz |
Merge from Chromium at DEPS revision r219274
This commit was generated by merge_to_master.py.
Change-Id: Ibb7f41396cadf4071e89153e1913c986d126f65d
Diffstat (limited to 'media/base/serial_runner_unittest.cc')
-rw-r--r-- | media/base/serial_runner_unittest.cc | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/media/base/serial_runner_unittest.cc b/media/base/serial_runner_unittest.cc new file mode 100644 index 0000000000..8df28bea42 --- /dev/null +++ b/media/base/serial_runner_unittest.cc @@ -0,0 +1,175 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/bind.h" +#include "base/debug/stack_trace.h" +#include "base/message_loop/message_loop.h" +#include "media/base/pipeline_status.h" +#include "media/base/serial_runner.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +class SerialRunnerTest : public ::testing::Test { + public: + SerialRunnerTest() + : inside_start_(false), done_called_(false), done_status_(PIPELINE_OK) {} + virtual ~SerialRunnerTest() {} + + void RunSerialRunner() { + message_loop_.PostTask(FROM_HERE, base::Bind( + &SerialRunnerTest::StartRunnerInternal, base::Unretained(this), + bound_fns_)); + message_loop_.RunUntilIdle(); + } + + // Pushes a bound function to the queue that will run its callback with + // |status|. called(i) returns whether the i'th bound function pushed to the + // queue was called while running the SerialRunner. + void PushBoundFunction(PipelineStatus status) { + bound_fns_.Push(base::Bind(&SerialRunnerTest::RunBoundFunction, + base::Unretained(this), + status, + called_.size())); + called_.push_back(false); + } + + // Push a bound function to the queue that will delete the SerialRunner, + // which should cancel all remaining queued work. + void PushCancellation() { + bound_fns_.Push(base::Bind(&SerialRunnerTest::CancelSerialRunner, + base::Unretained(this))); + } + + // Queries final status of pushed functions and done callback. Valid only + // after calling RunSerialRunner(). + bool called(size_t index) { return called_[index]; } + bool done_called() { return done_called_; } + PipelineStatus done_status() { return done_status_; } + + private: + void RunBoundFunction(PipelineStatus status, + size_t index, + const PipelineStatusCB& status_cb) { + EXPECT_FALSE(inside_start_) + << "Bound functions should not run on same stack as " + << "SerialRunner::Run()\n" << base::debug::StackTrace().ToString(); + + called_[index] = true; + status_cb.Run(status); + } + + void StartRunnerInternal(const SerialRunner::Queue& bound_fns) { + inside_start_ = true; + runner_ = SerialRunner::Run(bound_fns_, base::Bind( + &SerialRunnerTest::DoneCallback, base::Unretained(this))); + inside_start_ = false; + } + + void DoneCallback(PipelineStatus status) { + EXPECT_FALSE(inside_start_) + << "Done callback should not run on same stack as SerialRunner::Run()\n" + << base::debug::StackTrace().ToString(); + + done_called_ = true; + done_status_ = status; + message_loop_.QuitWhenIdle(); + } + + void CancelSerialRunner(const PipelineStatusCB& status_cb) { + // Tasks run by |runner_| shouldn't reset it, hence we post a task to do so. + message_loop_.PostTask(FROM_HERE, base::Bind( + &SerialRunnerTest::ResetSerialRunner, base::Unretained(this))); + status_cb.Run(PIPELINE_OK); + } + + void ResetSerialRunner() { + runner_.reset(); + } + + base::MessageLoop message_loop_; + SerialRunner::Queue bound_fns_; + scoped_ptr<SerialRunner> runner_; + + // Used to enforce calling stack guarantees of the API. + bool inside_start_; + + // Tracks whether the i'th bound function was called. + std::vector<bool> called_; + + // Tracks whether the final done callback was called + resulting status. + bool done_called_; + PipelineStatus done_status_; + + DISALLOW_COPY_AND_ASSIGN(SerialRunnerTest); +}; + +TEST_F(SerialRunnerTest, Empty) { + RunSerialRunner(); + + EXPECT_TRUE(done_called()); + EXPECT_EQ(PIPELINE_OK, done_status()); +} + +TEST_F(SerialRunnerTest, Single) { + PushBoundFunction(PIPELINE_OK); + RunSerialRunner(); + + EXPECT_TRUE(called(0)); + EXPECT_TRUE(done_called()); + EXPECT_EQ(PIPELINE_OK, done_status()); +} + +TEST_F(SerialRunnerTest, Single_Error) { + PushBoundFunction(PIPELINE_ERROR_ABORT); + RunSerialRunner(); + + EXPECT_TRUE(called(0)); + EXPECT_TRUE(done_called()); + EXPECT_EQ(PIPELINE_ERROR_ABORT, done_status()); +} + +TEST_F(SerialRunnerTest, Single_Cancel) { + PushBoundFunction(PIPELINE_OK); + PushCancellation(); + RunSerialRunner(); + + EXPECT_TRUE(called(0)); + EXPECT_FALSE(done_called()); +} + +TEST_F(SerialRunnerTest, Multiple) { + PushBoundFunction(PIPELINE_OK); + PushBoundFunction(PIPELINE_OK); + RunSerialRunner(); + + EXPECT_TRUE(called(0)); + EXPECT_TRUE(called(1)); + EXPECT_TRUE(done_called()); + EXPECT_EQ(PIPELINE_OK, done_status()); +} + +TEST_F(SerialRunnerTest, Multiple_Error) { + PushBoundFunction(PIPELINE_ERROR_ABORT); + PushBoundFunction(PIPELINE_OK); + RunSerialRunner(); + + EXPECT_TRUE(called(0)); + EXPECT_FALSE(called(1)); // A bad status cancels remaining work. + EXPECT_TRUE(done_called()); + EXPECT_EQ(PIPELINE_ERROR_ABORT, done_status()); +} + +TEST_F(SerialRunnerTest, Multiple_Cancel) { + PushBoundFunction(PIPELINE_OK); + PushCancellation(); + PushBoundFunction(PIPELINE_OK); + RunSerialRunner(); + + EXPECT_TRUE(called(0)); + EXPECT_FALSE(called(1)); + EXPECT_FALSE(done_called()); +} + +} // namespace media |