| Index: media/base/composite_filter_unittest.cc
|
| diff --git a/media/base/composite_filter_unittest.cc b/media/base/composite_filter_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..fe757c3638811261fa58db4a9d059e9aa6a1ab77
|
| --- /dev/null
|
| +++ b/media/base/composite_filter_unittest.cc
|
| @@ -0,0 +1,799 @@
|
| +// Copyright (c) 2010 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 "media/base/composite_filter.h"
|
| +#include "media/base/mock_filter_host.h"
|
| +#include "media/base/mock_filters.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +using ::testing::_;
|
| +using ::testing::InSequence;
|
| +using ::testing::Return;
|
| +using ::testing::SaveArg;
|
| +using ::testing::StrictMock;
|
| +
|
| +namespace media {
|
| +
|
| +class CompositeFilterTest : public testing::Test {
|
| + public:
|
| + CompositeFilterTest();
|
| + virtual ~CompositeFilterTest();
|
| +
|
| + // Sets up a new CompositeFilter in |composite_|, creates |filter_1_| and
|
| + // |filter_2_|, and adds these filters to |composite_|.
|
| + void SetupAndAdd2Filters();
|
| +
|
| + // Helper enum that indicates what filter method to call.
|
| + enum MethodToCall {
|
| + PLAY,
|
| + PAUSE,
|
| + FLUSH,
|
| + STOP,
|
| + SEEK,
|
| + };
|
| +
|
| + // Helper method that adds a filter method call expectation based on the value
|
| + // of |method_to_call|.
|
| + //
|
| + // |method_to_call| - Indicates which method we expect a call for.
|
| + // |filter| - The MockFilter to add the expectation to.
|
| + // |seek_time| - The time to pass to the Seek() call if |method_to_call|
|
| + // equals SEEK.
|
| + void ExpectFilterCall(MethodToCall method_to_call, MockFilter* filter,
|
| + base::TimeDelta seek_time);
|
| +
|
| + // Helper method that calls a filter method based on the value of
|
| + // |method_to_call|.
|
| + //
|
| + // |method_to_call| - Indicates which method to call.
|
| + // |filter| - The Filter to make the method call on.
|
| + // |seek_time| - The time to pass to the Seek() call if |method_to_call|
|
| + // equals SEEK.
|
| + // |callback| - The callback object to pass to the method.
|
| + void DoFilterCall(MethodToCall method_to_call, Filter* filter,
|
| + base::TimeDelta seek_time,
|
| + FilterCallback* callback);
|
| +
|
| + // Creates an expectation sequence based on the value of method_to_call.
|
| + //
|
| + // |method_to_call| - Indicates which method we want a success sequence for.
|
| + // |seek_time| - The time to pass in the Seek() call if |method_to_call|
|
| + // equals SEEK.
|
| + void ExpectSuccess(MethodToCall method_to_call,
|
| + base::TimeDelta seek_time = base::TimeDelta());
|
| +
|
| + // Issue a Play(), Pause(), Flush(), Stop(), or Seek() on the composite and
|
| + // verify all the expected calls on the filters.
|
| + void DoPlay();
|
| + void DoPause();
|
| + void DoFlush();
|
| + void DoStop();
|
| + void DoSeek(base::TimeDelta time);
|
| +
|
| + // Issue a Play(), Pause(), Flush(), or Seek() and expect the calls to fail
|
| + // with a PIPELINE_ERROR_INVALID_STATE error.
|
| + //
|
| + // |method_to_call| - Indicates whick method to call.
|
| + // |seek_time| - The time to pass to the Seek() call if |method_to_call|
|
| + // equals SEEK.
|
| + void ExpectInvalidStateFail(MethodToCall method_to_call,
|
| + base::TimeDelta seek_time = base::TimeDelta());
|
| +
|
| + // Run the callback stored in |filter_1_callback_|.
|
| + void RunFilter1Callback();
|
| +
|
| + // Run the callback stored in |filter_2_callback_|.
|
| + void RunFilter2Callback();
|
| +
|
| + protected:
|
| + MessageLoop message_loop_;
|
| +
|
| + // The composite object being tested.
|
| + scoped_refptr<CompositeFilter> composite_;
|
| +
|
| + // First filter added to the composite.
|
| + scoped_refptr<StrictMock<MockFilter> > filter_1_;
|
| +
|
| + // Callback passed to |filter_1_| during last Play(), Pause(), Flush(),
|
| + // Stop(), or Seek() call.
|
| + FilterCallback* filter_1_callback_;
|
| +
|
| + // Second filter added to the composite.
|
| + scoped_refptr<StrictMock<MockFilter> > filter_2_;
|
| +
|
| + // Callback passed to |filter_2_| during last Play(), Pause(), Flush(),
|
| + // Stop(), or Seek() call.
|
| + FilterCallback* filter_2_callback_;
|
| +
|
| + // FilterHost implementation passed to |composite_| via set_host().
|
| + scoped_ptr<StrictMock<MockFilterHost> > mock_filter_host_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(CompositeFilterTest);
|
| +};
|
| +
|
| +CompositeFilterTest::CompositeFilterTest() :
|
| + composite_(new CompositeFilter(&message_loop_)),
|
| + filter_1_callback_(NULL),
|
| + filter_2_callback_(NULL),
|
| + mock_filter_host_(new StrictMock<MockFilterHost>()) {
|
| +}
|
| +
|
| +CompositeFilterTest::~CompositeFilterTest() {}
|
| +
|
| +void CompositeFilterTest::SetupAndAdd2Filters() {
|
| + mock_filter_host_.reset(new StrictMock<MockFilterHost>());
|
| + composite_ = new CompositeFilter(&message_loop_);
|
| + composite_->set_host(mock_filter_host_.get());
|
| +
|
| + // Setup |filter_1_| and arrange for methods to set
|
| + // |filter_1_callback_| when they are called.
|
| + filter_1_ = new StrictMock<MockFilter>();
|
| + filter_1_callback_ = NULL;
|
| + ON_CALL(*filter_1_, Play(_))
|
| + .WillByDefault(SaveArg<0>(&filter_1_callback_));
|
| + ON_CALL(*filter_1_, Pause(_))
|
| + .WillByDefault(SaveArg<0>(&filter_1_callback_));
|
| + ON_CALL(*filter_1_, Flush(_))
|
| + .WillByDefault(SaveArg<0>(&filter_1_callback_));
|
| + ON_CALL(*filter_1_, Stop(_))
|
| + .WillByDefault(SaveArg<0>(&filter_1_callback_));
|
| + ON_CALL(*filter_1_, Seek(_,_))
|
| + .WillByDefault(SaveArg<1>(&filter_1_callback_));
|
| +
|
| + // Setup |filter_2_| and arrange for methods to set
|
| + // |filter_2_callback_| when they are called.
|
| + filter_2_ = new StrictMock<MockFilter>();
|
| + filter_2_callback_ = NULL;
|
| + ON_CALL(*filter_2_, Play(_))
|
| + .WillByDefault(SaveArg<0>(&filter_2_callback_));
|
| + ON_CALL(*filter_2_, Pause(_))
|
| + .WillByDefault(SaveArg<0>(&filter_2_callback_));
|
| + ON_CALL(*filter_2_, Flush(_))
|
| + .WillByDefault(SaveArg<0>(&filter_2_callback_));
|
| + ON_CALL(*filter_2_, Stop(_))
|
| + .WillByDefault(SaveArg<0>(&filter_2_callback_));
|
| + ON_CALL(*filter_2_, Seek(_,_))
|
| + .WillByDefault(SaveArg<1>(&filter_2_callback_));
|
| +
|
| + composite_->AddFilter(filter_1_);
|
| + composite_->AddFilter(filter_2_);
|
| +}
|
| +
|
| +void CompositeFilterTest::ExpectFilterCall(MethodToCall method_to_call,
|
| + MockFilter* filter,
|
| + base::TimeDelta seek_time) {
|
| + switch(method_to_call) {
|
| + case PLAY:
|
| + EXPECT_CALL(*filter, Play(_));
|
| + break;
|
| + case PAUSE:
|
| + EXPECT_CALL(*filter, Pause(_));
|
| + break;
|
| + case FLUSH:
|
| + EXPECT_CALL(*filter, Flush(_));
|
| + break;
|
| + case STOP:
|
| + EXPECT_CALL(*filter, Stop(_));
|
| + break;
|
| + case SEEK:
|
| + EXPECT_CALL(*filter, Seek(seek_time, _));
|
| + break;
|
| + };
|
| +}
|
| +
|
| +void CompositeFilterTest::DoFilterCall(MethodToCall method_to_call,
|
| + Filter* filter,
|
| + base::TimeDelta seek_time,
|
| + FilterCallback* callback) {
|
| + switch(method_to_call) {
|
| + case PLAY:
|
| + filter->Play(callback);
|
| + break;
|
| + case PAUSE:
|
| + filter->Pause(callback);
|
| + break;
|
| + case FLUSH:
|
| + filter->Flush(callback);
|
| + break;
|
| + case STOP:
|
| + filter->Stop(callback);
|
| + break;
|
| + case SEEK:
|
| + filter->Seek(seek_time, callback);
|
| + break;
|
| + };
|
| +}
|
| +
|
| +void CompositeFilterTest::ExpectSuccess(MethodToCall method_to_call,
|
| + base::TimeDelta seek_time) {
|
| + InSequence seq;
|
| +
|
| + scoped_ptr<StrictMock<MockFilterCallback> > mock_callback(
|
| + new StrictMock<MockFilterCallback>(false));
|
| +
|
| + bool is_parallel_call = (method_to_call == FLUSH);
|
| +
|
| + ExpectFilterCall(method_to_call, filter_1_.get(), seek_time);
|
| +
|
| + if (is_parallel_call) {
|
| + ExpectFilterCall(method_to_call, filter_2_.get(), seek_time);
|
| + }
|
| +
|
| + // Make method call on the composite.
|
| + DoFilterCall(method_to_call, composite_.get(), seek_time,
|
| + mock_callback->NewCallback());
|
| +
|
| + if (is_parallel_call) {
|
| + // Make sure both filters have their callbacks set.
|
| + EXPECT_TRUE(filter_1_callback_ != NULL);
|
| + EXPECT_TRUE(filter_2_callback_ != NULL);
|
| +
|
| + RunFilter1Callback();
|
| + } else {
|
| + // Make sure that only |filter_1_| has its callback set.
|
| + EXPECT_TRUE(filter_1_callback_ != NULL);
|
| + EXPECT_EQ((FilterCallback*)NULL, filter_2_callback_);
|
| +
|
| + ExpectFilterCall(method_to_call, filter_2_.get(), seek_time);
|
| +
|
| + RunFilter1Callback();
|
| +
|
| + // Verify that |filter_2_| was called by checking the callback pointer.
|
| + EXPECT_TRUE(filter_2_callback_ != NULL);
|
| + }
|
| +
|
| + EXPECT_CALL(*mock_callback, OnFilterCallback());
|
| +
|
| + RunFilter2Callback();
|
| +}
|
| +
|
| +void CompositeFilterTest::DoPlay() {
|
| + ExpectSuccess(PLAY);
|
| +}
|
| +
|
| +void CompositeFilterTest::DoPause() {
|
| + ExpectSuccess(PAUSE);
|
| +}
|
| +
|
| +void CompositeFilterTest::DoFlush() {
|
| + ExpectSuccess(FLUSH);
|
| +}
|
| +
|
| +void CompositeFilterTest::DoStop() {
|
| + ExpectSuccess(STOP);
|
| +}
|
| +
|
| +void CompositeFilterTest::DoSeek(base::TimeDelta time) {
|
| + ExpectSuccess(SEEK, time);
|
| +}
|
| +
|
| +void CompositeFilterTest::ExpectInvalidStateFail(MethodToCall method_to_call,
|
| + base::TimeDelta seek_time) {
|
| + InSequence seq;
|
| + scoped_ptr<StrictMock<MockFilterCallback> > mock_callback(
|
| + new StrictMock<MockFilterCallback>(false));
|
| +
|
| + EXPECT_CALL(*mock_filter_host_, SetError(PIPELINE_ERROR_INVALID_STATE))
|
| + .WillOnce(Return());
|
| + EXPECT_CALL(*mock_callback, OnFilterCallback());
|
| +
|
| + DoFilterCall(method_to_call, composite_, seek_time,
|
| + mock_callback->NewCallback());
|
| +
|
| + // Make sure that neither of the filters were called by
|
| + // verifying that the callback pointers weren't set.
|
| + EXPECT_EQ((FilterCallback*)NULL, filter_1_callback_);
|
| + EXPECT_EQ((FilterCallback*)NULL, filter_2_callback_);
|
| +}
|
| +
|
| +void CompositeFilterTest::RunFilter1Callback() {
|
| + EXPECT_TRUE(filter_1_callback_ != NULL);
|
| + FilterCallback* callback = filter_1_callback_;
|
| + filter_1_callback_ = NULL;
|
| + callback->Run();
|
| + delete callback;
|
| +}
|
| +
|
| +void CompositeFilterTest::RunFilter2Callback() {
|
| + EXPECT_TRUE(filter_2_callback_ != NULL);
|
| + FilterCallback* callback = filter_2_callback_;
|
| + filter_2_callback_ = NULL;
|
| + callback->Run();
|
| + delete callback;
|
| +}
|
| +
|
| +static base::Thread* NullThreadFactory(const char* thread_name) {
|
| + return NULL;
|
| +}
|
| +
|
| +// Test AddFilter() failure cases.
|
| +TEST_F(CompositeFilterTest, TestAddFilterFailCases) {
|
| + // Test adding a null pointer.
|
| + EXPECT_FALSE(composite_->AddFilter(NULL));
|
| +
|
| + scoped_refptr<StrictMock<MockFilter> > filter =
|
| + new StrictMock<MockFilter>(true);
|
| + EXPECT_EQ(NULL, filter->host());
|
| + EXPECT_EQ(NULL, filter->message_loop());
|
| +
|
| + // Test failing because set_host() hasn't been called yet.
|
| + EXPECT_FALSE(composite_->AddFilter(filter));
|
| +
|
| + // Test thread creation failure.
|
| + composite_ = new CompositeFilter(&message_loop_, &NullThreadFactory);
|
| + composite_->set_host(mock_filter_host_.get());
|
| + EXPECT_FALSE(composite_->AddFilter(filter));
|
| + EXPECT_EQ(NULL, filter->host());
|
| + EXPECT_EQ(NULL, filter->message_loop());
|
| +}
|
| +
|
| +// Test successful AddFilter() cases.
|
| +TEST_F(CompositeFilterTest, TestAddFilter) {
|
| + composite_->set_host(mock_filter_host_.get());
|
| +
|
| + // Add a filter that doesn't require a message loop.
|
| + scoped_refptr<StrictMock<MockFilter> > filter = new StrictMock<MockFilter>();
|
| + EXPECT_EQ(NULL, filter->host());
|
| + EXPECT_EQ(NULL, filter->message_loop());
|
| +
|
| + EXPECT_TRUE(composite_->AddFilter(filter));
|
| +
|
| + EXPECT_TRUE(filter->host() != NULL);
|
| + EXPECT_EQ(NULL, filter->message_loop());
|
| +
|
| + // Add a filter that requires a message loop.
|
| + scoped_refptr<StrictMock<MockFilter> > filter_2 =
|
| + new StrictMock<MockFilter>(true);
|
| +
|
| + EXPECT_EQ(NULL, filter_2->host());
|
| + EXPECT_EQ(NULL, filter_2->message_loop());
|
| +
|
| + EXPECT_TRUE(composite_->AddFilter(filter_2));
|
| +
|
| + EXPECT_TRUE(filter_2->host() != NULL);
|
| + EXPECT_TRUE(filter_2->message_loop() != NULL);
|
| +}
|
| +
|
| +TEST_F(CompositeFilterTest, TestPlay) {
|
| + InSequence sequence;
|
| +
|
| + SetupAndAdd2Filters();
|
| +
|
| + // Verify successful call to Play().
|
| + DoPlay();
|
| +
|
| + // At this point we are now in the kPlaying state.
|
| + scoped_ptr<StrictMock<MockFilterCallback> > mock_callback(
|
| + new StrictMock<MockFilterCallback>(false));
|
| +
|
| + // Try calling Play() again to make sure that we simply get a callback.
|
| + // We are already in the Play() state so there is no point calling the
|
| + // filters.
|
| + EXPECT_CALL(*mock_callback, OnFilterCallback());
|
| +
|
| + composite_->Play(mock_callback->NewCallback());
|
| +
|
| + // Verify that neither of the filter callbacks were set.
|
| + EXPECT_EQ((FilterCallback*)NULL, filter_1_callback_);
|
| + EXPECT_EQ((FilterCallback*)NULL, filter_2_callback_);
|
| +
|
| + // Stop playback.
|
| + DoStop();
|
| +
|
| + // At this point we should be in the kStopped state.
|
| +
|
| + // Try calling Stop() again to make sure neither filter is called.
|
| + EXPECT_CALL(*mock_callback, OnFilterCallback());
|
| +
|
| + composite_->Stop(mock_callback->NewCallback());
|
| +
|
| + // Verify that neither of the filter callbacks were set.
|
| + EXPECT_EQ((FilterCallback*)NULL, filter_1_callback_);
|
| + EXPECT_EQ((FilterCallback*)NULL, filter_2_callback_);
|
| +
|
| + // Try calling Play() again to make sure we get an error.
|
| + ExpectInvalidStateFail(PLAY);
|
| +}
|
| +
|
| +// Test errors in the middle of a serial call sequence like Play().
|
| +TEST_F(CompositeFilterTest, TestPlayErrors) {
|
| + InSequence sequence;
|
| +
|
| + SetupAndAdd2Filters();
|
| +
|
| + scoped_ptr<StrictMock<MockFilterCallback> > mock_callback(
|
| + new StrictMock<MockFilterCallback>(false));
|
| +
|
| + EXPECT_CALL(*filter_1_, Play(_));
|
| +
|
| + // Call Play() on the composite.
|
| + composite_->Play(mock_callback->NewCallback());
|
| +
|
| + EXPECT_CALL(*filter_2_, Play(_));
|
| +
|
| + // Run callback to indicate that |filter_1_|'s Play() has completed.
|
| + RunFilter1Callback();
|
| +
|
| + // At this point Play() has been called on |filter_2_|. Simulate an
|
| + // error by calling SetError() on its FilterHost interface.
|
| + filter_2_->host()->SetError(PIPELINE_ERROR_OUT_OF_MEMORY);
|
| +
|
| + // Expect error to be reported and "play done" callback to be called.
|
| + EXPECT_CALL(*mock_filter_host_, SetError(PIPELINE_ERROR_OUT_OF_MEMORY));
|
| + EXPECT_CALL(*mock_callback, OnFilterCallback());
|
| +
|
| + // Run callback to indicate that |filter_2_|'s Play() has completed.
|
| + RunFilter2Callback();
|
| +
|
| + // Verify that Play/Pause/Flush/Seek fail now that an error occured.
|
| + ExpectInvalidStateFail(PLAY);
|
| + ExpectInvalidStateFail(PAUSE);
|
| + ExpectInvalidStateFail(FLUSH);
|
| + ExpectInvalidStateFail(SEEK);
|
| +
|
| + // Make sure you can still Stop().
|
| + DoStop();
|
| +}
|
| +
|
| +TEST_F(CompositeFilterTest, TestPause) {
|
| + InSequence sequence;
|
| +
|
| + SetupAndAdd2Filters();
|
| +
|
| + scoped_ptr<StrictMock<MockFilterCallback> > mock_callback(
|
| + new StrictMock<MockFilterCallback>(false));
|
| +
|
| + // Try calling Pause() to make sure we get an error because we aren't in
|
| + // the playing state.
|
| + ExpectInvalidStateFail(PAUSE);
|
| +
|
| + // Transition to playing state.
|
| + DoPlay();
|
| +
|
| + // Issue a successful Pause().
|
| + DoPause();
|
| +
|
| + // At this point we are paused.
|
| +
|
| + // Try calling Pause() again to make sure that the filters aren't called
|
| + // because we are already in the paused state.
|
| + EXPECT_CALL(*mock_callback, OnFilterCallback());
|
| +
|
| + composite_->Pause(mock_callback->NewCallback());
|
| +
|
| + // Verify that neither of the filter callbacks were set.
|
| + EXPECT_EQ((FilterCallback*)NULL, filter_1_callback_);
|
| + EXPECT_EQ((FilterCallback*)NULL, filter_2_callback_);
|
| +
|
| + // Verify that we can transition pack to the play state.
|
| + DoPlay();
|
| +
|
| + // Go back to the pause state.
|
| + DoPause();
|
| +
|
| + // Transition to the stop state.
|
| + DoStop();
|
| +
|
| + // Try calling Pause() to make sure we get an error because we aren't in
|
| + // the playing state.
|
| + ExpectInvalidStateFail(PAUSE);
|
| +}
|
| +
|
| +// Test errors in the middle of a serial call sequence like Pause().
|
| +TEST_F(CompositeFilterTest, TestPauseErrors) {
|
| + InSequence sequence;
|
| +
|
| + SetupAndAdd2Filters();
|
| +
|
| + DoPlay();
|
| +
|
| + scoped_ptr<StrictMock<MockFilterCallback> > mock_callback(
|
| + new StrictMock<MockFilterCallback>(false));
|
| +
|
| + EXPECT_CALL(*filter_1_, Pause(_));
|
| +
|
| + // Call Pause() on the composite.
|
| + composite_->Pause(mock_callback->NewCallback());
|
| +
|
| + // Simulate an error by calling SetError() on |filter_1_|'s FilterHost
|
| + // interface.
|
| + filter_1_->host()->SetError(PIPELINE_ERROR_OUT_OF_MEMORY);
|
| +
|
| + // Expect error to be reported and "pause done" callback to be called.
|
| + EXPECT_CALL(*mock_filter_host_, SetError(PIPELINE_ERROR_OUT_OF_MEMORY));
|
| + EXPECT_CALL(*mock_callback, OnFilterCallback());
|
| +
|
| + RunFilter1Callback();
|
| +
|
| + // Make sure |filter_2_callback_| was not set.
|
| + EXPECT_EQ((FilterCallback*)NULL, filter_2_callback_);
|
| +
|
| + // Verify that Play/Pause/Flush/Seek fail now that an error occured.
|
| + ExpectInvalidStateFail(PLAY);
|
| + ExpectInvalidStateFail(PAUSE);
|
| + ExpectInvalidStateFail(FLUSH);
|
| + ExpectInvalidStateFail(SEEK);
|
| +
|
| + // Make sure you can still Stop().
|
| + DoStop();
|
| +}
|
| +
|
| +TEST_F(CompositeFilterTest, TestFlush) {
|
| + InSequence sequence;
|
| +
|
| + SetupAndAdd2Filters();
|
| +
|
| + scoped_ptr<StrictMock<MockFilterCallback> > mock_callback(
|
| + new StrictMock<MockFilterCallback>(false));
|
| +
|
| + // Make sure Flush() works before calling Play().
|
| + DoFlush();
|
| +
|
| + // Transition to playing state.
|
| + DoPlay();
|
| +
|
| + // Call Flush() to make sure we get an error because we are in
|
| + // the playing state.
|
| + ExpectInvalidStateFail(FLUSH);
|
| +
|
| + // Issue a successful Pause().
|
| + DoPause();
|
| +
|
| + // Make sure Flush() works after pausing.
|
| + DoFlush();
|
| +
|
| + // Verify that we can transition back to the play state.
|
| + DoPlay();
|
| +
|
| + // Transition to the stop state.
|
| + DoStop();
|
| +
|
| + // Try calling Flush() to make sure we get an error because we are stopped.
|
| + ExpectInvalidStateFail(FLUSH);
|
| +}
|
| +
|
| +// Test errors in the middle of a parallel call sequence like Flush().
|
| +TEST_F(CompositeFilterTest, TestFlushErrors) {
|
| + InSequence sequence;
|
| +
|
| + SetupAndAdd2Filters();
|
| +
|
| + scoped_ptr<StrictMock<MockFilterCallback> > mock_callback(
|
| + new StrictMock<MockFilterCallback>(false));
|
| +
|
| + EXPECT_CALL(*filter_1_, Flush(_));
|
| + EXPECT_CALL(*filter_2_, Flush(_));
|
| +
|
| + // Call Flush() on the composite.
|
| + composite_->Flush(mock_callback->NewCallback());
|
| +
|
| + // Simulate an error by calling SetError() on |filter_1_|'s FilterHost
|
| + // interface.
|
| + filter_1_->host()->SetError(PIPELINE_ERROR_OUT_OF_MEMORY);
|
| +
|
| + RunFilter1Callback();
|
| +
|
| + // Expect error to be reported and "pause done" callback to be called.
|
| + EXPECT_CALL(*mock_filter_host_, SetError(PIPELINE_ERROR_OUT_OF_MEMORY));
|
| + EXPECT_CALL(*mock_callback, OnFilterCallback());
|
| +
|
| + RunFilter2Callback();
|
| +
|
| + // Verify that Play/Pause/Flush/Seek fail now that an error occured.
|
| + ExpectInvalidStateFail(PLAY);
|
| + ExpectInvalidStateFail(PAUSE);
|
| + ExpectInvalidStateFail(FLUSH);
|
| + ExpectInvalidStateFail(SEEK);
|
| +
|
| + // Make sure you can still Stop().
|
| + DoStop();
|
| +}
|
| +
|
| +TEST_F(CompositeFilterTest, TestSeek) {
|
| + InSequence sequence;
|
| +
|
| + SetupAndAdd2Filters();
|
| +
|
| + // Verify that seek is allowed to be called before a Play() call.
|
| + DoSeek(base::TimeDelta::FromSeconds(5));
|
| +
|
| + // Verify we can issue a Play() after the Seek().
|
| + DoPlay();
|
| +
|
| + scoped_ptr<StrictMock<MockFilterCallback> > mock_callback(
|
| + new StrictMock<MockFilterCallback>(false));
|
| +
|
| + // Try calling Seek() while playing to make sure we get an error.
|
| + ExpectInvalidStateFail(SEEK);
|
| +
|
| + // Transition to paused state.
|
| + DoPause();
|
| +
|
| + // Verify that seek is allowed after pausing.
|
| + DoSeek(base::TimeDelta::FromSeconds(5));
|
| +
|
| + // Verify we can still play again.
|
| + DoPlay();
|
| +
|
| + // Stop playback.
|
| + DoStop();
|
| +
|
| + // Try calling Seek() to make sure we get an error.
|
| + ExpectInvalidStateFail(SEEK);
|
| +}
|
| +
|
| +TEST_F(CompositeFilterTest, TestStop) {
|
| + InSequence sequence;
|
| +
|
| + // Test Stop() before any other call.
|
| + SetupAndAdd2Filters();
|
| + DoStop();
|
| +
|
| + // Test error during Stop() sequence.
|
| + SetupAndAdd2Filters();
|
| + scoped_ptr<StrictMock<MockFilterCallback> > mock_callback(
|
| + new StrictMock<MockFilterCallback>(false));
|
| +
|
| + EXPECT_CALL(*filter_1_, Stop(_));
|
| +
|
| + composite_->Stop(mock_callback->NewCallback());
|
| +
|
| + // Have |filter_1_| signal an error.
|
| + filter_1_->host()->SetError(PIPELINE_ERROR_READ);
|
| +
|
| + EXPECT_CALL(*filter_2_, Stop(_));
|
| +
|
| + RunFilter1Callback();
|
| +
|
| + EXPECT_CALL(*mock_callback, OnFilterCallback());
|
| +
|
| + RunFilter2Callback();
|
| +}
|
| +
|
| +// Test stopping in the middle of a serial call sequence.
|
| +TEST_F(CompositeFilterTest, TestStopWhilePlayPending) {
|
| + InSequence sequence;
|
| +
|
| + SetupAndAdd2Filters();
|
| +
|
| + scoped_ptr<StrictMock<MockFilterCallback> > mock_callback(
|
| + new StrictMock<MockFilterCallback>());
|
| +
|
| + EXPECT_CALL(*filter_1_, Play(_));
|
| +
|
| + composite_->Play(mock_callback->NewCallback());
|
| +
|
| + // Note: Play() is pending on |filter_1_| right now.
|
| +
|
| + scoped_ptr<StrictMock<MockFilterCallback> > mock_callback_2(
|
| + new StrictMock<MockFilterCallback>(false));
|
| +
|
| + EXPECT_CALL(*mock_callback, OnCallbackDestroyed());
|
| +
|
| + composite_->Stop(mock_callback_2->NewCallback());
|
| +
|
| + EXPECT_CALL(*filter_1_, Stop(_));
|
| +
|
| + // Run |filter_1_|'s callback again to indicate Play() has completed.
|
| + RunFilter1Callback();
|
| +
|
| + EXPECT_CALL(*filter_2_, Stop(_));
|
| +
|
| + // Run |filter_1_|'s callback again to indicate Stop() has completed.
|
| + RunFilter1Callback();
|
| +
|
| + EXPECT_CALL(*mock_callback_2, OnFilterCallback());
|
| +
|
| + // Run |filter_2_|'s callback to indicate Stop() has completed.
|
| + RunFilter2Callback();
|
| +}
|
| +
|
| +// Test stopping in the middle of a parallel call sequence.
|
| +TEST_F(CompositeFilterTest, TestStopWhileFlushPending) {
|
| + InSequence sequence;
|
| +
|
| + SetupAndAdd2Filters();
|
| +
|
| + scoped_ptr<StrictMock<MockFilterCallback> > mock_callback(
|
| + new StrictMock<MockFilterCallback>());
|
| +
|
| + EXPECT_CALL(*filter_1_, Flush(_));
|
| + EXPECT_CALL(*filter_2_, Flush(_));
|
| +
|
| + composite_->Flush(mock_callback->NewCallback());
|
| +
|
| + // Note: |filter_1_| and |filter_2_| have pending Flush() calls at this point.
|
| +
|
| + scoped_ptr<StrictMock<MockFilterCallback> > mock_callback_2(
|
| + new StrictMock<MockFilterCallback>(false));
|
| +
|
| + EXPECT_CALL(*mock_callback, OnCallbackDestroyed());
|
| +
|
| + composite_->Stop(mock_callback_2->NewCallback());
|
| +
|
| + // Run callback to indicate that |filter_1_|'s Flush() has completed.
|
| + RunFilter1Callback();
|
| +
|
| + EXPECT_CALL(*filter_1_, Stop(_));
|
| +
|
| + // Run callback to indicate that |filter_2_|'s Flush() has completed.
|
| + RunFilter2Callback();
|
| +
|
| + EXPECT_CALL(*filter_2_, Stop(_));
|
| +
|
| + // Run callback to indicate that |filter_1_|'s Stop() has completed.
|
| + RunFilter1Callback();
|
| +
|
| + EXPECT_CALL(*mock_callback_2, OnFilterCallback());
|
| +
|
| + // Run callback to indicate that |filter_2_|'s Stop() has completed.
|
| + RunFilter2Callback();
|
| +}
|
| +
|
| +TEST_F(CompositeFilterTest, TestErrorWhilePlaying) {
|
| + InSequence sequence;
|
| +
|
| + SetupAndAdd2Filters();
|
| +
|
| + // Simulate an error on |filter_2_| while in kCreated state. This
|
| + // can happen if an error occurs during filter initialization.
|
| + EXPECT_CALL(*mock_filter_host_, SetError(PIPELINE_ERROR_OUT_OF_MEMORY));
|
| + filter_2_->host()->SetError(PIPELINE_ERROR_OUT_OF_MEMORY);
|
| +
|
| + DoPlay();
|
| +
|
| + // Simulate an error on |filter_2_| while playing.
|
| + EXPECT_CALL(*mock_filter_host_, SetError(PIPELINE_ERROR_OUT_OF_MEMORY));
|
| + filter_2_->host()->SetError(PIPELINE_ERROR_OUT_OF_MEMORY);
|
| +
|
| + DoPause();
|
| +
|
| + // Simulate an error on |filter_2_| while paused.
|
| + EXPECT_CALL(*mock_filter_host_, SetError(PIPELINE_ERROR_NETWORK));
|
| + filter_2_->host()->SetError(PIPELINE_ERROR_NETWORK);
|
| +
|
| + DoStop();
|
| +
|
| + // Verify that errors are not passed to |mock_filter_host_|
|
| + // after Stop() has been called.
|
| + filter_2_->host()->SetError(PIPELINE_ERROR_NETWORK);
|
| +}
|
| +
|
| +// Make sure that state transitions act as expected even
|
| +// if the composite doesn't contain any filters.
|
| +TEST_F(CompositeFilterTest, TestEmptyComposite) {
|
| + InSequence sequence;
|
| +
|
| + composite_->set_host(mock_filter_host_.get());
|
| +
|
| + scoped_ptr<StrictMock<MockFilterCallback> > mock_callback(
|
| + new StrictMock<MockFilterCallback>(false));
|
| +
|
| + // Issue a Play() and expect no errors.
|
| + EXPECT_CALL(*mock_callback, OnFilterCallback());
|
| + composite_->Play(mock_callback->NewCallback());
|
| +
|
| + // Issue a Pause() and expect no errors.
|
| + EXPECT_CALL(*mock_callback, OnFilterCallback());
|
| + composite_->Pause(mock_callback->NewCallback());
|
| +
|
| + // Issue a Flush() and expect no errors.
|
| + EXPECT_CALL(*mock_callback, OnFilterCallback());
|
| + composite_->Flush(mock_callback->NewCallback());
|
| +
|
| + // Issue a Seek() and expect no errors.
|
| + EXPECT_CALL(*mock_callback, OnFilterCallback());
|
| + composite_->Seek(base::TimeDelta::FromSeconds(5),
|
| + mock_callback->NewCallback());
|
| +
|
| + // Issue a Play() and expect no errors.
|
| + EXPECT_CALL(*mock_callback, OnFilterCallback());
|
| + composite_->Play(mock_callback->NewCallback());
|
| +
|
| + // Issue a Stop() and expect no errors.
|
| + EXPECT_CALL(*mock_callback, OnFilterCallback());
|
| + composite_->Stop(mock_callback->NewCallback());
|
| +}
|
| +
|
| +} // namespace media
|
|
|