Allow overlapping sync and async startup requests
[chromium-blink-merge.git] / media / base / pipeline_unittest.cc
blob4c8640c7807b65b6d2c0a7b25f0fd714b6ebbc97
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/clock.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 "testing/gtest/include/gtest/gtest.h"
20 #include "ui/gfx/size.h"
22 using ::testing::_;
23 using ::testing::DeleteArg;
24 using ::testing::DoAll;
25 // TODO(scherkus): Remove InSequence after refactoring Pipeline.
26 using ::testing::InSequence;
27 using ::testing::Invoke;
28 using ::testing::InvokeWithoutArgs;
29 using ::testing::Mock;
30 using ::testing::NotNull;
31 using ::testing::Return;
32 using ::testing::SaveArg;
33 using ::testing::StrictMock;
34 using ::testing::WithArg;
36 namespace media {
38 // Demuxer properties.
39 static const int kTotalBytes = 1024;
40 static const int kBitrate = 1234;
42 ACTION_P(SetDemuxerProperties, duration) {
43 arg0->SetTotalBytes(kTotalBytes);
44 arg0->SetDuration(duration);
47 ACTION_P2(Stop, pipeline, stop_cb) {
48 pipeline->Stop(stop_cb);
51 ACTION_P2(SetError, pipeline, status) {
52 pipeline->SetErrorForTesting(status);
55 // Used for setting expectations on pipeline callbacks. Using a StrictMock
56 // also lets us test for missing callbacks.
57 class CallbackHelper {
58 public:
59 CallbackHelper() {}
60 virtual ~CallbackHelper() {}
62 MOCK_METHOD1(OnStart, void(PipelineStatus));
63 MOCK_METHOD1(OnSeek, void(PipelineStatus));
64 MOCK_METHOD0(OnStop, void());
65 MOCK_METHOD0(OnEnded, void());
66 MOCK_METHOD1(OnError, void(PipelineStatus));
67 MOCK_METHOD1(OnBufferingState, void(Pipeline::BufferingState));
68 MOCK_METHOD0(OnDurationChange, void());
70 private:
71 DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
74 // TODO(scherkus): even though some filters are initialized on separate
75 // threads these test aren't flaky... why? It's because filters' Initialize()
76 // is executed on |message_loop_| and the mock filters instantly call
77 // InitializationComplete(), which keeps the pipeline humming along. If
78 // either filters don't call InitializationComplete() immediately or filter
79 // initialization is moved to a separate thread this test will become flaky.
80 class PipelineTest : public ::testing::Test {
81 public:
82 PipelineTest()
83 : pipeline_(new Pipeline(message_loop_.message_loop_proxy(),
84 new MediaLog())),
85 filter_collection_(new FilterCollection()),
86 demuxer_(new MockDemuxer()) {
87 filter_collection_->SetDemuxer(demuxer_.get());
89 video_renderer_ = new MockVideoRenderer();
90 scoped_ptr<VideoRenderer> video_renderer(video_renderer_);
91 filter_collection_->SetVideoRenderer(video_renderer.Pass());
93 audio_renderer_ = new MockAudioRenderer();
94 scoped_ptr<AudioRenderer> audio_renderer(audio_renderer_);
95 filter_collection_->SetAudioRenderer(audio_renderer.Pass());
97 // InitializeDemuxer() adds overriding expectations for expected non-NULL
98 // streams.
99 DemuxerStream* null_pointer = NULL;
100 EXPECT_CALL(*demuxer_, GetStream(_))
101 .WillRepeatedly(Return(null_pointer));
103 EXPECT_CALL(*demuxer_, GetStartTime())
104 .WillRepeatedly(Return(base::TimeDelta()));
107 virtual ~PipelineTest() {
108 if (!pipeline_ || !pipeline_->IsRunning())
109 return;
111 ExpectStop();
113 // Expect a stop callback if we were started.
114 EXPECT_CALL(callbacks_, OnStop());
115 pipeline_->Stop(base::Bind(&CallbackHelper::OnStop,
116 base::Unretained(&callbacks_)));
117 message_loop_.RunUntilIdle();
120 protected:
121 // Sets up expectations to allow the demuxer to initialize.
122 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector;
123 void InitializeDemuxer(MockDemuxerStreamVector* streams,
124 const base::TimeDelta& duration) {
125 EXPECT_CALL(callbacks_, OnDurationChange());
126 EXPECT_CALL(*demuxer_, Initialize(_, _))
127 .WillOnce(DoAll(SetDemuxerProperties(duration),
128 RunCallback<1>(PIPELINE_OK)));
130 // Configure the demuxer to return the streams.
131 for (size_t i = 0; i < streams->size(); ++i) {
132 DemuxerStream* stream = (*streams)[i];
133 EXPECT_CALL(*demuxer_, GetStream(stream->type()))
134 .WillRepeatedly(Return(stream));
138 void InitializeDemuxer(MockDemuxerStreamVector* streams) {
139 // Initialize with a default non-zero duration.
140 InitializeDemuxer(streams, base::TimeDelta::FromSeconds(10));
143 scoped_ptr<StrictMock<MockDemuxerStream> > CreateStream(
144 DemuxerStream::Type type) {
145 scoped_ptr<StrictMock<MockDemuxerStream> > stream(
146 new StrictMock<MockDemuxerStream>(type));
147 return stream.Pass();
150 // Sets up expectations to allow the video renderer to initialize.
151 void InitializeVideoRenderer(DemuxerStream* stream) {
152 EXPECT_CALL(*video_renderer_, Initialize(stream, _, _, _, _, _, _, _, _))
153 .WillOnce(RunCallback<1>(PIPELINE_OK));
154 EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f));
156 // Startup sequence.
157 EXPECT_CALL(*video_renderer_, Preroll(demuxer_->GetStartTime(), _))
158 .WillOnce(RunCallback<1>(PIPELINE_OK));
159 EXPECT_CALL(*video_renderer_, Play(_))
160 .WillOnce(RunClosure<0>());
163 // Sets up expectations to allow the audio renderer to initialize.
164 void InitializeAudioRenderer(DemuxerStream* stream,
165 bool disable_after_init_cb) {
166 if (disable_after_init_cb) {
167 EXPECT_CALL(*audio_renderer_, Initialize(stream, _, _, _, _, _, _, _))
168 .WillOnce(DoAll(RunCallback<1>(PIPELINE_OK),
169 WithArg<6>(RunClosure<0>()))); // |disabled_cb|.
170 } else {
171 EXPECT_CALL(*audio_renderer_, Initialize(stream, _, _, _, _, _, _, _))
172 .WillOnce(DoAll(SaveArg<4>(&audio_time_cb_),
173 RunCallback<1>(PIPELINE_OK)));
177 // Sets up expectations on the callback and initializes the pipeline. Called
178 // after tests have set expectations any filters they wish to use.
179 void InitializePipeline(PipelineStatus start_status) {
180 EXPECT_CALL(callbacks_, OnStart(start_status));
182 if (start_status == PIPELINE_OK) {
183 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kHaveMetadata));
184 EXPECT_CALL(*demuxer_, SetPlaybackRate(0.0f));
186 if (audio_stream_) {
187 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f));
188 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
190 // Startup sequence.
191 EXPECT_CALL(*audio_renderer_, Preroll(base::TimeDelta(), _))
192 .WillOnce(RunCallback<1>(PIPELINE_OK));
193 EXPECT_CALL(*audio_renderer_, Play(_))
194 .WillOnce(RunClosure<0>());
196 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kPrerollCompleted));
199 pipeline_->Start(
200 filter_collection_.Pass(),
201 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
202 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
203 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
204 base::Bind(&CallbackHelper::OnBufferingState,
205 base::Unretained(&callbacks_)),
206 base::Bind(&CallbackHelper::OnDurationChange,
207 base::Unretained(&callbacks_)));
208 message_loop_.RunUntilIdle();
211 void CreateAudioStream() {
212 audio_stream_ = CreateStream(DemuxerStream::AUDIO);
215 void CreateVideoStream() {
216 video_stream_ = CreateStream(DemuxerStream::VIDEO);
217 video_stream_->set_video_decoder_config(video_decoder_config_);
220 MockDemuxerStream* audio_stream() {
221 return audio_stream_.get();
224 MockDemuxerStream* video_stream() {
225 return video_stream_.get();
228 void ExpectSeek(const base::TimeDelta& seek_time) {
229 // Every filter should receive a call to Seek().
230 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
231 .WillOnce(RunCallback<1>(PIPELINE_OK));
232 EXPECT_CALL(*demuxer_, SetPlaybackRate(_));
234 if (audio_stream_) {
235 EXPECT_CALL(*audio_renderer_, Pause(_))
236 .WillOnce(RunClosure<0>());
237 EXPECT_CALL(*audio_renderer_, Flush(_))
238 .WillOnce(RunClosure<0>());
239 EXPECT_CALL(*audio_renderer_, Preroll(seek_time, _))
240 .WillOnce(RunCallback<1>(PIPELINE_OK));
241 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(_));
242 EXPECT_CALL(*audio_renderer_, SetVolume(_));
243 EXPECT_CALL(*audio_renderer_, Play(_))
244 .WillOnce(RunClosure<0>());
247 if (video_stream_) {
248 EXPECT_CALL(*video_renderer_, Pause(_))
249 .WillOnce(RunClosure<0>());
250 EXPECT_CALL(*video_renderer_, Flush(_))
251 .WillOnce(RunClosure<0>());
252 EXPECT_CALL(*video_renderer_, Preroll(seek_time, _))
253 .WillOnce(RunCallback<1>(PIPELINE_OK));
254 EXPECT_CALL(*video_renderer_, SetPlaybackRate(_));
255 EXPECT_CALL(*video_renderer_, Play(_))
256 .WillOnce(RunClosure<0>());
259 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kPrerollCompleted));
261 // We expect a successful seek callback.
262 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
265 void DoSeek(const base::TimeDelta& seek_time) {
266 pipeline_->Seek(seek_time,
267 base::Bind(&CallbackHelper::OnSeek,
268 base::Unretained(&callbacks_)));
270 // We expect the time to be updated only after the seek has completed.
271 EXPECT_NE(seek_time, pipeline_->GetMediaTime());
272 message_loop_.RunUntilIdle();
273 EXPECT_EQ(seek_time, pipeline_->GetMediaTime());
276 void ExpectStop() {
277 if (demuxer_)
278 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
280 if (audio_stream_)
281 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
283 if (video_stream_)
284 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
287 // Fixture members.
288 StrictMock<CallbackHelper> callbacks_;
289 base::SimpleTestTickClock test_tick_clock_;
290 base::MessageLoop message_loop_;
291 scoped_ptr<Pipeline> pipeline_;
293 scoped_ptr<FilterCollection> filter_collection_;
294 scoped_ptr<MockDemuxer> demuxer_;
295 MockVideoRenderer* video_renderer_;
296 MockAudioRenderer* audio_renderer_;
297 scoped_ptr<StrictMock<MockDemuxerStream> > audio_stream_;
298 scoped_ptr<StrictMock<MockDemuxerStream> > video_stream_;
299 AudioRenderer::TimeCB audio_time_cb_;
300 VideoDecoderConfig video_decoder_config_;
302 private:
303 DISALLOW_COPY_AND_ASSIGN(PipelineTest);
306 // Test that playback controls methods no-op when the pipeline hasn't been
307 // started.
308 TEST_F(PipelineTest, NotStarted) {
309 const base::TimeDelta kZero;
311 EXPECT_FALSE(pipeline_->IsRunning());
312 EXPECT_FALSE(pipeline_->HasAudio());
313 EXPECT_FALSE(pipeline_->HasVideo());
315 // Setting should still work.
316 EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
317 pipeline_->SetPlaybackRate(-1.0f);
318 EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
319 pipeline_->SetPlaybackRate(1.0f);
320 EXPECT_EQ(1.0f, pipeline_->GetPlaybackRate());
322 // Setting should still work.
323 EXPECT_EQ(1.0f, pipeline_->GetVolume());
324 pipeline_->SetVolume(-1.0f);
325 EXPECT_EQ(1.0f, pipeline_->GetVolume());
326 pipeline_->SetVolume(0.0f);
327 EXPECT_EQ(0.0f, pipeline_->GetVolume());
329 EXPECT_TRUE(kZero == pipeline_->GetMediaTime());
330 EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
331 EXPECT_TRUE(kZero == pipeline_->GetMediaDuration());
333 EXPECT_EQ(0, pipeline_->GetTotalBytes());
335 // Should always get set to zero.
336 gfx::Size size(1, 1);
337 pipeline_->GetNaturalVideoSize(&size);
338 EXPECT_EQ(0, size.width());
339 EXPECT_EQ(0, size.height());
342 TEST_F(PipelineTest, NeverInitializes) {
343 // Don't execute the callback passed into Initialize().
344 EXPECT_CALL(*demuxer_, Initialize(_, _));
346 // This test hangs during initialization by never calling
347 // InitializationComplete(). StrictMock<> will ensure that the callback is
348 // never executed.
349 pipeline_->Start(
350 filter_collection_.Pass(),
351 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
352 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
353 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
354 base::Bind(&CallbackHelper::OnBufferingState,
355 base::Unretained(&callbacks_)),
356 base::Bind(&CallbackHelper::OnDurationChange,
357 base::Unretained(&callbacks_)));
358 message_loop_.RunUntilIdle();
361 // Because our callback will get executed when the test tears down, we'll
362 // verify that nothing has been called, then set our expectation for the call
363 // made during tear down.
364 Mock::VerifyAndClear(&callbacks_);
365 EXPECT_CALL(callbacks_, OnStart(PIPELINE_OK));
368 TEST_F(PipelineTest, URLNotFound) {
369 EXPECT_CALL(*demuxer_, Initialize(_, _))
370 .WillOnce(RunCallback<1>(PIPELINE_ERROR_URL_NOT_FOUND));
371 EXPECT_CALL(*demuxer_, Stop(_))
372 .WillOnce(RunClosure<0>());
374 InitializePipeline(PIPELINE_ERROR_URL_NOT_FOUND);
377 TEST_F(PipelineTest, NoStreams) {
378 EXPECT_CALL(*demuxer_, Initialize(_, _))
379 .WillOnce(RunCallback<1>(PIPELINE_OK));
380 EXPECT_CALL(*demuxer_, Stop(_))
381 .WillOnce(RunClosure<0>());
383 InitializePipeline(PIPELINE_ERROR_COULD_NOT_RENDER);
386 TEST_F(PipelineTest, AudioStream) {
387 CreateAudioStream();
388 MockDemuxerStreamVector streams;
389 streams.push_back(audio_stream());
391 InitializeDemuxer(&streams);
392 InitializeAudioRenderer(audio_stream(), false);
394 InitializePipeline(PIPELINE_OK);
395 EXPECT_TRUE(pipeline_->HasAudio());
396 EXPECT_FALSE(pipeline_->HasVideo());
399 TEST_F(PipelineTest, VideoStream) {
400 CreateVideoStream();
401 MockDemuxerStreamVector streams;
402 streams.push_back(video_stream());
404 InitializeDemuxer(&streams);
405 InitializeVideoRenderer(video_stream());
407 InitializePipeline(PIPELINE_OK);
408 EXPECT_FALSE(pipeline_->HasAudio());
409 EXPECT_TRUE(pipeline_->HasVideo());
412 TEST_F(PipelineTest, AudioVideoStream) {
413 CreateAudioStream();
414 CreateVideoStream();
415 MockDemuxerStreamVector streams;
416 streams.push_back(audio_stream());
417 streams.push_back(video_stream());
419 InitializeDemuxer(&streams);
420 InitializeAudioRenderer(audio_stream(), false);
421 InitializeVideoRenderer(video_stream());
423 InitializePipeline(PIPELINE_OK);
424 EXPECT_TRUE(pipeline_->HasAudio());
425 EXPECT_TRUE(pipeline_->HasVideo());
428 TEST_F(PipelineTest, Seek) {
429 CreateAudioStream();
430 CreateVideoStream();
431 MockDemuxerStreamVector streams;
432 streams.push_back(audio_stream());
433 streams.push_back(video_stream());
435 InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(3000));
436 InitializeAudioRenderer(audio_stream(), false);
437 InitializeVideoRenderer(video_stream());
439 // Initialize then seek!
440 InitializePipeline(PIPELINE_OK);
442 // Every filter should receive a call to Seek().
443 base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
444 ExpectSeek(expected);
445 DoSeek(expected);
448 TEST_F(PipelineTest, SetVolume) {
449 CreateAudioStream();
450 MockDemuxerStreamVector streams;
451 streams.push_back(audio_stream());
453 InitializeDemuxer(&streams);
454 InitializeAudioRenderer(audio_stream(), false);
456 // The audio renderer should receive a call to SetVolume().
457 float expected = 0.5f;
458 EXPECT_CALL(*audio_renderer_, SetVolume(expected));
460 // Initialize then set volume!
461 InitializePipeline(PIPELINE_OK);
462 pipeline_->SetVolume(expected);
465 TEST_F(PipelineTest, Properties) {
466 CreateVideoStream();
467 MockDemuxerStreamVector streams;
468 streams.push_back(video_stream());
470 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
471 InitializeDemuxer(&streams, kDuration);
472 InitializeVideoRenderer(video_stream());
474 InitializePipeline(PIPELINE_OK);
475 EXPECT_EQ(kDuration.ToInternalValue(),
476 pipeline_->GetMediaDuration().ToInternalValue());
477 EXPECT_EQ(kTotalBytes, pipeline_->GetTotalBytes());
478 EXPECT_FALSE(pipeline_->DidLoadingProgress());
481 TEST_F(PipelineTest, GetBufferedTimeRanges) {
482 CreateVideoStream();
483 MockDemuxerStreamVector streams;
484 streams.push_back(video_stream());
486 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
487 InitializeDemuxer(&streams, kDuration);
488 InitializeVideoRenderer(video_stream());
490 InitializePipeline(PIPELINE_OK);
492 EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
494 EXPECT_FALSE(pipeline_->DidLoadingProgress());
495 pipeline_->AddBufferedByteRange(0, kTotalBytes / 8);
496 EXPECT_TRUE(pipeline_->DidLoadingProgress());
497 EXPECT_FALSE(pipeline_->DidLoadingProgress());
498 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
499 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
500 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
501 pipeline_->AddBufferedTimeRange(base::TimeDelta(), kDuration / 8);
502 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
503 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
505 base::TimeDelta kSeekTime = kDuration / 2;
506 ExpectSeek(kSeekTime);
507 DoSeek(kSeekTime);
509 EXPECT_TRUE(pipeline_->DidLoadingProgress());
510 EXPECT_FALSE(pipeline_->DidLoadingProgress());
511 pipeline_->AddBufferedByteRange(kTotalBytes / 2,
512 kTotalBytes / 2 + kTotalBytes / 8);
513 EXPECT_TRUE(pipeline_->DidLoadingProgress());
514 EXPECT_FALSE(pipeline_->DidLoadingProgress());
515 EXPECT_EQ(2u, pipeline_->GetBufferedTimeRanges().size());
516 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
517 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
518 EXPECT_EQ(kDuration / 2, pipeline_->GetBufferedTimeRanges().start(1));
519 EXPECT_EQ(kDuration / 2 + kDuration / 8,
520 pipeline_->GetBufferedTimeRanges().end(1));
522 pipeline_->AddBufferedTimeRange(kDuration / 4, 3 * kDuration / 8);
523 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
524 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
525 EXPECT_EQ(kDuration / 4, pipeline_->GetBufferedTimeRanges().start(1));
526 EXPECT_EQ(3* kDuration / 8, pipeline_->GetBufferedTimeRanges().end(1));
527 EXPECT_EQ(kDuration / 2, pipeline_->GetBufferedTimeRanges().start(2));
528 EXPECT_EQ(kDuration / 2 + kDuration / 8,
529 pipeline_->GetBufferedTimeRanges().end(2));
532 TEST_F(PipelineTest, DisableAudioRenderer) {
533 CreateAudioStream();
534 CreateVideoStream();
535 MockDemuxerStreamVector streams;
536 streams.push_back(audio_stream());
537 streams.push_back(video_stream());
539 InitializeDemuxer(&streams);
540 InitializeAudioRenderer(audio_stream(), false);
541 InitializeVideoRenderer(video_stream());
543 InitializePipeline(PIPELINE_OK);
544 EXPECT_TRUE(pipeline_->HasAudio());
545 EXPECT_TRUE(pipeline_->HasVideo());
547 EXPECT_CALL(*demuxer_, OnAudioRendererDisabled());
548 pipeline_->OnAudioDisabled();
550 // Verify that ended event is fired when video ends.
551 EXPECT_CALL(callbacks_, OnEnded());
552 pipeline_->OnVideoRendererEnded();
555 TEST_F(PipelineTest, DisableAudioRendererDuringInit) {
556 CreateAudioStream();
557 CreateVideoStream();
558 MockDemuxerStreamVector streams;
559 streams.push_back(audio_stream());
560 streams.push_back(video_stream());
562 InitializeDemuxer(&streams);
563 InitializeAudioRenderer(audio_stream(), true);
564 InitializeVideoRenderer(video_stream());
566 EXPECT_CALL(*demuxer_, OnAudioRendererDisabled());
568 InitializePipeline(PIPELINE_OK);
569 EXPECT_FALSE(pipeline_->HasAudio());
570 EXPECT_TRUE(pipeline_->HasVideo());
572 // Verify that ended event is fired when video ends.
573 EXPECT_CALL(callbacks_, OnEnded());
574 pipeline_->OnVideoRendererEnded();
577 TEST_F(PipelineTest, EndedCallback) {
578 CreateAudioStream();
579 CreateVideoStream();
580 MockDemuxerStreamVector streams;
581 streams.push_back(audio_stream());
582 streams.push_back(video_stream());
584 InitializeDemuxer(&streams);
585 InitializeAudioRenderer(audio_stream(), false);
586 InitializeVideoRenderer(video_stream());
587 InitializePipeline(PIPELINE_OK);
589 // The ended callback shouldn't run until both renderers have ended.
590 pipeline_->OnAudioRendererEnded();
591 message_loop_.RunUntilIdle();
593 EXPECT_CALL(callbacks_, OnEnded());
594 pipeline_->OnVideoRendererEnded();
595 message_loop_.RunUntilIdle();
598 TEST_F(PipelineTest, AudioStreamShorterThanVideo) {
599 base::TimeDelta duration = base::TimeDelta::FromSeconds(10);
601 CreateAudioStream();
602 CreateVideoStream();
603 MockDemuxerStreamVector streams;
604 streams.push_back(audio_stream());
605 streams.push_back(video_stream());
607 // Replace the clock so we can simulate wallclock time advancing w/o using
608 // Sleep().
609 pipeline_->SetClockForTesting(new Clock(&test_tick_clock_));
611 InitializeDemuxer(&streams, duration);
612 InitializeAudioRenderer(audio_stream(), false);
613 InitializeVideoRenderer(video_stream());
614 InitializePipeline(PIPELINE_OK);
616 EXPECT_EQ(0, pipeline_->GetMediaTime().ToInternalValue());
618 float playback_rate = 1.0f;
619 EXPECT_CALL(*demuxer_, SetPlaybackRate(playback_rate));
620 EXPECT_CALL(*video_renderer_, SetPlaybackRate(playback_rate));
621 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate));
622 pipeline_->SetPlaybackRate(playback_rate);
623 message_loop_.RunUntilIdle();
625 InSequence s;
627 // Verify that the clock doesn't advance since it hasn't been started by
628 // a time update from the audio stream.
629 int64 start_time = pipeline_->GetMediaTime().ToInternalValue();
630 test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
631 EXPECT_EQ(pipeline_->GetMediaTime().ToInternalValue(), start_time);
633 // Signal end of audio stream.
634 pipeline_->OnAudioRendererEnded();
635 message_loop_.RunUntilIdle();
637 // Verify that the clock advances.
638 start_time = pipeline_->GetMediaTime().ToInternalValue();
639 test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
640 EXPECT_GT(pipeline_->GetMediaTime().ToInternalValue(), start_time);
642 // Signal end of video stream and make sure OnEnded() callback occurs.
643 EXPECT_CALL(callbacks_, OnEnded());
644 pipeline_->OnVideoRendererEnded();
647 TEST_F(PipelineTest, ErrorDuringSeek) {
648 CreateAudioStream();
649 MockDemuxerStreamVector streams;
650 streams.push_back(audio_stream());
652 InitializeDemuxer(&streams);
653 InitializeAudioRenderer(audio_stream(), false);
654 InitializePipeline(PIPELINE_OK);
656 float playback_rate = 1.0f;
657 EXPECT_CALL(*demuxer_, SetPlaybackRate(playback_rate));
658 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate));
659 pipeline_->SetPlaybackRate(playback_rate);
660 message_loop_.RunUntilIdle();
662 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
664 // Preroll() isn't called as the demuxer errors out first.
665 EXPECT_CALL(*audio_renderer_, Pause(_))
666 .WillOnce(RunClosure<0>());
667 EXPECT_CALL(*audio_renderer_, Flush(_))
668 .WillOnce(RunClosure<0>());
669 EXPECT_CALL(*audio_renderer_, Stop(_))
670 .WillOnce(RunClosure<0>());
672 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
673 .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
674 EXPECT_CALL(*demuxer_, Stop(_))
675 .WillOnce(RunClosure<0>());
677 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
678 base::Unretained(&callbacks_)));
679 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
680 message_loop_.RunUntilIdle();
683 // Invoked function OnError. This asserts that the pipeline does not enqueue
684 // non-teardown related tasks while tearing down.
685 static void TestNoCallsAfterError(
686 Pipeline* pipeline, base::MessageLoop* message_loop,
687 PipelineStatus /* status */) {
688 CHECK(pipeline);
689 CHECK(message_loop);
691 // When we get to this stage, the message loop should be empty.
692 EXPECT_TRUE(message_loop->IsIdleForTesting());
694 // Make calls on pipeline after error has occurred.
695 pipeline->SetPlaybackRate(0.5f);
696 pipeline->SetVolume(0.5f);
698 // No additional tasks should be queued as a result of these calls.
699 EXPECT_TRUE(message_loop->IsIdleForTesting());
702 TEST_F(PipelineTest, NoMessageDuringTearDownFromError) {
703 CreateAudioStream();
704 MockDemuxerStreamVector streams;
705 streams.push_back(audio_stream());
707 InitializeDemuxer(&streams);
708 InitializeAudioRenderer(audio_stream(), false);
709 InitializePipeline(PIPELINE_OK);
711 // Trigger additional requests on the pipeline during tear down from error.
712 base::Callback<void(PipelineStatus)> cb = base::Bind(
713 &TestNoCallsAfterError, pipeline_.get(), &message_loop_);
714 ON_CALL(callbacks_, OnError(_))
715 .WillByDefault(Invoke(&cb, &base::Callback<void(PipelineStatus)>::Run));
717 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
719 // Seek() isn't called as the demuxer errors out first.
720 EXPECT_CALL(*audio_renderer_, Pause(_))
721 .WillOnce(RunClosure<0>());
722 EXPECT_CALL(*audio_renderer_, Flush(_))
723 .WillOnce(RunClosure<0>());
724 EXPECT_CALL(*audio_renderer_, Stop(_))
725 .WillOnce(RunClosure<0>());
727 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
728 .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
729 EXPECT_CALL(*demuxer_, Stop(_))
730 .WillOnce(RunClosure<0>());
732 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
733 base::Unretained(&callbacks_)));
734 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
735 message_loop_.RunUntilIdle();
738 TEST_F(PipelineTest, StartTimeIsZero) {
739 CreateVideoStream();
740 MockDemuxerStreamVector streams;
741 streams.push_back(video_stream());
743 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
744 InitializeDemuxer(&streams, kDuration);
745 InitializeVideoRenderer(video_stream());
747 InitializePipeline(PIPELINE_OK);
748 EXPECT_FALSE(pipeline_->HasAudio());
749 EXPECT_TRUE(pipeline_->HasVideo());
751 EXPECT_EQ(base::TimeDelta(), pipeline_->GetMediaTime());
754 TEST_F(PipelineTest, StartTimeIsNonZero) {
755 const base::TimeDelta kStartTime = base::TimeDelta::FromSeconds(4);
756 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
758 EXPECT_CALL(*demuxer_, GetStartTime())
759 .WillRepeatedly(Return(kStartTime));
761 CreateVideoStream();
762 MockDemuxerStreamVector streams;
763 streams.push_back(video_stream());
765 InitializeDemuxer(&streams, kDuration);
766 InitializeVideoRenderer(video_stream());
768 InitializePipeline(PIPELINE_OK);
769 EXPECT_FALSE(pipeline_->HasAudio());
770 EXPECT_TRUE(pipeline_->HasVideo());
772 EXPECT_EQ(kStartTime, pipeline_->GetMediaTime());
775 static void RunTimeCB(const AudioRenderer::TimeCB& time_cb,
776 int time_in_ms,
777 int max_time_in_ms) {
778 time_cb.Run(base::TimeDelta::FromMilliseconds(time_in_ms),
779 base::TimeDelta::FromMilliseconds(max_time_in_ms));
782 TEST_F(PipelineTest, AudioTimeUpdateDuringSeek) {
783 CreateAudioStream();
784 MockDemuxerStreamVector streams;
785 streams.push_back(audio_stream());
787 InitializeDemuxer(&streams);
788 InitializeAudioRenderer(audio_stream(), false);
789 InitializePipeline(PIPELINE_OK);
791 float playback_rate = 1.0f;
792 EXPECT_CALL(*demuxer_, SetPlaybackRate(playback_rate));
793 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate));
794 pipeline_->SetPlaybackRate(playback_rate);
795 message_loop_.RunUntilIdle();
797 // Provide an initial time update so that the pipeline transitions out of the
798 // "waiting for time update" state.
799 audio_time_cb_.Run(base::TimeDelta::FromMilliseconds(100),
800 base::TimeDelta::FromMilliseconds(500));
802 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
804 // Arrange to trigger a time update while the demuxer is in the middle of
805 // seeking. This update should be ignored by the pipeline and the clock should
806 // not get updated.
807 base::Closure closure = base::Bind(&RunTimeCB, audio_time_cb_, 300, 700);
808 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
809 .WillOnce(DoAll(InvokeWithoutArgs(&closure, &base::Closure::Run),
810 RunCallback<1>(PIPELINE_OK)));
812 EXPECT_CALL(*audio_renderer_, Pause(_))
813 .WillOnce(RunClosure<0>());
814 EXPECT_CALL(*audio_renderer_, Flush(_))
815 .WillOnce(RunClosure<0>());
816 EXPECT_CALL(*audio_renderer_, Preroll(seek_time, _))
817 .WillOnce(RunCallback<1>(PIPELINE_OK));
818 EXPECT_CALL(*demuxer_, SetPlaybackRate(_));
819 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(_));
820 EXPECT_CALL(*audio_renderer_, SetVolume(_));
821 EXPECT_CALL(*audio_renderer_, Play(_))
822 .WillOnce(RunClosure<0>());
824 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kPrerollCompleted));
825 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
826 DoSeek(seek_time);
828 EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
830 // Now that the seek is complete, verify that time updates advance the current
831 // time.
832 base::TimeDelta new_time = seek_time + base::TimeDelta::FromMilliseconds(100);
833 audio_time_cb_.Run(new_time, new_time);
835 EXPECT_EQ(pipeline_->GetMediaTime(), new_time);
838 static void DeletePipeline(scoped_ptr<Pipeline> pipeline) {
839 // |pipeline| will go out of scope.
842 TEST_F(PipelineTest, DeleteAfterStop) {
843 CreateAudioStream();
844 MockDemuxerStreamVector streams;
845 streams.push_back(audio_stream());
846 InitializeDemuxer(&streams);
847 InitializeAudioRenderer(audio_stream(), false);
848 InitializePipeline(PIPELINE_OK);
850 ExpectStop();
852 Pipeline* pipeline = pipeline_.get();
853 pipeline->Stop(base::Bind(&DeletePipeline, base::Passed(&pipeline_)));
854 message_loop_.RunUntilIdle();
857 class PipelineTeardownTest : public PipelineTest {
858 public:
859 enum TeardownState {
860 kInitDemuxer,
861 kInitAudioRenderer,
862 kInitVideoRenderer,
863 kPausing,
864 kFlushing,
865 kSeeking,
866 kPrerolling,
867 kStarting,
868 kPlaying,
871 enum StopOrError {
872 kStop,
873 kError,
874 kErrorAndStop,
877 PipelineTeardownTest() {}
878 virtual ~PipelineTeardownTest() {}
880 void RunTest(TeardownState state, StopOrError stop_or_error) {
881 switch (state) {
882 case kInitDemuxer:
883 case kInitAudioRenderer:
884 case kInitVideoRenderer:
885 DoInitialize(state, stop_or_error);
886 break;
888 case kPausing:
889 case kFlushing:
890 case kSeeking:
891 case kPrerolling:
892 case kStarting:
893 DoInitialize(state, stop_or_error);
894 DoSeek(state, stop_or_error);
895 break;
897 case kPlaying:
898 DoInitialize(state, stop_or_error);
899 DoStopOrError(stop_or_error);
900 break;
904 private:
905 // TODO(scherkus): We do radically different things whether teardown is
906 // invoked via stop vs error. The teardown path should be the same,
907 // see http://crbug.com/110228
908 void DoInitialize(TeardownState state, StopOrError stop_or_error) {
909 PipelineStatus expected_status =
910 SetInitializeExpectations(state, stop_or_error);
912 EXPECT_CALL(callbacks_, OnStart(expected_status));
913 pipeline_->Start(
914 filter_collection_.Pass(),
915 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
916 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
917 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
918 base::Bind(&CallbackHelper::OnBufferingState,
919 base::Unretained(&callbacks_)),
920 base::Bind(&CallbackHelper::OnDurationChange,
921 base::Unretained(&callbacks_)));
922 message_loop_.RunUntilIdle();
925 PipelineStatus SetInitializeExpectations(TeardownState state,
926 StopOrError stop_or_error) {
927 PipelineStatus status = PIPELINE_OK;
928 base::Closure stop_cb = base::Bind(
929 &CallbackHelper::OnStop, base::Unretained(&callbacks_));
931 if (state == kInitDemuxer) {
932 if (stop_or_error == kStop) {
933 EXPECT_CALL(*demuxer_, Initialize(_, _))
934 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
935 RunCallback<1>(PIPELINE_OK)));
936 EXPECT_CALL(callbacks_, OnStop());
937 } else {
938 status = DEMUXER_ERROR_COULD_NOT_OPEN;
939 EXPECT_CALL(*demuxer_, Initialize(_, _))
940 .WillOnce(RunCallback<1>(status));
943 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
944 return status;
947 CreateAudioStream();
948 CreateVideoStream();
949 MockDemuxerStreamVector streams;
950 streams.push_back(audio_stream());
951 streams.push_back(video_stream());
952 InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(3000));
954 if (state == kInitAudioRenderer) {
955 if (stop_or_error == kStop) {
956 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _, _))
957 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
958 RunCallback<1>(PIPELINE_OK)));
959 EXPECT_CALL(callbacks_, OnStop());
960 } else {
961 status = PIPELINE_ERROR_INITIALIZATION_FAILED;
962 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _, _))
963 .WillOnce(RunCallback<1>(status));
966 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
967 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
968 return status;
971 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _, _))
972 .WillOnce(RunCallback<1>(PIPELINE_OK));
974 if (state == kInitVideoRenderer) {
975 if (stop_or_error == kStop) {
976 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _))
977 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
978 RunCallback<1>(PIPELINE_OK)));
979 EXPECT_CALL(callbacks_, OnStop());
980 } else {
981 status = PIPELINE_ERROR_INITIALIZATION_FAILED;
982 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _))
983 .WillOnce(RunCallback<1>(status));
986 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
987 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
988 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
989 return status;
992 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _))
993 .WillOnce(RunCallback<1>(PIPELINE_OK));
995 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kHaveMetadata));
997 // If we get here it's a successful initialization.
998 EXPECT_CALL(*audio_renderer_, Preroll(base::TimeDelta(), _))
999 .WillOnce(RunCallback<1>(PIPELINE_OK));
1000 EXPECT_CALL(*video_renderer_, Preroll(base::TimeDelta(), _))
1001 .WillOnce(RunCallback<1>(PIPELINE_OK));
1003 EXPECT_CALL(*demuxer_, SetPlaybackRate(0.0f));
1004 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f));
1005 EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f));
1006 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
1008 EXPECT_CALL(*audio_renderer_, Play(_))
1009 .WillOnce(RunClosure<0>());
1010 EXPECT_CALL(*video_renderer_, Play(_))
1011 .WillOnce(RunClosure<0>());
1013 if (status == PIPELINE_OK)
1014 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kPrerollCompleted));
1016 return status;
1019 void DoSeek(TeardownState state, StopOrError stop_or_error) {
1020 InSequence s;
1021 PipelineStatus status = SetSeekExpectations(state, stop_or_error);
1023 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1024 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1025 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1026 EXPECT_CALL(callbacks_, OnSeek(status));
1028 if (status == PIPELINE_OK) {
1029 EXPECT_CALL(callbacks_, OnStop());
1032 pipeline_->Seek(base::TimeDelta::FromSeconds(10), base::Bind(
1033 &CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
1034 message_loop_.RunUntilIdle();
1037 PipelineStatus SetSeekExpectations(TeardownState state,
1038 StopOrError stop_or_error) {
1039 PipelineStatus status = PIPELINE_OK;
1040 base::Closure stop_cb = base::Bind(
1041 &CallbackHelper::OnStop, base::Unretained(&callbacks_));
1043 if (state == kPausing) {
1044 if (stop_or_error == kStop) {
1045 EXPECT_CALL(*audio_renderer_, Pause(_))
1046 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), RunClosure<0>()));
1047 } else {
1048 status = PIPELINE_ERROR_READ;
1049 EXPECT_CALL(*audio_renderer_, Pause(_)).WillOnce(
1050 DoAll(SetError(pipeline_.get(), status), RunClosure<0>()));
1053 return status;
1056 EXPECT_CALL(*audio_renderer_, Pause(_)).WillOnce(RunClosure<0>());
1057 EXPECT_CALL(*video_renderer_, Pause(_)).WillOnce(RunClosure<0>());
1059 if (state == kFlushing) {
1060 if (stop_or_error == kStop) {
1061 EXPECT_CALL(*audio_renderer_, Flush(_))
1062 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), RunClosure<0>()));
1063 } else {
1064 status = PIPELINE_ERROR_READ;
1065 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(
1066 DoAll(SetError(pipeline_.get(), status), RunClosure<0>()));
1069 return status;
1072 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(RunClosure<0>());
1073 EXPECT_CALL(*video_renderer_, Flush(_)).WillOnce(RunClosure<0>());
1075 if (state == kSeeking) {
1076 if (stop_or_error == kStop) {
1077 EXPECT_CALL(*demuxer_, Seek(_, _))
1078 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1079 RunCallback<1>(PIPELINE_OK)));
1080 } else {
1081 status = PIPELINE_ERROR_READ;
1082 EXPECT_CALL(*demuxer_, Seek(_, _))
1083 .WillOnce(RunCallback<1>(status));
1086 return status;
1089 EXPECT_CALL(*demuxer_, Seek(_, _))
1090 .WillOnce(RunCallback<1>(PIPELINE_OK));
1092 if (state == kPrerolling) {
1093 if (stop_or_error == kStop) {
1094 EXPECT_CALL(*audio_renderer_, Preroll(_, _))
1095 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1096 RunCallback<1>(PIPELINE_OK)));
1097 } else {
1098 status = PIPELINE_ERROR_READ;
1099 EXPECT_CALL(*audio_renderer_, Preroll(_, _))
1100 .WillOnce(RunCallback<1>(status));
1103 return status;
1106 EXPECT_CALL(*audio_renderer_, Preroll(_, _))
1107 .WillOnce(RunCallback<1>(PIPELINE_OK));
1108 EXPECT_CALL(*video_renderer_, Preroll(_, _))
1109 .WillOnce(RunCallback<1>(PIPELINE_OK));
1111 // Playback rate and volume are updated prior to starting.
1112 EXPECT_CALL(*demuxer_, SetPlaybackRate(0.0f));
1113 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f));
1114 EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f));
1115 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
1117 if (state == kStarting) {
1118 if (stop_or_error == kStop) {
1119 EXPECT_CALL(*audio_renderer_, Play(_))
1120 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), RunClosure<0>()));
1121 } else {
1122 status = PIPELINE_ERROR_READ;
1123 EXPECT_CALL(*audio_renderer_, Play(_)).WillOnce(
1124 DoAll(SetError(pipeline_.get(), status), RunClosure<0>()));
1126 return status;
1129 NOTREACHED() << "State not supported: " << state;
1130 return status;
1133 void DoStopOrError(StopOrError stop_or_error) {
1134 InSequence s;
1136 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1137 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1138 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1140 switch (stop_or_error) {
1141 case kStop:
1142 EXPECT_CALL(callbacks_, OnStop());
1143 pipeline_->Stop(base::Bind(
1144 &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1145 break;
1147 case kError:
1148 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
1149 pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1150 break;
1152 case kErrorAndStop:
1153 EXPECT_CALL(callbacks_, OnStop());
1154 pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1155 pipeline_->Stop(base::Bind(
1156 &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1157 break;
1160 message_loop_.RunUntilIdle();
1163 DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest);
1166 #define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state) \
1167 TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \
1168 RunTest(k##state, k##stop_or_error); \
1171 INSTANTIATE_TEARDOWN_TEST(Stop, InitDemuxer);
1172 INSTANTIATE_TEARDOWN_TEST(Stop, InitAudioRenderer);
1173 INSTANTIATE_TEARDOWN_TEST(Stop, InitVideoRenderer);
1174 INSTANTIATE_TEARDOWN_TEST(Stop, Pausing);
1175 INSTANTIATE_TEARDOWN_TEST(Stop, Flushing);
1176 INSTANTIATE_TEARDOWN_TEST(Stop, Seeking);
1177 INSTANTIATE_TEARDOWN_TEST(Stop, Prerolling);
1178 INSTANTIATE_TEARDOWN_TEST(Stop, Starting);
1179 INSTANTIATE_TEARDOWN_TEST(Stop, Playing);
1181 INSTANTIATE_TEARDOWN_TEST(Error, InitDemuxer);
1182 INSTANTIATE_TEARDOWN_TEST(Error, InitAudioRenderer);
1183 INSTANTIATE_TEARDOWN_TEST(Error, InitVideoRenderer);
1184 INSTANTIATE_TEARDOWN_TEST(Error, Pausing);
1185 INSTANTIATE_TEARDOWN_TEST(Error, Flushing);
1186 INSTANTIATE_TEARDOWN_TEST(Error, Seeking);
1187 INSTANTIATE_TEARDOWN_TEST(Error, Prerolling);
1188 INSTANTIATE_TEARDOWN_TEST(Error, Starting);
1189 INSTANTIATE_TEARDOWN_TEST(Error, Playing);
1191 INSTANTIATE_TEARDOWN_TEST(ErrorAndStop, Playing);
1193 } // namespace media