Don't send a SHChangeNotify for creating an app icon when creating a shortcut.
[chromium-blink-merge.git] / media / renderers / renderer_impl_unittest.cc
blob30bad2fe27040a12da619aa263b819472278cadf
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/renderers/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>&));
53 MOCK_METHOD0(OnWaitingForDecryptionKey, void());
55 private:
56 DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
59 RendererImplTest()
60 : demuxer_(new StrictMock<MockDemuxer>()),
61 video_renderer_(new StrictMock<MockVideoRenderer>()),
62 audio_renderer_(new StrictMock<MockAudioRenderer>()),
63 renderer_impl_(
64 new RendererImpl(message_loop_.message_loop_proxy(),
65 scoped_ptr<AudioRenderer>(audio_renderer_),
66 scoped_ptr<VideoRenderer>(video_renderer_))) {
67 // SetDemuxerExpectations() adds overriding expectations for expected
68 // non-NULL streams.
69 DemuxerStream* null_pointer = NULL;
70 EXPECT_CALL(*demuxer_, GetStream(_))
71 .WillRepeatedly(Return(null_pointer));
74 virtual ~RendererImplTest() {
75 renderer_impl_.reset();
76 base::RunLoop().RunUntilIdle();
79 protected:
80 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector;
82 scoped_ptr<StrictMock<MockDemuxerStream> > CreateStream(
83 DemuxerStream::Type type) {
84 scoped_ptr<StrictMock<MockDemuxerStream> > stream(
85 new StrictMock<MockDemuxerStream>(type));
86 return stream.Pass();
89 // Sets up expectations to allow the audio renderer to initialize.
90 void SetAudioRendererInitializeExpectations(PipelineStatus status) {
91 EXPECT_CALL(*audio_renderer_,
92 Initialize(audio_stream_.get(), _, _, _, _, _, _, _))
93 .WillOnce(DoAll(SaveArg<4>(&audio_buffering_state_cb_),
94 SaveArg<5>(&audio_ended_cb_),
95 SaveArg<6>(&audio_error_cb_), RunCallback<1>(status)));
98 // Sets up expectations to allow the video renderer to initialize.
99 void SetVideoRendererInitializeExpectations(PipelineStatus status) {
100 EXPECT_CALL(*video_renderer_,
101 Initialize(video_stream_.get(), _, _, _, _, _, _, _, _, _))
102 .WillOnce(DoAll(SaveArg<4>(&video_buffering_state_cb_),
103 SaveArg<6>(&video_ended_cb_), RunCallback<1>(status)));
106 void InitializeAndExpect(PipelineStatus start_status) {
107 EXPECT_CALL(callbacks_, OnInitialize(start_status));
108 EXPECT_CALL(callbacks_, OnWaitingForDecryptionKey()).Times(0);
110 if (start_status == PIPELINE_OK && audio_stream_) {
111 EXPECT_CALL(*audio_renderer_, GetTimeSource())
112 .WillOnce(Return(&time_source_));
115 renderer_impl_->Initialize(
116 demuxer_.get(),
117 base::Bind(&CallbackHelper::OnInitialize,
118 base::Unretained(&callbacks_)),
119 base::Bind(&CallbackHelper::OnUpdateStatistics,
120 base::Unretained(&callbacks_)),
121 base::Bind(&CallbackHelper::OnBufferingStateChange,
122 base::Unretained(&callbacks_)),
123 base::Bind(&CallbackHelper::OnVideoFramePaint,
124 base::Unretained(&callbacks_)),
125 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
126 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
127 base::Bind(&CallbackHelper::OnWaitingForDecryptionKey,
128 base::Unretained(&callbacks_)));
129 base::RunLoop().RunUntilIdle();
132 void CreateAudioStream() {
133 audio_stream_ = CreateStream(DemuxerStream::AUDIO);
134 streams_.push_back(audio_stream_.get());
135 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::AUDIO))
136 .WillRepeatedly(Return(audio_stream_.get()));
139 void CreateVideoStream() {
140 video_stream_ = CreateStream(DemuxerStream::VIDEO);
141 video_stream_->set_video_decoder_config(video_decoder_config_);
142 streams_.push_back(video_stream_.get());
143 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::VIDEO))
144 .WillRepeatedly(Return(video_stream_.get()));
147 void CreateAudioAndVideoStream() {
148 CreateAudioStream();
149 CreateVideoStream();
152 void InitializeWithAudio() {
153 CreateAudioStream();
154 SetAudioRendererInitializeExpectations(PIPELINE_OK);
155 InitializeAndExpect(PIPELINE_OK);
158 void InitializeWithVideo() {
159 CreateVideoStream();
160 SetVideoRendererInitializeExpectations(PIPELINE_OK);
161 InitializeAndExpect(PIPELINE_OK);
164 void InitializeWithAudioAndVideo() {
165 CreateAudioAndVideoStream();
166 SetAudioRendererInitializeExpectations(PIPELINE_OK);
167 SetVideoRendererInitializeExpectations(PIPELINE_OK);
168 InitializeAndExpect(PIPELINE_OK);
171 void Play() {
172 DCHECK(audio_stream_ || video_stream_);
173 EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
175 base::TimeDelta start_time(
176 base::TimeDelta::FromMilliseconds(kStartPlayingTimeInMs));
178 if (audio_stream_) {
179 EXPECT_CALL(time_source_, SetMediaTime(start_time));
180 EXPECT_CALL(time_source_, StartTicking());
181 EXPECT_CALL(*audio_renderer_, StartPlaying())
182 .WillOnce(SetBufferingState(&audio_buffering_state_cb_,
183 BUFFERING_HAVE_ENOUGH));
186 if (video_stream_) {
187 EXPECT_CALL(*video_renderer_, StartPlayingFrom(start_time))
188 .WillOnce(SetBufferingState(&video_buffering_state_cb_,
189 BUFFERING_HAVE_ENOUGH));
192 renderer_impl_->StartPlayingFrom(start_time);
193 base::RunLoop().RunUntilIdle();
196 void Flush(bool underflowed) {
197 if (audio_stream_) {
198 if (!underflowed)
199 EXPECT_CALL(time_source_, StopTicking());
200 EXPECT_CALL(*audio_renderer_, Flush(_))
201 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
202 BUFFERING_HAVE_NOTHING),
203 RunClosure<0>()));
206 if (video_stream_) {
207 EXPECT_CALL(*video_renderer_, Flush(_))
208 .WillOnce(DoAll(SetBufferingState(&video_buffering_state_cb_,
209 BUFFERING_HAVE_NOTHING),
210 RunClosure<0>()));
213 EXPECT_CALL(callbacks_, OnFlushed());
215 renderer_impl_->Flush(
216 base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_)));
217 base::RunLoop().RunUntilIdle();
220 void SetPlaybackRate(float playback_rate) {
221 EXPECT_CALL(time_source_, SetPlaybackRate(playback_rate));
222 renderer_impl_->SetPlaybackRate(playback_rate);
223 base::RunLoop().RunUntilIdle();
226 int64 GetMediaTimeMs() {
227 return renderer_impl_->GetMediaTime().InMilliseconds();
230 bool IsMediaTimeAdvancing(float playback_rate) {
231 int64 start_time_ms = GetMediaTimeMs();
232 const int64 time_to_advance_ms = 100;
234 test_tick_clock_.Advance(
235 base::TimeDelta::FromMilliseconds(time_to_advance_ms));
237 if (GetMediaTimeMs() == start_time_ms + time_to_advance_ms * playback_rate)
238 return true;
240 DCHECK_EQ(start_time_ms, GetMediaTimeMs());
241 return false;
244 bool IsMediaTimeAdvancing() {
245 return IsMediaTimeAdvancing(1.0f);
248 // Fixture members.
249 base::MessageLoop message_loop_;
250 StrictMock<CallbackHelper> callbacks_;
251 base::SimpleTestTickClock test_tick_clock_;
253 scoped_ptr<StrictMock<MockDemuxer> > demuxer_;
254 StrictMock<MockVideoRenderer>* video_renderer_;
255 StrictMock<MockAudioRenderer>* audio_renderer_;
256 scoped_ptr<RendererImpl> renderer_impl_;
258 StrictMock<MockTimeSource> time_source_;
259 scoped_ptr<StrictMock<MockDemuxerStream> > audio_stream_;
260 scoped_ptr<StrictMock<MockDemuxerStream> > video_stream_;
261 MockDemuxerStreamVector streams_;
262 BufferingStateCB audio_buffering_state_cb_;
263 BufferingStateCB video_buffering_state_cb_;
264 base::Closure audio_ended_cb_;
265 base::Closure video_ended_cb_;
266 PipelineStatusCB audio_error_cb_;
267 VideoDecoderConfig video_decoder_config_;
269 private:
270 DISALLOW_COPY_AND_ASSIGN(RendererImplTest);
273 TEST_F(RendererImplTest, DestroyBeforeInitialize) {
274 // |renderer_impl_| will be destroyed in the dtor.
277 TEST_F(RendererImplTest, InitializeWithAudio) {
278 InitializeWithAudio();
281 TEST_F(RendererImplTest, InitializeWithVideo) {
282 InitializeWithVideo();
285 TEST_F(RendererImplTest, InitializeWithAudioVideo) {
286 InitializeWithAudioAndVideo();
289 TEST_F(RendererImplTest, InitializeWithAudio_Failed) {
290 CreateAudioStream();
291 SetAudioRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
292 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
295 TEST_F(RendererImplTest, InitializeWithVideo_Failed) {
296 CreateVideoStream();
297 SetVideoRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
298 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
301 TEST_F(RendererImplTest, InitializeWithAudioVideo_AudioRendererFailed) {
302 CreateAudioAndVideoStream();
303 SetAudioRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
304 // VideoRenderer::Initialize() should not be called.
305 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
308 TEST_F(RendererImplTest, InitializeWithAudioVideo_VideoRendererFailed) {
309 CreateAudioAndVideoStream();
310 SetAudioRendererInitializeExpectations(PIPELINE_OK);
311 SetVideoRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
312 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
315 TEST_F(RendererImplTest, StartPlayingFrom) {
316 InitializeWithAudioAndVideo();
317 Play();
320 TEST_F(RendererImplTest, FlushAfterInitialization) {
321 InitializeWithAudioAndVideo();
322 Flush(true);
325 TEST_F(RendererImplTest, FlushAfterPlay) {
326 InitializeWithAudioAndVideo();
327 Play();
328 Flush(false);
331 TEST_F(RendererImplTest, FlushAfterUnderflow) {
332 InitializeWithAudioAndVideo();
333 Play();
335 // Simulate underflow.
336 EXPECT_CALL(time_source_, StopTicking());
337 audio_buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
339 // Flush while underflowed. We shouldn't call StopTicking() again.
340 Flush(true);
343 TEST_F(RendererImplTest, SetPlaybackRate) {
344 InitializeWithAudioAndVideo();
345 SetPlaybackRate(1.0f);
346 SetPlaybackRate(2.0f);
349 TEST_F(RendererImplTest, SetVolume) {
350 InitializeWithAudioAndVideo();
351 EXPECT_CALL(*audio_renderer_, SetVolume(2.0f));
352 renderer_impl_->SetVolume(2.0f);
355 TEST_F(RendererImplTest, AudioStreamEnded) {
356 InitializeWithAudio();
357 Play();
359 EXPECT_CALL(time_source_, StopTicking());
360 EXPECT_CALL(callbacks_, OnEnded());
362 audio_ended_cb_.Run();
363 base::RunLoop().RunUntilIdle();
366 TEST_F(RendererImplTest, VideoStreamEnded) {
367 InitializeWithVideo();
368 Play();
370 // Video ended won't affect |time_source_|.
371 EXPECT_CALL(callbacks_, OnEnded());
373 video_ended_cb_.Run();
374 base::RunLoop().RunUntilIdle();
377 TEST_F(RendererImplTest, AudioVideoStreamsEnded) {
378 InitializeWithAudioAndVideo();
379 Play();
381 // OnEnded() is called only when all streams have finished.
382 audio_ended_cb_.Run();
383 base::RunLoop().RunUntilIdle();
385 EXPECT_CALL(time_source_, StopTicking());
386 EXPECT_CALL(callbacks_, OnEnded());
388 video_ended_cb_.Run();
389 base::RunLoop().RunUntilIdle();
392 TEST_F(RendererImplTest, ErrorAfterInitialize) {
393 InitializeWithAudio();
394 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
395 audio_error_cb_.Run(PIPELINE_ERROR_DECODE);
396 base::RunLoop().RunUntilIdle();
399 TEST_F(RendererImplTest, ErrorDuringPlaying) {
400 InitializeWithAudio();
401 Play();
403 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
404 audio_error_cb_.Run(PIPELINE_ERROR_DECODE);
405 base::RunLoop().RunUntilIdle();
408 TEST_F(RendererImplTest, ErrorDuringFlush) {
409 InitializeWithAudio();
410 Play();
412 InSequence s;
413 EXPECT_CALL(time_source_, StopTicking());
414 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(DoAll(
415 AudioError(&audio_error_cb_, PIPELINE_ERROR_DECODE),
416 RunClosure<0>()));
417 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
418 EXPECT_CALL(callbacks_, OnFlushed());
419 renderer_impl_->Flush(
420 base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_)));
421 base::RunLoop().RunUntilIdle();
424 TEST_F(RendererImplTest, ErrorAfterFlush) {
425 InitializeWithAudio();
426 Play();
427 Flush(false);
429 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
430 audio_error_cb_.Run(PIPELINE_ERROR_DECODE);
431 base::RunLoop().RunUntilIdle();
434 TEST_F(RendererImplTest, ErrorDuringInitialize) {
435 CreateAudioAndVideoStream();
436 SetAudioRendererInitializeExpectations(PIPELINE_OK);
438 // Force an audio error to occur during video renderer initialization.
439 EXPECT_CALL(*video_renderer_,
440 Initialize(video_stream_.get(), _, _, _, _, _, _, _, _, _))
441 .WillOnce(DoAll(AudioError(&audio_error_cb_, PIPELINE_ERROR_DECODE),
442 SaveArg<4>(&video_buffering_state_cb_),
443 SaveArg<6>(&video_ended_cb_),
444 RunCallback<1>(PIPELINE_OK)));
446 InitializeAndExpect(PIPELINE_ERROR_DECODE);
449 } // namespace media