| OLD | NEW |
| (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_ | |
| OLD | NEW |