Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / media / base / pipeline_unittest.cc
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.
4
5 #include <vector>
6
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/fake_text_track_stream.h"
15 #include "media/base/gmock_callback_support.h"
16 #include "media/base/media_log.h"
17 #include "media/base/mock_filters.h"
18 #include "media/base/pipeline.h"
19 #include "media/base/test_helpers.h"
20 #include "media/base/text_renderer.h"
21 #include "media/base/text_track_config.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "ui/gfx/size.h"
24
25 using ::testing::_;
26 using ::testing::DeleteArg;
27 using ::testing::DoAll;
28 // TODO(scherkus): Remove InSequence after refactoring Pipeline.
29 using ::testing::InSequence;
30 using ::testing::Invoke;
31 using ::testing::InvokeWithoutArgs;
32 using ::testing::Mock;
33 using ::testing::NotNull;
34 using ::testing::Return;
35 using ::testing::SaveArg;
36 using ::testing::StrictMock;
37 using ::testing::WithArg;
38
39 namespace media {
40
41 ACTION_P(SetDemuxerProperties, duration) {
42   arg0->SetDuration(duration);
43 }
44
45 ACTION_P2(Stop, pipeline, stop_cb) {
46   pipeline->Stop(stop_cb);
47 }
48
49 ACTION_P2(SetError, pipeline, status) {
50   pipeline->SetErrorForTesting(status);
51 }
52
53 // Used for setting expectations on pipeline callbacks.  Using a StrictMock
54 // also lets us test for missing callbacks.
55 class CallbackHelper {
56  public:
57   CallbackHelper() {}
58   virtual ~CallbackHelper() {}
59
60   MOCK_METHOD1(OnStart, void(PipelineStatus));
61   MOCK_METHOD1(OnSeek, void(PipelineStatus));
62   MOCK_METHOD0(OnStop, void());
63   MOCK_METHOD0(OnEnded, void());
64   MOCK_METHOD1(OnError, void(PipelineStatus));
65   MOCK_METHOD1(OnMetadata, void(PipelineMetadata));
66   MOCK_METHOD0(OnPrerollCompleted, void());
67   MOCK_METHOD0(OnDurationChange, void());
68
69  private:
70   DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
71 };
72
73 // TODO(scherkus): even though some filters are initialized on separate
74 // threads these test aren't flaky... why?  It's because filters' Initialize()
75 // is executed on |message_loop_| and the mock filters instantly call
76 // InitializationComplete(), which keeps the pipeline humming along.  If
77 // either filters don't call InitializationComplete() immediately or filter
78 // initialization is moved to a separate thread this test will become flaky.
79 class PipelineTest : public ::testing::Test {
80  public:
81   PipelineTest()
82       : pipeline_(new Pipeline(message_loop_.message_loop_proxy(),
83                                new MediaLog())),
84         filter_collection_(new FilterCollection()),
85         demuxer_(new MockDemuxer()) {
86     filter_collection_->SetDemuxer(demuxer_.get());
87
88     video_renderer_ = new MockVideoRenderer();
89     scoped_ptr<VideoRenderer> video_renderer(video_renderer_);
90     filter_collection_->SetVideoRenderer(video_renderer.Pass());
91
92     audio_renderer_ = new MockAudioRenderer();
93     scoped_ptr<AudioRenderer> audio_renderer(audio_renderer_);
94     filter_collection_->SetAudioRenderer(audio_renderer.Pass());
95
96     text_renderer_ = new TextRenderer(
97                          message_loop_.message_loop_proxy(),
98                          base::Bind(&PipelineTest::OnAddTextTrack,
99                                     base::Unretained(this)));
100     scoped_ptr<TextRenderer> text_renderer(text_renderer_);
101     filter_collection_->SetTextRenderer(text_renderer.Pass());
102
103     // InitializeDemuxer() adds overriding expectations for expected non-NULL
104     // streams.
105     DemuxerStream* null_pointer = NULL;
106     EXPECT_CALL(*demuxer_, GetStream(_))
107         .WillRepeatedly(Return(null_pointer));
108
109     EXPECT_CALL(*demuxer_, GetStartTime())
110         .WillRepeatedly(Return(base::TimeDelta()));
111
112     EXPECT_CALL(*demuxer_, GetTimelineOffset())
113         .WillRepeatedly(Return(base::Time()));
114
115     EXPECT_CALL(*demuxer_, GetLiveness())
116         .WillRepeatedly(Return(Demuxer::LIVENESS_UNKNOWN));
117   }
118
119   virtual ~PipelineTest() {
120     if (!pipeline_ || !pipeline_->IsRunning())
121       return;
122
123     ExpectStop();
124
125     // The mock demuxer doesn't stop the fake text track stream,
126     // so just stop it manually.
127     if (text_stream_) {
128       text_stream_->Stop();
129       message_loop_.RunUntilIdle();
130     }
131
132     // Expect a stop callback if we were started.
133     EXPECT_CALL(callbacks_, OnStop());
134     pipeline_->Stop(base::Bind(&CallbackHelper::OnStop,
135                                base::Unretained(&callbacks_)));
136     message_loop_.RunUntilIdle();
137   }
138
139  protected:
140   // Sets up expectations to allow the demuxer to initialize.
141   typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector;
142   void InitializeDemuxer(MockDemuxerStreamVector* streams,
143                          const base::TimeDelta& duration) {
144     EXPECT_CALL(callbacks_, OnDurationChange());
145     EXPECT_CALL(*demuxer_, Initialize(_, _, _))
146         .WillOnce(DoAll(SetDemuxerProperties(duration),
147                         RunCallback<1>(PIPELINE_OK)));
148
149     // Configure the demuxer to return the streams.
150     for (size_t i = 0; i < streams->size(); ++i) {
151       DemuxerStream* stream = (*streams)[i];
152       EXPECT_CALL(*demuxer_, GetStream(stream->type()))
153           .WillRepeatedly(Return(stream));
154     }
155   }
156
157   void InitializeDemuxer(MockDemuxerStreamVector* streams) {
158     // Initialize with a default non-zero duration.
159     InitializeDemuxer(streams, base::TimeDelta::FromSeconds(10));
160   }
161
162   scoped_ptr<StrictMock<MockDemuxerStream> > CreateStream(
163       DemuxerStream::Type type) {
164     scoped_ptr<StrictMock<MockDemuxerStream> > stream(
165         new StrictMock<MockDemuxerStream>(type));
166     return stream.Pass();
167   }
168
169   // Sets up expectations to allow the video renderer to initialize.
170   void InitializeVideoRenderer(DemuxerStream* stream) {
171     EXPECT_CALL(*video_renderer_, Initialize(stream, _, _, _, _, _, _, _, _))
172         .WillOnce(RunCallback<2>(PIPELINE_OK));
173     EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f));
174
175     // Startup sequence.
176     EXPECT_CALL(*video_renderer_, Preroll(demuxer_->GetStartTime(), _))
177         .WillOnce(RunCallback<1>(PIPELINE_OK));
178     EXPECT_CALL(*video_renderer_, Play(_))
179         .WillOnce(RunClosure<0>());
180   }
181
182   // Sets up expectations to allow the audio renderer to initialize.
183   void InitializeAudioRenderer(DemuxerStream* stream) {
184     EXPECT_CALL(*audio_renderer_, Initialize(stream, _, _, _, _, _, _))
185         .WillOnce(DoAll(SaveArg<4>(&audio_time_cb_),
186                         RunCallback<1>(PIPELINE_OK)));
187   }
188
189   void AddTextStream() {
190     EXPECT_CALL(*this, OnAddTextTrack(_,_))
191         .WillOnce(Invoke(this, &PipelineTest::DoOnAddTextTrack));
192     static_cast<DemuxerHost*>(pipeline_.get())->AddTextStream(text_stream(),
193                               TextTrackConfig(kTextSubtitles, "", "", ""));
194   }
195
196   // Sets up expectations on the callback and initializes the pipeline.  Called
197   // after tests have set expectations any filters they wish to use.
198   void InitializePipeline(PipelineStatus start_status) {
199     EXPECT_CALL(callbacks_, OnStart(start_status));
200
201     if (start_status == PIPELINE_OK) {
202       EXPECT_CALL(callbacks_, OnMetadata(_)).WillOnce(SaveArg<0>(&metadata_));
203
204       if (audio_stream_) {
205         EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f));
206         EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
207
208         // Startup sequence.
209         EXPECT_CALL(*audio_renderer_, Preroll(base::TimeDelta(), _))
210             .WillOnce(RunCallback<1>(PIPELINE_OK));
211         EXPECT_CALL(*audio_renderer_, Play(_))
212             .WillOnce(RunClosure<0>());
213       }
214       EXPECT_CALL(callbacks_, OnPrerollCompleted());
215     }
216
217     pipeline_->Start(
218         filter_collection_.Pass(),
219         base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
220         base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
221         base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
222         base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
223         base::Bind(&CallbackHelper::OnPrerollCompleted,
224                    base::Unretained(&callbacks_)),
225         base::Bind(&CallbackHelper::OnDurationChange,
226                    base::Unretained(&callbacks_)));
227     message_loop_.RunUntilIdle();
228   }
229
230   void CreateAudioStream() {
231     audio_stream_ = CreateStream(DemuxerStream::AUDIO);
232   }
233
234   void CreateVideoStream() {
235     video_stream_ = CreateStream(DemuxerStream::VIDEO);
236     video_stream_->set_video_decoder_config(video_decoder_config_);
237   }
238
239   void CreateTextStream() {
240     scoped_ptr<FakeTextTrackStream> text_stream(new FakeTextTrackStream);
241     text_stream_ = text_stream.Pass();
242   }
243
244   MockDemuxerStream* audio_stream() {
245     return audio_stream_.get();
246   }
247
248   MockDemuxerStream* video_stream() {
249     return video_stream_.get();
250   }
251
252   FakeTextTrackStream* text_stream() {
253     return text_stream_.get();
254   }
255
256   void ExpectSeek(const base::TimeDelta& seek_time) {
257     // Every filter should receive a call to Seek().
258     EXPECT_CALL(*demuxer_, Seek(seek_time, _))
259         .WillOnce(RunCallback<1>(PIPELINE_OK));
260
261     if (audio_stream_) {
262       EXPECT_CALL(*audio_renderer_, Pause(_))
263           .WillOnce(RunClosure<0>());
264       EXPECT_CALL(*audio_renderer_, Flush(_))
265           .WillOnce(RunClosure<0>());
266       EXPECT_CALL(*audio_renderer_, Preroll(seek_time, _))
267           .WillOnce(RunCallback<1>(PIPELINE_OK));
268       EXPECT_CALL(*audio_renderer_, SetPlaybackRate(_));
269       EXPECT_CALL(*audio_renderer_, SetVolume(_));
270       EXPECT_CALL(*audio_renderer_, Play(_))
271           .WillOnce(RunClosure<0>());
272     }
273
274     if (video_stream_) {
275       EXPECT_CALL(*video_renderer_, Pause(_))
276           .WillOnce(RunClosure<0>());
277       EXPECT_CALL(*video_renderer_, Flush(_))
278           .WillOnce(RunClosure<0>());
279       EXPECT_CALL(*video_renderer_, Preroll(seek_time, _))
280           .WillOnce(RunCallback<1>(PIPELINE_OK));
281       EXPECT_CALL(*video_renderer_, SetPlaybackRate(_));
282       EXPECT_CALL(*video_renderer_, Play(_))
283           .WillOnce(RunClosure<0>());
284     }
285
286     EXPECT_CALL(callbacks_, OnPrerollCompleted());
287
288     // We expect a successful seek callback.
289     EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
290   }
291
292   void DoSeek(const base::TimeDelta& seek_time) {
293     pipeline_->Seek(seek_time,
294                     base::Bind(&CallbackHelper::OnSeek,
295                                base::Unretained(&callbacks_)));
296
297     // We expect the time to be updated only after the seek has completed.
298     EXPECT_NE(seek_time, pipeline_->GetMediaTime());
299     message_loop_.RunUntilIdle();
300     EXPECT_EQ(seek_time, pipeline_->GetMediaTime());
301   }
302
303   void ExpectStop() {
304     if (demuxer_)
305       EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
306
307     if (audio_stream_)
308       EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
309
310     if (video_stream_)
311       EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
312   }
313
314   MOCK_METHOD2(OnAddTextTrack, void(const TextTrackConfig&,
315                                     const AddTextTrackDoneCB&));
316
317   void DoOnAddTextTrack(const TextTrackConfig& config,
318                         const AddTextTrackDoneCB& done_cb) {
319     scoped_ptr<TextTrack> text_track(new MockTextTrack);
320     done_cb.Run(text_track.Pass());
321   }
322
323   // Fixture members.
324   StrictMock<CallbackHelper> callbacks_;
325   base::SimpleTestTickClock test_tick_clock_;
326   base::MessageLoop message_loop_;
327   scoped_ptr<Pipeline> pipeline_;
328
329   scoped_ptr<FilterCollection> filter_collection_;
330   scoped_ptr<MockDemuxer> demuxer_;
331   MockVideoRenderer* video_renderer_;
332   MockAudioRenderer* audio_renderer_;
333   StrictMock<CallbackHelper> text_renderer_callbacks_;
334   TextRenderer* text_renderer_;
335   scoped_ptr<StrictMock<MockDemuxerStream> > audio_stream_;
336   scoped_ptr<StrictMock<MockDemuxerStream> > video_stream_;
337   scoped_ptr<FakeTextTrackStream> text_stream_;
338   AudioRenderer::TimeCB audio_time_cb_;
339   VideoDecoderConfig video_decoder_config_;
340   PipelineMetadata metadata_;
341
342  private:
343   DISALLOW_COPY_AND_ASSIGN(PipelineTest);
344 };
345
346 // Test that playback controls methods no-op when the pipeline hasn't been
347 // started.
348 TEST_F(PipelineTest, NotStarted) {
349   const base::TimeDelta kZero;
350
351   EXPECT_FALSE(pipeline_->IsRunning());
352
353   // Setting should still work.
354   EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
355   pipeline_->SetPlaybackRate(-1.0f);
356   EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
357   pipeline_->SetPlaybackRate(1.0f);
358   EXPECT_EQ(1.0f, pipeline_->GetPlaybackRate());
359
360   // Setting should still work.
361   EXPECT_EQ(1.0f, pipeline_->GetVolume());
362   pipeline_->SetVolume(-1.0f);
363   EXPECT_EQ(1.0f, pipeline_->GetVolume());
364   pipeline_->SetVolume(0.0f);
365   EXPECT_EQ(0.0f, pipeline_->GetVolume());
366
367   EXPECT_TRUE(kZero == pipeline_->GetMediaTime());
368   EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
369   EXPECT_TRUE(kZero == pipeline_->GetMediaDuration());
370 }
371
372 TEST_F(PipelineTest, NeverInitializes) {
373   // Don't execute the callback passed into Initialize().
374   EXPECT_CALL(*demuxer_, Initialize(_, _, _));
375
376   // This test hangs during initialization by never calling
377   // InitializationComplete().  StrictMock<> will ensure that the callback is
378   // never executed.
379   pipeline_->Start(
380         filter_collection_.Pass(),
381         base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
382         base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
383         base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
384         base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
385         base::Bind(&CallbackHelper::OnPrerollCompleted,
386                    base::Unretained(&callbacks_)),
387         base::Bind(&CallbackHelper::OnDurationChange,
388                    base::Unretained(&callbacks_)));
389   message_loop_.RunUntilIdle();
390
391
392   // Because our callback will get executed when the test tears down, we'll
393   // verify that nothing has been called, then set our expectation for the call
394   // made during tear down.
395   Mock::VerifyAndClear(&callbacks_);
396   EXPECT_CALL(callbacks_, OnStart(PIPELINE_OK));
397 }
398
399 TEST_F(PipelineTest, URLNotFound) {
400   EXPECT_CALL(*demuxer_, Initialize(_, _, _))
401       .WillOnce(RunCallback<1>(PIPELINE_ERROR_URL_NOT_FOUND));
402   EXPECT_CALL(*demuxer_, Stop(_))
403       .WillOnce(RunClosure<0>());
404
405   InitializePipeline(PIPELINE_ERROR_URL_NOT_FOUND);
406 }
407
408 TEST_F(PipelineTest, NoStreams) {
409   EXPECT_CALL(*demuxer_, Initialize(_, _, _))
410       .WillOnce(RunCallback<1>(PIPELINE_OK));
411   EXPECT_CALL(*demuxer_, Stop(_))
412       .WillOnce(RunClosure<0>());
413
414   InitializePipeline(PIPELINE_ERROR_COULD_NOT_RENDER);
415 }
416
417 TEST_F(PipelineTest, AudioStream) {
418   CreateAudioStream();
419   MockDemuxerStreamVector streams;
420   streams.push_back(audio_stream());
421
422   InitializeDemuxer(&streams);
423   InitializeAudioRenderer(audio_stream());
424
425   InitializePipeline(PIPELINE_OK);
426   EXPECT_TRUE(metadata_.has_audio);
427   EXPECT_FALSE(metadata_.has_video);
428 }
429
430 TEST_F(PipelineTest, VideoStream) {
431   CreateVideoStream();
432   MockDemuxerStreamVector streams;
433   streams.push_back(video_stream());
434
435   InitializeDemuxer(&streams);
436   InitializeVideoRenderer(video_stream());
437
438   InitializePipeline(PIPELINE_OK);
439   EXPECT_FALSE(metadata_.has_audio);
440   EXPECT_TRUE(metadata_.has_video);
441 }
442
443 TEST_F(PipelineTest, AudioVideoStream) {
444   CreateAudioStream();
445   CreateVideoStream();
446   MockDemuxerStreamVector streams;
447   streams.push_back(audio_stream());
448   streams.push_back(video_stream());
449
450   InitializeDemuxer(&streams);
451   InitializeAudioRenderer(audio_stream());
452   InitializeVideoRenderer(video_stream());
453
454   InitializePipeline(PIPELINE_OK);
455   EXPECT_TRUE(metadata_.has_audio);
456   EXPECT_TRUE(metadata_.has_video);
457 }
458
459 TEST_F(PipelineTest, VideoTextStream) {
460   CreateVideoStream();
461   CreateTextStream();
462   MockDemuxerStreamVector streams;
463   streams.push_back(video_stream());
464
465   InitializeDemuxer(&streams);
466   InitializeVideoRenderer(video_stream());
467
468   InitializePipeline(PIPELINE_OK);
469   EXPECT_FALSE(metadata_.has_audio);
470   EXPECT_TRUE(metadata_.has_video);
471
472   AddTextStream();
473   message_loop_.RunUntilIdle();
474 }
475
476 TEST_F(PipelineTest, VideoAudioTextStream) {
477   CreateVideoStream();
478   CreateAudioStream();
479   CreateTextStream();
480   MockDemuxerStreamVector streams;
481   streams.push_back(video_stream());
482   streams.push_back(audio_stream());
483
484   InitializeDemuxer(&streams);
485   InitializeVideoRenderer(video_stream());
486   InitializeAudioRenderer(audio_stream());
487
488   InitializePipeline(PIPELINE_OK);
489   EXPECT_TRUE(metadata_.has_audio);
490   EXPECT_TRUE(metadata_.has_video);
491
492   AddTextStream();
493   message_loop_.RunUntilIdle();
494 }
495
496 TEST_F(PipelineTest, Seek) {
497   CreateAudioStream();
498   CreateVideoStream();
499   CreateTextStream();
500   MockDemuxerStreamVector streams;
501   streams.push_back(audio_stream());
502   streams.push_back(video_stream());
503
504   InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(3000));
505   InitializeAudioRenderer(audio_stream());
506   InitializeVideoRenderer(video_stream());
507
508   // Initialize then seek!
509   InitializePipeline(PIPELINE_OK);
510
511   AddTextStream();
512   message_loop_.RunUntilIdle();
513
514   // Every filter should receive a call to Seek().
515   base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
516   ExpectSeek(expected);
517   DoSeek(expected);
518 }
519
520 TEST_F(PipelineTest, SetVolume) {
521   CreateAudioStream();
522   MockDemuxerStreamVector streams;
523   streams.push_back(audio_stream());
524
525   InitializeDemuxer(&streams);
526   InitializeAudioRenderer(audio_stream());
527
528   // The audio renderer should receive a call to SetVolume().
529   float expected = 0.5f;
530   EXPECT_CALL(*audio_renderer_, SetVolume(expected));
531
532   // Initialize then set volume!
533   InitializePipeline(PIPELINE_OK);
534   pipeline_->SetVolume(expected);
535 }
536
537 TEST_F(PipelineTest, Properties) {
538   CreateVideoStream();
539   MockDemuxerStreamVector streams;
540   streams.push_back(video_stream());
541
542   const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
543   InitializeDemuxer(&streams, kDuration);
544   InitializeVideoRenderer(video_stream());
545
546   InitializePipeline(PIPELINE_OK);
547   EXPECT_EQ(kDuration.ToInternalValue(),
548             pipeline_->GetMediaDuration().ToInternalValue());
549   EXPECT_FALSE(pipeline_->DidLoadingProgress());
550 }
551
552 TEST_F(PipelineTest, GetBufferedTimeRanges) {
553   CreateVideoStream();
554   MockDemuxerStreamVector streams;
555   streams.push_back(video_stream());
556
557   const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
558   InitializeDemuxer(&streams, kDuration);
559   InitializeVideoRenderer(video_stream());
560
561   InitializePipeline(PIPELINE_OK);
562
563   EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
564
565   EXPECT_FALSE(pipeline_->DidLoadingProgress());
566   pipeline_->AddBufferedTimeRange(base::TimeDelta(), kDuration / 8);
567   EXPECT_TRUE(pipeline_->DidLoadingProgress());
568   EXPECT_FALSE(pipeline_->DidLoadingProgress());
569   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
570   EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
571   EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
572
573   base::TimeDelta kSeekTime = kDuration / 2;
574   ExpectSeek(kSeekTime);
575   DoSeek(kSeekTime);
576
577   EXPECT_FALSE(pipeline_->DidLoadingProgress());
578 }
579
580 TEST_F(PipelineTest, EndedCallback) {
581   CreateAudioStream();
582   CreateVideoStream();
583   CreateTextStream();
584   MockDemuxerStreamVector streams;
585   streams.push_back(audio_stream());
586   streams.push_back(video_stream());
587
588   InitializeDemuxer(&streams);
589   InitializeAudioRenderer(audio_stream());
590   InitializeVideoRenderer(video_stream());
591   InitializePipeline(PIPELINE_OK);
592
593   AddTextStream();
594
595   // The ended callback shouldn't run until all renderers have ended.
596   pipeline_->OnAudioRendererEnded();
597   message_loop_.RunUntilIdle();
598
599   pipeline_->OnVideoRendererEnded();
600   message_loop_.RunUntilIdle();
601
602   EXPECT_CALL(callbacks_, OnEnded());
603   text_stream()->SendEosNotification();
604   message_loop_.RunUntilIdle();
605 }
606
607 TEST_F(PipelineTest, AudioStreamShorterThanVideo) {
608   base::TimeDelta duration = base::TimeDelta::FromSeconds(10);
609
610   CreateAudioStream();
611   CreateVideoStream();
612   MockDemuxerStreamVector streams;
613   streams.push_back(audio_stream());
614   streams.push_back(video_stream());
615
616   // Replace the clock so we can simulate wall clock time advancing w/o using
617   // Sleep().
618   pipeline_->SetClockForTesting(new Clock(&test_tick_clock_));
619
620   InitializeDemuxer(&streams, duration);
621   InitializeAudioRenderer(audio_stream());
622   InitializeVideoRenderer(video_stream());
623   InitializePipeline(PIPELINE_OK);
624
625   EXPECT_EQ(0, pipeline_->GetMediaTime().ToInternalValue());
626
627   float playback_rate = 1.0f;
628   EXPECT_CALL(*video_renderer_, SetPlaybackRate(playback_rate));
629   EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate));
630   pipeline_->SetPlaybackRate(playback_rate);
631   message_loop_.RunUntilIdle();
632
633   InSequence s;
634
635   // Verify that the clock doesn't advance since it hasn't been started by
636   // a time update from the audio stream.
637   int64 start_time = pipeline_->GetMediaTime().ToInternalValue();
638   test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
639   EXPECT_EQ(pipeline_->GetMediaTime().ToInternalValue(), start_time);
640
641   // Signal end of audio stream.
642   pipeline_->OnAudioRendererEnded();
643   message_loop_.RunUntilIdle();
644
645   // Verify that the clock advances.
646   start_time = pipeline_->GetMediaTime().ToInternalValue();
647   test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
648   EXPECT_GT(pipeline_->GetMediaTime().ToInternalValue(), start_time);
649
650   // Signal end of video stream and make sure OnEnded() callback occurs.
651   EXPECT_CALL(callbacks_, OnEnded());
652   pipeline_->OnVideoRendererEnded();
653 }
654
655 TEST_F(PipelineTest, ErrorDuringSeek) {
656   CreateAudioStream();
657   MockDemuxerStreamVector streams;
658   streams.push_back(audio_stream());
659
660   InitializeDemuxer(&streams);
661   InitializeAudioRenderer(audio_stream());
662   InitializePipeline(PIPELINE_OK);
663
664   float playback_rate = 1.0f;
665   EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate));
666   pipeline_->SetPlaybackRate(playback_rate);
667   message_loop_.RunUntilIdle();
668
669   base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
670
671   // Preroll() isn't called as the demuxer errors out first.
672   EXPECT_CALL(*audio_renderer_, Pause(_))
673       .WillOnce(RunClosure<0>());
674   EXPECT_CALL(*audio_renderer_, Flush(_))
675       .WillOnce(RunClosure<0>());
676   EXPECT_CALL(*audio_renderer_, Stop(_))
677       .WillOnce(RunClosure<0>());
678
679   EXPECT_CALL(*demuxer_, Seek(seek_time, _))
680       .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
681   EXPECT_CALL(*demuxer_, Stop(_))
682       .WillOnce(RunClosure<0>());
683
684   pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
685                                         base::Unretained(&callbacks_)));
686   EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
687   message_loop_.RunUntilIdle();
688 }
689
690 // Invoked function OnError. This asserts that the pipeline does not enqueue
691 // non-teardown related tasks while tearing down.
692 static void TestNoCallsAfterError(
693     Pipeline* pipeline, base::MessageLoop* message_loop,
694     PipelineStatus /* status */) {
695   CHECK(pipeline);
696   CHECK(message_loop);
697
698   // When we get to this stage, the message loop should be empty.
699   EXPECT_TRUE(message_loop->IsIdleForTesting());
700
701   // Make calls on pipeline after error has occurred.
702   pipeline->SetPlaybackRate(0.5f);
703   pipeline->SetVolume(0.5f);
704
705   // No additional tasks should be queued as a result of these calls.
706   EXPECT_TRUE(message_loop->IsIdleForTesting());
707 }
708
709 TEST_F(PipelineTest, NoMessageDuringTearDownFromError) {
710   CreateAudioStream();
711   MockDemuxerStreamVector streams;
712   streams.push_back(audio_stream());
713
714   InitializeDemuxer(&streams);
715   InitializeAudioRenderer(audio_stream());
716   InitializePipeline(PIPELINE_OK);
717
718   // Trigger additional requests on the pipeline during tear down from error.
719   base::Callback<void(PipelineStatus)> cb = base::Bind(
720       &TestNoCallsAfterError, pipeline_.get(), &message_loop_);
721   ON_CALL(callbacks_, OnError(_))
722       .WillByDefault(Invoke(&cb, &base::Callback<void(PipelineStatus)>::Run));
723
724   base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
725
726   // Seek() isn't called as the demuxer errors out first.
727   EXPECT_CALL(*audio_renderer_, Pause(_))
728       .WillOnce(RunClosure<0>());
729   EXPECT_CALL(*audio_renderer_, Flush(_))
730       .WillOnce(RunClosure<0>());
731   EXPECT_CALL(*audio_renderer_, Stop(_))
732       .WillOnce(RunClosure<0>());
733
734   EXPECT_CALL(*demuxer_, Seek(seek_time, _))
735       .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
736   EXPECT_CALL(*demuxer_, Stop(_))
737       .WillOnce(RunClosure<0>());
738
739   pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
740                                         base::Unretained(&callbacks_)));
741   EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
742   message_loop_.RunUntilIdle();
743 }
744
745 TEST_F(PipelineTest, StartTimeIsZero) {
746   CreateVideoStream();
747   MockDemuxerStreamVector streams;
748   streams.push_back(video_stream());
749
750   const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
751   InitializeDemuxer(&streams, kDuration);
752   InitializeVideoRenderer(video_stream());
753
754   InitializePipeline(PIPELINE_OK);
755   EXPECT_FALSE(metadata_.has_audio);
756   EXPECT_TRUE(metadata_.has_video);
757
758   EXPECT_EQ(base::TimeDelta(), pipeline_->GetMediaTime());
759 }
760
761 TEST_F(PipelineTest, StartTimeIsNonZero) {
762   const base::TimeDelta kStartTime = base::TimeDelta::FromSeconds(4);
763   const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
764
765   EXPECT_CALL(*demuxer_, GetStartTime())
766       .WillRepeatedly(Return(kStartTime));
767
768   CreateVideoStream();
769   MockDemuxerStreamVector streams;
770   streams.push_back(video_stream());
771
772   InitializeDemuxer(&streams, kDuration);
773   InitializeVideoRenderer(video_stream());
774
775   InitializePipeline(PIPELINE_OK);
776   EXPECT_FALSE(metadata_.has_audio);
777   EXPECT_TRUE(metadata_.has_video);
778
779   EXPECT_EQ(kStartTime, pipeline_->GetMediaTime());
780 }
781
782 static void RunTimeCB(const AudioRenderer::TimeCB& time_cb,
783                        int time_in_ms,
784                        int max_time_in_ms) {
785   time_cb.Run(base::TimeDelta::FromMilliseconds(time_in_ms),
786               base::TimeDelta::FromMilliseconds(max_time_in_ms));
787 }
788
789 TEST_F(PipelineTest, AudioTimeUpdateDuringSeek) {
790   CreateAudioStream();
791   MockDemuxerStreamVector streams;
792   streams.push_back(audio_stream());
793
794   InitializeDemuxer(&streams);
795   InitializeAudioRenderer(audio_stream());
796   InitializePipeline(PIPELINE_OK);
797
798   float playback_rate = 1.0f;
799   EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate));
800   pipeline_->SetPlaybackRate(playback_rate);
801   message_loop_.RunUntilIdle();
802
803   // Provide an initial time update so that the pipeline transitions out of the
804   // "waiting for time update" state.
805   audio_time_cb_.Run(base::TimeDelta::FromMilliseconds(100),
806                      base::TimeDelta::FromMilliseconds(500));
807
808   base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
809
810   // Arrange to trigger a time update while the demuxer is in the middle of
811   // seeking. This update should be ignored by the pipeline and the clock should
812   // not get updated.
813   base::Closure closure = base::Bind(&RunTimeCB, audio_time_cb_, 300, 700);
814   EXPECT_CALL(*demuxer_, Seek(seek_time, _))
815       .WillOnce(DoAll(InvokeWithoutArgs(&closure, &base::Closure::Run),
816                       RunCallback<1>(PIPELINE_OK)));
817
818   EXPECT_CALL(*audio_renderer_, Pause(_))
819       .WillOnce(RunClosure<0>());
820   EXPECT_CALL(*audio_renderer_, Flush(_))
821       .WillOnce(RunClosure<0>());
822   EXPECT_CALL(*audio_renderer_, Preroll(seek_time, _))
823       .WillOnce(RunCallback<1>(PIPELINE_OK));
824   EXPECT_CALL(*audio_renderer_, SetPlaybackRate(_));
825   EXPECT_CALL(*audio_renderer_, SetVolume(_));
826   EXPECT_CALL(*audio_renderer_, Play(_))
827       .WillOnce(RunClosure<0>());
828
829   EXPECT_CALL(callbacks_, OnPrerollCompleted());
830   EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
831   DoSeek(seek_time);
832
833   EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
834
835   // Now that the seek is complete, verify that time updates advance the current
836   // time.
837   base::TimeDelta new_time = seek_time + base::TimeDelta::FromMilliseconds(100);
838   audio_time_cb_.Run(new_time, new_time);
839
840   EXPECT_EQ(pipeline_->GetMediaTime(), new_time);
841 }
842
843 static void DeletePipeline(scoped_ptr<Pipeline> pipeline) {
844   // |pipeline| will go out of scope.
845 }
846
847 TEST_F(PipelineTest, DeleteAfterStop) {
848   CreateAudioStream();
849   MockDemuxerStreamVector streams;
850   streams.push_back(audio_stream());
851   InitializeDemuxer(&streams);
852   InitializeAudioRenderer(audio_stream());
853   InitializePipeline(PIPELINE_OK);
854
855   ExpectStop();
856
857   Pipeline* pipeline = pipeline_.get();
858   pipeline->Stop(base::Bind(&DeletePipeline, base::Passed(&pipeline_)));
859   message_loop_.RunUntilIdle();
860 }
861
862 class PipelineTeardownTest : public PipelineTest {
863  public:
864   enum TeardownState {
865     kInitDemuxer,
866     kInitAudioRenderer,
867     kInitVideoRenderer,
868     kPausing,
869     kFlushing,
870     kSeeking,
871     kPrerolling,
872     kStarting,
873     kPlaying,
874   };
875
876   enum StopOrError {
877     kStop,
878     kError,
879     kErrorAndStop,
880   };
881
882   PipelineTeardownTest() {}
883   virtual ~PipelineTeardownTest() {}
884
885   void RunTest(TeardownState state, StopOrError stop_or_error) {
886     switch (state) {
887       case kInitDemuxer:
888       case kInitAudioRenderer:
889       case kInitVideoRenderer:
890         DoInitialize(state, stop_or_error);
891         break;
892
893       case kPausing:
894       case kFlushing:
895       case kSeeking:
896       case kPrerolling:
897       case kStarting:
898         DoInitialize(state, stop_or_error);
899         DoSeek(state, stop_or_error);
900         break;
901
902       case kPlaying:
903         DoInitialize(state, stop_or_error);
904         DoStopOrError(stop_or_error);
905         break;
906     }
907   }
908
909  private:
910   // TODO(scherkus): We do radically different things whether teardown is
911   // invoked via stop vs error. The teardown path should be the same,
912   // see http://crbug.com/110228
913   void DoInitialize(TeardownState state, StopOrError stop_or_error) {
914     PipelineStatus expected_status =
915         SetInitializeExpectations(state, stop_or_error);
916
917     EXPECT_CALL(callbacks_, OnStart(expected_status));
918     pipeline_->Start(
919         filter_collection_.Pass(),
920         base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
921         base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
922         base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
923         base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
924         base::Bind(&CallbackHelper::OnPrerollCompleted,
925                    base::Unretained(&callbacks_)),
926         base::Bind(&CallbackHelper::OnDurationChange,
927                    base::Unretained(&callbacks_)));
928     message_loop_.RunUntilIdle();
929   }
930
931   PipelineStatus SetInitializeExpectations(TeardownState state,
932                                            StopOrError stop_or_error) {
933     PipelineStatus status = PIPELINE_OK;
934     base::Closure stop_cb = base::Bind(
935         &CallbackHelper::OnStop, base::Unretained(&callbacks_));
936
937     if (state == kInitDemuxer) {
938       if (stop_or_error == kStop) {
939         EXPECT_CALL(*demuxer_, Initialize(_, _, _))
940             .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
941                             RunCallback<1>(PIPELINE_OK)));
942         EXPECT_CALL(callbacks_, OnStop());
943       } else {
944         status = DEMUXER_ERROR_COULD_NOT_OPEN;
945         EXPECT_CALL(*demuxer_, Initialize(_, _, _))
946             .WillOnce(RunCallback<1>(status));
947       }
948
949       EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
950       return status;
951     }
952
953     CreateAudioStream();
954     CreateVideoStream();
955     MockDemuxerStreamVector streams;
956     streams.push_back(audio_stream());
957     streams.push_back(video_stream());
958     InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(3000));
959
960     if (state == kInitAudioRenderer) {
961       if (stop_or_error == kStop) {
962         EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _))
963             .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
964                             RunCallback<1>(PIPELINE_OK)));
965         EXPECT_CALL(callbacks_, OnStop());
966       } else {
967         status = PIPELINE_ERROR_INITIALIZATION_FAILED;
968         EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _))
969             .WillOnce(RunCallback<1>(status));
970       }
971
972       EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
973       EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
974       return status;
975     }
976
977     EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _))
978         .WillOnce(RunCallback<1>(PIPELINE_OK));
979
980     if (state == kInitVideoRenderer) {
981       if (stop_or_error == kStop) {
982         EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _))
983             .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
984                             RunCallback<2>(PIPELINE_OK)));
985         EXPECT_CALL(callbacks_, OnStop());
986       } else {
987         status = PIPELINE_ERROR_INITIALIZATION_FAILED;
988         EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _))
989             .WillOnce(RunCallback<2>(status));
990       }
991
992       EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
993       EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
994       EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
995       return status;
996     }
997
998     EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _))
999         .WillOnce(RunCallback<2>(PIPELINE_OK));
1000
1001     EXPECT_CALL(callbacks_, OnMetadata(_));
1002
1003     // If we get here it's a successful initialization.
1004     EXPECT_CALL(*audio_renderer_, Preroll(base::TimeDelta(), _))
1005         .WillOnce(RunCallback<1>(PIPELINE_OK));
1006     EXPECT_CALL(*video_renderer_, Preroll(base::TimeDelta(), _))
1007         .WillOnce(RunCallback<1>(PIPELINE_OK));
1008
1009     EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f));
1010     EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f));
1011     EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
1012
1013     EXPECT_CALL(*audio_renderer_, Play(_))
1014         .WillOnce(RunClosure<0>());
1015     EXPECT_CALL(*video_renderer_, Play(_))
1016         .WillOnce(RunClosure<0>());
1017
1018     if (status == PIPELINE_OK)
1019       EXPECT_CALL(callbacks_, OnPrerollCompleted());
1020
1021     return status;
1022   }
1023
1024   void DoSeek(TeardownState state, StopOrError stop_or_error) {
1025     InSequence s;
1026     PipelineStatus status = SetSeekExpectations(state, stop_or_error);
1027
1028     EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1029     EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1030     EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1031     EXPECT_CALL(callbacks_, OnSeek(status));
1032
1033     if (status == PIPELINE_OK) {
1034       EXPECT_CALL(callbacks_, OnStop());
1035     }
1036
1037     pipeline_->Seek(base::TimeDelta::FromSeconds(10), base::Bind(
1038         &CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
1039     message_loop_.RunUntilIdle();
1040   }
1041
1042   PipelineStatus SetSeekExpectations(TeardownState state,
1043                                      StopOrError stop_or_error) {
1044     PipelineStatus status = PIPELINE_OK;
1045     base::Closure stop_cb = base::Bind(
1046         &CallbackHelper::OnStop, base::Unretained(&callbacks_));
1047
1048     if (state == kPausing) {
1049       if (stop_or_error == kStop) {
1050         EXPECT_CALL(*audio_renderer_, Pause(_))
1051             .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), RunClosure<0>()));
1052       } else {
1053         status = PIPELINE_ERROR_READ;
1054         EXPECT_CALL(*audio_renderer_, Pause(_)).WillOnce(
1055             DoAll(SetError(pipeline_.get(), status), RunClosure<0>()));
1056       }
1057
1058       return status;
1059     }
1060
1061     EXPECT_CALL(*audio_renderer_, Pause(_)).WillOnce(RunClosure<0>());
1062     EXPECT_CALL(*video_renderer_, Pause(_)).WillOnce(RunClosure<0>());
1063
1064     if (state == kFlushing) {
1065       if (stop_or_error == kStop) {
1066         EXPECT_CALL(*audio_renderer_, Flush(_))
1067             .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), RunClosure<0>()));
1068       } else {
1069         status = PIPELINE_ERROR_READ;
1070         EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(
1071             DoAll(SetError(pipeline_.get(), status), RunClosure<0>()));
1072       }
1073
1074       return status;
1075     }
1076
1077     EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(RunClosure<0>());
1078     EXPECT_CALL(*video_renderer_, Flush(_)).WillOnce(RunClosure<0>());
1079
1080     if (state == kSeeking) {
1081       if (stop_or_error == kStop) {
1082         EXPECT_CALL(*demuxer_, Seek(_, _))
1083             .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1084                             RunCallback<1>(PIPELINE_OK)));
1085       } else {
1086         status = PIPELINE_ERROR_READ;
1087         EXPECT_CALL(*demuxer_, Seek(_, _))
1088             .WillOnce(RunCallback<1>(status));
1089       }
1090
1091       return status;
1092     }
1093
1094     EXPECT_CALL(*demuxer_, Seek(_, _))
1095         .WillOnce(RunCallback<1>(PIPELINE_OK));
1096
1097     if (state == kPrerolling) {
1098       if (stop_or_error == kStop) {
1099         EXPECT_CALL(*audio_renderer_, Preroll(_, _))
1100             .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1101                             RunCallback<1>(PIPELINE_OK)));
1102       } else {
1103         status = PIPELINE_ERROR_READ;
1104         EXPECT_CALL(*audio_renderer_, Preroll(_, _))
1105             .WillOnce(RunCallback<1>(status));
1106       }
1107
1108       return status;
1109     }
1110
1111     EXPECT_CALL(*audio_renderer_, Preroll(_, _))
1112         .WillOnce(RunCallback<1>(PIPELINE_OK));
1113     EXPECT_CALL(*video_renderer_, Preroll(_, _))
1114         .WillOnce(RunCallback<1>(PIPELINE_OK));
1115
1116     // Playback rate and volume are updated prior to starting.
1117     EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f));
1118     EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f));
1119     EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
1120
1121     if (state == kStarting) {
1122       if (stop_or_error == kStop) {
1123         EXPECT_CALL(*audio_renderer_, Play(_))
1124             .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), RunClosure<0>()));
1125       } else {
1126         status = PIPELINE_ERROR_READ;
1127         EXPECT_CALL(*audio_renderer_, Play(_)).WillOnce(
1128             DoAll(SetError(pipeline_.get(), status), RunClosure<0>()));
1129       }
1130       return status;
1131     }
1132
1133     NOTREACHED() << "State not supported: " << state;
1134     return status;
1135   }
1136
1137   void DoStopOrError(StopOrError stop_or_error) {
1138     InSequence s;
1139
1140     EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1141     EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1142     EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1143
1144     switch (stop_or_error) {
1145       case kStop:
1146         EXPECT_CALL(callbacks_, OnStop());
1147         pipeline_->Stop(base::Bind(
1148             &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1149         break;
1150
1151       case kError:
1152         EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
1153         pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1154         break;
1155
1156       case kErrorAndStop:
1157         EXPECT_CALL(callbacks_, OnStop());
1158         pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1159         pipeline_->Stop(base::Bind(
1160             &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1161         break;
1162     }
1163
1164     message_loop_.RunUntilIdle();
1165   }
1166
1167   DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest);
1168 };
1169
1170 #define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state) \
1171     TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \
1172       RunTest(k##state, k##stop_or_error); \
1173     }
1174
1175 INSTANTIATE_TEARDOWN_TEST(Stop, InitDemuxer);
1176 INSTANTIATE_TEARDOWN_TEST(Stop, InitAudioRenderer);
1177 INSTANTIATE_TEARDOWN_TEST(Stop, InitVideoRenderer);
1178 INSTANTIATE_TEARDOWN_TEST(Stop, Pausing);
1179 INSTANTIATE_TEARDOWN_TEST(Stop, Flushing);
1180 INSTANTIATE_TEARDOWN_TEST(Stop, Seeking);
1181 INSTANTIATE_TEARDOWN_TEST(Stop, Prerolling);
1182 INSTANTIATE_TEARDOWN_TEST(Stop, Starting);
1183 INSTANTIATE_TEARDOWN_TEST(Stop, Playing);
1184
1185 INSTANTIATE_TEARDOWN_TEST(Error, InitDemuxer);
1186 INSTANTIATE_TEARDOWN_TEST(Error, InitAudioRenderer);
1187 INSTANTIATE_TEARDOWN_TEST(Error, InitVideoRenderer);
1188 INSTANTIATE_TEARDOWN_TEST(Error, Pausing);
1189 INSTANTIATE_TEARDOWN_TEST(Error, Flushing);
1190 INSTANTIATE_TEARDOWN_TEST(Error, Seeking);
1191 INSTANTIATE_TEARDOWN_TEST(Error, Prerolling);
1192 INSTANTIATE_TEARDOWN_TEST(Error, Starting);
1193 INSTANTIATE_TEARDOWN_TEST(Error, Playing);
1194
1195 INSTANTIATE_TEARDOWN_TEST(ErrorAndStop, Playing);
1196
1197 }  // namespace media