| Index: webkit/glue/media/buffered_data_source_unittest.cc
|
| diff --git a/webkit/glue/media/buffered_data_source_unittest.cc b/webkit/glue/media/buffered_data_source_unittest.cc
|
| index 6e9a87d15dded92b600c33d6e3399db78ebbe665..f3708038a05314ae5d2d54e20bf88e861d430b92 100644
|
| --- a/webkit/glue/media/buffered_data_source_unittest.cc
|
| +++ b/webkit/glue/media/buffered_data_source_unittest.cc
|
| @@ -492,4 +492,70 @@ TEST_F(BufferedDataSourceTest, FileHasLoadedState) {
|
| StopDataSource();
|
| }
|
|
|
| +// This test makes sure that Stop() does not require a task to run on
|
| +// |message_loop_| before it calls its callback. This prevents accidental
|
| +// introduction of a pipeline teardown deadlock. The pipeline owner blocks
|
| +// the render message loop while waiting for Stop() to complete. Since this
|
| +// object runs on the render message loop, Stop() will not complete if it
|
| +// requires a task to run on the the message loop that is being blocked.
|
| +TEST_F(BufferedDataSourceTest, StopDoesNotUseMessageLoopForCallback) {
|
| + InitializeDataSource(kFileUrl, net::OK, true, 1024, LOADED);
|
| +
|
| + // Create a callback that lets us verify that it was called before
|
| + // Stop() returns. This is to make sure that the callback does not
|
| + // require |message_loop_| to execute tasks before being called.
|
| + media::MockCallback* stop_callback = media::NewExpectedCallback();
|
| + bool stop_done_called = false;
|
| + ON_CALL(*stop_callback, RunWithParams(_))
|
| + .WillByDefault(Assign(&stop_done_called, true));
|
| +
|
| + // Stop() the data source like normal.
|
| + data_source_->Stop(stop_callback);
|
| +
|
| + // Verify that the callback was called inside the Stop() call.
|
| + EXPECT_TRUE(stop_done_called);
|
| +
|
| + message_loop_->RunAllPending();
|
| +}
|
| +
|
| +TEST_F(BufferedDataSourceTest, AbortDuringPendingRead) {
|
| + InitializeDataSource(kFileUrl, net::OK, true, 1024, LOADED);
|
| +
|
| + // Setup a way to verify that Read() is not called on the loader.
|
| + // We are doing this to make sure that the ReadTask() is still on
|
| + // the message loop queue when Abort() is called.
|
| + bool read_called = false;
|
| + ON_CALL(*loader_, Read(_, _, _ , _))
|
| + .WillByDefault(DoAll(Assign(&read_called, true),
|
| + DeleteArg<3>()));
|
| +
|
| + // Initiate a Read() on the data source, but don't allow the
|
| + // message loop to run.
|
| + data_source_->Read(
|
| + 0, 10, buffer_,
|
| + NewCallback(static_cast<BufferedDataSourceTest*>(this),
|
| + &BufferedDataSourceTest::ReadCallback));
|
| +
|
| + // Call Abort() with the read pending.
|
| + EXPECT_CALL(*this, ReadCallback(-1));
|
| + EXPECT_CALL(*loader_, Stop());
|
| + data_source_->Abort();
|
| +
|
| + // Verify that Read()'s after the Abort() issue callback with an error.
|
| + EXPECT_CALL(*this, ReadCallback(-1));
|
| + data_source_->Read(
|
| + 0, 10, buffer_,
|
| + NewCallback(static_cast<BufferedDataSourceTest*>(this),
|
| + &BufferedDataSourceTest::ReadCallback));
|
| +
|
| + // Stop() the data source like normal.
|
| + data_source_->Stop(media::NewExpectedCallback());
|
| +
|
| + // Allow cleanup task to run.
|
| + message_loop_->RunAllPending();
|
| +
|
| + // Verify that Read() was not called on the loader.
|
| + EXPECT_FALSE(read_called);
|
| +}
|
| +
|
| } // namespace webkit_glue
|
|
|