Add integration browser tests for settings hardening.
[chromium-blink-merge.git] / media / base / pipeline_unittest.cc
blob412fd88bafd836fd51371eaefdf3922d42126ad3
1 // Copyright (c) 2012 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.
5 #include <vector>
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/stl_util.h"
10 #include "base/test/simple_test_tick_clock.h"
11 #include "base/threading/simple_thread.h"
12 #include "base/time/clock.h"
13 #include "media/base/fake_text_track_stream.h"
14 #include "media/base/gmock_callback_support.h"
15 #include "media/base/media_log.h"
16 #include "media/base/mock_filters.h"
17 #include "media/base/pipeline.h"
18 #include "media/base/test_helpers.h"
19 #include "media/base/text_renderer.h"
20 #include "media/base/text_track_config.h"
21 #include "media/base/time_delta_interpolator.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "ui/gfx/size.h"
25 using ::testing::_;
26 using ::testing::AnyNumber;
27 using ::testing::DeleteArg;
28 using ::testing::DoAll;
29 // TODO(scherkus): Remove InSequence after refactoring Pipeline.
30 using ::testing::InSequence;
31 using ::testing::Invoke;
32 using ::testing::InvokeWithoutArgs;
33 using ::testing::Mock;
34 using ::testing::NotNull;
35 using ::testing::Return;
36 using ::testing::SaveArg;
37 using ::testing::StrictMock;
38 using ::testing::WithArg;
40 namespace media {
42 ACTION_P(SetDemuxerProperties, duration) {
43 arg0->SetDuration(duration);
46 ACTION_P2(Stop, pipeline, stop_cb) {
47 pipeline->Stop(stop_cb);
50 ACTION_P2(SetError, pipeline, status) {
51 pipeline->SetErrorForTesting(status);
54 ACTION_P2(SetBufferingState, cb, buffering_state) {
55 cb->Run(buffering_state);
58 // Used for setting expectations on pipeline callbacks. Using a StrictMock
59 // also lets us test for missing callbacks.
60 class CallbackHelper {
61 public:
62 CallbackHelper() {}
63 virtual ~CallbackHelper() {}
65 MOCK_METHOD1(OnStart, void(PipelineStatus));
66 MOCK_METHOD1(OnSeek, void(PipelineStatus));
67 MOCK_METHOD0(OnStop, void());
68 MOCK_METHOD0(OnEnded, void());
69 MOCK_METHOD1(OnError, void(PipelineStatus));
70 MOCK_METHOD1(OnMetadata, void(PipelineMetadata));
71 MOCK_METHOD1(OnBufferingStateChange, void(BufferingState));
72 MOCK_METHOD0(OnDurationChange, void());
74 private:
75 DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
78 // TODO(scherkus): even though some filters are initialized on separate
79 // threads these test aren't flaky... why? It's because filters' Initialize()
80 // is executed on |message_loop_| and the mock filters instantly call
81 // InitializationComplete(), which keeps the pipeline humming along. If
82 // either filters don't call InitializationComplete() immediately or filter
83 // initialization is moved to a separate thread this test will become flaky.
84 class PipelineTest : public ::testing::Test {
85 public:
86 PipelineTest()
87 : pipeline_(new Pipeline(message_loop_.message_loop_proxy(),
88 new MediaLog())),
89 filter_collection_(new FilterCollection()),
90 demuxer_(new StrictMock<MockDemuxer>()) {
91 filter_collection_->SetDemuxer(demuxer_.get());
93 video_renderer_ = new StrictMock<MockVideoRenderer>();
94 scoped_ptr<VideoRenderer> video_renderer(video_renderer_);
95 filter_collection_->SetVideoRenderer(video_renderer.Pass());
97 audio_renderer_ = new StrictMock<MockAudioRenderer>();
98 scoped_ptr<AudioRenderer> audio_renderer(audio_renderer_);
99 filter_collection_->SetAudioRenderer(audio_renderer.Pass());
101 text_renderer_ = new TextRenderer(
102 message_loop_.message_loop_proxy(),
103 base::Bind(&PipelineTest::OnAddTextTrack,
104 base::Unretained(this)));
105 scoped_ptr<TextRenderer> text_renderer(text_renderer_);
106 filter_collection_->SetTextRenderer(text_renderer.Pass());
108 // SetDemuxerExpectations() adds overriding expectations for expected
109 // non-NULL streams.
110 DemuxerStream* null_pointer = NULL;
111 EXPECT_CALL(*demuxer_, GetStream(_))
112 .WillRepeatedly(Return(null_pointer));
114 EXPECT_CALL(*demuxer_, GetTimelineOffset())
115 .WillRepeatedly(Return(base::Time()));
117 EXPECT_CALL(*demuxer_, GetLiveness())
118 .WillRepeatedly(Return(Demuxer::LIVENESS_UNKNOWN));
121 virtual ~PipelineTest() {
122 if (!pipeline_ || !pipeline_->IsRunning())
123 return;
125 ExpectDemuxerStop();
127 // The mock demuxer doesn't stop the fake text track stream,
128 // so just stop it manually.
129 if (text_stream_) {
130 text_stream_->Stop();
131 message_loop_.RunUntilIdle();
134 // Expect a stop callback if we were started.
135 ExpectPipelineStopAndDestroyPipeline();
136 pipeline_->Stop(base::Bind(&CallbackHelper::OnStop,
137 base::Unretained(&callbacks_)));
138 message_loop_.RunUntilIdle();
141 void OnDemuxerError() {
142 // Cast because OnDemuxerError is private in Pipeline.
143 static_cast<DemuxerHost*>(pipeline_.get())
144 ->OnDemuxerError(PIPELINE_ERROR_ABORT);
147 protected:
148 // Sets up expectations to allow the demuxer to initialize.
149 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector;
150 void SetDemuxerExpectations(MockDemuxerStreamVector* streams,
151 const base::TimeDelta& duration) {
152 EXPECT_CALL(callbacks_, OnDurationChange());
153 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
154 .WillOnce(DoAll(SetDemuxerProperties(duration),
155 RunCallback<1>(PIPELINE_OK)));
157 // Configure the demuxer to return the streams.
158 for (size_t i = 0; i < streams->size(); ++i) {
159 DemuxerStream* stream = (*streams)[i];
160 EXPECT_CALL(*demuxer_, GetStream(stream->type()))
161 .WillRepeatedly(Return(stream));
165 void SetDemuxerExpectations(MockDemuxerStreamVector* streams) {
166 // Initialize with a default non-zero duration.
167 SetDemuxerExpectations(streams, base::TimeDelta::FromSeconds(10));
170 scoped_ptr<StrictMock<MockDemuxerStream> > CreateStream(
171 DemuxerStream::Type type) {
172 scoped_ptr<StrictMock<MockDemuxerStream> > stream(
173 new StrictMock<MockDemuxerStream>(type));
174 return stream.Pass();
177 // Sets up expectations to allow the video renderer to initialize.
178 void SetVideoRendererExpectations(DemuxerStream* stream) {
179 EXPECT_CALL(*video_renderer_, Initialize(stream, _, _, _, _, _, _, _, _, _))
180 .WillOnce(DoAll(SaveArg<5>(&video_buffering_state_cb_),
181 SaveArg<6>(&video_ended_cb_),
182 RunCallback<2>(PIPELINE_OK)));
185 // Sets up expectations to allow the audio renderer to initialize.
186 void SetAudioRendererExpectations(DemuxerStream* stream) {
187 EXPECT_CALL(*audio_renderer_, Initialize(stream, _, _, _, _, _, _))
188 .WillOnce(DoAll(SaveArg<3>(&audio_time_cb_),
189 SaveArg<4>(&audio_buffering_state_cb_),
190 SaveArg<5>(&audio_ended_cb_),
191 RunCallback<1>(PIPELINE_OK)));
194 void AddTextStream() {
195 EXPECT_CALL(*this, OnAddTextTrack(_,_))
196 .WillOnce(Invoke(this, &PipelineTest::DoOnAddTextTrack));
197 static_cast<DemuxerHost*>(pipeline_.get())->AddTextStream(text_stream(),
198 TextTrackConfig(kTextSubtitles, "", "", ""));
201 // Sets up expectations on the callback and initializes the pipeline. Called
202 // after tests have set expectations any filters they wish to use.
203 void StartPipeline(PipelineStatus start_status) {
204 EXPECT_CALL(callbacks_, OnStart(start_status));
206 if (start_status == PIPELINE_OK) {
207 EXPECT_CALL(callbacks_, OnMetadata(_)).WillOnce(SaveArg<0>(&metadata_));
209 if (audio_stream_) {
210 EXPECT_CALL(*audio_renderer_, GetTimeSource())
211 .WillOnce(Return(&time_source_));
212 EXPECT_CALL(time_source_, SetPlaybackRate(0.0f));
213 EXPECT_CALL(time_source_, SetMediaTime(base::TimeDelta()));
214 EXPECT_CALL(time_source_, StartTicking());
215 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
216 EXPECT_CALL(*audio_renderer_, StartPlaying())
217 .WillOnce(SetBufferingState(&audio_buffering_state_cb_,
218 BUFFERING_HAVE_ENOUGH));
221 if (video_stream_) {
222 EXPECT_CALL(*video_renderer_, StartPlaying())
223 .WillOnce(SetBufferingState(&video_buffering_state_cb_,
224 BUFFERING_HAVE_ENOUGH));
227 EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
230 pipeline_->Start(
231 filter_collection_.Pass(),
232 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
233 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
234 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
235 base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
236 base::Bind(&CallbackHelper::OnBufferingStateChange,
237 base::Unretained(&callbacks_)),
238 base::Bind(&CallbackHelper::OnDurationChange,
239 base::Unretained(&callbacks_)));
240 message_loop_.RunUntilIdle();
243 void CreateAudioStream() {
244 audio_stream_ = CreateStream(DemuxerStream::AUDIO);
247 void CreateVideoStream() {
248 video_stream_ = CreateStream(DemuxerStream::VIDEO);
249 video_stream_->set_video_decoder_config(video_decoder_config_);
252 void CreateTextStream() {
253 scoped_ptr<FakeTextTrackStream> text_stream(new FakeTextTrackStream());
254 EXPECT_CALL(*text_stream, OnRead()).Times(AnyNumber());
255 text_stream_ = text_stream.Pass();
258 MockDemuxerStream* audio_stream() {
259 return audio_stream_.get();
262 MockDemuxerStream* video_stream() {
263 return video_stream_.get();
266 FakeTextTrackStream* text_stream() {
267 return text_stream_.get();
270 void ExpectSeek(const base::TimeDelta& seek_time, bool underflowed) {
271 // Every filter should receive a call to Seek().
272 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
273 .WillOnce(RunCallback<1>(PIPELINE_OK));
275 if (audio_stream_) {
276 if (!underflowed)
277 EXPECT_CALL(time_source_, StopTicking());
278 EXPECT_CALL(*audio_renderer_, Flush(_))
279 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
280 BUFFERING_HAVE_NOTHING),
281 RunClosure<0>()));
282 EXPECT_CALL(time_source_, SetMediaTime(seek_time));
283 EXPECT_CALL(time_source_, SetPlaybackRate(_));
284 EXPECT_CALL(time_source_, StartTicking());
285 EXPECT_CALL(*audio_renderer_, StartPlaying())
286 .WillOnce(SetBufferingState(&audio_buffering_state_cb_,
287 BUFFERING_HAVE_ENOUGH));
288 EXPECT_CALL(*audio_renderer_, SetVolume(_));
291 if (video_stream_) {
292 EXPECT_CALL(*video_renderer_, Flush(_))
293 .WillOnce(DoAll(SetBufferingState(&video_buffering_state_cb_,
294 BUFFERING_HAVE_NOTHING),
295 RunClosure<0>()));
296 EXPECT_CALL(*video_renderer_, StartPlaying())
297 .WillOnce(SetBufferingState(&video_buffering_state_cb_,
298 BUFFERING_HAVE_ENOUGH));
301 // We expect a successful seek callback followed by a buffering update.
302 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
303 EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
306 void DoSeek(const base::TimeDelta& seek_time) {
307 pipeline_->Seek(seek_time,
308 base::Bind(&CallbackHelper::OnSeek,
309 base::Unretained(&callbacks_)));
311 // We expect the time to be updated only after the seek has completed.
312 EXPECT_NE(seek_time, pipeline_->GetMediaTime());
313 message_loop_.RunUntilIdle();
314 EXPECT_EQ(seek_time, pipeline_->GetMediaTime());
317 void DestroyPipeline() {
318 pipeline_.reset();
321 void ExpectDemuxerStop() {
322 if (demuxer_)
323 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
326 void ExpectPipelineStopAndDestroyPipeline() {
327 // After the Pipeline is stopped, it could be destroyed any time. Always
328 // destroy the pipeline immediately after OnStop() to test this.
329 EXPECT_CALL(callbacks_, OnStop())
330 .WillOnce(Invoke(this, &PipelineTest::DestroyPipeline));
333 MOCK_METHOD2(OnAddTextTrack, void(const TextTrackConfig&,
334 const AddTextTrackDoneCB&));
336 void DoOnAddTextTrack(const TextTrackConfig& config,
337 const AddTextTrackDoneCB& done_cb) {
338 scoped_ptr<TextTrack> text_track(new MockTextTrack);
339 done_cb.Run(text_track.Pass());
342 // Fixture members.
343 StrictMock<CallbackHelper> callbacks_;
344 base::SimpleTestTickClock test_tick_clock_;
345 base::MessageLoop message_loop_;
346 scoped_ptr<Pipeline> pipeline_;
348 scoped_ptr<FilterCollection> filter_collection_;
349 scoped_ptr<StrictMock<MockDemuxer> > demuxer_;
350 StrictMock<MockVideoRenderer>* video_renderer_;
351 StrictMock<MockAudioRenderer>* audio_renderer_;
352 StrictMock<MockTimeSource> time_source_;
353 StrictMock<CallbackHelper> text_renderer_callbacks_;
354 TextRenderer* text_renderer_;
355 scoped_ptr<StrictMock<MockDemuxerStream> > audio_stream_;
356 scoped_ptr<StrictMock<MockDemuxerStream> > video_stream_;
357 scoped_ptr<FakeTextTrackStream> text_stream_;
358 AudioRenderer::TimeCB audio_time_cb_;
359 BufferingStateCB audio_buffering_state_cb_;
360 BufferingStateCB video_buffering_state_cb_;
361 base::Closure audio_ended_cb_;
362 base::Closure video_ended_cb_;
363 VideoDecoderConfig video_decoder_config_;
364 PipelineMetadata metadata_;
366 private:
367 DISALLOW_COPY_AND_ASSIGN(PipelineTest);
370 // Test that playback controls methods no-op when the pipeline hasn't been
371 // started.
372 TEST_F(PipelineTest, NotStarted) {
373 const base::TimeDelta kZero;
375 EXPECT_FALSE(pipeline_->IsRunning());
377 // Setting should still work.
378 EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
379 pipeline_->SetPlaybackRate(-1.0f);
380 EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
381 pipeline_->SetPlaybackRate(1.0f);
382 EXPECT_EQ(1.0f, pipeline_->GetPlaybackRate());
384 // Setting should still work.
385 EXPECT_EQ(1.0f, pipeline_->GetVolume());
386 pipeline_->SetVolume(-1.0f);
387 EXPECT_EQ(1.0f, pipeline_->GetVolume());
388 pipeline_->SetVolume(0.0f);
389 EXPECT_EQ(0.0f, pipeline_->GetVolume());
391 EXPECT_TRUE(kZero == pipeline_->GetMediaTime());
392 EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
393 EXPECT_TRUE(kZero == pipeline_->GetMediaDuration());
396 TEST_F(PipelineTest, NeverInitializes) {
397 // Don't execute the callback passed into Initialize().
398 EXPECT_CALL(*demuxer_, Initialize(_, _, _));
400 // This test hangs during initialization by never calling
401 // InitializationComplete(). StrictMock<> will ensure that the callback is
402 // never executed.
403 pipeline_->Start(
404 filter_collection_.Pass(),
405 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
406 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
407 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
408 base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
409 base::Bind(&CallbackHelper::OnBufferingStateChange,
410 base::Unretained(&callbacks_)),
411 base::Bind(&CallbackHelper::OnDurationChange,
412 base::Unretained(&callbacks_)));
413 message_loop_.RunUntilIdle();
415 // Because our callback will get executed when the test tears down, we'll
416 // verify that nothing has been called, then set our expectation for the call
417 // made during tear down.
418 Mock::VerifyAndClear(&callbacks_);
419 EXPECT_CALL(callbacks_, OnStart(PIPELINE_OK));
422 TEST_F(PipelineTest, StopWithoutStart) {
423 ExpectPipelineStopAndDestroyPipeline();
424 pipeline_->Stop(
425 base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
426 message_loop_.RunUntilIdle();
429 TEST_F(PipelineTest, StartThenStopImmediately) {
430 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
431 .WillOnce(RunCallback<1>(PIPELINE_OK));
432 EXPECT_CALL(*demuxer_, Stop(_))
433 .WillOnce(RunClosure<0>());
435 EXPECT_CALL(callbacks_, OnStart(_));
437 pipeline_->Start(
438 filter_collection_.Pass(),
439 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
440 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
441 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
442 base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
443 base::Bind(&CallbackHelper::OnBufferingStateChange,
444 base::Unretained(&callbacks_)),
445 base::Bind(&CallbackHelper::OnDurationChange,
446 base::Unretained(&callbacks_)));
448 // Expect a stop callback if we were started.
449 ExpectPipelineStopAndDestroyPipeline();
450 pipeline_->Stop(
451 base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
452 message_loop_.RunUntilIdle();
455 TEST_F(PipelineTest, DemuxerErrorDuringStop) {
456 CreateAudioStream();
457 MockDemuxerStreamVector streams;
458 streams.push_back(audio_stream());
460 SetDemuxerExpectations(&streams);
461 SetAudioRendererExpectations(audio_stream());
463 StartPipeline(PIPELINE_OK);
465 EXPECT_CALL(*demuxer_, Stop(_))
466 .WillOnce(DoAll(InvokeWithoutArgs(this, &PipelineTest::OnDemuxerError),
467 RunClosure<0>()));
468 ExpectPipelineStopAndDestroyPipeline();
470 pipeline_->Stop(
471 base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
472 message_loop_.RunUntilIdle();
475 TEST_F(PipelineTest, URLNotFound) {
476 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
477 .WillOnce(RunCallback<1>(PIPELINE_ERROR_URL_NOT_FOUND));
478 EXPECT_CALL(*demuxer_, Stop(_))
479 .WillOnce(RunClosure<0>());
481 StartPipeline(PIPELINE_ERROR_URL_NOT_FOUND);
484 TEST_F(PipelineTest, NoStreams) {
485 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
486 .WillOnce(RunCallback<1>(PIPELINE_OK));
487 EXPECT_CALL(*demuxer_, Stop(_))
488 .WillOnce(RunClosure<0>());
490 StartPipeline(PIPELINE_ERROR_COULD_NOT_RENDER);
493 TEST_F(PipelineTest, AudioStream) {
494 CreateAudioStream();
495 MockDemuxerStreamVector streams;
496 streams.push_back(audio_stream());
498 SetDemuxerExpectations(&streams);
499 SetAudioRendererExpectations(audio_stream());
501 StartPipeline(PIPELINE_OK);
502 EXPECT_TRUE(metadata_.has_audio);
503 EXPECT_FALSE(metadata_.has_video);
506 TEST_F(PipelineTest, VideoStream) {
507 CreateVideoStream();
508 MockDemuxerStreamVector streams;
509 streams.push_back(video_stream());
511 SetDemuxerExpectations(&streams);
512 SetVideoRendererExpectations(video_stream());
514 StartPipeline(PIPELINE_OK);
515 EXPECT_FALSE(metadata_.has_audio);
516 EXPECT_TRUE(metadata_.has_video);
519 TEST_F(PipelineTest, AudioVideoStream) {
520 CreateAudioStream();
521 CreateVideoStream();
522 MockDemuxerStreamVector streams;
523 streams.push_back(audio_stream());
524 streams.push_back(video_stream());
526 SetDemuxerExpectations(&streams);
527 SetAudioRendererExpectations(audio_stream());
528 SetVideoRendererExpectations(video_stream());
530 StartPipeline(PIPELINE_OK);
531 EXPECT_TRUE(metadata_.has_audio);
532 EXPECT_TRUE(metadata_.has_video);
535 TEST_F(PipelineTest, VideoTextStream) {
536 CreateVideoStream();
537 CreateTextStream();
538 MockDemuxerStreamVector streams;
539 streams.push_back(video_stream());
541 SetDemuxerExpectations(&streams);
542 SetVideoRendererExpectations(video_stream());
544 StartPipeline(PIPELINE_OK);
545 EXPECT_FALSE(metadata_.has_audio);
546 EXPECT_TRUE(metadata_.has_video);
548 AddTextStream();
549 message_loop_.RunUntilIdle();
552 TEST_F(PipelineTest, VideoAudioTextStream) {
553 CreateVideoStream();
554 CreateAudioStream();
555 CreateTextStream();
556 MockDemuxerStreamVector streams;
557 streams.push_back(video_stream());
558 streams.push_back(audio_stream());
560 SetDemuxerExpectations(&streams);
561 SetVideoRendererExpectations(video_stream());
562 SetAudioRendererExpectations(audio_stream());
564 StartPipeline(PIPELINE_OK);
565 EXPECT_TRUE(metadata_.has_audio);
566 EXPECT_TRUE(metadata_.has_video);
568 AddTextStream();
569 message_loop_.RunUntilIdle();
572 TEST_F(PipelineTest, Seek) {
573 CreateAudioStream();
574 CreateVideoStream();
575 CreateTextStream();
576 MockDemuxerStreamVector streams;
577 streams.push_back(audio_stream());
578 streams.push_back(video_stream());
580 SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
581 SetAudioRendererExpectations(audio_stream());
582 SetVideoRendererExpectations(video_stream());
584 // Initialize then seek!
585 StartPipeline(PIPELINE_OK);
587 // Every filter should receive a call to Seek().
588 base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
589 ExpectSeek(expected, false);
590 DoSeek(expected);
593 TEST_F(PipelineTest, SeekAfterError) {
594 CreateAudioStream();
595 MockDemuxerStreamVector streams;
596 streams.push_back(audio_stream());
598 SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
599 SetAudioRendererExpectations(audio_stream());
601 // Initialize then seek!
602 StartPipeline(PIPELINE_OK);
604 EXPECT_CALL(*demuxer_, Stop(_))
605 .WillOnce(RunClosure<0>());
606 EXPECT_CALL(callbacks_, OnError(_));
608 static_cast<DemuxerHost*>(pipeline_.get())
609 ->OnDemuxerError(PIPELINE_ERROR_ABORT);
610 message_loop_.RunUntilIdle();
612 pipeline_->Seek(
613 base::TimeDelta::FromMilliseconds(100),
614 base::Bind(&CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
615 message_loop_.RunUntilIdle();
618 TEST_F(PipelineTest, SetVolume) {
619 CreateAudioStream();
620 MockDemuxerStreamVector streams;
621 streams.push_back(audio_stream());
623 SetDemuxerExpectations(&streams);
624 SetAudioRendererExpectations(audio_stream());
626 // The audio renderer should receive a call to SetVolume().
627 float expected = 0.5f;
628 EXPECT_CALL(*audio_renderer_, SetVolume(expected));
630 // Initialize then set volume!
631 StartPipeline(PIPELINE_OK);
632 pipeline_->SetVolume(expected);
635 TEST_F(PipelineTest, Properties) {
636 CreateVideoStream();
637 MockDemuxerStreamVector streams;
638 streams.push_back(video_stream());
640 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
641 SetDemuxerExpectations(&streams, kDuration);
642 SetVideoRendererExpectations(video_stream());
644 StartPipeline(PIPELINE_OK);
645 EXPECT_EQ(kDuration.ToInternalValue(),
646 pipeline_->GetMediaDuration().ToInternalValue());
647 EXPECT_FALSE(pipeline_->DidLoadingProgress());
650 TEST_F(PipelineTest, GetBufferedTimeRanges) {
651 CreateVideoStream();
652 MockDemuxerStreamVector streams;
653 streams.push_back(video_stream());
655 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
656 SetDemuxerExpectations(&streams, kDuration);
657 SetVideoRendererExpectations(video_stream());
659 StartPipeline(PIPELINE_OK);
661 EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
663 EXPECT_FALSE(pipeline_->DidLoadingProgress());
664 pipeline_->AddBufferedTimeRange(base::TimeDelta(), kDuration / 8);
665 EXPECT_TRUE(pipeline_->DidLoadingProgress());
666 EXPECT_FALSE(pipeline_->DidLoadingProgress());
667 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
668 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
669 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
671 base::TimeDelta kSeekTime = kDuration / 2;
672 ExpectSeek(kSeekTime, false);
673 DoSeek(kSeekTime);
675 EXPECT_FALSE(pipeline_->DidLoadingProgress());
678 TEST_F(PipelineTest, EndedCallback) {
679 CreateAudioStream();
680 CreateVideoStream();
681 CreateTextStream();
682 MockDemuxerStreamVector streams;
683 streams.push_back(audio_stream());
684 streams.push_back(video_stream());
686 SetDemuxerExpectations(&streams);
687 SetAudioRendererExpectations(audio_stream());
688 SetVideoRendererExpectations(video_stream());
689 StartPipeline(PIPELINE_OK);
691 AddTextStream();
693 // The ended callback shouldn't run until all renderers have ended.
694 audio_ended_cb_.Run();
695 message_loop_.RunUntilIdle();
697 video_ended_cb_.Run();
698 message_loop_.RunUntilIdle();
700 EXPECT_CALL(time_source_, StopTicking());
701 EXPECT_CALL(callbacks_, OnEnded());
702 text_stream()->SendEosNotification();
703 message_loop_.RunUntilIdle();
706 TEST_F(PipelineTest, AudioStreamShorterThanVideo) {
707 base::TimeDelta duration = base::TimeDelta::FromSeconds(10);
709 CreateAudioStream();
710 CreateVideoStream();
711 MockDemuxerStreamVector streams;
712 streams.push_back(audio_stream());
713 streams.push_back(video_stream());
715 // Replace what's used for interpolating to simulate wall clock time.
716 pipeline_->SetTimeDeltaInterpolatorForTesting(
717 new TimeDeltaInterpolator(&test_tick_clock_));
719 SetDemuxerExpectations(&streams, duration);
720 SetAudioRendererExpectations(audio_stream());
721 SetVideoRendererExpectations(video_stream());
722 StartPipeline(PIPELINE_OK);
724 EXPECT_EQ(0, pipeline_->GetMediaTime().ToInternalValue());
726 float playback_rate = 1.0f;
727 EXPECT_CALL(time_source_, SetPlaybackRate(playback_rate));
728 pipeline_->SetPlaybackRate(playback_rate);
729 message_loop_.RunUntilIdle();
731 InSequence s;
733 // Verify that the clock doesn't advance since it hasn't been started by
734 // a time update from the audio stream.
735 int64 start_time = pipeline_->GetMediaTime().ToInternalValue();
736 test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
737 EXPECT_EQ(pipeline_->GetMediaTime().ToInternalValue(), start_time);
739 // Signal end of audio stream.
740 audio_ended_cb_.Run();
741 message_loop_.RunUntilIdle();
743 // Verify that the clock advances.
744 start_time = pipeline_->GetMediaTime().ToInternalValue();
745 test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
746 EXPECT_GT(pipeline_->GetMediaTime().ToInternalValue(), start_time);
748 // Signal end of video stream and make sure OnEnded() callback occurs.
749 EXPECT_CALL(time_source_, StopTicking());
750 EXPECT_CALL(callbacks_, OnEnded());
751 video_ended_cb_.Run();
754 TEST_F(PipelineTest, ErrorDuringSeek) {
755 CreateAudioStream();
756 MockDemuxerStreamVector streams;
757 streams.push_back(audio_stream());
759 SetDemuxerExpectations(&streams);
760 SetAudioRendererExpectations(audio_stream());
761 StartPipeline(PIPELINE_OK);
763 float playback_rate = 1.0f;
764 EXPECT_CALL(time_source_, SetPlaybackRate(playback_rate));
765 pipeline_->SetPlaybackRate(playback_rate);
766 message_loop_.RunUntilIdle();
768 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
770 // Preroll() isn't called as the demuxer errors out first.
771 EXPECT_CALL(time_source_, StopTicking());
772 EXPECT_CALL(*audio_renderer_, Flush(_))
773 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
774 BUFFERING_HAVE_NOTHING),
775 RunClosure<0>()));
777 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
778 .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
779 EXPECT_CALL(*demuxer_, Stop(_))
780 .WillOnce(RunClosure<0>());
782 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
783 base::Unretained(&callbacks_)));
784 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
785 message_loop_.RunUntilIdle();
788 // Invoked function OnError. This asserts that the pipeline does not enqueue
789 // non-teardown related tasks while tearing down.
790 static void TestNoCallsAfterError(
791 Pipeline* pipeline, base::MessageLoop* message_loop,
792 PipelineStatus /* status */) {
793 CHECK(pipeline);
794 CHECK(message_loop);
796 // When we get to this stage, the message loop should be empty.
797 EXPECT_TRUE(message_loop->IsIdleForTesting());
799 // Make calls on pipeline after error has occurred.
800 pipeline->SetPlaybackRate(0.5f);
801 pipeline->SetVolume(0.5f);
803 // No additional tasks should be queued as a result of these calls.
804 EXPECT_TRUE(message_loop->IsIdleForTesting());
807 TEST_F(PipelineTest, NoMessageDuringTearDownFromError) {
808 CreateAudioStream();
809 MockDemuxerStreamVector streams;
810 streams.push_back(audio_stream());
812 SetDemuxerExpectations(&streams);
813 SetAudioRendererExpectations(audio_stream());
814 StartPipeline(PIPELINE_OK);
816 // Trigger additional requests on the pipeline during tear down from error.
817 base::Callback<void(PipelineStatus)> cb = base::Bind(
818 &TestNoCallsAfterError, pipeline_.get(), &message_loop_);
819 ON_CALL(callbacks_, OnError(_))
820 .WillByDefault(Invoke(&cb, &base::Callback<void(PipelineStatus)>::Run));
822 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
824 // Seek() isn't called as the demuxer errors out first.
825 EXPECT_CALL(time_source_, StopTicking());
826 EXPECT_CALL(*audio_renderer_, Flush(_))
827 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
828 BUFFERING_HAVE_NOTHING),
829 RunClosure<0>()));
831 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
832 .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
833 EXPECT_CALL(*demuxer_, Stop(_))
834 .WillOnce(RunClosure<0>());
836 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
837 base::Unretained(&callbacks_)));
838 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
839 message_loop_.RunUntilIdle();
842 static void RunTimeCB(const AudioRenderer::TimeCB& time_cb,
843 int time_in_ms,
844 int max_time_in_ms) {
845 time_cb.Run(base::TimeDelta::FromMilliseconds(time_in_ms),
846 base::TimeDelta::FromMilliseconds(max_time_in_ms));
849 TEST_F(PipelineTest, AudioTimeUpdateDuringSeek) {
850 CreateAudioStream();
851 MockDemuxerStreamVector streams;
852 streams.push_back(audio_stream());
854 SetDemuxerExpectations(&streams);
855 SetAudioRendererExpectations(audio_stream());
856 StartPipeline(PIPELINE_OK);
858 float playback_rate = 1.0f;
859 EXPECT_CALL(time_source_, SetPlaybackRate(playback_rate));
860 pipeline_->SetPlaybackRate(playback_rate);
861 message_loop_.RunUntilIdle();
863 // Provide an initial time update so that the pipeline transitions out of the
864 // "waiting for time update" state.
865 audio_time_cb_.Run(base::TimeDelta::FromMilliseconds(100),
866 base::TimeDelta::FromMilliseconds(500));
868 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
870 // Arrange to trigger a time update while the demuxer is in the middle of
871 // seeking. This update should be ignored by the pipeline and the clock should
872 // not get updated.
873 base::Closure closure = base::Bind(&RunTimeCB, audio_time_cb_, 300, 700);
874 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
875 .WillOnce(DoAll(InvokeWithoutArgs(&closure, &base::Closure::Run),
876 RunCallback<1>(PIPELINE_OK)));
878 EXPECT_CALL(time_source_, StopTicking());
879 EXPECT_CALL(*audio_renderer_, Flush(_))
880 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
881 BUFFERING_HAVE_NOTHING),
882 RunClosure<0>()));
883 EXPECT_CALL(time_source_, SetMediaTime(seek_time));
884 EXPECT_CALL(time_source_, SetPlaybackRate(_));
885 EXPECT_CALL(time_source_, StartTicking());
886 EXPECT_CALL(*audio_renderer_, StartPlaying())
887 .WillOnce(SetBufferingState(&audio_buffering_state_cb_,
888 BUFFERING_HAVE_ENOUGH));
889 EXPECT_CALL(*audio_renderer_, SetVolume(_));
891 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
892 EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
893 DoSeek(seek_time);
895 EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
897 // Now that the seek is complete, verify that time updates advance the current
898 // time.
899 base::TimeDelta new_time = seek_time + base::TimeDelta::FromMilliseconds(100);
900 audio_time_cb_.Run(new_time, new_time);
902 EXPECT_EQ(pipeline_->GetMediaTime(), new_time);
905 TEST_F(PipelineTest, DestroyAfterStop) {
906 CreateAudioStream();
907 MockDemuxerStreamVector streams;
908 streams.push_back(audio_stream());
909 SetDemuxerExpectations(&streams);
910 SetAudioRendererExpectations(audio_stream());
911 StartPipeline(PIPELINE_OK);
913 ExpectDemuxerStop();
915 ExpectPipelineStopAndDestroyPipeline();
916 pipeline_->Stop(
917 base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
918 message_loop_.RunUntilIdle();
921 TEST_F(PipelineTest, Underflow) {
922 CreateAudioStream();
923 CreateVideoStream();
924 MockDemuxerStreamVector streams;
925 streams.push_back(audio_stream());
926 streams.push_back(video_stream());
928 SetDemuxerExpectations(&streams);
929 SetAudioRendererExpectations(audio_stream());
930 SetVideoRendererExpectations(video_stream());
931 StartPipeline(PIPELINE_OK);
933 // Simulate underflow.
934 EXPECT_CALL(time_source_, StopTicking());
935 audio_buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
937 // Seek while underflowed. We shouldn't call StopTicking() again.
938 base::TimeDelta expected = base::TimeDelta::FromSeconds(5);
939 ExpectSeek(expected, true);
940 DoSeek(expected);
943 static void PostTimeCB(base::MessageLoop* message_loop,
944 const AudioRenderer::TimeCB& time_cb) {
945 base::TimeDelta new_time = base::TimeDelta::FromMilliseconds(100);
946 message_loop->PostTask(FROM_HERE, base::Bind(time_cb, new_time, new_time));
949 TEST_F(PipelineTest, TimeUpdateAfterStop) {
950 CreateAudioStream();
951 CreateVideoStream();
952 MockDemuxerStreamVector streams;
953 streams.push_back(audio_stream());
954 streams.push_back(video_stream());
956 SetDemuxerExpectations(&streams);
957 SetAudioRendererExpectations(audio_stream());
958 SetVideoRendererExpectations(video_stream());
959 StartPipeline(PIPELINE_OK);
961 // Double post here! This is a hack to simulate the case where TimeCB is
962 // posted during ~AudioRenderer(), which is triggered in Pipeline::DoStop.
963 // Since we can't EXPECT_CALL the dtor and Pipeline::DoStop() is posted
964 // as well, we need to post twice here.
965 message_loop_.PostTask(
966 FROM_HERE, base::Bind(&PostTimeCB, &message_loop_, audio_time_cb_));
968 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
970 ExpectPipelineStopAndDestroyPipeline();
971 pipeline_->Stop(
972 base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
973 message_loop_.RunUntilIdle();
976 class PipelineTeardownTest : public PipelineTest {
977 public:
978 enum TeardownState {
979 kInitDemuxer,
980 kInitAudioRenderer,
981 kInitVideoRenderer,
982 kFlushing,
983 kSeeking,
984 kPlaying,
987 enum StopOrError {
988 kStop,
989 kError,
990 kErrorAndStop,
993 PipelineTeardownTest() {}
994 virtual ~PipelineTeardownTest() {}
996 void RunTest(TeardownState state, StopOrError stop_or_error) {
997 switch (state) {
998 case kInitDemuxer:
999 case kInitAudioRenderer:
1000 case kInitVideoRenderer:
1001 DoInitialize(state, stop_or_error);
1002 break;
1004 case kFlushing:
1005 case kSeeking:
1006 DoInitialize(state, stop_or_error);
1007 DoSeek(state, stop_or_error);
1008 break;
1010 case kPlaying:
1011 DoInitialize(state, stop_or_error);
1012 DoStopOrError(stop_or_error);
1013 break;
1017 private:
1018 // TODO(scherkus): We do radically different things whether teardown is
1019 // invoked via stop vs error. The teardown path should be the same,
1020 // see http://crbug.com/110228
1021 void DoInitialize(TeardownState state, StopOrError stop_or_error) {
1022 PipelineStatus expected_status =
1023 SetInitializeExpectations(state, stop_or_error);
1025 EXPECT_CALL(callbacks_, OnStart(expected_status));
1026 pipeline_->Start(
1027 filter_collection_.Pass(),
1028 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
1029 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
1030 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
1031 base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
1032 base::Bind(&CallbackHelper::OnBufferingStateChange,
1033 base::Unretained(&callbacks_)),
1034 base::Bind(&CallbackHelper::OnDurationChange,
1035 base::Unretained(&callbacks_)));
1036 message_loop_.RunUntilIdle();
1039 PipelineStatus SetInitializeExpectations(TeardownState state,
1040 StopOrError stop_or_error) {
1041 PipelineStatus status = PIPELINE_OK;
1042 base::Closure stop_cb = base::Bind(
1043 &CallbackHelper::OnStop, base::Unretained(&callbacks_));
1045 if (state == kInitDemuxer) {
1046 if (stop_or_error == kStop) {
1047 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
1048 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1049 RunCallback<1>(PIPELINE_OK)));
1050 ExpectPipelineStopAndDestroyPipeline();
1051 } else {
1052 status = DEMUXER_ERROR_COULD_NOT_OPEN;
1053 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
1054 .WillOnce(RunCallback<1>(status));
1057 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1058 return status;
1061 CreateAudioStream();
1062 CreateVideoStream();
1063 MockDemuxerStreamVector streams;
1064 streams.push_back(audio_stream());
1065 streams.push_back(video_stream());
1066 SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
1068 if (state == kInitAudioRenderer) {
1069 if (stop_or_error == kStop) {
1070 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _))
1071 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1072 RunCallback<1>(PIPELINE_OK)));
1073 ExpectPipelineStopAndDestroyPipeline();
1074 } else {
1075 status = PIPELINE_ERROR_INITIALIZATION_FAILED;
1076 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _))
1077 .WillOnce(RunCallback<1>(status));
1080 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1081 return status;
1084 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _))
1085 .WillOnce(DoAll(SaveArg<4>(&audio_buffering_state_cb_),
1086 RunCallback<1>(PIPELINE_OK)));
1088 if (state == kInitVideoRenderer) {
1089 if (stop_or_error == kStop) {
1090 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _, _))
1091 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1092 RunCallback<2>(PIPELINE_OK)));
1093 ExpectPipelineStopAndDestroyPipeline();
1094 } else {
1095 status = PIPELINE_ERROR_INITIALIZATION_FAILED;
1096 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _, _))
1097 .WillOnce(RunCallback<2>(status));
1100 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1101 return status;
1104 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _, _))
1105 .WillOnce(DoAll(SaveArg<5>(&video_buffering_state_cb_),
1106 RunCallback<2>(PIPELINE_OK)));
1108 EXPECT_CALL(callbacks_, OnMetadata(_));
1110 // If we get here it's a successful initialization.
1111 EXPECT_CALL(*audio_renderer_, GetTimeSource())
1112 .WillOnce(Return(&time_source_));
1113 EXPECT_CALL(time_source_, SetMediaTime(base::TimeDelta()));
1114 EXPECT_CALL(time_source_, SetPlaybackRate(0.0f));
1115 EXPECT_CALL(time_source_, StartTicking());
1116 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
1117 EXPECT_CALL(*audio_renderer_, StartPlaying())
1118 .WillOnce(SetBufferingState(&audio_buffering_state_cb_,
1119 BUFFERING_HAVE_ENOUGH));
1120 EXPECT_CALL(*video_renderer_, StartPlaying())
1121 .WillOnce(SetBufferingState(&video_buffering_state_cb_,
1122 BUFFERING_HAVE_ENOUGH));
1124 if (status == PIPELINE_OK)
1125 EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
1127 return status;
1130 void DoSeek(TeardownState state, StopOrError stop_or_error) {
1131 InSequence s;
1132 PipelineStatus status = SetSeekExpectations(state, stop_or_error);
1134 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1135 EXPECT_CALL(callbacks_, OnSeek(status));
1137 if (status == PIPELINE_OK) {
1138 ExpectPipelineStopAndDestroyPipeline();
1141 pipeline_->Seek(base::TimeDelta::FromSeconds(10), base::Bind(
1142 &CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
1143 message_loop_.RunUntilIdle();
1146 PipelineStatus SetSeekExpectations(TeardownState state,
1147 StopOrError stop_or_error) {
1148 PipelineStatus status = PIPELINE_OK;
1149 base::Closure stop_cb = base::Bind(
1150 &CallbackHelper::OnStop, base::Unretained(&callbacks_));
1152 EXPECT_CALL(time_source_, StopTicking());
1154 if (state == kFlushing) {
1155 if (stop_or_error == kStop) {
1156 EXPECT_CALL(*audio_renderer_, Flush(_))
1157 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1158 SetBufferingState(&audio_buffering_state_cb_,
1159 BUFFERING_HAVE_NOTHING),
1160 RunClosure<0>()));
1161 } else {
1162 status = PIPELINE_ERROR_READ;
1163 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(
1164 DoAll(SetError(pipeline_.get(), status),
1165 SetBufferingState(&audio_buffering_state_cb_,
1166 BUFFERING_HAVE_NOTHING),
1167 RunClosure<0>()));
1170 return status;
1173 EXPECT_CALL(*audio_renderer_, Flush(_))
1174 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
1175 BUFFERING_HAVE_NOTHING),
1176 RunClosure<0>()));
1177 EXPECT_CALL(*video_renderer_, Flush(_))
1178 .WillOnce(DoAll(SetBufferingState(&video_buffering_state_cb_,
1179 BUFFERING_HAVE_NOTHING),
1180 RunClosure<0>()));
1182 if (state == kSeeking) {
1183 if (stop_or_error == kStop) {
1184 EXPECT_CALL(*demuxer_, Seek(_, _))
1185 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1186 RunCallback<1>(PIPELINE_OK)));
1187 } else {
1188 status = PIPELINE_ERROR_READ;
1189 EXPECT_CALL(*demuxer_, Seek(_, _))
1190 .WillOnce(RunCallback<1>(status));
1193 return status;
1196 NOTREACHED() << "State not supported: " << state;
1197 return status;
1200 void DoStopOrError(StopOrError stop_or_error) {
1201 InSequence s;
1203 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1205 switch (stop_or_error) {
1206 case kStop:
1207 ExpectPipelineStopAndDestroyPipeline();
1208 pipeline_->Stop(base::Bind(
1209 &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1210 break;
1212 case kError:
1213 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
1214 pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1215 break;
1217 case kErrorAndStop:
1218 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
1219 ExpectPipelineStopAndDestroyPipeline();
1220 pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1221 pipeline_->Stop(base::Bind(
1222 &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1223 break;
1226 message_loop_.RunUntilIdle();
1229 DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest);
1232 #define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state) \
1233 TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \
1234 RunTest(k##state, k##stop_or_error); \
1237 INSTANTIATE_TEARDOWN_TEST(Stop, InitDemuxer);
1238 INSTANTIATE_TEARDOWN_TEST(Stop, InitAudioRenderer);
1239 INSTANTIATE_TEARDOWN_TEST(Stop, InitVideoRenderer);
1240 INSTANTIATE_TEARDOWN_TEST(Stop, Flushing);
1241 INSTANTIATE_TEARDOWN_TEST(Stop, Seeking);
1242 INSTANTIATE_TEARDOWN_TEST(Stop, Playing);
1244 INSTANTIATE_TEARDOWN_TEST(Error, InitDemuxer);
1245 INSTANTIATE_TEARDOWN_TEST(Error, InitAudioRenderer);
1246 INSTANTIATE_TEARDOWN_TEST(Error, InitVideoRenderer);
1247 INSTANTIATE_TEARDOWN_TEST(Error, Flushing);
1248 INSTANTIATE_TEARDOWN_TEST(Error, Seeking);
1249 INSTANTIATE_TEARDOWN_TEST(Error, Playing);
1251 INSTANTIATE_TEARDOWN_TEST(ErrorAndStop, Playing);
1253 } // namespace media