Upstream version 9.38.198.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/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"
24
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;
39
40 namespace media {
41
42 ACTION_P(SetDemuxerProperties, duration) {
43   arg0->SetDuration(duration);
44 }
45
46 ACTION_P2(Stop, pipeline, stop_cb) {
47   pipeline->Stop(stop_cb);
48 }
49
50 ACTION_P2(SetError, pipeline, status) {
51   pipeline->SetErrorForTesting(status);
52 }
53
54 ACTION_P2(SetBufferingState, cb, buffering_state) {
55   cb->Run(buffering_state);
56 }
57
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() {}
64
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());
73
74  private:
75   DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
76 };
77
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());
92
93     video_renderer_ = new StrictMock<MockVideoRenderer>();
94     scoped_ptr<VideoRenderer> video_renderer(video_renderer_);
95     filter_collection_->SetVideoRenderer(video_renderer.Pass());
96
97     audio_renderer_ = new StrictMock<MockAudioRenderer>();
98     scoped_ptr<AudioRenderer> audio_renderer(audio_renderer_);
99     filter_collection_->SetAudioRenderer(audio_renderer.Pass());
100
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());
107
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));
113
114     EXPECT_CALL(*demuxer_, GetTimelineOffset())
115         .WillRepeatedly(Return(base::Time()));
116
117     EXPECT_CALL(*demuxer_, GetLiveness())
118         .WillRepeatedly(Return(Demuxer::LIVENESS_UNKNOWN));
119   }
120
121   virtual ~PipelineTest() {
122     if (!pipeline_ || !pipeline_->IsRunning())
123       return;
124
125     ExpectDemuxerStop();
126
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();
132     }
133
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();
139   }
140
141   void OnDemuxerError() {
142     // Cast because OnDemuxerError is private in Pipeline.
143     static_cast<DemuxerHost*>(pipeline_.get())
144         ->OnDemuxerError(PIPELINE_ERROR_ABORT);
145   }
146
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)));
156
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));
162     }
163   }
164
165   void SetDemuxerExpectations(MockDemuxerStreamVector* streams) {
166     // Initialize with a default non-zero duration.
167     SetDemuxerExpectations(streams, base::TimeDelta::FromSeconds(10));
168   }
169
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();
175   }
176
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)));
183   }
184
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)));
192   }
193
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, "", "", ""));
199   }
200
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));
205
206     if (start_status == PIPELINE_OK) {
207       EXPECT_CALL(callbacks_, OnMetadata(_)).WillOnce(SaveArg<0>(&metadata_));
208
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));
219       }
220
221       if (video_stream_) {
222         EXPECT_CALL(*video_renderer_, StartPlaying())
223             .WillOnce(SetBufferingState(&video_buffering_state_cb_,
224                                         BUFFERING_HAVE_ENOUGH));
225       }
226
227       EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
228     }
229
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();
241   }
242
243   void CreateAudioStream() {
244     audio_stream_ = CreateStream(DemuxerStream::AUDIO);
245   }
246
247   void CreateVideoStream() {
248     video_stream_ = CreateStream(DemuxerStream::VIDEO);
249     video_stream_->set_video_decoder_config(video_decoder_config_);
250   }
251
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();
256   }
257
258   MockDemuxerStream* audio_stream() {
259     return audio_stream_.get();
260   }
261
262   MockDemuxerStream* video_stream() {
263     return video_stream_.get();
264   }
265
266   FakeTextTrackStream* text_stream() {
267     return text_stream_.get();
268   }
269
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));
274
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(_));
289     }
290
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));
299     }
300
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));
304   }
305
306   void DoSeek(const base::TimeDelta& seek_time) {
307     pipeline_->Seek(seek_time,
308                     base::Bind(&CallbackHelper::OnSeek,
309                                base::Unretained(&callbacks_)));
310
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());
315   }
316
317   void DestroyPipeline() {
318     // In real code Pipeline could be destroyed on a different thread. All weak
319     // pointers must have been invalidated before the stop callback returns.
320     DCHECK(!pipeline_->HasWeakPtrsForTesting());
321     pipeline_.reset();
322   }
323
324   void ExpectDemuxerStop() {
325     if (demuxer_)
326       EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
327   }
328
329   void ExpectPipelineStopAndDestroyPipeline() {
330     // After the Pipeline is stopped, it could be destroyed any time. Always
331     // destroy the pipeline immediately after OnStop() to test this.
332     EXPECT_CALL(callbacks_, OnStop())
333         .WillOnce(Invoke(this, &PipelineTest::DestroyPipeline));
334   }
335
336   MOCK_METHOD2(OnAddTextTrack, void(const TextTrackConfig&,
337                                     const AddTextTrackDoneCB&));
338
339   void DoOnAddTextTrack(const TextTrackConfig& config,
340                         const AddTextTrackDoneCB& done_cb) {
341     scoped_ptr<TextTrack> text_track(new MockTextTrack);
342     done_cb.Run(text_track.Pass());
343   }
344
345   // Fixture members.
346   StrictMock<CallbackHelper> callbacks_;
347   base::SimpleTestTickClock test_tick_clock_;
348   base::MessageLoop message_loop_;
349   scoped_ptr<Pipeline> pipeline_;
350
351   scoped_ptr<FilterCollection> filter_collection_;
352   scoped_ptr<StrictMock<MockDemuxer> > demuxer_;
353   StrictMock<MockVideoRenderer>* video_renderer_;
354   StrictMock<MockAudioRenderer>* audio_renderer_;
355   StrictMock<MockTimeSource> time_source_;
356   StrictMock<CallbackHelper> text_renderer_callbacks_;
357   TextRenderer* text_renderer_;
358   scoped_ptr<StrictMock<MockDemuxerStream> > audio_stream_;
359   scoped_ptr<StrictMock<MockDemuxerStream> > video_stream_;
360   scoped_ptr<FakeTextTrackStream> text_stream_;
361   AudioRenderer::TimeCB audio_time_cb_;
362   BufferingStateCB audio_buffering_state_cb_;
363   BufferingStateCB video_buffering_state_cb_;
364   base::Closure audio_ended_cb_;
365   base::Closure video_ended_cb_;
366   VideoDecoderConfig video_decoder_config_;
367   PipelineMetadata metadata_;
368
369  private:
370   DISALLOW_COPY_AND_ASSIGN(PipelineTest);
371 };
372
373 // Test that playback controls methods no-op when the pipeline hasn't been
374 // started.
375 TEST_F(PipelineTest, NotStarted) {
376   const base::TimeDelta kZero;
377
378   EXPECT_FALSE(pipeline_->IsRunning());
379
380   // Setting should still work.
381   EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
382   pipeline_->SetPlaybackRate(-1.0f);
383   EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
384   pipeline_->SetPlaybackRate(1.0f);
385   EXPECT_EQ(1.0f, pipeline_->GetPlaybackRate());
386
387   // Setting should still work.
388   EXPECT_EQ(1.0f, pipeline_->GetVolume());
389   pipeline_->SetVolume(-1.0f);
390   EXPECT_EQ(1.0f, pipeline_->GetVolume());
391   pipeline_->SetVolume(0.0f);
392   EXPECT_EQ(0.0f, pipeline_->GetVolume());
393
394   EXPECT_TRUE(kZero == pipeline_->GetMediaTime());
395   EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
396   EXPECT_TRUE(kZero == pipeline_->GetMediaDuration());
397 }
398
399 TEST_F(PipelineTest, NeverInitializes) {
400   // Don't execute the callback passed into Initialize().
401   EXPECT_CALL(*demuxer_, Initialize(_, _, _));
402
403   // This test hangs during initialization by never calling
404   // InitializationComplete().  StrictMock<> will ensure that the callback is
405   // never executed.
406   pipeline_->Start(
407         filter_collection_.Pass(),
408         base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
409         base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
410         base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
411         base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
412         base::Bind(&CallbackHelper::OnBufferingStateChange,
413                    base::Unretained(&callbacks_)),
414         base::Bind(&CallbackHelper::OnDurationChange,
415                    base::Unretained(&callbacks_)));
416   message_loop_.RunUntilIdle();
417
418   // Because our callback will get executed when the test tears down, we'll
419   // verify that nothing has been called, then set our expectation for the call
420   // made during tear down.
421   Mock::VerifyAndClear(&callbacks_);
422   EXPECT_CALL(callbacks_, OnStart(PIPELINE_OK));
423 }
424
425 TEST_F(PipelineTest, StopWithoutStart) {
426   ExpectPipelineStopAndDestroyPipeline();
427   pipeline_->Stop(
428       base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
429   message_loop_.RunUntilIdle();
430 }
431
432 TEST_F(PipelineTest, StartThenStopImmediately) {
433   EXPECT_CALL(*demuxer_, Initialize(_, _, _))
434       .WillOnce(RunCallback<1>(PIPELINE_OK));
435   EXPECT_CALL(*demuxer_, Stop(_))
436       .WillOnce(RunClosure<0>());
437
438   EXPECT_CALL(callbacks_, OnStart(_));
439
440   pipeline_->Start(
441       filter_collection_.Pass(),
442       base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
443       base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
444       base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
445       base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
446       base::Bind(&CallbackHelper::OnBufferingStateChange,
447                  base::Unretained(&callbacks_)),
448       base::Bind(&CallbackHelper::OnDurationChange,
449                  base::Unretained(&callbacks_)));
450
451   // Expect a stop callback if we were started.
452   ExpectPipelineStopAndDestroyPipeline();
453   pipeline_->Stop(
454       base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
455   message_loop_.RunUntilIdle();
456 }
457
458 TEST_F(PipelineTest, DemuxerErrorDuringStop) {
459   CreateAudioStream();
460   MockDemuxerStreamVector streams;
461   streams.push_back(audio_stream());
462
463   SetDemuxerExpectations(&streams);
464   SetAudioRendererExpectations(audio_stream());
465
466   StartPipeline(PIPELINE_OK);
467
468   EXPECT_CALL(*demuxer_, Stop(_))
469       .WillOnce(DoAll(InvokeWithoutArgs(this, &PipelineTest::OnDemuxerError),
470                       RunClosure<0>()));
471   ExpectPipelineStopAndDestroyPipeline();
472
473   pipeline_->Stop(
474       base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
475   message_loop_.RunUntilIdle();
476 }
477
478 TEST_F(PipelineTest, URLNotFound) {
479   EXPECT_CALL(*demuxer_, Initialize(_, _, _))
480       .WillOnce(RunCallback<1>(PIPELINE_ERROR_URL_NOT_FOUND));
481   EXPECT_CALL(*demuxer_, Stop(_))
482       .WillOnce(RunClosure<0>());
483
484   StartPipeline(PIPELINE_ERROR_URL_NOT_FOUND);
485 }
486
487 TEST_F(PipelineTest, NoStreams) {
488   EXPECT_CALL(*demuxer_, Initialize(_, _, _))
489       .WillOnce(RunCallback<1>(PIPELINE_OK));
490   EXPECT_CALL(*demuxer_, Stop(_))
491       .WillOnce(RunClosure<0>());
492
493   StartPipeline(PIPELINE_ERROR_COULD_NOT_RENDER);
494 }
495
496 TEST_F(PipelineTest, AudioStream) {
497   CreateAudioStream();
498   MockDemuxerStreamVector streams;
499   streams.push_back(audio_stream());
500
501   SetDemuxerExpectations(&streams);
502   SetAudioRendererExpectations(audio_stream());
503
504   StartPipeline(PIPELINE_OK);
505   EXPECT_TRUE(metadata_.has_audio);
506   EXPECT_FALSE(metadata_.has_video);
507 }
508
509 TEST_F(PipelineTest, VideoStream) {
510   CreateVideoStream();
511   MockDemuxerStreamVector streams;
512   streams.push_back(video_stream());
513
514   SetDemuxerExpectations(&streams);
515   SetVideoRendererExpectations(video_stream());
516
517   StartPipeline(PIPELINE_OK);
518   EXPECT_FALSE(metadata_.has_audio);
519   EXPECT_TRUE(metadata_.has_video);
520 }
521
522 TEST_F(PipelineTest, AudioVideoStream) {
523   CreateAudioStream();
524   CreateVideoStream();
525   MockDemuxerStreamVector streams;
526   streams.push_back(audio_stream());
527   streams.push_back(video_stream());
528
529   SetDemuxerExpectations(&streams);
530   SetAudioRendererExpectations(audio_stream());
531   SetVideoRendererExpectations(video_stream());
532
533   StartPipeline(PIPELINE_OK);
534   EXPECT_TRUE(metadata_.has_audio);
535   EXPECT_TRUE(metadata_.has_video);
536 }
537
538 TEST_F(PipelineTest, VideoTextStream) {
539   CreateVideoStream();
540   CreateTextStream();
541   MockDemuxerStreamVector streams;
542   streams.push_back(video_stream());
543
544   SetDemuxerExpectations(&streams);
545   SetVideoRendererExpectations(video_stream());
546
547   StartPipeline(PIPELINE_OK);
548   EXPECT_FALSE(metadata_.has_audio);
549   EXPECT_TRUE(metadata_.has_video);
550
551   AddTextStream();
552   message_loop_.RunUntilIdle();
553 }
554
555 TEST_F(PipelineTest, VideoAudioTextStream) {
556   CreateVideoStream();
557   CreateAudioStream();
558   CreateTextStream();
559   MockDemuxerStreamVector streams;
560   streams.push_back(video_stream());
561   streams.push_back(audio_stream());
562
563   SetDemuxerExpectations(&streams);
564   SetVideoRendererExpectations(video_stream());
565   SetAudioRendererExpectations(audio_stream());
566
567   StartPipeline(PIPELINE_OK);
568   EXPECT_TRUE(metadata_.has_audio);
569   EXPECT_TRUE(metadata_.has_video);
570
571   AddTextStream();
572   message_loop_.RunUntilIdle();
573 }
574
575 TEST_F(PipelineTest, Seek) {
576   CreateAudioStream();
577   CreateVideoStream();
578   CreateTextStream();
579   MockDemuxerStreamVector streams;
580   streams.push_back(audio_stream());
581   streams.push_back(video_stream());
582
583   SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
584   SetAudioRendererExpectations(audio_stream());
585   SetVideoRendererExpectations(video_stream());
586
587   // Initialize then seek!
588   StartPipeline(PIPELINE_OK);
589
590   // Every filter should receive a call to Seek().
591   base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
592   ExpectSeek(expected, false);
593   DoSeek(expected);
594 }
595
596 TEST_F(PipelineTest, SeekAfterError) {
597   CreateAudioStream();
598   MockDemuxerStreamVector streams;
599   streams.push_back(audio_stream());
600
601   SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
602   SetAudioRendererExpectations(audio_stream());
603
604   // Initialize then seek!
605   StartPipeline(PIPELINE_OK);
606
607   EXPECT_CALL(*demuxer_, Stop(_))
608       .WillOnce(RunClosure<0>());
609   EXPECT_CALL(callbacks_, OnError(_));
610
611   static_cast<DemuxerHost*>(pipeline_.get())
612       ->OnDemuxerError(PIPELINE_ERROR_ABORT);
613   message_loop_.RunUntilIdle();
614
615   pipeline_->Seek(
616       base::TimeDelta::FromMilliseconds(100),
617       base::Bind(&CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
618   message_loop_.RunUntilIdle();
619 }
620
621 TEST_F(PipelineTest, SetVolume) {
622   CreateAudioStream();
623   MockDemuxerStreamVector streams;
624   streams.push_back(audio_stream());
625
626   SetDemuxerExpectations(&streams);
627   SetAudioRendererExpectations(audio_stream());
628
629   // The audio renderer should receive a call to SetVolume().
630   float expected = 0.5f;
631   EXPECT_CALL(*audio_renderer_, SetVolume(expected));
632
633   // Initialize then set volume!
634   StartPipeline(PIPELINE_OK);
635   pipeline_->SetVolume(expected);
636 }
637
638 TEST_F(PipelineTest, Properties) {
639   CreateVideoStream();
640   MockDemuxerStreamVector streams;
641   streams.push_back(video_stream());
642
643   const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
644   SetDemuxerExpectations(&streams, kDuration);
645   SetVideoRendererExpectations(video_stream());
646
647   StartPipeline(PIPELINE_OK);
648   EXPECT_EQ(kDuration.ToInternalValue(),
649             pipeline_->GetMediaDuration().ToInternalValue());
650   EXPECT_FALSE(pipeline_->DidLoadingProgress());
651 }
652
653 TEST_F(PipelineTest, GetBufferedTimeRanges) {
654   CreateVideoStream();
655   MockDemuxerStreamVector streams;
656   streams.push_back(video_stream());
657
658   const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
659   SetDemuxerExpectations(&streams, kDuration);
660   SetVideoRendererExpectations(video_stream());
661
662   StartPipeline(PIPELINE_OK);
663
664   EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
665
666   EXPECT_FALSE(pipeline_->DidLoadingProgress());
667   pipeline_->AddBufferedTimeRange(base::TimeDelta(), kDuration / 8);
668   EXPECT_TRUE(pipeline_->DidLoadingProgress());
669   EXPECT_FALSE(pipeline_->DidLoadingProgress());
670   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
671   EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
672   EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
673
674   base::TimeDelta kSeekTime = kDuration / 2;
675   ExpectSeek(kSeekTime, false);
676   DoSeek(kSeekTime);
677
678   EXPECT_FALSE(pipeline_->DidLoadingProgress());
679 }
680
681 TEST_F(PipelineTest, EndedCallback) {
682   CreateAudioStream();
683   CreateVideoStream();
684   CreateTextStream();
685   MockDemuxerStreamVector streams;
686   streams.push_back(audio_stream());
687   streams.push_back(video_stream());
688
689   SetDemuxerExpectations(&streams);
690   SetAudioRendererExpectations(audio_stream());
691   SetVideoRendererExpectations(video_stream());
692   StartPipeline(PIPELINE_OK);
693
694   AddTextStream();
695
696   // The ended callback shouldn't run until all renderers have ended.
697   audio_ended_cb_.Run();
698   message_loop_.RunUntilIdle();
699
700   video_ended_cb_.Run();
701   message_loop_.RunUntilIdle();
702
703   EXPECT_CALL(time_source_, StopTicking());
704   EXPECT_CALL(callbacks_, OnEnded());
705   text_stream()->SendEosNotification();
706   message_loop_.RunUntilIdle();
707 }
708
709 TEST_F(PipelineTest, AudioStreamShorterThanVideo) {
710   base::TimeDelta duration = base::TimeDelta::FromSeconds(10);
711
712   CreateAudioStream();
713   CreateVideoStream();
714   MockDemuxerStreamVector streams;
715   streams.push_back(audio_stream());
716   streams.push_back(video_stream());
717
718   // Replace what's used for interpolating to simulate wall clock time.
719   pipeline_->SetTimeDeltaInterpolatorForTesting(
720       new TimeDeltaInterpolator(&test_tick_clock_));
721
722   SetDemuxerExpectations(&streams, duration);
723   SetAudioRendererExpectations(audio_stream());
724   SetVideoRendererExpectations(video_stream());
725   StartPipeline(PIPELINE_OK);
726
727   EXPECT_EQ(0, pipeline_->GetMediaTime().ToInternalValue());
728
729   float playback_rate = 1.0f;
730   EXPECT_CALL(time_source_, SetPlaybackRate(playback_rate));
731   pipeline_->SetPlaybackRate(playback_rate);
732   message_loop_.RunUntilIdle();
733
734   InSequence s;
735
736   // Verify that the clock doesn't advance since it hasn't been started by
737   // a time update from the audio stream.
738   int64 start_time = pipeline_->GetMediaTime().ToInternalValue();
739   test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
740   EXPECT_EQ(pipeline_->GetMediaTime().ToInternalValue(), start_time);
741
742   // Signal end of audio stream.
743   audio_ended_cb_.Run();
744   message_loop_.RunUntilIdle();
745
746   // Verify that the clock advances.
747   start_time = pipeline_->GetMediaTime().ToInternalValue();
748   test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
749   EXPECT_GT(pipeline_->GetMediaTime().ToInternalValue(), start_time);
750
751   // Signal end of video stream and make sure OnEnded() callback occurs.
752   EXPECT_CALL(time_source_, StopTicking());
753   EXPECT_CALL(callbacks_, OnEnded());
754   video_ended_cb_.Run();
755 }
756
757 TEST_F(PipelineTest, ErrorDuringSeek) {
758   CreateAudioStream();
759   MockDemuxerStreamVector streams;
760   streams.push_back(audio_stream());
761
762   SetDemuxerExpectations(&streams);
763   SetAudioRendererExpectations(audio_stream());
764   StartPipeline(PIPELINE_OK);
765
766   float playback_rate = 1.0f;
767   EXPECT_CALL(time_source_, SetPlaybackRate(playback_rate));
768   pipeline_->SetPlaybackRate(playback_rate);
769   message_loop_.RunUntilIdle();
770
771   base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
772
773   // Preroll() isn't called as the demuxer errors out first.
774   EXPECT_CALL(time_source_, StopTicking());
775   EXPECT_CALL(*audio_renderer_, Flush(_))
776       .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
777                                         BUFFERING_HAVE_NOTHING),
778                       RunClosure<0>()));
779
780   EXPECT_CALL(*demuxer_, Seek(seek_time, _))
781       .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
782   EXPECT_CALL(*demuxer_, Stop(_))
783       .WillOnce(RunClosure<0>());
784
785   pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
786                                         base::Unretained(&callbacks_)));
787   EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
788   message_loop_.RunUntilIdle();
789 }
790
791 // Invoked function OnError. This asserts that the pipeline does not enqueue
792 // non-teardown related tasks while tearing down.
793 static void TestNoCallsAfterError(
794     Pipeline* pipeline, base::MessageLoop* message_loop,
795     PipelineStatus /* status */) {
796   CHECK(pipeline);
797   CHECK(message_loop);
798
799   // When we get to this stage, the message loop should be empty.
800   EXPECT_TRUE(message_loop->IsIdleForTesting());
801
802   // Make calls on pipeline after error has occurred.
803   pipeline->SetPlaybackRate(0.5f);
804   pipeline->SetVolume(0.5f);
805
806   // No additional tasks should be queued as a result of these calls.
807   EXPECT_TRUE(message_loop->IsIdleForTesting());
808 }
809
810 TEST_F(PipelineTest, NoMessageDuringTearDownFromError) {
811   CreateAudioStream();
812   MockDemuxerStreamVector streams;
813   streams.push_back(audio_stream());
814
815   SetDemuxerExpectations(&streams);
816   SetAudioRendererExpectations(audio_stream());
817   StartPipeline(PIPELINE_OK);
818
819   // Trigger additional requests on the pipeline during tear down from error.
820   base::Callback<void(PipelineStatus)> cb = base::Bind(
821       &TestNoCallsAfterError, pipeline_.get(), &message_loop_);
822   ON_CALL(callbacks_, OnError(_))
823       .WillByDefault(Invoke(&cb, &base::Callback<void(PipelineStatus)>::Run));
824
825   base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
826
827   // Seek() isn't called as the demuxer errors out first.
828   EXPECT_CALL(time_source_, StopTicking());
829   EXPECT_CALL(*audio_renderer_, Flush(_))
830       .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
831                                         BUFFERING_HAVE_NOTHING),
832                       RunClosure<0>()));
833
834   EXPECT_CALL(*demuxer_, Seek(seek_time, _))
835       .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
836   EXPECT_CALL(*demuxer_, Stop(_))
837       .WillOnce(RunClosure<0>());
838
839   pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
840                                         base::Unretained(&callbacks_)));
841   EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
842   message_loop_.RunUntilIdle();
843 }
844
845 static void RunTimeCB(const AudioRenderer::TimeCB& time_cb,
846                        int time_in_ms,
847                        int max_time_in_ms) {
848   time_cb.Run(base::TimeDelta::FromMilliseconds(time_in_ms),
849               base::TimeDelta::FromMilliseconds(max_time_in_ms));
850 }
851
852 TEST_F(PipelineTest, AudioTimeUpdateDuringSeek) {
853   CreateAudioStream();
854   MockDemuxerStreamVector streams;
855   streams.push_back(audio_stream());
856
857   SetDemuxerExpectations(&streams);
858   SetAudioRendererExpectations(audio_stream());
859   StartPipeline(PIPELINE_OK);
860
861   float playback_rate = 1.0f;
862   EXPECT_CALL(time_source_, SetPlaybackRate(playback_rate));
863   pipeline_->SetPlaybackRate(playback_rate);
864   message_loop_.RunUntilIdle();
865
866   // Provide an initial time update so that the pipeline transitions out of the
867   // "waiting for time update" state.
868   audio_time_cb_.Run(base::TimeDelta::FromMilliseconds(100),
869                      base::TimeDelta::FromMilliseconds(500));
870
871   base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
872
873   // Arrange to trigger a time update while the demuxer is in the middle of
874   // seeking. This update should be ignored by the pipeline and the clock should
875   // not get updated.
876   base::Closure closure = base::Bind(&RunTimeCB, audio_time_cb_, 300, 700);
877   EXPECT_CALL(*demuxer_, Seek(seek_time, _))
878       .WillOnce(DoAll(InvokeWithoutArgs(&closure, &base::Closure::Run),
879                       RunCallback<1>(PIPELINE_OK)));
880
881   EXPECT_CALL(time_source_, StopTicking());
882   EXPECT_CALL(*audio_renderer_, Flush(_))
883       .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
884                                         BUFFERING_HAVE_NOTHING),
885                       RunClosure<0>()));
886   EXPECT_CALL(time_source_, SetMediaTime(seek_time));
887   EXPECT_CALL(time_source_, SetPlaybackRate(_));
888   EXPECT_CALL(time_source_, StartTicking());
889   EXPECT_CALL(*audio_renderer_, StartPlaying())
890       .WillOnce(SetBufferingState(&audio_buffering_state_cb_,
891                                   BUFFERING_HAVE_ENOUGH));
892   EXPECT_CALL(*audio_renderer_, SetVolume(_));
893
894   EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
895   EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
896   DoSeek(seek_time);
897
898   EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
899
900   // Now that the seek is complete, verify that time updates advance the current
901   // time.
902   base::TimeDelta new_time = seek_time + base::TimeDelta::FromMilliseconds(100);
903   audio_time_cb_.Run(new_time, new_time);
904
905   EXPECT_EQ(pipeline_->GetMediaTime(), new_time);
906 }
907
908 TEST_F(PipelineTest, DestroyAfterStop) {
909   CreateAudioStream();
910   MockDemuxerStreamVector streams;
911   streams.push_back(audio_stream());
912   SetDemuxerExpectations(&streams);
913   SetAudioRendererExpectations(audio_stream());
914   StartPipeline(PIPELINE_OK);
915
916   ExpectDemuxerStop();
917
918   ExpectPipelineStopAndDestroyPipeline();
919   pipeline_->Stop(
920       base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
921   message_loop_.RunUntilIdle();
922 }
923
924 TEST_F(PipelineTest, Underflow) {
925   CreateAudioStream();
926   CreateVideoStream();
927   MockDemuxerStreamVector streams;
928   streams.push_back(audio_stream());
929   streams.push_back(video_stream());
930
931   SetDemuxerExpectations(&streams);
932   SetAudioRendererExpectations(audio_stream());
933   SetVideoRendererExpectations(video_stream());
934   StartPipeline(PIPELINE_OK);
935
936   // Simulate underflow.
937   EXPECT_CALL(time_source_, StopTicking());
938   audio_buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
939
940   // Seek while underflowed. We shouldn't call StopTicking() again.
941   base::TimeDelta expected = base::TimeDelta::FromSeconds(5);
942   ExpectSeek(expected, true);
943   DoSeek(expected);
944 }
945
946 static void PostTimeCB(base::MessageLoop* message_loop,
947                        const AudioRenderer::TimeCB& time_cb) {
948   base::TimeDelta new_time = base::TimeDelta::FromMilliseconds(100);
949   message_loop->PostTask(FROM_HERE, base::Bind(time_cb, new_time, new_time));
950 }
951
952 TEST_F(PipelineTest, TimeUpdateAfterStop) {
953   CreateAudioStream();
954   CreateVideoStream();
955   MockDemuxerStreamVector streams;
956   streams.push_back(audio_stream());
957   streams.push_back(video_stream());
958
959   SetDemuxerExpectations(&streams);
960   SetAudioRendererExpectations(audio_stream());
961   SetVideoRendererExpectations(video_stream());
962   StartPipeline(PIPELINE_OK);
963
964   // Double post here! This is a hack to simulate the case where TimeCB is
965   // posted during ~AudioRenderer(), which is triggered in Pipeline::DoStop.
966   // Since we can't EXPECT_CALL the dtor and Pipeline::DoStop() is posted
967   // as well, we need to post twice here.
968   message_loop_.PostTask(
969       FROM_HERE, base::Bind(&PostTimeCB, &message_loop_, audio_time_cb_));
970
971   EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
972
973   ExpectPipelineStopAndDestroyPipeline();
974   pipeline_->Stop(
975       base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
976   message_loop_.RunUntilIdle();
977 }
978
979 class PipelineTeardownTest : public PipelineTest {
980  public:
981   enum TeardownState {
982     kInitDemuxer,
983     kInitAudioRenderer,
984     kInitVideoRenderer,
985     kFlushing,
986     kSeeking,
987     kPlaying,
988   };
989
990   enum StopOrError {
991     kStop,
992     kError,
993     kErrorAndStop,
994   };
995
996   PipelineTeardownTest() {}
997   virtual ~PipelineTeardownTest() {}
998
999   void RunTest(TeardownState state, StopOrError stop_or_error) {
1000     switch (state) {
1001       case kInitDemuxer:
1002       case kInitAudioRenderer:
1003       case kInitVideoRenderer:
1004         DoInitialize(state, stop_or_error);
1005         break;
1006
1007       case kFlushing:
1008       case kSeeking:
1009         DoInitialize(state, stop_or_error);
1010         DoSeek(state, stop_or_error);
1011         break;
1012
1013       case kPlaying:
1014         DoInitialize(state, stop_or_error);
1015         DoStopOrError(stop_or_error);
1016         break;
1017     }
1018   }
1019
1020  private:
1021   // TODO(scherkus): We do radically different things whether teardown is
1022   // invoked via stop vs error. The teardown path should be the same,
1023   // see http://crbug.com/110228
1024   void DoInitialize(TeardownState state, StopOrError stop_or_error) {
1025     PipelineStatus expected_status =
1026         SetInitializeExpectations(state, stop_or_error);
1027
1028     EXPECT_CALL(callbacks_, OnStart(expected_status));
1029     pipeline_->Start(
1030         filter_collection_.Pass(),
1031         base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
1032         base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
1033         base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
1034         base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
1035         base::Bind(&CallbackHelper::OnBufferingStateChange,
1036                    base::Unretained(&callbacks_)),
1037         base::Bind(&CallbackHelper::OnDurationChange,
1038                    base::Unretained(&callbacks_)));
1039     message_loop_.RunUntilIdle();
1040   }
1041
1042   PipelineStatus SetInitializeExpectations(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 == kInitDemuxer) {
1049       if (stop_or_error == kStop) {
1050         EXPECT_CALL(*demuxer_, Initialize(_, _, _))
1051             .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1052                             RunCallback<1>(PIPELINE_OK)));
1053         ExpectPipelineStopAndDestroyPipeline();
1054       } else {
1055         status = DEMUXER_ERROR_COULD_NOT_OPEN;
1056         EXPECT_CALL(*demuxer_, Initialize(_, _, _))
1057             .WillOnce(RunCallback<1>(status));
1058       }
1059
1060       EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1061       return status;
1062     }
1063
1064     CreateAudioStream();
1065     CreateVideoStream();
1066     MockDemuxerStreamVector streams;
1067     streams.push_back(audio_stream());
1068     streams.push_back(video_stream());
1069     SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
1070
1071     if (state == kInitAudioRenderer) {
1072       if (stop_or_error == kStop) {
1073         EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _))
1074             .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1075                             RunCallback<1>(PIPELINE_OK)));
1076         ExpectPipelineStopAndDestroyPipeline();
1077       } else {
1078         status = PIPELINE_ERROR_INITIALIZATION_FAILED;
1079         EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _))
1080             .WillOnce(RunCallback<1>(status));
1081       }
1082
1083       EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1084       return status;
1085     }
1086
1087     EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _))
1088         .WillOnce(DoAll(SaveArg<4>(&audio_buffering_state_cb_),
1089                         RunCallback<1>(PIPELINE_OK)));
1090
1091     if (state == kInitVideoRenderer) {
1092       if (stop_or_error == kStop) {
1093         EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _, _))
1094             .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1095                             RunCallback<2>(PIPELINE_OK)));
1096         ExpectPipelineStopAndDestroyPipeline();
1097       } else {
1098         status = PIPELINE_ERROR_INITIALIZATION_FAILED;
1099         EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _, _))
1100             .WillOnce(RunCallback<2>(status));
1101       }
1102
1103       EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1104       return status;
1105     }
1106
1107     EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _, _))
1108         .WillOnce(DoAll(SaveArg<5>(&video_buffering_state_cb_),
1109                         RunCallback<2>(PIPELINE_OK)));
1110
1111     EXPECT_CALL(callbacks_, OnMetadata(_));
1112
1113     // If we get here it's a successful initialization.
1114     EXPECT_CALL(*audio_renderer_, GetTimeSource())
1115         .WillOnce(Return(&time_source_));
1116     EXPECT_CALL(time_source_, SetMediaTime(base::TimeDelta()));
1117     EXPECT_CALL(time_source_, SetPlaybackRate(0.0f));
1118     EXPECT_CALL(time_source_, StartTicking());
1119     EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
1120     EXPECT_CALL(*audio_renderer_, StartPlaying())
1121         .WillOnce(SetBufferingState(&audio_buffering_state_cb_,
1122                                     BUFFERING_HAVE_ENOUGH));
1123     EXPECT_CALL(*video_renderer_, StartPlaying())
1124         .WillOnce(SetBufferingState(&video_buffering_state_cb_,
1125                                     BUFFERING_HAVE_ENOUGH));
1126
1127     if (status == PIPELINE_OK)
1128       EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
1129
1130     return status;
1131   }
1132
1133   void DoSeek(TeardownState state, StopOrError stop_or_error) {
1134     InSequence s;
1135     PipelineStatus status = SetSeekExpectations(state, stop_or_error);
1136
1137     EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1138     EXPECT_CALL(callbacks_, OnSeek(status));
1139
1140     if (status == PIPELINE_OK) {
1141       ExpectPipelineStopAndDestroyPipeline();
1142     }
1143
1144     pipeline_->Seek(base::TimeDelta::FromSeconds(10), base::Bind(
1145         &CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
1146     message_loop_.RunUntilIdle();
1147   }
1148
1149   PipelineStatus SetSeekExpectations(TeardownState state,
1150                                      StopOrError stop_or_error) {
1151     PipelineStatus status = PIPELINE_OK;
1152     base::Closure stop_cb = base::Bind(
1153         &CallbackHelper::OnStop, base::Unretained(&callbacks_));
1154
1155     EXPECT_CALL(time_source_, StopTicking());
1156
1157     if (state == kFlushing) {
1158       if (stop_or_error == kStop) {
1159         EXPECT_CALL(*audio_renderer_, Flush(_))
1160             .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1161                             SetBufferingState(&audio_buffering_state_cb_,
1162                                               BUFFERING_HAVE_NOTHING),
1163                             RunClosure<0>()));
1164       } else {
1165         status = PIPELINE_ERROR_READ;
1166         EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(
1167             DoAll(SetError(pipeline_.get(), status),
1168                   SetBufferingState(&audio_buffering_state_cb_,
1169                                     BUFFERING_HAVE_NOTHING),
1170                   RunClosure<0>()));
1171       }
1172
1173       return status;
1174     }
1175
1176     EXPECT_CALL(*audio_renderer_, Flush(_))
1177         .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
1178                                           BUFFERING_HAVE_NOTHING),
1179                         RunClosure<0>()));
1180     EXPECT_CALL(*video_renderer_, Flush(_))
1181         .WillOnce(DoAll(SetBufferingState(&video_buffering_state_cb_,
1182                                           BUFFERING_HAVE_NOTHING),
1183                         RunClosure<0>()));
1184
1185     if (state == kSeeking) {
1186       if (stop_or_error == kStop) {
1187         EXPECT_CALL(*demuxer_, Seek(_, _))
1188             .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1189                             RunCallback<1>(PIPELINE_OK)));
1190       } else {
1191         status = PIPELINE_ERROR_READ;
1192         EXPECT_CALL(*demuxer_, Seek(_, _))
1193             .WillOnce(RunCallback<1>(status));
1194       }
1195
1196       return status;
1197     }
1198
1199     NOTREACHED() << "State not supported: " << state;
1200     return status;
1201   }
1202
1203   void DoStopOrError(StopOrError stop_or_error) {
1204     InSequence s;
1205
1206     EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1207
1208     switch (stop_or_error) {
1209       case kStop:
1210         ExpectPipelineStopAndDestroyPipeline();
1211         pipeline_->Stop(base::Bind(
1212             &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1213         break;
1214
1215       case kError:
1216         EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
1217         pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1218         break;
1219
1220       case kErrorAndStop:
1221         EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
1222         ExpectPipelineStopAndDestroyPipeline();
1223         pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1224         pipeline_->Stop(base::Bind(
1225             &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1226         break;
1227     }
1228
1229     message_loop_.RunUntilIdle();
1230   }
1231
1232   DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest);
1233 };
1234
1235 #define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state) \
1236     TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \
1237       RunTest(k##state, k##stop_or_error); \
1238     }
1239
1240 INSTANTIATE_TEARDOWN_TEST(Stop, InitDemuxer);
1241 INSTANTIATE_TEARDOWN_TEST(Stop, InitAudioRenderer);
1242 INSTANTIATE_TEARDOWN_TEST(Stop, InitVideoRenderer);
1243 INSTANTIATE_TEARDOWN_TEST(Stop, Flushing);
1244 INSTANTIATE_TEARDOWN_TEST(Stop, Seeking);
1245 INSTANTIATE_TEARDOWN_TEST(Stop, Playing);
1246
1247 INSTANTIATE_TEARDOWN_TEST(Error, InitDemuxer);
1248 INSTANTIATE_TEARDOWN_TEST(Error, InitAudioRenderer);
1249 INSTANTIATE_TEARDOWN_TEST(Error, InitVideoRenderer);
1250 INSTANTIATE_TEARDOWN_TEST(Error, Flushing);
1251 INSTANTIATE_TEARDOWN_TEST(Error, Seeking);
1252 INSTANTIATE_TEARDOWN_TEST(Error, Playing);
1253
1254 INSTANTIATE_TEARDOWN_TEST(ErrorAndStop, Playing);
1255
1256 }  // namespace media