Chromium Code Reviews| Index: media/base/pipeline_unittest.cc |
| diff --git a/media/base/pipeline_unittest.cc b/media/base/pipeline_unittest.cc |
| index bd00361c47959848dbf2c66e8ff21d59480b0ed5..27f0ecca3a3e56db2c0fcd20353c73fa371a854d 100644 |
| --- a/media/base/pipeline_unittest.cc |
| +++ b/media/base/pipeline_unittest.cc |
| @@ -19,6 +19,7 @@ |
| using ::testing::_; |
| using ::testing::DeleteArg; |
| using ::testing::DoAll; |
| +// TODO(scherkus): Remove InSequence after refactoring Pipeline. |
| using ::testing::InSequence; |
| using ::testing::Invoke; |
| using ::testing::InvokeWithoutArgs; |
| @@ -41,6 +42,14 @@ ACTION_P(SetDemuxerProperties, duration) { |
| arg0->SetDuration(duration); |
| } |
| +ACTION_P2(Stop, pipeline, stop_cb) { |
| + pipeline->Stop(stop_cb); |
| +} |
| + |
| +ACTION_P2(SetError, pipeline, status) { |
| + pipeline->SetErrorForTesting(status); |
| +} |
| + |
| ACTION(RunPipelineStatusCB1) { |
|
Ami GONE FROM CHROMIUM
2012/08/08 23:43:55
s/1//
scherkus (not reviewing)
2012/08/09 01:18:19
I swore we had other versions around but I guess I
|
| arg1.Run(PIPELINE_OK); |
| } |
| @@ -98,6 +107,8 @@ class PipelineTest : public ::testing::Test { |
| EXPECT_CALL(*mocks_->demuxer(), Stop(_)) |
| .WillOnce(RunClosure()); |
| + // TODO(scherkus): Don't pause+flush on shutdown, |
| + // see http://crbug.com/110228 |
| if (audio_stream_) { |
| EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) |
| .WillOnce(RunClosure()); |
| @@ -283,6 +294,124 @@ class PipelineTest : public ::testing::Test { |
| EXPECT_EQ(seek_time, pipeline_->GetMediaTime()); |
| } |
| + // Initializes a pipeline containing a single audio stream. |
| + void InitializeAudioPipeline() { |
| + CreateAudioStream(); |
| + MockDemuxerStreamVector streams; |
| + streams.push_back(audio_stream()); |
| + |
| + InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(3000)); |
| + InitializeAudioDecoder(audio_stream()); |
| + InitializeAudioRenderer(); |
| + InitializePipeline(PIPELINE_OK); |
| + } |
| + |
| + // TODO(scherkus): Why separate stop/error enums and helper functions? We do |
| + // radically different things whether teardown is invoked via stop vs error. |
| + // The teardown path should be the same, see http://crbug.com/110228 |
| + |
| + enum StopOnSeekState { |
|
Ami GONE FROM CHROMIUM
2012/08/08 23:43:55
I read your TODO above, but AFAICT these are only
scherkus (not reviewing)
2012/08/09 01:18:19
Took a stab but I strongly dislike how gtest param
Ami GONE FROM CHROMIUM
2012/08/09 04:41:43
Yeah, I didn't mean TEST_P necessarily.
|
| + kStopOnPause, |
| + kStopOnFlush, |
| + kStopOnSeek, |
| + }; |
| + |
| + enum ErrorOnSeekState { |
|
Ami GONE FROM CHROMIUM
2012/08/08 23:43:55
Ditto.
|
| + kErrorOnPause, |
| + kErrorOnFlush, |
| + kErrorOnSeek, |
| + }; |
| + |
| + void ExpectAudioPipelineSeekStop(StopOnSeekState action) { |
| + base::Closure stop_cb = base::Bind( |
| + &CallbackHelper::OnStop, base::Unretained(&callbacks_)); |
| + |
| + if (action == kStopOnPause) { |
| + EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) |
| + .WillOnce(DoAll(Stop(pipeline_, stop_cb), RunClosure())); |
| + } else { |
| + EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)).WillOnce(RunClosure()); |
| + } |
| + |
| + if (action == kStopOnFlush) { |
| + EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) |
| + .WillOnce(DoAll(Stop(pipeline_, stop_cb), RunClosure())); |
| + } else { |
| + EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)).WillOnce(RunClosure()); |
| + } |
| + |
| + if (action == kStopOnSeek) { |
| + EXPECT_CALL(*mocks_->demuxer(), Seek(_, _)) |
| + .WillOnce(DoAll(Stop(pipeline_, stop_cb), |
| + RunPipelineStatusCB1WithStatus(PIPELINE_OK))); |
|
Ami GONE FROM CHROMIUM
2012/08/08 23:43:55
Isn't this just RunPipelineStatusCB1()?
scherkus (not reviewing)
2012/08/09 01:18:19
Done.
|
| + } else { |
| + EXPECT_CALL(*mocks_->demuxer(), Seek(_, _)) |
| + .WillOnce(RunPipelineStatusCB1()); |
| + } |
| + |
| + EXPECT_CALL(*mocks_->audio_renderer(), Preroll(_, _)) |
| + .WillOnce(RunPipelineStatusCB1()); |
| + EXPECT_CALL(*mocks_->audio_renderer(), Play(_)).WillOnce(RunClosure()); |
| + EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK)); |
| + } |
| + |
| + void ExpectAudioPipelineSeekError(ErrorOnSeekState action) { |
| + if (action == kErrorOnPause) { |
| + EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) |
| + .WillOnce(DoAll(SetError(pipeline_, PIPELINE_ERROR_READ), |
| + RunClosure())); |
| + EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)); |
| + return; |
| + } |
| + |
| + EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)).WillOnce(RunClosure()); |
| + |
| + if (action == kErrorOnFlush) { |
| + EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) |
| + .WillOnce(DoAll(SetError(pipeline_, PIPELINE_ERROR_READ), |
| + RunClosure())); |
| + EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)); |
| + return; |
| + } |
| + |
| + EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)).WillOnce(RunClosure()); |
| + |
| + if (action == kErrorOnSeek) { |
| + EXPECT_CALL(*mocks_->demuxer(), Seek(_, _)) |
| + .WillOnce(RunPipelineStatusCB1WithStatus(PIPELINE_ERROR_READ)); |
| + EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)); |
| + return; |
| + } |
| + |
| + NOTREACHED(); |
| + } |
| + |
| + void ExpectAudioPipelineStop() { |
| + // TODO(scherkus): Don't pause+flush, see http://crbug.com/110228 |
| + EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)).WillOnce(RunClosure()); |
| + EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)).WillOnce(RunClosure()); |
| + EXPECT_CALL(*mocks_->demuxer(), Stop(_)).WillOnce(RunClosure()); |
| + EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)).WillOnce(RunClosure()); |
| + EXPECT_CALL(callbacks_, OnStop()); |
| + } |
| + |
| + void ExpectAudioPipelineError() { |
| + EXPECT_CALL(*mocks_->demuxer(), Stop(_)).WillOnce(RunClosure()); |
| + EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)).WillOnce(RunClosure()); |
| + } |
| + |
| + void DoAudioPipelineSeek() { |
| + pipeline_->Seek(base::TimeDelta::FromSeconds(10), base::Bind( |
| + &CallbackHelper::OnSeek, base::Unretained(&callbacks_))); |
| + message_loop_.RunAllPending(); |
| + } |
| + |
| + void DoAudioPipelineStop() { |
| + pipeline_->Stop(base::Bind( |
| + &CallbackHelper::OnStop, base::Unretained(&callbacks_))); |
| + message_loop_.RunAllPending(); |
| + } |
| + |
| // Fixture members. |
| StrictMock<CallbackHelper> callbacks_; |
| MessageLoop message_loop_; |
| @@ -464,6 +593,140 @@ TEST_F(PipelineTest, Seek) { |
| DoSeek(expected); |
| } |
| +TEST_F(PipelineTest, Stop_DuringStart) { |
| + base::Closure stop_cb = base::Bind( |
| + &CallbackHelper::OnStop, base::Unretained(&callbacks_)); |
| + |
| + EXPECT_CALL(*mocks_->demuxer(), Initialize(_, _)) |
| + .WillOnce(DoAll(Stop(pipeline_, stop_cb), RunPipelineStatusCB1())); |
| + |
| + // Stop sequence. |
| + EXPECT_CALL(*mocks_->demuxer(), Stop(_)) |
| + .WillOnce(RunClosure()); |
| + EXPECT_CALL(callbacks_, OnStop()); |
| + |
| + InitializePipeline(PIPELINE_OK); |
| +} |
| + |
| +TEST_F(PipelineTest, Stop_DuringPause) { |
| + InitializeAudioPipeline(); |
| + |
| + InSequence s; |
| + ExpectAudioPipelineSeekStop(kStopOnPause); |
| + ExpectAudioPipelineStop(); |
| + |
| + DoAudioPipelineSeek(); |
| +} |
| + |
| +TEST_F(PipelineTest, Stop_DuringFlush) { |
| + InitializeAudioPipeline(); |
| + |
| + InSequence s; |
| + ExpectAudioPipelineSeekStop(kStopOnFlush); |
| + ExpectAudioPipelineStop(); |
| + |
| + DoAudioPipelineSeek(); |
| +} |
| + |
| +TEST_F(PipelineTest, Stop_DuringSeek) { |
| + InitializeAudioPipeline(); |
| + |
| + InSequence s; |
| + ExpectAudioPipelineSeekStop(kStopOnSeek); |
| + ExpectAudioPipelineStop(); |
| + |
| + DoAudioPipelineSeek(); |
| +} |
| + |
| +TEST_F(PipelineTest, Stop_DuringPlayback) { |
| + InitializeAudioPipeline(); |
| + |
| + InSequence s; |
| + ExpectAudioPipelineStop(); |
| + |
| + DoAudioPipelineStop(); |
| +} |
| + |
| +TEST_F(PipelineTest, Error_DuringStart) { |
| + EXPECT_CALL(*mocks_->demuxer(), Initialize(_, _)) |
| + .WillOnce(RunPipelineStatusCB1WithStatus(PIPELINE_ERROR_READ)); |
| + |
| + // Stop sequence. |
| + EXPECT_CALL(*mocks_->demuxer(), Stop(_)) |
| + .WillOnce(RunClosure()); |
| + |
| + // Start callback should fire with error but nothing else. |
| + InitializePipeline(PIPELINE_ERROR_READ); |
| +} |
| + |
| +TEST_F(PipelineTest, Error_DuringPause) { |
| + InitializeAudioPipeline(); |
| + |
| + InSequence s; |
| + ExpectAudioPipelineSeekError(kErrorOnPause); |
| + ExpectAudioPipelineError(); |
| + |
| + DoAudioPipelineSeek(); |
| +} |
| + |
| +TEST_F(PipelineTest, Error_DuringFlush) { |
| + InitializeAudioPipeline(); |
| + |
| + InSequence s; |
| + ExpectAudioPipelineSeekError(kErrorOnFlush); |
| + ExpectAudioPipelineError(); |
| + |
| + DoAudioPipelineSeek(); |
| +} |
| + |
| +TEST_F(PipelineTest, Error_DuringSeek) { |
| + InitializeAudioPipeline(); |
| + |
| + InSequence s; |
| + ExpectAudioPipelineSeekError(kErrorOnSeek); |
| + ExpectAudioPipelineError(); |
| + |
| + DoAudioPipelineSeek(); |
| +} |
| + |
| +TEST_F(PipelineTest, Error_DuringPlayback) { |
| + InitializeAudioPipeline(); |
| + |
| + InSequence s; |
| + |
| + // Curiously enough, errors during playback invokes the pause+flush shutdown |
| + // path and not the error path. |
| + // |
| + // TODO(scherkus): Don't pause+flush, see http://crbug.com/110228 |
| + EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)).WillOnce(RunClosure()); |
| + EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)).WillOnce(RunClosure()); |
| + EXPECT_CALL(*mocks_->demuxer(), Stop(_)).WillOnce(RunClosure()); |
| + EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)).WillOnce(RunClosure()); |
| + |
| + EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ)); |
| + |
| + pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ); |
| + message_loop_.RunAllPending(); |
| +} |
| + |
| +TEST_F(PipelineTest, Error_DuringStop) { |
| + InitializeAudioPipeline(); |
| + |
| + InSequence s; |
| + |
| + // TODO(scherkus): Don't pause+flush on shutdown, see http://crbug.com/110228 |
| + EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)).WillOnce(RunClosure()); |
| + EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)).WillOnce(RunClosure()); |
| + EXPECT_CALL(*mocks_->demuxer(), Stop(_)) |
| + .WillOnce(DoAll(SetError(pipeline_, PIPELINE_ERROR_READ), RunClosure())); |
| + EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)).WillOnce(RunClosure()); |
| + |
| + // No error callback should fire. |
| + EXPECT_CALL(callbacks_, OnStop()); |
| + |
| + DoAudioPipelineStop(); |
| +} |
| + |
| TEST_F(PipelineTest, SetVolume) { |
| CreateAudioStream(); |
| MockDemuxerStreamVector streams; |