Unregister from GCM when the only GCM app is removed
[chromium-blink-merge.git] / media / filters / renderer_impl_unittest.cc
blobd8bb49ef815332354cea465841495ebad518aad0
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <vector>
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "base/test/simple_test_tick_clock.h"
11 #include "media/base/gmock_callback_support.h"
12 #include "media/base/mock_filters.h"
13 #include "media/base/test_helpers.h"
14 #include "media/filters/renderer_impl.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 using ::testing::_;
18 using ::testing::DoAll;
19 using ::testing::InSequence;
20 using ::testing::Mock;
21 using ::testing::Return;
22 using ::testing::SaveArg;
23 using ::testing::StrictMock;
25 namespace media {
27 const int64 kStartPlayingTimeInMs = 100;
29 ACTION_P2(SetBufferingState, cb, buffering_state) {
30 cb->Run(buffering_state);
33 ACTION_P2(AudioError, cb, error) {
34 cb->Run(error);
37 class RendererImplTest : public ::testing::Test {
38 public:
39 // Used for setting expectations on pipeline callbacks. Using a StrictMock
40 // also lets us test for missing callbacks.
41 class CallbackHelper {
42 public:
43 CallbackHelper() {}
44 virtual ~CallbackHelper() {}
46 MOCK_METHOD1(OnInitialize, void(PipelineStatus));
47 MOCK_METHOD0(OnFlushed, void());
48 MOCK_METHOD0(OnEnded, void());
49 MOCK_METHOD1(OnError, void(PipelineStatus));
50 MOCK_METHOD1(OnUpdateStatistics, void(const PipelineStatistics&));
51 MOCK_METHOD1(OnBufferingStateChange, void(BufferingState));
52 MOCK_METHOD1(OnVideoFramePaint, void(const scoped_refptr<VideoFrame>&));
54 private:
55 DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
58 RendererImplTest()
59 : demuxer_(new StrictMock<MockDemuxer>()),
60 video_renderer_(new StrictMock<MockVideoRenderer>()),
61 audio_renderer_(new StrictMock<MockAudioRenderer>()),
62 renderer_impl_(
63 new RendererImpl(message_loop_.message_loop_proxy(),
64 scoped_ptr<AudioRenderer>(audio_renderer_),
65 scoped_ptr<VideoRenderer>(video_renderer_))) {
66 // SetDemuxerExpectations() adds overriding expectations for expected
67 // non-NULL streams.
68 DemuxerStream* null_pointer = NULL;
69 EXPECT_CALL(*demuxer_, GetStream(_))
70 .WillRepeatedly(Return(null_pointer));
73 virtual ~RendererImplTest() {
74 renderer_impl_.reset();
75 base::RunLoop().RunUntilIdle();
78 protected:
79 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector;
81 scoped_ptr<StrictMock<MockDemuxerStream> > CreateStream(
82 DemuxerStream::Type type) {
83 scoped_ptr<StrictMock<MockDemuxerStream> > stream(
84 new StrictMock<MockDemuxerStream>(type));
85 return stream.Pass();
88 // Sets up expectations to allow the audio renderer to initialize.
89 void SetAudioRendererInitializeExpectations(PipelineStatus status) {
90 EXPECT_CALL(*audio_renderer_,
91 Initialize(audio_stream_.get(), _, _, _, _, _, _))
92 .WillOnce(DoAll(SaveArg<4>(&audio_buffering_state_cb_),
93 SaveArg<5>(&audio_ended_cb_),
94 SaveArg<6>(&audio_error_cb_), RunCallback<1>(status)));
97 // Sets up expectations to allow the video renderer to initialize.
98 void SetVideoRendererInitializeExpectations(PipelineStatus status) {
99 EXPECT_CALL(*video_renderer_,
100 Initialize(video_stream_.get(), _, _, _, _, _, _, _, _))
101 .WillOnce(DoAll(SaveArg<4>(&video_buffering_state_cb_),
102 SaveArg<6>(&video_ended_cb_), RunCallback<1>(status)));
105 void InitializeAndExpect(PipelineStatus start_status) {
106 EXPECT_CALL(callbacks_, OnInitialize(start_status));
108 if (start_status == PIPELINE_OK && audio_stream_) {
109 EXPECT_CALL(*audio_renderer_, GetTimeSource())
110 .WillOnce(Return(&time_source_));
113 renderer_impl_->Initialize(
114 demuxer_.get(),
115 base::Bind(&CallbackHelper::OnInitialize,
116 base::Unretained(&callbacks_)),
117 base::Bind(&CallbackHelper::OnUpdateStatistics,
118 base::Unretained(&callbacks_)),
119 base::Bind(&CallbackHelper::OnBufferingStateChange,
120 base::Unretained(&callbacks_)),
121 base::Bind(&CallbackHelper::OnVideoFramePaint,
122 base::Unretained(&callbacks_)),
123 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
124 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)));
125 base::RunLoop().RunUntilIdle();
128 void CreateAudioStream() {
129 audio_stream_ = CreateStream(DemuxerStream::AUDIO);
130 streams_.push_back(audio_stream_.get());
131 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::AUDIO))
132 .WillRepeatedly(Return(audio_stream_.get()));
135 void CreateVideoStream() {
136 video_stream_ = CreateStream(DemuxerStream::VIDEO);
137 video_stream_->set_video_decoder_config(video_decoder_config_);
138 streams_.push_back(video_stream_.get());
139 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::VIDEO))
140 .WillRepeatedly(Return(video_stream_.get()));
143 void CreateAudioAndVideoStream() {
144 CreateAudioStream();
145 CreateVideoStream();
148 void InitializeWithAudio() {
149 CreateAudioStream();
150 SetAudioRendererInitializeExpectations(PIPELINE_OK);
151 InitializeAndExpect(PIPELINE_OK);
154 void InitializeWithVideo() {
155 CreateVideoStream();
156 SetVideoRendererInitializeExpectations(PIPELINE_OK);
157 InitializeAndExpect(PIPELINE_OK);
160 void InitializeWithAudioAndVideo() {
161 CreateAudioAndVideoStream();
162 SetAudioRendererInitializeExpectations(PIPELINE_OK);
163 SetVideoRendererInitializeExpectations(PIPELINE_OK);
164 InitializeAndExpect(PIPELINE_OK);
167 void Play() {
168 DCHECK(audio_stream_ || video_stream_);
169 EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
171 base::TimeDelta start_time(
172 base::TimeDelta::FromMilliseconds(kStartPlayingTimeInMs));
174 if (audio_stream_) {
175 EXPECT_CALL(time_source_, SetMediaTime(start_time));
176 EXPECT_CALL(time_source_, StartTicking());
177 EXPECT_CALL(*audio_renderer_, StartPlaying())
178 .WillOnce(SetBufferingState(&audio_buffering_state_cb_,
179 BUFFERING_HAVE_ENOUGH));
182 if (video_stream_) {
183 EXPECT_CALL(*video_renderer_, StartPlayingFrom(start_time))
184 .WillOnce(SetBufferingState(&video_buffering_state_cb_,
185 BUFFERING_HAVE_ENOUGH));
188 renderer_impl_->StartPlayingFrom(start_time);
189 base::RunLoop().RunUntilIdle();
192 void Flush(bool underflowed) {
193 if (audio_stream_) {
194 if (!underflowed)
195 EXPECT_CALL(time_source_, StopTicking());
196 EXPECT_CALL(*audio_renderer_, Flush(_))
197 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
198 BUFFERING_HAVE_NOTHING),
199 RunClosure<0>()));
202 if (video_stream_) {
203 EXPECT_CALL(*video_renderer_, Flush(_))
204 .WillOnce(DoAll(SetBufferingState(&video_buffering_state_cb_,
205 BUFFERING_HAVE_NOTHING),
206 RunClosure<0>()));
209 EXPECT_CALL(callbacks_, OnFlushed());
211 renderer_impl_->Flush(
212 base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_)));
213 base::RunLoop().RunUntilIdle();
216 void SetPlaybackRate(float playback_rate) {
217 EXPECT_CALL(time_source_, SetPlaybackRate(playback_rate));
218 renderer_impl_->SetPlaybackRate(playback_rate);
219 base::RunLoop().RunUntilIdle();
222 int64 GetMediaTimeMs() {
223 return renderer_impl_->GetMediaTime().InMilliseconds();
226 bool IsMediaTimeAdvancing(float playback_rate) {
227 int64 start_time_ms = GetMediaTimeMs();
228 const int64 time_to_advance_ms = 100;
230 test_tick_clock_.Advance(
231 base::TimeDelta::FromMilliseconds(time_to_advance_ms));
233 if (GetMediaTimeMs() == start_time_ms + time_to_advance_ms * playback_rate)
234 return true;
236 DCHECK_EQ(start_time_ms, GetMediaTimeMs());
237 return false;
240 bool IsMediaTimeAdvancing() {
241 return IsMediaTimeAdvancing(1.0f);
244 // Fixture members.
245 base::MessageLoop message_loop_;
246 StrictMock<CallbackHelper> callbacks_;
247 base::SimpleTestTickClock test_tick_clock_;
249 scoped_ptr<StrictMock<MockDemuxer> > demuxer_;
250 StrictMock<MockVideoRenderer>* video_renderer_;
251 StrictMock<MockAudioRenderer>* audio_renderer_;
252 scoped_ptr<RendererImpl> renderer_impl_;
254 StrictMock<MockTimeSource> time_source_;
255 scoped_ptr<StrictMock<MockDemuxerStream> > audio_stream_;
256 scoped_ptr<StrictMock<MockDemuxerStream> > video_stream_;
257 MockDemuxerStreamVector streams_;
258 BufferingStateCB audio_buffering_state_cb_;
259 BufferingStateCB video_buffering_state_cb_;
260 base::Closure audio_ended_cb_;
261 base::Closure video_ended_cb_;
262 PipelineStatusCB audio_error_cb_;
263 VideoDecoderConfig video_decoder_config_;
265 private:
266 DISALLOW_COPY_AND_ASSIGN(RendererImplTest);
269 TEST_F(RendererImplTest, DestroyBeforeInitialize) {
270 // |renderer_impl_| will be destroyed in the dtor.
273 TEST_F(RendererImplTest, InitializeWithAudio) {
274 InitializeWithAudio();
277 TEST_F(RendererImplTest, InitializeWithVideo) {
278 InitializeWithVideo();
281 TEST_F(RendererImplTest, InitializeWithAudioVideo) {
282 InitializeWithAudioAndVideo();
285 TEST_F(RendererImplTest, InitializeWithAudio_Failed) {
286 CreateAudioStream();
287 SetAudioRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
288 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
291 TEST_F(RendererImplTest, InitializeWithVideo_Failed) {
292 CreateVideoStream();
293 SetVideoRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
294 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
297 TEST_F(RendererImplTest, InitializeWithAudioVideo_AudioRendererFailed) {
298 CreateAudioAndVideoStream();
299 SetAudioRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
300 // VideoRenderer::Initialize() should not be called.
301 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
304 TEST_F(RendererImplTest, InitializeWithAudioVideo_VideoRendererFailed) {
305 CreateAudioAndVideoStream();
306 SetAudioRendererInitializeExpectations(PIPELINE_OK);
307 SetVideoRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
308 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
311 TEST_F(RendererImplTest, StartPlayingFrom) {
312 InitializeWithAudioAndVideo();
313 Play();
316 TEST_F(RendererImplTest, FlushAfterInitialization) {
317 InitializeWithAudioAndVideo();
318 Flush(true);
321 TEST_F(RendererImplTest, FlushAfterPlay) {
322 InitializeWithAudioAndVideo();
323 Play();
324 Flush(false);
327 TEST_F(RendererImplTest, FlushAfterUnderflow) {
328 InitializeWithAudioAndVideo();
329 Play();
331 // Simulate underflow.
332 EXPECT_CALL(time_source_, StopTicking());
333 audio_buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
335 // Flush while underflowed. We shouldn't call StopTicking() again.
336 Flush(true);
339 TEST_F(RendererImplTest, SetPlaybackRate) {
340 InitializeWithAudioAndVideo();
341 SetPlaybackRate(1.0f);
342 SetPlaybackRate(2.0f);
345 TEST_F(RendererImplTest, SetVolume) {
346 InitializeWithAudioAndVideo();
347 EXPECT_CALL(*audio_renderer_, SetVolume(2.0f));
348 renderer_impl_->SetVolume(2.0f);
351 TEST_F(RendererImplTest, AudioStreamEnded) {
352 InitializeWithAudio();
353 Play();
355 EXPECT_CALL(time_source_, StopTicking());
356 EXPECT_CALL(callbacks_, OnEnded());
358 audio_ended_cb_.Run();
359 base::RunLoop().RunUntilIdle();
362 TEST_F(RendererImplTest, VideoStreamEnded) {
363 InitializeWithVideo();
364 Play();
366 // Video ended won't affect |time_source_|.
367 EXPECT_CALL(callbacks_, OnEnded());
369 video_ended_cb_.Run();
370 base::RunLoop().RunUntilIdle();
373 TEST_F(RendererImplTest, AudioVideoStreamsEnded) {
374 InitializeWithAudioAndVideo();
375 Play();
377 // OnEnded() is called only when all streams have finished.
378 audio_ended_cb_.Run();
379 base::RunLoop().RunUntilIdle();
381 EXPECT_CALL(time_source_, StopTicking());
382 EXPECT_CALL(callbacks_, OnEnded());
384 video_ended_cb_.Run();
385 base::RunLoop().RunUntilIdle();
388 TEST_F(RendererImplTest, ErrorAfterInitialize) {
389 InitializeWithAudio();
390 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
391 audio_error_cb_.Run(PIPELINE_ERROR_DECODE);
392 base::RunLoop().RunUntilIdle();
395 TEST_F(RendererImplTest, ErrorDuringPlaying) {
396 InitializeWithAudio();
397 Play();
399 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
400 audio_error_cb_.Run(PIPELINE_ERROR_DECODE);
401 base::RunLoop().RunUntilIdle();
404 TEST_F(RendererImplTest, ErrorDuringFlush) {
405 InitializeWithAudio();
406 Play();
408 InSequence s;
409 EXPECT_CALL(time_source_, StopTicking());
410 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(DoAll(
411 AudioError(&audio_error_cb_, PIPELINE_ERROR_DECODE),
412 RunClosure<0>()));
413 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
414 EXPECT_CALL(callbacks_, OnFlushed());
415 renderer_impl_->Flush(
416 base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_)));
417 base::RunLoop().RunUntilIdle();
420 TEST_F(RendererImplTest, ErrorAfterFlush) {
421 InitializeWithAudio();
422 Play();
423 Flush(false);
425 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
426 audio_error_cb_.Run(PIPELINE_ERROR_DECODE);
427 base::RunLoop().RunUntilIdle();
430 TEST_F(RendererImplTest, ErrorDuringInitialize) {
431 CreateAudioAndVideoStream();
432 SetAudioRendererInitializeExpectations(PIPELINE_OK);
434 // Force an audio error to occur during video renderer initialization.
435 EXPECT_CALL(*video_renderer_,
436 Initialize(video_stream_.get(), _, _, _, _, _, _, _, _))
437 .WillOnce(DoAll(AudioError(&audio_error_cb_, PIPELINE_ERROR_DECODE),
438 SaveArg<4>(&video_buffering_state_cb_),
439 SaveArg<6>(&video_ended_cb_),
440 RunCallback<1>(PIPELINE_OK)));
442 InitializeAndExpect(PIPELINE_ERROR_DECODE);
445 } // namespace media