Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(783)

Side by Side Diff: media/base/mock_media_filters.h

Issue 149423: Converted remaining tests to use gmock and deleted all old mocking code. (Closed)
Patch Set: Fix again Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/base/mock_filters.h ('k') | media/base/pipeline_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
2 // source code is governed by a BSD-style license that can be found in the
3 // LICENSE file.
4 //
5 // TODO(ajwong): This whole file is deprecated in favor or gmock style mocks.
6 // The deprecated classes have been moved into the old_mocks to avoid colliding
7 // with the newer mock classes. Once all the unittests have been migrated, this
8 // should be deleted.
9
10 #ifndef MEDIA_BASE_MOCK_MEDIA_FILTERS_H_
11 #define MEDIA_BASE_MOCK_MEDIA_FILTERS_H_
12
13 #include <string>
14
15 #include "base/scoped_ptr.h"
16 #include "base/waitable_event.h"
17 #include "media/base/buffers.h"
18 #include "media/base/factory.h"
19 #include "media/base/filter_host.h"
20 #include "media/base/filters.h"
21 #include "media/base/media_format.h"
22 #include "media/base/pipeline.h"
23 #include "media/base/video_frame_impl.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 namespace media {
27
28 namespace old_mocks {
29
30 // Behaviors for MockDataSource filter.
31 enum MockDataSourceBehavior {
32 MOCK_DATA_SOURCE_NORMAL_INIT,
33 MOCK_DATA_SOURCE_NEVER_INIT,
34 MOCK_DATA_SOURCE_URL_ERROR_IN_INIT,
35 MOCK_DATA_SOURCE_INIT_RETURN_FALSE,
36 };
37
38
39 // This class is used by all of the mock filters to change the configuration
40 // of the desired pipeline. The test using this must ensure that the lifetime
41 // of the object is at least as long as the lifetime of the filters, as this
42 // is typically allocated on the stack.
43 struct MockFilterConfig {
44 MockFilterConfig()
45 : create_filter(true),
46 data_source_behavior(MOCK_DATA_SOURCE_NORMAL_INIT),
47 data_source_value('!'),
48 has_video(true),
49 video_width(1280u),
50 video_height(720u),
51 video_surface_format(VideoSurface::YV12),
52 has_audio(true),
53 compressed_audio_mime_type(mime_type::kAACAudio),
54 uncompressed_audio_mime_type(mime_type::kUncompressedAudio),
55 compressed_video_mime_type(mime_type::kH264AnnexB),
56 uncompressed_video_mime_type(mime_type::kUncompressedVideo),
57 frame_duration(base::TimeDelta::FromMicroseconds(33333)),
58 media_duration(base::TimeDelta::FromSeconds(5)),
59 media_total_bytes(media_duration.InMilliseconds() * 250) {
60 }
61
62 bool create_filter;
63 MockDataSourceBehavior data_source_behavior;
64 char data_source_value;
65 bool has_video;
66 size_t video_width;
67 size_t video_height;
68 VideoSurface::Format video_surface_format;
69 bool has_audio;
70 std::string compressed_audio_mime_type;
71 std::string uncompressed_audio_mime_type;
72 std::string compressed_video_mime_type;
73 std::string uncompressed_video_mime_type;
74 base::TimeDelta frame_duration;
75 base::TimeDelta media_duration;
76 int64 media_total_bytes;
77 };
78
79
80 class MockDataSource : public DataSource {
81 public:
82 explicit MockDataSource(const MockFilterConfig* config)
83 : config_(config),
84 position_(0),
85 deleted_(NULL) {
86 }
87
88 MockDataSource(const MockFilterConfig* config, bool* deleted)
89 : config_(config),
90 position_(0),
91 deleted_(deleted) {
92 EXPECT_TRUE(deleted);
93 EXPECT_FALSE(*deleted);
94 }
95
96 // Implementation of MediaFilter.
97 virtual void Stop() {}
98
99 virtual void Seek(base::TimeDelta time) {
100 seek_time_ = time;
101 }
102
103 // Implementation of DataSource.
104 virtual bool Initialize(const std::string& url) {
105 media_format_.SetAsString(MediaFormat::kMimeType,
106 mime_type::kApplicationOctetStream);
107 media_format_.SetAsString(MediaFormat::kURL, url);
108 host()->SetTotalBytes(config_->media_total_bytes);
109 switch (config_->data_source_behavior) {
110 case MOCK_DATA_SOURCE_NORMAL_INIT:
111 host()->InitializationComplete();
112 return true;
113 case MOCK_DATA_SOURCE_NEVER_INIT:
114 return true;
115 case MOCK_DATA_SOURCE_URL_ERROR_IN_INIT:
116 host()->Error(PIPELINE_ERROR_URL_NOT_FOUND);
117 return false;
118 case MOCK_DATA_SOURCE_INIT_RETURN_FALSE:
119 return false;
120 default:
121 NOTREACHED();
122 return false;
123 }
124 }
125
126 virtual const MediaFormat& media_format() {
127 return media_format_;
128 }
129
130 virtual size_t Read(uint8* data, size_t size) {
131 size_t read = static_cast<size_t>(config_->media_total_bytes - position_);
132 if (size < read) {
133 read = size;
134 }
135 memset(data, config_->data_source_value, read);
136 return read;
137 }
138
139 virtual bool GetPosition(int64* position_out) {
140 *position_out = position_;
141 return true;
142 }
143
144 virtual bool SetPosition(int64 position) {
145 if (position < 0u || position > config_->media_total_bytes) {
146 return false;
147 }
148 position_ = position;
149 return true;
150 }
151
152 virtual bool GetSize(int64* size_out) {
153 if (config_->media_total_bytes >= 0) {
154 *size_out = config_->media_total_bytes;
155 return true;
156 }
157 return false;
158 }
159
160 virtual bool IsSeekable() {
161 return true;
162 }
163
164 // Mock accessors.
165 int64 position() const { return position_; }
166 const base::TimeDelta& seek_time() const { return seek_time_; }
167
168 private:
169 virtual ~MockDataSource() {
170 if (deleted_) {
171 *deleted_ = true;
172 }
173 }
174
175 const MockFilterConfig* config_;
176 int64 position_;
177 MediaFormat media_format_;
178 base::TimeDelta seek_time_;
179
180 // Set to true inside the destructor. Used in FFmpegGlue unit tests for
181 // testing proper reference counting.
182 bool* deleted_;
183
184 DISALLOW_COPY_AND_ASSIGN(MockDataSource);
185 };
186
187
188 class MockDemuxerStream : public DemuxerStream {
189 public:
190 MockDemuxerStream(const MockFilterConfig* config, bool is_audio) {
191 if (is_audio) {
192 media_format_.SetAsString(MediaFormat::kMimeType,
193 config->compressed_audio_mime_type);
194 } else {
195 media_format_.SetAsString(MediaFormat::kMimeType,
196 config->compressed_video_mime_type);
197 media_format_.SetAsInteger(MediaFormat::kWidth, config->video_width);
198 media_format_.SetAsInteger(MediaFormat::kHeight, config->video_height);
199 }
200 }
201
202 // Implementation of DemuxerStream.
203 virtual const MediaFormat& media_format() {
204 return media_format_;
205 }
206
207 virtual void Read(Callback1<Buffer*>::Type* read_callback) {
208 NOTREACHED(); // TODO(ralphl): fix me!!
209 }
210
211 private:
212 virtual ~MockDemuxerStream() {}
213
214 MediaFormat media_format_;
215
216 DISALLOW_COPY_AND_ASSIGN(MockDemuxerStream);
217 };
218
219
220 class MockDemuxer : public Demuxer {
221 public:
222 explicit MockDemuxer(const MockFilterConfig* config)
223 : config_(config),
224 mock_audio_stream_(new MockDemuxerStream(config, true)),
225 mock_video_stream_(new MockDemuxerStream(config, false)) {
226 }
227
228 // Implementation of MediaFilter.
229 virtual void Stop() {}
230
231 virtual void Seek(base::TimeDelta time) {
232 seek_time_ = time;
233 }
234
235 // Implementation of Demuxer.
236 virtual bool Initialize(DataSource* data_source) {
237 host()->InitializationComplete();
238 return true;
239 }
240
241 virtual size_t GetNumberOfStreams() {
242 size_t num_streams = 0;
243 if (config_->has_audio) {
244 ++num_streams;
245 }
246 if (config_->has_video) {
247 ++num_streams;
248 }
249 return num_streams;
250 }
251
252 virtual scoped_refptr<DemuxerStream> GetStream(int stream_id) {
253 switch (stream_id) {
254 case 0:
255 if (config_->has_audio) {
256 return mock_audio_stream_;
257 } else if (config_->has_video) {
258 return mock_video_stream_;
259 }
260 break;
261 case 1:
262 if (config_->has_audio && config_->has_video) {
263 return mock_video_stream_;
264 }
265 break;
266 }
267 ADD_FAILURE();
268 return NULL;
269 }
270
271 // Mock accessors.
272 const base::TimeDelta& seek_time() const { return seek_time_; }
273
274 private:
275 virtual ~MockDemuxer() {}
276
277 const MockFilterConfig* config_;
278 scoped_refptr<DemuxerStream> mock_audio_stream_;
279 scoped_refptr<DemuxerStream> mock_video_stream_;
280 base::TimeDelta seek_time_;
281
282 DISALLOW_COPY_AND_ASSIGN(MockDemuxer);
283 };
284
285
286 class MockAudioDecoder : public AudioDecoder {
287 public:
288 explicit MockAudioDecoder(const MockFilterConfig* config) {
289 media_format_.SetAsString(MediaFormat::kMimeType,
290 config->uncompressed_audio_mime_type);
291 }
292
293 // Implementation of MediaFilter.
294 virtual void Stop() {}
295
296 virtual void Seek(base::TimeDelta time) {
297 seek_time_ = time;
298 }
299
300 // Implementation of AudioDecoder.
301 virtual bool Initialize(DemuxerStream* stream) {
302 host()->InitializationComplete();
303 return true;
304 }
305
306 virtual const MediaFormat& media_format() {
307 return media_format_;
308 }
309
310 virtual void Read(Callback1<Buffer*>::Type* callback) {
311 // TODO(ralphl): implement mock read.
312 NOTREACHED();
313 }
314
315 // Mock accessors.
316 const base::TimeDelta& seek_time() const { return seek_time_; }
317
318 private:
319 virtual ~MockAudioDecoder() {}
320
321 MediaFormat media_format_;
322 base::TimeDelta seek_time_;
323
324 DISALLOW_COPY_AND_ASSIGN(MockAudioDecoder);
325 };
326
327
328 class MockAudioRenderer : public AudioRenderer {
329 public:
330 explicit MockAudioRenderer(const MockFilterConfig* config) {}
331
332 // Implementation of MediaFilter.
333 virtual void Stop() {}
334
335 virtual void Seek(base::TimeDelta time) {
336 seek_time_ = time;
337 }
338
339 // Implementation of AudioRenderer.
340 virtual bool Initialize(AudioDecoder* decoder) {
341 host()->InitializationComplete();
342 return true;
343 }
344
345 virtual void SetVolume(float volume) {}
346
347 // Mock accessors.
348 const base::TimeDelta& seek_time() const { return seek_time_; }
349
350 private:
351 virtual ~MockAudioRenderer() {}
352
353 base::TimeDelta seek_time_;
354
355 DISALLOW_COPY_AND_ASSIGN(MockAudioRenderer);
356 };
357
358
359 class MockVideoDecoder : public VideoDecoder {
360 public:
361 // Helper function that initializes a YV12 frame with white and black scan
362 // lines based on the |white_to_black| parameter. If 0, then the entire
363 // frame will be black, if 1 then the entire frame will be white.
364 static void InitializeYV12Frame(VideoFrame* frame, double white_to_black) {
365 VideoSurface surface;
366 if (!frame->Lock(&surface)) {
367 ADD_FAILURE();
368 } else {
369 EXPECT_EQ(surface.format, VideoSurface::YV12);
370 size_t first_black_row = static_cast<size_t>(surface.height *
371 white_to_black);
372 uint8* y_plane = surface.data[VideoSurface::kYPlane];
373 for (size_t row = 0; row < surface.height; ++row) {
374 int color = (row < first_black_row) ? 0xFF : 0x00;
375 memset(y_plane, color, surface.width);
376 y_plane += surface.strides[VideoSurface::kYPlane];
377 }
378 uint8* u_plane = surface.data[VideoSurface::kUPlane];
379 uint8* v_plane = surface.data[VideoSurface::kVPlane];
380 for (size_t row = 0; row < surface.height; row += 2) {
381 memset(u_plane, 0x80, surface.width / 2);
382 memset(v_plane, 0x80, surface.width / 2);
383 u_plane += surface.strides[VideoSurface::kUPlane];
384 v_plane += surface.strides[VideoSurface::kVPlane];
385 }
386 frame->Unlock();
387 }
388 }
389
390 explicit MockVideoDecoder(const MockFilterConfig* config)
391 : config_(config) {
392 media_format_.SetAsString(MediaFormat::kMimeType,
393 config->uncompressed_video_mime_type);
394 media_format_.SetAsInteger(MediaFormat::kWidth, config->video_width);
395 media_format_.SetAsInteger(MediaFormat::kHeight, config->video_height);
396 }
397
398 // Implementation of MediaFilter.
399 virtual void Stop() {}
400
401 virtual void Seek(base::TimeDelta time) {
402 seek_time_ = time;
403 }
404
405 // Implementation of VideoDecoder.
406 virtual bool Initialize(DemuxerStream* stream) {
407 host()->InitializationComplete();
408 return true;
409 }
410
411 virtual const MediaFormat& media_format() {
412 return media_format_;
413 }
414
415 virtual void Read(Callback1<VideoFrame*>::Type* callback) {
416 DoRead(callback);
417 }
418
419 // Mock accessors.
420 const base::TimeDelta& seek_time() const { return seek_time_; }
421
422 private:
423 virtual ~MockVideoDecoder() {}
424
425 void DoRead(Callback1<VideoFrame*>::Type* callback) {
426 scoped_ptr<Callback1<VideoFrame*>::Type> scoped_callback(callback);
427 if (mock_frame_time_ < config_->media_duration) {
428 // TODO(ralphl): Mock video decoder only works with YV12. Implement other
429 // formats as needed.
430 EXPECT_EQ(config_->video_surface_format, VideoSurface::YV12);
431 scoped_refptr<VideoFrame> frame;
432 VideoFrameImpl::CreateFrame(config_->video_surface_format,
433 config_->video_width,
434 config_->video_height,
435 mock_frame_time_,
436 config_->frame_duration,
437 &frame);
438 if (!frame) {
439 host()->Error(PIPELINE_ERROR_OUT_OF_MEMORY);
440 ADD_FAILURE();
441 } else {
442 mock_frame_time_ += config_->frame_duration;
443 if (mock_frame_time_ >= config_->media_duration) {
444 VideoFrameImpl::CreateEmptyFrame(&frame);
445 } else {
446 InitializeYV12Frame(frame, (mock_frame_time_.InSecondsF() /
447 config_->media_duration.InSecondsF()));
448 }
449 callback->Run(frame);
450 }
451 }
452 }
453
454 MediaFormat media_format_;
455 base::TimeDelta mock_frame_time_;
456 base::TimeDelta seek_time_;
457 const MockFilterConfig* config_;
458
459 DISALLOW_COPY_AND_ASSIGN(MockVideoDecoder);
460 };
461
462
463 class MockVideoRenderer : public VideoRenderer {
464 public:
465 explicit MockVideoRenderer(const MockFilterConfig* config)
466 : config_(config) {
467 }
468
469 // Implementation of MediaFilter.
470 virtual void Stop() {}
471
472 virtual void Seek(base::TimeDelta time) {
473 seek_time_ = time;
474 }
475
476 // Implementation of VideoRenderer.
477 virtual bool Initialize(VideoDecoder* decoder) {
478 host()->SetVideoSize(config_->video_width, config_->video_height);
479 host()->InitializationComplete();
480 return true;
481 }
482
483 // Mock accessors.
484 const base::TimeDelta& seek_time() const { return seek_time_; }
485
486 private:
487 virtual ~MockVideoRenderer() {}
488
489 base::TimeDelta seek_time_;
490 const MockFilterConfig* config_;
491
492 DISALLOW_COPY_AND_ASSIGN(MockVideoRenderer);
493 };
494
495
496 // FilterFactory capable of creating each mock filter type. Only one instance
497 // of each filter type can exist at any time. Filters can be inspected for
498 // expectations using the accessors, which may return NULL if the filter was
499 // never created (i.e., streams containing no video).
500 class MockFilterFactory : public FilterFactory {
501 public:
502 explicit MockFilterFactory(const MockFilterConfig* config)
503 : config_(config) {
504 }
505
506 // Mock accessors.
507 MockDataSource* data_source() const { return data_source_; }
508 MockDemuxer* demuxer() const { return demuxer_; }
509 MockAudioDecoder* audio_decoder() const { return audio_decoder_; }
510 MockVideoDecoder* video_decoder() const { return video_decoder_; }
511 MockAudioRenderer* audio_renderer() const { return audio_renderer_; }
512 MockVideoRenderer* video_renderer() const { return video_renderer_; }
513
514 protected:
515 MediaFilter* Create(FilterType filter_type, const MediaFormat& media_format) {
516 if (!config_->create_filter)
517 return NULL;
518
519 switch (filter_type) {
520 case FILTER_DATA_SOURCE:
521 DCHECK(!data_source_);
522 data_source_ = new MockDataSource(config_);
523 return data_source_;
524
525 case FILTER_DEMUXER:
526 DCHECK(!demuxer_);
527 demuxer_ = new MockDemuxer(config_);
528 return demuxer_;
529
530 case FILTER_AUDIO_DECODER:
531 DCHECK(!audio_decoder_);
532 audio_decoder_ = new MockAudioDecoder(config_);
533 return audio_decoder_;
534
535 case FILTER_VIDEO_DECODER:
536 DCHECK(!video_decoder_);
537 video_decoder_ = new MockVideoDecoder(config_);
538 return video_decoder_;
539
540 case FILTER_AUDIO_RENDERER:
541 DCHECK(!audio_renderer_);
542 audio_renderer_ = new MockAudioRenderer(config_);
543 return audio_renderer_;
544
545 case FILTER_VIDEO_RENDERER:
546 DCHECK(!video_renderer_);
547 video_renderer_ = new MockVideoRenderer(config_);
548 return video_renderer_;
549
550 default:
551 NOTREACHED();
552 }
553 return NULL;
554 }
555
556 private:
557 const MockFilterConfig* config_;
558 scoped_refptr<MockDataSource> data_source_;
559 scoped_refptr<MockDemuxer> demuxer_;
560 scoped_refptr<MockAudioDecoder> audio_decoder_;
561 scoped_refptr<MockVideoDecoder> video_decoder_;
562 scoped_refptr<MockAudioRenderer> audio_renderer_;
563 scoped_refptr<MockVideoRenderer> video_renderer_;
564
565 DISALLOW_COPY_AND_ASSIGN(MockFilterFactory);
566 };
567
568 // A simple class that waits for a pipeline to be started and checks some
569 // basic initialization values. The Start() method will not return until
570 // either a pre-determined amount of time has passed or the pipeline calls the
571 // InitCallback() callback. A typical use would be:
572 // Pipeline p;
573 // FilterFactoryCollection f;
574 // f->AddFactory(a);
575 // f->AddFactory(b);
576 // ...
577 // InitializationHelper h;
578 // h.Start(&p, f, uri);
579 //
580 // If the test is expecting to produce an error use would be:
581 // h.Start(&p, f, uri, PIPELINE_ERROR_REQUIRED_FILTER_MISSING)
582 //
583 // If the test expects the pipeline to hang during initialization (a filter
584 // never calls FilterHost::InitializationComplete()) then the use would be:
585 // h.Start(&p, f, uri, PIPELINE_OK, true);
586 //
587 // TODO(scherkus): Keep refactoring tests until we can remove this entirely.
588 class InitializationHelper {
589 public:
590 InitializationHelper()
591 : event_(true, false),
592 callback_success_status_(false),
593 waiting_for_callback_(false) {}
594
595 // If callback has been called, then returns the boolean passed by the
596 // pipeline to the callback.
597 bool callback_success_status() { return callback_success_status_; }
598
599 // Returns true if Start has been called, but the pipeline has not yet
600 // called the initialization complete callback.
601 bool waiting_for_callback() { return waiting_for_callback_; }
602
603 // Starts the pipeline, providing an initialization callback that points
604 // to this object.
605 void Start(Pipeline* pipeline,
606 FilterFactory* filter_factory,
607 const std::string& uri,
608 PipelineError expect_error = PIPELINE_OK,
609 bool expect_hang = false) {
610 // For tests that we expect to hang in initialization, we want to
611 // wait a short time. If a hang is not expected, then wait long enough
612 // to make sure that the filters have time to initalize. 1/2 second if
613 // we expect to hang, and 3 seconds if we expect success.
614 base::TimeDelta max_wait = base::TimeDelta::FromMilliseconds(expect_hang ?
615 500 : 3000);
616 EXPECT_FALSE(waiting_for_callback_);
617 waiting_for_callback_ = true;
618 callback_success_status_ = false;
619 event_.Reset();
620 pipeline->Start(filter_factory, uri,
621 NewCallback(this, &InitializationHelper::InitCallback));
622 bool signaled = event_.TimedWait(max_wait);
623 if (expect_hang) {
624 EXPECT_FALSE(signaled);
625 EXPECT_FALSE(pipeline->IsInitialized());
626 EXPECT_TRUE(waiting_for_callback_);
627 } else {
628 EXPECT_TRUE(signaled);
629 EXPECT_FALSE(waiting_for_callback_);
630 EXPECT_EQ(pipeline->GetError(), expect_error);
631 EXPECT_EQ(callback_success_status_, (expect_error == PIPELINE_OK));
632 EXPECT_EQ(pipeline->IsInitialized(), (expect_error == PIPELINE_OK));
633 }
634 }
635
636 private:
637 void InitCallback(bool success) {
638 EXPECT_TRUE(waiting_for_callback_);
639 EXPECT_FALSE(event_.IsSignaled());
640 waiting_for_callback_ = false;
641 callback_success_status_ = success;
642 event_.Signal();
643 }
644
645 base::WaitableEvent event_;
646 bool callback_success_status_;
647 bool waiting_for_callback_;
648
649 DISALLOW_COPY_AND_ASSIGN(InitializationHelper);
650 };
651
652 } // namespace old_mocks
653
654 } // namespace media
655
656 #endif // MEDIA_BASE_MOCK_MEDIA_FILTERS_H_
OLDNEW
« no previous file with comments | « media/base/mock_filters.h ('k') | media/base/pipeline_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698