Update To 11.40.268.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 // TODO(scherkus): even though some filters are initialized on separate
59 // threads these test aren't flaky... why?  It's because filters' Initialize()
60 // is executed on |message_loop_| and the mock filters instantly call
61 // InitializationComplete(), which keeps the pipeline humming along.  If
62 // either filters don't call InitializationComplete() immediately or filter
63 // initialization is moved to a separate thread this test will become flaky.
64 class PipelineTest : public ::testing::Test {
65  public:
66   // Used for setting expectations on pipeline callbacks.  Using a StrictMock
67   // also lets us test for missing callbacks.
68   class CallbackHelper {
69    public:
70     CallbackHelper() {}
71     virtual ~CallbackHelper() {}
72
73     MOCK_METHOD1(OnStart, void(PipelineStatus));
74     MOCK_METHOD1(OnSeek, void(PipelineStatus));
75     MOCK_METHOD0(OnStop, void());
76     MOCK_METHOD0(OnEnded, void());
77     MOCK_METHOD1(OnError, void(PipelineStatus));
78     MOCK_METHOD1(OnMetadata, void(PipelineMetadata));
79     MOCK_METHOD1(OnBufferingStateChange, void(BufferingState));
80     MOCK_METHOD0(OnDurationChange, void());
81
82    private:
83     DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
84   };
85
86   PipelineTest()
87       : pipeline_(new Pipeline(message_loop_.message_loop_proxy(),
88                                new MediaLog())),
89         demuxer_(new StrictMock<MockDemuxer>()),
90         scoped_renderer_(new StrictMock<MockRenderer>()),
91         renderer_(scoped_renderer_.get()) {
92     // SetDemuxerExpectations() adds overriding expectations for expected
93     // non-NULL streams.
94     DemuxerStream* null_pointer = NULL;
95     EXPECT_CALL(*demuxer_, GetStream(_))
96         .WillRepeatedly(Return(null_pointer));
97
98     EXPECT_CALL(*demuxer_, GetTimelineOffset())
99         .WillRepeatedly(Return(base::Time()));
100
101     EXPECT_CALL(*demuxer_, GetLiveness())
102         .WillRepeatedly(Return(Demuxer::LIVENESS_UNKNOWN));
103
104     EXPECT_CALL(*renderer_, GetMediaTime())
105         .WillRepeatedly(Return(base::TimeDelta()));
106
107     EXPECT_CALL(*demuxer_, GetStartTime()).WillRepeatedly(Return(start_time_));
108   }
109
110   virtual ~PipelineTest() {
111     if (!pipeline_ || !pipeline_->IsRunning())
112       return;
113
114     ExpectDemuxerStop();
115
116     // The mock demuxer doesn't stop the fake text track stream,
117     // so just stop it manually.
118     if (text_stream_) {
119       text_stream_->Stop();
120       message_loop_.RunUntilIdle();
121     }
122
123     // Expect a stop callback if we were started.
124     ExpectPipelineStopAndDestroyPipeline();
125     pipeline_->Stop(base::Bind(&CallbackHelper::OnStop,
126                                base::Unretained(&callbacks_)));
127     message_loop_.RunUntilIdle();
128   }
129
130   void OnDemuxerError() {
131     // Cast because OnDemuxerError is private in Pipeline.
132     static_cast<DemuxerHost*>(pipeline_.get())
133         ->OnDemuxerError(PIPELINE_ERROR_ABORT);
134   }
135
136  protected:
137   // Sets up expectations to allow the demuxer to initialize.
138   typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector;
139   void SetDemuxerExpectations(MockDemuxerStreamVector* streams,
140                               const base::TimeDelta& duration) {
141     EXPECT_CALL(callbacks_, OnDurationChange());
142     EXPECT_CALL(*demuxer_, Initialize(_, _, _))
143         .WillOnce(DoAll(SetDemuxerProperties(duration),
144                         RunCallback<1>(PIPELINE_OK)));
145
146     // Configure the demuxer to return the streams.
147     for (size_t i = 0; i < streams->size(); ++i) {
148       DemuxerStream* stream = (*streams)[i];
149       EXPECT_CALL(*demuxer_, GetStream(stream->type()))
150           .WillRepeatedly(Return(stream));
151     }
152   }
153
154   void SetDemuxerExpectations(MockDemuxerStreamVector* streams) {
155     // Initialize with a default non-zero duration.
156     SetDemuxerExpectations(streams, base::TimeDelta::FromSeconds(10));
157   }
158
159   scoped_ptr<StrictMock<MockDemuxerStream> > CreateStream(
160       DemuxerStream::Type type) {
161     scoped_ptr<StrictMock<MockDemuxerStream> > stream(
162         new StrictMock<MockDemuxerStream>(type));
163     return stream.Pass();
164   }
165
166   // Sets up expectations to allow the video renderer to initialize.
167   void SetRendererExpectations() {
168     EXPECT_CALL(*renderer_, Initialize(_, _, _, _, _, _))
169         .WillOnce(DoAll(SaveArg<3>(&ended_cb_),
170                         SaveArg<5>(&buffering_state_cb_),
171                         RunCallback<1>()));
172     EXPECT_CALL(*renderer_, HasAudio()).WillRepeatedly(Return(audio_stream()));
173     EXPECT_CALL(*renderer_, HasVideo()).WillRepeatedly(Return(video_stream()));
174   }
175
176   void AddTextStream() {
177     EXPECT_CALL(*this, OnAddTextTrack(_,_))
178         .WillOnce(Invoke(this, &PipelineTest::DoOnAddTextTrack));
179     static_cast<DemuxerHost*>(pipeline_.get())->AddTextStream(text_stream(),
180                               TextTrackConfig(kTextSubtitles, "", "", ""));
181     message_loop_.RunUntilIdle();
182   }
183
184   void StartPipeline() {
185     pipeline_->Start(
186         demuxer_.get(),
187         scoped_renderer_.Pass(),
188         base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
189         base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
190         base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
191         base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
192         base::Bind(&CallbackHelper::OnBufferingStateChange,
193                    base::Unretained(&callbacks_)),
194         base::Bind(&CallbackHelper::OnDurationChange,
195                    base::Unretained(&callbacks_)),
196         base::Bind(&PipelineTest::OnAddTextTrack, base::Unretained(this)));
197   }
198
199   // Sets up expectations on the callback and initializes the pipeline. Called
200   // after tests have set expectations any filters they wish to use.
201   void StartPipelineAndExpect(PipelineStatus start_status) {
202     EXPECT_CALL(callbacks_, OnStart(start_status));
203
204     if (start_status == PIPELINE_OK) {
205       EXPECT_CALL(callbacks_, OnMetadata(_)).WillOnce(SaveArg<0>(&metadata_));
206       EXPECT_CALL(*renderer_, SetPlaybackRate(0.0f));
207       EXPECT_CALL(*renderer_, SetVolume(1.0f));
208       EXPECT_CALL(*renderer_, StartPlayingFrom(start_time_))
209           .WillOnce(SetBufferingState(&buffering_state_cb_,
210                                       BUFFERING_HAVE_ENOUGH));
211       EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
212     }
213
214     StartPipeline();
215     message_loop_.RunUntilIdle();
216   }
217
218   void CreateAudioStream() {
219     audio_stream_ = CreateStream(DemuxerStream::AUDIO);
220   }
221
222   void CreateVideoStream() {
223     video_stream_ = CreateStream(DemuxerStream::VIDEO);
224     video_stream_->set_video_decoder_config(video_decoder_config_);
225   }
226
227   void CreateTextStream() {
228     scoped_ptr<FakeTextTrackStream> text_stream(new FakeTextTrackStream());
229     EXPECT_CALL(*text_stream, OnRead()).Times(AnyNumber());
230     text_stream_ = text_stream.Pass();
231   }
232
233   MockDemuxerStream* audio_stream() {
234     return audio_stream_.get();
235   }
236
237   MockDemuxerStream* video_stream() {
238     return video_stream_.get();
239   }
240
241   FakeTextTrackStream* text_stream() {
242     return text_stream_.get();
243   }
244
245   void ExpectSeek(const base::TimeDelta& seek_time, bool underflowed) {
246     EXPECT_CALL(*demuxer_, Seek(seek_time, _))
247         .WillOnce(RunCallback<1>(PIPELINE_OK));
248
249     EXPECT_CALL(*renderer_, Flush(_))
250         .WillOnce(DoAll(SetBufferingState(&buffering_state_cb_,
251                                           BUFFERING_HAVE_NOTHING),
252                         RunClosure<0>()));
253     EXPECT_CALL(*renderer_, SetPlaybackRate(_));
254     EXPECT_CALL(*renderer_, SetVolume(_));
255     EXPECT_CALL(*renderer_, StartPlayingFrom(seek_time))
256         .WillOnce(SetBufferingState(&buffering_state_cb_,
257                                     BUFFERING_HAVE_ENOUGH));
258     EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
259
260     // We expect a successful seek callback followed by a buffering update.
261     EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
262     EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
263   }
264
265   void DoSeek(const base::TimeDelta& seek_time) {
266     pipeline_->Seek(seek_time,
267                     base::Bind(&CallbackHelper::OnSeek,
268                                base::Unretained(&callbacks_)));
269     message_loop_.RunUntilIdle();
270   }
271
272   void DestroyPipeline() {
273     // In real code Pipeline could be destroyed on a different thread. All weak
274     // pointers must have been invalidated before the stop callback returns.
275     DCHECK(!pipeline_->HasWeakPtrsForTesting());
276     pipeline_.reset();
277   }
278
279   void ExpectDemuxerStop() {
280     if (demuxer_)
281       EXPECT_CALL(*demuxer_, Stop());
282   }
283
284   void ExpectPipelineStopAndDestroyPipeline() {
285     // After the Pipeline is stopped, it could be destroyed any time. Always
286     // destroy the pipeline immediately after OnStop() to test this.
287     EXPECT_CALL(callbacks_, OnStop())
288         .WillOnce(Invoke(this, &PipelineTest::DestroyPipeline));
289   }
290
291   MOCK_METHOD2(OnAddTextTrack, void(const TextTrackConfig&,
292                                     const AddTextTrackDoneCB&));
293
294   void DoOnAddTextTrack(const TextTrackConfig& config,
295                         const AddTextTrackDoneCB& done_cb) {
296     scoped_ptr<TextTrack> text_track(new MockTextTrack);
297     done_cb.Run(text_track.Pass());
298   }
299
300   // Fixture members.
301   StrictMock<CallbackHelper> callbacks_;
302   base::SimpleTestTickClock test_tick_clock_;
303   base::MessageLoop message_loop_;
304   scoped_ptr<Pipeline> pipeline_;
305
306   scoped_ptr<StrictMock<MockDemuxer> > demuxer_;
307   scoped_ptr<StrictMock<MockRenderer> > scoped_renderer_;
308   StrictMock<MockRenderer>* renderer_;
309   StrictMock<CallbackHelper> text_renderer_callbacks_;
310   TextRenderer* text_renderer_;
311   scoped_ptr<StrictMock<MockDemuxerStream> > audio_stream_;
312   scoped_ptr<StrictMock<MockDemuxerStream> > video_stream_;
313   scoped_ptr<FakeTextTrackStream> text_stream_;
314   BufferingStateCB buffering_state_cb_;
315   base::Closure ended_cb_;
316   VideoDecoderConfig video_decoder_config_;
317   PipelineMetadata metadata_;
318   base::TimeDelta start_time_;
319
320  private:
321   DISALLOW_COPY_AND_ASSIGN(PipelineTest);
322 };
323
324 // Test that playback controls methods no-op when the pipeline hasn't been
325 // started.
326 TEST_F(PipelineTest, NotStarted) {
327   const base::TimeDelta kZero;
328
329   EXPECT_FALSE(pipeline_->IsRunning());
330
331   // Setting should still work.
332   EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
333   pipeline_->SetPlaybackRate(-1.0f);
334   EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
335   pipeline_->SetPlaybackRate(1.0f);
336   EXPECT_EQ(1.0f, pipeline_->GetPlaybackRate());
337
338   // Setting should still work.
339   EXPECT_EQ(1.0f, pipeline_->GetVolume());
340   pipeline_->SetVolume(-1.0f);
341   EXPECT_EQ(1.0f, pipeline_->GetVolume());
342   pipeline_->SetVolume(0.0f);
343   EXPECT_EQ(0.0f, pipeline_->GetVolume());
344
345   EXPECT_TRUE(kZero == pipeline_->GetMediaTime());
346   EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
347   EXPECT_TRUE(kZero == pipeline_->GetMediaDuration());
348 }
349
350 TEST_F(PipelineTest, NeverInitializes) {
351   // Don't execute the callback passed into Initialize().
352   EXPECT_CALL(*demuxer_, Initialize(_, _, _));
353
354   // This test hangs during initialization by never calling
355   // InitializationComplete().  StrictMock<> will ensure that the callback is
356   // never executed.
357   StartPipeline();
358   message_loop_.RunUntilIdle();
359
360   // Because our callback will get executed when the test tears down, we'll
361   // verify that nothing has been called, then set our expectation for the call
362   // made during tear down.
363   Mock::VerifyAndClear(&callbacks_);
364   EXPECT_CALL(callbacks_, OnStart(PIPELINE_OK));
365 }
366
367 TEST_F(PipelineTest, StopWithoutStart) {
368   ExpectPipelineStopAndDestroyPipeline();
369   pipeline_->Stop(
370       base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
371   message_loop_.RunUntilIdle();
372 }
373
374 TEST_F(PipelineTest, StartThenStopImmediately) {
375   EXPECT_CALL(*demuxer_, Initialize(_, _, _))
376       .WillOnce(RunCallback<1>(PIPELINE_OK));
377   EXPECT_CALL(*demuxer_, Stop());
378
379   EXPECT_CALL(callbacks_, OnStart(_));
380   StartPipeline();
381
382   // Expect a stop callback if we were started.
383   ExpectPipelineStopAndDestroyPipeline();
384   pipeline_->Stop(
385       base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
386   message_loop_.RunUntilIdle();
387 }
388
389 TEST_F(PipelineTest, DemuxerErrorDuringStop) {
390   CreateAudioStream();
391   MockDemuxerStreamVector streams;
392   streams.push_back(audio_stream());
393
394   SetDemuxerExpectations(&streams);
395   SetRendererExpectations();
396
397   StartPipelineAndExpect(PIPELINE_OK);
398
399   EXPECT_CALL(*demuxer_, Stop())
400       .WillOnce(InvokeWithoutArgs(this, &PipelineTest::OnDemuxerError));
401   ExpectPipelineStopAndDestroyPipeline();
402
403   pipeline_->Stop(
404       base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
405   message_loop_.RunUntilIdle();
406 }
407
408 TEST_F(PipelineTest, URLNotFound) {
409   EXPECT_CALL(*demuxer_, Initialize(_, _, _))
410       .WillOnce(RunCallback<1>(PIPELINE_ERROR_URL_NOT_FOUND));
411   EXPECT_CALL(*demuxer_, Stop());
412
413   StartPipelineAndExpect(PIPELINE_ERROR_URL_NOT_FOUND);
414 }
415
416 TEST_F(PipelineTest, NoStreams) {
417   EXPECT_CALL(*demuxer_, Initialize(_, _, _))
418       .WillOnce(RunCallback<1>(PIPELINE_OK));
419   EXPECT_CALL(*demuxer_, Stop());
420
421   StartPipelineAndExpect(PIPELINE_ERROR_COULD_NOT_RENDER);
422 }
423
424 TEST_F(PipelineTest, AudioStream) {
425   CreateAudioStream();
426   MockDemuxerStreamVector streams;
427   streams.push_back(audio_stream());
428
429   SetDemuxerExpectations(&streams);
430   SetRendererExpectations();
431
432   StartPipelineAndExpect(PIPELINE_OK);
433   EXPECT_TRUE(metadata_.has_audio);
434   EXPECT_FALSE(metadata_.has_video);
435 }
436
437 TEST_F(PipelineTest, VideoStream) {
438   CreateVideoStream();
439   MockDemuxerStreamVector streams;
440   streams.push_back(video_stream());
441
442   SetDemuxerExpectations(&streams);
443   SetRendererExpectations();
444
445   StartPipelineAndExpect(PIPELINE_OK);
446   EXPECT_FALSE(metadata_.has_audio);
447   EXPECT_TRUE(metadata_.has_video);
448 }
449
450 TEST_F(PipelineTest, AudioVideoStream) {
451   CreateAudioStream();
452   CreateVideoStream();
453   MockDemuxerStreamVector streams;
454   streams.push_back(audio_stream());
455   streams.push_back(video_stream());
456
457   SetDemuxerExpectations(&streams);
458   SetRendererExpectations();
459
460   StartPipelineAndExpect(PIPELINE_OK);
461   EXPECT_TRUE(metadata_.has_audio);
462   EXPECT_TRUE(metadata_.has_video);
463 }
464
465 TEST_F(PipelineTest, VideoTextStream) {
466   CreateVideoStream();
467   CreateTextStream();
468   MockDemuxerStreamVector streams;
469   streams.push_back(video_stream());
470
471   SetDemuxerExpectations(&streams);
472   SetRendererExpectations();
473
474   StartPipelineAndExpect(PIPELINE_OK);
475   EXPECT_FALSE(metadata_.has_audio);
476   EXPECT_TRUE(metadata_.has_video);
477
478   AddTextStream();
479 }
480
481 TEST_F(PipelineTest, VideoAudioTextStream) {
482   CreateVideoStream();
483   CreateAudioStream();
484   CreateTextStream();
485   MockDemuxerStreamVector streams;
486   streams.push_back(video_stream());
487   streams.push_back(audio_stream());
488
489   SetDemuxerExpectations(&streams);
490   SetRendererExpectations();
491
492   StartPipelineAndExpect(PIPELINE_OK);
493   EXPECT_TRUE(metadata_.has_audio);
494   EXPECT_TRUE(metadata_.has_video);
495
496   AddTextStream();
497 }
498
499 TEST_F(PipelineTest, Seek) {
500   CreateAudioStream();
501   CreateVideoStream();
502   CreateTextStream();
503   MockDemuxerStreamVector streams;
504   streams.push_back(audio_stream());
505   streams.push_back(video_stream());
506
507   SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
508   SetRendererExpectations();
509
510   // Initialize then seek!
511   StartPipelineAndExpect(PIPELINE_OK);
512
513   // Every filter should receive a call to Seek().
514   base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
515   ExpectSeek(expected, false);
516   DoSeek(expected);
517 }
518
519 TEST_F(PipelineTest, SeekAfterError) {
520   CreateAudioStream();
521   MockDemuxerStreamVector streams;
522   streams.push_back(audio_stream());
523
524   SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
525   SetRendererExpectations();
526
527   // Initialize then seek!
528   StartPipelineAndExpect(PIPELINE_OK);
529
530   EXPECT_CALL(*demuxer_, Stop());
531   EXPECT_CALL(callbacks_, OnError(_));
532
533   static_cast<DemuxerHost*>(pipeline_.get())
534       ->OnDemuxerError(PIPELINE_ERROR_ABORT);
535   message_loop_.RunUntilIdle();
536
537   pipeline_->Seek(
538       base::TimeDelta::FromMilliseconds(100),
539       base::Bind(&CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
540   message_loop_.RunUntilIdle();
541 }
542
543 TEST_F(PipelineTest, SetVolume) {
544   CreateAudioStream();
545   MockDemuxerStreamVector streams;
546   streams.push_back(audio_stream());
547
548   SetDemuxerExpectations(&streams);
549   SetRendererExpectations();
550
551   // The audio renderer should receive a call to SetVolume().
552   float expected = 0.5f;
553   EXPECT_CALL(*renderer_, SetVolume(expected));
554
555   // Initialize then set volume!
556   StartPipelineAndExpect(PIPELINE_OK);
557   pipeline_->SetVolume(expected);
558 }
559
560 TEST_F(PipelineTest, Properties) {
561   CreateVideoStream();
562   MockDemuxerStreamVector streams;
563   streams.push_back(video_stream());
564
565   const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
566   SetDemuxerExpectations(&streams, kDuration);
567   SetRendererExpectations();
568
569   StartPipelineAndExpect(PIPELINE_OK);
570   EXPECT_EQ(kDuration.ToInternalValue(),
571             pipeline_->GetMediaDuration().ToInternalValue());
572   EXPECT_FALSE(pipeline_->DidLoadingProgress());
573 }
574
575 TEST_F(PipelineTest, GetBufferedTimeRanges) {
576   CreateVideoStream();
577   MockDemuxerStreamVector streams;
578   streams.push_back(video_stream());
579
580   const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
581   SetDemuxerExpectations(&streams, kDuration);
582   SetRendererExpectations();
583
584   StartPipelineAndExpect(PIPELINE_OK);
585
586   EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
587
588   EXPECT_FALSE(pipeline_->DidLoadingProgress());
589   pipeline_->AddBufferedTimeRange(base::TimeDelta(), kDuration / 8);
590   EXPECT_TRUE(pipeline_->DidLoadingProgress());
591   EXPECT_FALSE(pipeline_->DidLoadingProgress());
592   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
593   EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
594   EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
595
596   base::TimeDelta kSeekTime = kDuration / 2;
597   ExpectSeek(kSeekTime, false);
598   DoSeek(kSeekTime);
599
600   EXPECT_FALSE(pipeline_->DidLoadingProgress());
601 }
602
603 TEST_F(PipelineTest, EndedCallback) {
604   CreateAudioStream();
605   CreateVideoStream();
606   CreateTextStream();
607   MockDemuxerStreamVector streams;
608   streams.push_back(audio_stream());
609   streams.push_back(video_stream());
610
611   SetDemuxerExpectations(&streams);
612   SetRendererExpectations();
613   StartPipelineAndExpect(PIPELINE_OK);
614
615   AddTextStream();
616
617   // The ended callback shouldn't run until all renderers have ended.
618   ended_cb_.Run();
619   message_loop_.RunUntilIdle();
620
621   EXPECT_CALL(callbacks_, OnEnded());
622   text_stream()->SendEosNotification();
623   message_loop_.RunUntilIdle();
624 }
625
626 TEST_F(PipelineTest, ErrorDuringSeek) {
627   CreateAudioStream();
628   MockDemuxerStreamVector streams;
629   streams.push_back(audio_stream());
630
631   SetDemuxerExpectations(&streams);
632   SetRendererExpectations();
633   StartPipelineAndExpect(PIPELINE_OK);
634
635   float playback_rate = 1.0f;
636   EXPECT_CALL(*renderer_, SetPlaybackRate(playback_rate));
637   pipeline_->SetPlaybackRate(playback_rate);
638   message_loop_.RunUntilIdle();
639
640   base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
641
642   EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
643   EXPECT_CALL(*renderer_, Flush(_))
644       .WillOnce(DoAll(SetBufferingState(&buffering_state_cb_,
645                                         BUFFERING_HAVE_NOTHING),
646                       RunClosure<0>()));
647
648   EXPECT_CALL(*demuxer_, Seek(seek_time, _))
649       .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
650   EXPECT_CALL(*demuxer_, Stop());
651
652   pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
653                                         base::Unretained(&callbacks_)));
654   EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
655   message_loop_.RunUntilIdle();
656 }
657
658 // Invoked function OnError. This asserts that the pipeline does not enqueue
659 // non-teardown related tasks while tearing down.
660 static void TestNoCallsAfterError(
661     Pipeline* pipeline, base::MessageLoop* message_loop,
662     PipelineStatus /* status */) {
663   CHECK(pipeline);
664   CHECK(message_loop);
665
666   // When we get to this stage, the message loop should be empty.
667   EXPECT_TRUE(message_loop->IsIdleForTesting());
668
669   // Make calls on pipeline after error has occurred.
670   pipeline->SetPlaybackRate(0.5f);
671   pipeline->SetVolume(0.5f);
672
673   // No additional tasks should be queued as a result of these calls.
674   EXPECT_TRUE(message_loop->IsIdleForTesting());
675 }
676
677 TEST_F(PipelineTest, NoMessageDuringTearDownFromError) {
678   CreateAudioStream();
679   MockDemuxerStreamVector streams;
680   streams.push_back(audio_stream());
681
682   SetDemuxerExpectations(&streams);
683   SetRendererExpectations();
684   StartPipelineAndExpect(PIPELINE_OK);
685
686   // Trigger additional requests on the pipeline during tear down from error.
687   base::Callback<void(PipelineStatus)> cb = base::Bind(
688       &TestNoCallsAfterError, pipeline_.get(), &message_loop_);
689   ON_CALL(callbacks_, OnError(_))
690       .WillByDefault(Invoke(&cb, &base::Callback<void(PipelineStatus)>::Run));
691
692   base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
693
694   // Seek() isn't called as the demuxer errors out first.
695   EXPECT_CALL(*renderer_, Flush(_))
696       .WillOnce(DoAll(SetBufferingState(&buffering_state_cb_,
697                                         BUFFERING_HAVE_NOTHING),
698                       RunClosure<0>()));
699   EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
700
701   EXPECT_CALL(*demuxer_, Seek(seek_time, _))
702       .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
703   EXPECT_CALL(*demuxer_, Stop());
704
705   pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
706                                         base::Unretained(&callbacks_)));
707   EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
708   message_loop_.RunUntilIdle();
709 }
710
711 TEST_F(PipelineTest, DestroyAfterStop) {
712   CreateAudioStream();
713   MockDemuxerStreamVector streams;
714   streams.push_back(audio_stream());
715   SetDemuxerExpectations(&streams);
716   SetRendererExpectations();
717   StartPipelineAndExpect(PIPELINE_OK);
718
719   ExpectDemuxerStop();
720
721   ExpectPipelineStopAndDestroyPipeline();
722   pipeline_->Stop(
723       base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
724   message_loop_.RunUntilIdle();
725 }
726
727 TEST_F(PipelineTest, Underflow) {
728   CreateAudioStream();
729   CreateVideoStream();
730   MockDemuxerStreamVector streams;
731   streams.push_back(audio_stream());
732   streams.push_back(video_stream());
733
734   SetDemuxerExpectations(&streams);
735   SetRendererExpectations();
736   StartPipelineAndExpect(PIPELINE_OK);
737
738   // Simulate underflow.
739   EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
740   buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
741
742   // Seek while underflowed.
743   base::TimeDelta expected = base::TimeDelta::FromSeconds(5);
744   ExpectSeek(expected, true);
745   DoSeek(expected);
746 }
747
748 TEST_F(PipelineTest, PositiveStartTime) {
749   start_time_ = base::TimeDelta::FromSeconds(1);
750   EXPECT_CALL(*demuxer_, GetStartTime()).WillRepeatedly(Return(start_time_));
751   CreateAudioStream();
752   MockDemuxerStreamVector streams;
753   streams.push_back(audio_stream());
754   SetDemuxerExpectations(&streams);
755   SetRendererExpectations();
756   StartPipelineAndExpect(PIPELINE_OK);
757   ExpectDemuxerStop();
758   ExpectPipelineStopAndDestroyPipeline();
759   pipeline_->Stop(
760       base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
761   message_loop_.RunUntilIdle();
762 }
763
764 class PipelineTeardownTest : public PipelineTest {
765  public:
766   enum TeardownState {
767     kInitDemuxer,
768     kInitRenderer,
769     kFlushing,
770     kSeeking,
771     kPlaying,
772   };
773
774   enum StopOrError {
775     kStop,
776     kError,
777     kErrorAndStop,
778   };
779
780   PipelineTeardownTest() {}
781   ~PipelineTeardownTest() override {}
782
783   void RunTest(TeardownState state, StopOrError stop_or_error) {
784     switch (state) {
785       case kInitDemuxer:
786       case kInitRenderer:
787         DoInitialize(state, stop_or_error);
788         break;
789
790       case kFlushing:
791       case kSeeking:
792         DoInitialize(state, stop_or_error);
793         DoSeek(state, stop_or_error);
794         break;
795
796       case kPlaying:
797         DoInitialize(state, stop_or_error);
798         DoStopOrError(stop_or_error);
799         break;
800     }
801   }
802
803  private:
804   // TODO(scherkus): We do radically different things whether teardown is
805   // invoked via stop vs error. The teardown path should be the same,
806   // see http://crbug.com/110228
807   void DoInitialize(TeardownState state, StopOrError stop_or_error) {
808     PipelineStatus expected_status =
809         SetInitializeExpectations(state, stop_or_error);
810
811     EXPECT_CALL(callbacks_, OnStart(expected_status));
812     StartPipeline();
813     message_loop_.RunUntilIdle();
814   }
815
816   PipelineStatus SetInitializeExpectations(TeardownState state,
817                                            StopOrError stop_or_error) {
818     PipelineStatus status = PIPELINE_OK;
819     base::Closure stop_cb = base::Bind(
820         &CallbackHelper::OnStop, base::Unretained(&callbacks_));
821
822     if (state == kInitDemuxer) {
823       if (stop_or_error == kStop) {
824         EXPECT_CALL(*demuxer_, Initialize(_, _, _))
825             .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
826                             RunCallback<1>(PIPELINE_OK)));
827         ExpectPipelineStopAndDestroyPipeline();
828       } else {
829         status = DEMUXER_ERROR_COULD_NOT_OPEN;
830         EXPECT_CALL(*demuxer_, Initialize(_, _, _))
831             .WillOnce(RunCallback<1>(status));
832       }
833
834       EXPECT_CALL(*demuxer_, Stop());
835       return status;
836     }
837
838     CreateAudioStream();
839     CreateVideoStream();
840     MockDemuxerStreamVector streams;
841     streams.push_back(audio_stream());
842     streams.push_back(video_stream());
843     SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
844
845     EXPECT_CALL(*renderer_, HasAudio()).WillRepeatedly(Return(true));
846     EXPECT_CALL(*renderer_, HasVideo()).WillRepeatedly(Return(true));
847
848     if (state == kInitRenderer) {
849       if (stop_or_error == kStop) {
850         EXPECT_CALL(*renderer_, Initialize(_, _, _, _, _, _))
851             .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
852                             RunCallback<1>()));
853         ExpectPipelineStopAndDestroyPipeline();
854       } else {
855         status = PIPELINE_ERROR_INITIALIZATION_FAILED;
856         EXPECT_CALL(*renderer_, Initialize(_, _, _, _, _, _))
857             .WillOnce(DoAll(RunCallback<4>(status), RunCallback<1>()));
858       }
859
860       EXPECT_CALL(*demuxer_, Stop());
861       return status;
862     }
863
864     EXPECT_CALL(*renderer_, Initialize(_, _, _, _, _, _))
865         .WillOnce(DoAll(SaveArg<5>(&buffering_state_cb_),
866                         RunCallback<1>()));
867
868     EXPECT_CALL(callbacks_, OnMetadata(_));
869
870     // If we get here it's a successful initialization.
871     EXPECT_CALL(*renderer_, SetPlaybackRate(0.0f));
872     EXPECT_CALL(*renderer_, SetVolume(1.0f));
873     EXPECT_CALL(*renderer_, StartPlayingFrom(base::TimeDelta()))
874         .WillOnce(SetBufferingState(&buffering_state_cb_,
875                                     BUFFERING_HAVE_ENOUGH));
876
877     if (status == PIPELINE_OK)
878       EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
879
880     return status;
881   }
882
883   void DoSeek(TeardownState state, StopOrError stop_or_error) {
884     InSequence s;
885     PipelineStatus status = SetSeekExpectations(state, stop_or_error);
886
887     EXPECT_CALL(*demuxer_, Stop());
888     EXPECT_CALL(callbacks_, OnSeek(status));
889
890     if (status == PIPELINE_OK) {
891       ExpectPipelineStopAndDestroyPipeline();
892     }
893
894     pipeline_->Seek(base::TimeDelta::FromSeconds(10), base::Bind(
895         &CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
896     message_loop_.RunUntilIdle();
897   }
898
899   PipelineStatus SetSeekExpectations(TeardownState state,
900                                      StopOrError stop_or_error) {
901     PipelineStatus status = PIPELINE_OK;
902     base::Closure stop_cb = base::Bind(
903         &CallbackHelper::OnStop, base::Unretained(&callbacks_));
904
905     if (state == kFlushing) {
906       if (stop_or_error == kStop) {
907         EXPECT_CALL(*renderer_, Flush(_))
908             .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
909                             SetBufferingState(&buffering_state_cb_,
910                                               BUFFERING_HAVE_NOTHING),
911                             RunClosure<0>()));
912         EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
913       } else {
914         status = PIPELINE_ERROR_READ;
915         EXPECT_CALL(*renderer_, Flush(_))
916             .WillOnce(DoAll(SetError(pipeline_.get(), status),
917                             SetBufferingState(&buffering_state_cb_,
918                                               BUFFERING_HAVE_NOTHING),
919                             RunClosure<0>()));
920         EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
921       }
922
923       return status;
924     }
925
926     EXPECT_CALL(*renderer_, Flush(_))
927         .WillOnce(DoAll(SetBufferingState(&buffering_state_cb_,
928                                           BUFFERING_HAVE_NOTHING),
929                         RunClosure<0>()));
930     EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
931
932     if (state == kSeeking) {
933       if (stop_or_error == kStop) {
934         EXPECT_CALL(*demuxer_, Seek(_, _))
935             .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
936                             RunCallback<1>(PIPELINE_OK)));
937       } else {
938         status = PIPELINE_ERROR_READ;
939         EXPECT_CALL(*demuxer_, Seek(_, _))
940             .WillOnce(RunCallback<1>(status));
941       }
942
943       return status;
944     }
945
946     NOTREACHED() << "State not supported: " << state;
947     return status;
948   }
949
950   void DoStopOrError(StopOrError stop_or_error) {
951     InSequence s;
952
953     EXPECT_CALL(*demuxer_, Stop());
954
955     switch (stop_or_error) {
956       case kStop:
957         ExpectPipelineStopAndDestroyPipeline();
958         pipeline_->Stop(base::Bind(
959             &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
960         break;
961
962       case kError:
963         EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
964         pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
965         break;
966
967       case kErrorAndStop:
968         EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
969         ExpectPipelineStopAndDestroyPipeline();
970         pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
971         message_loop_.RunUntilIdle();
972         pipeline_->Stop(base::Bind(
973             &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
974         break;
975     }
976
977     message_loop_.RunUntilIdle();
978   }
979
980   DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest);
981 };
982
983 #define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state) \
984     TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \
985       RunTest(k##state, k##stop_or_error); \
986     }
987
988 INSTANTIATE_TEARDOWN_TEST(Stop, InitDemuxer);
989 INSTANTIATE_TEARDOWN_TEST(Stop, InitRenderer);
990 INSTANTIATE_TEARDOWN_TEST(Stop, Flushing);
991 INSTANTIATE_TEARDOWN_TEST(Stop, Seeking);
992 INSTANTIATE_TEARDOWN_TEST(Stop, Playing);
993
994 INSTANTIATE_TEARDOWN_TEST(Error, InitDemuxer);
995 INSTANTIATE_TEARDOWN_TEST(Error, InitRenderer);
996 INSTANTIATE_TEARDOWN_TEST(Error, Flushing);
997 INSTANTIATE_TEARDOWN_TEST(Error, Seeking);
998 INSTANTIATE_TEARDOWN_TEST(Error, Playing);
999
1000 INSTANTIATE_TEARDOWN_TEST(ErrorAndStop, Playing);
1001
1002 }  // namespace media