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

Side by Side Diff: content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc

Issue 14197014: Add TestBrowserThreadBundle into RenderViewHostTestHarness. Kill some unnecessary real threads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge to head, address jyasskin's comments. Created 7 years, 6 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/renderer_host/media/web_contents_video_capture_device. h" 5 #include "content/browser/renderer_host/media/web_contents_video_capture_device. h"
6 6
7 #include "base/bind_helpers.h" 7 #include "base/bind_helpers.h"
8 #include "base/debug/debugger.h" 8 #include "base/debug/debugger.h"
9 #include "base/run_loop.h" 9 #include "base/run_loop.h"
10 #include "base/test/test_timeouts.h" 10 #include "base/test/test_timeouts.h"
11 #include "base/time.h" 11 #include "base/time.h"
12 #include "base/timer.h" 12 #include "base/timer.h"
13 #include "content/browser/browser_thread_impl.h" 13 #include "content/browser/browser_thread_impl.h"
14 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h" 14 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h"
15 #include "content/browser/renderer_host/media/video_capture_oracle.h" 15 #include "content/browser/renderer_host/media/video_capture_oracle.h"
16 #include "content/browser/renderer_host/media/web_contents_capture_util.h" 16 #include "content/browser/renderer_host/media/web_contents_capture_util.h"
17 #include "content/browser/renderer_host/render_view_host_factory.h" 17 #include "content/browser/renderer_host/render_view_host_factory.h"
18 #include "content/browser/renderer_host/render_widget_host_impl.h" 18 #include "content/browser/renderer_host/render_widget_host_impl.h"
19 #include "content/browser/renderer_host/test_render_view_host.h" 19 #include "content/browser/renderer_host/test_render_view_host.h"
20 #include "content/port/browser/render_widget_host_view_frame_subscriber.h" 20 #include "content/port/browser/render_widget_host_view_frame_subscriber.h"
21 #include "content/public/browser/notification_service.h" 21 #include "content/public/browser/notification_service.h"
22 #include "content/public/browser/notification_types.h" 22 #include "content/public/browser/notification_types.h"
23 #include "content/public/test/mock_render_process_host.h" 23 #include "content/public/test/mock_render_process_host.h"
24 #include "content/public/test/test_browser_context.h" 24 #include "content/public/test/test_browser_context.h"
25 #include "content/public/test/test_browser_thread.h" 25 #include "content/public/test/test_browser_thread_bundle.h"
26 #include "content/public/test/test_utils.h" 26 #include "content/public/test/test_utils.h"
27 #include "content/test/test_web_contents.h" 27 #include "content/test/test_web_contents.h"
28 #include "media/base/video_util.h" 28 #include "media/base/video_util.h"
29 #include "media/base/yuv_convert.h" 29 #include "media/base/yuv_convert.h"
30 #include "media/video/capture/video_capture_types.h" 30 #include "media/video/capture/video_capture_types.h"
31 #include "skia/ext/platform_canvas.h" 31 #include "skia/ext/platform_canvas.h"
32 #include "testing/gtest/include/gtest/gtest.h" 32 #include "testing/gtest/include/gtest/gtest.h"
33 #include "third_party/skia/include/core/SkColor.h" 33 #include "third_party/skia/include/core/SkColor.h"
34 34
35 namespace content { 35 namespace content {
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 bool error_encountered_; 404 bool error_encountered_;
405 SkColor wait_color_yuv_; 405 SkColor wait_color_yuv_;
406 scoped_refptr<VideoCaptureBufferPool> buffer_pool_; 406 scoped_refptr<VideoCaptureBufferPool> buffer_pool_;
407 407
408 DISALLOW_COPY_AND_ASSIGN(StubConsumer); 408 DISALLOW_COPY_AND_ASSIGN(StubConsumer);
409 }; 409 };
410 410
411 // Test harness that sets up a minimal environment with necessary stubs. 411 // Test harness that sets up a minimal environment with necessary stubs.
412 class WebContentsVideoCaptureDeviceTest : public testing::Test { 412 class WebContentsVideoCaptureDeviceTest : public testing::Test {
413 public: 413 public:
414 WebContentsVideoCaptureDeviceTest() {} 414 // This is public because C++ method pointer scoping rules are silly and make
415 415 // this hard to use with Bind().
416 void ResetWebContents() { 416 void ResetWebContents() {
417 web_contents_.reset(); 417 web_contents_.reset();
418 } 418 }
419 419
420 protected: 420 protected:
421 virtual void SetUp() { 421 virtual void SetUp() {
422 // TODO(nick): Sadness and woe! Much "mock-the-world" boilerplate could be 422 // TODO(nick): Sadness and woe! Much "mock-the-world" boilerplate could be
423 // eliminated here, if only we could use RenderViewHostTestHarness. The 423 // eliminated here, if only we could use RenderViewHostTestHarness. The
424 // catch is that we need our TestRenderViewHost to support a 424 // catch is that we need our TestRenderViewHost to support a
425 // CopyFromBackingStore operation that we control. To accomplish that, 425 // CopyFromBackingStore operation that we control. To accomplish that,
426 // either RenderViewHostTestHarness would have to support installing a 426 // either RenderViewHostTestHarness would have to support installing a
427 // custom RenderViewHostFactory, or else we implant some kind of delegated 427 // custom RenderViewHostFactory, or else we implant some kind of delegated
428 // CopyFromBackingStore functionality into TestRenderViewHost itself. 428 // CopyFromBackingStore functionality into TestRenderViewHost itself.
429 429
430 // The main thread will serve as the UI thread as well as the test thread.
431 // We'll manually pump the run loop at appropriate times in the test.
432 ui_thread_.reset(new TestBrowserThread(BrowserThread::UI, &message_loop_));
433
434 render_process_host_factory_.reset(new MockRenderProcessHostFactory()); 430 render_process_host_factory_.reset(new MockRenderProcessHostFactory());
435 // Create our (self-registering) RVH factory, so that when we create a 431 // Create our (self-registering) RVH factory, so that when we create a
436 // WebContents, it in turn creates CaptureTestRenderViewHosts. 432 // WebContents, it in turn creates CaptureTestRenderViewHosts.
437 render_view_host_factory_.reset( 433 render_view_host_factory_.reset(
438 new CaptureTestRenderViewHostFactory(&controller_)); 434 new CaptureTestRenderViewHostFactory(&controller_));
439 435
440 browser_context_.reset(new TestBrowserContext()); 436 browser_context_.reset(new TestBrowserContext());
441 437
442 scoped_refptr<SiteInstance> site_instance = 438 scoped_refptr<SiteInstance> site_instance =
443 SiteInstance::Create(browser_context_.get()); 439 SiteInstance::Create(browser_context_.get());
444 static_cast<SiteInstanceImpl*>(site_instance.get())-> 440 static_cast<SiteInstanceImpl*>(site_instance.get())->
445 set_render_process_host_factory(render_process_host_factory_.get()); 441 set_render_process_host_factory(render_process_host_factory_.get());
446 web_contents_.reset( 442 web_contents_.reset(
447 TestWebContents::Create(browser_context_.get(), site_instance)); 443 TestWebContents::Create(browser_context_.get(), site_instance));
448 444
449 // This is actually a CaptureTestRenderViewHost. 445 // This is actually a CaptureTestRenderViewHost.
450 RenderWidgetHostImpl* rwh = 446 RenderWidgetHostImpl* rwh =
451 RenderWidgetHostImpl::From(web_contents_->GetRenderViewHost()); 447 RenderWidgetHostImpl::From(web_contents_->GetRenderViewHost());
452 448
453 std::string device_id = 449 std::string device_id =
454 WebContentsCaptureUtil::AppendWebContentsDeviceScheme( 450 WebContentsCaptureUtil::AppendWebContentsDeviceScheme(
455 base::StringPrintf("%d:%d", rwh->GetProcess()->GetID(), 451 base::StringPrintf("%d:%d", rwh->GetProcess()->GetID(),
456 rwh->GetRoutingID())); 452 rwh->GetRoutingID()));
457 453
458 device_.reset(WebContentsVideoCaptureDevice::Create(device_id)); 454 device_.reset(WebContentsVideoCaptureDevice::Create(device_id));
459 455
460 content::RunAllPendingInMessageLoop(); 456 base::RunLoop().RunUntilIdle();
461 } 457 }
462 458
463 virtual void TearDown() { 459 virtual void TearDown() {
464 // Tear down in opposite order of set-up. 460 // Tear down in opposite order of set-up.
465 461
466 // The device is destroyed asynchronously, and will notify the 462 // The device is destroyed asynchronously, and will notify the
467 // CaptureTestSourceController when it finishes destruction. 463 // CaptureTestSourceController when it finishes destruction.
468 // Trigger this, and wait. 464 // Trigger this, and wait.
469 if (device_) { 465 if (device_) {
470 device_->DeAllocate(); 466 device_->DeAllocate();
471 device_.reset(); 467 device_.reset();
472 } 468 }
473 469
474 content::RunAllPendingInMessageLoop(); 470 base::RunLoop().RunUntilIdle();
475 471
476 // Destroy the browser objects. 472 // Destroy the browser objects.
477 web_contents_.reset(); 473 web_contents_.reset();
478 browser_context_.reset(); 474 browser_context_.reset();
479 475
480 content::RunAllPendingInMessageLoop(); 476 base::RunLoop().RunUntilIdle();
481 477
482 render_view_host_factory_.reset(); 478 render_view_host_factory_.reset();
483 render_process_host_factory_.reset(); 479 render_process_host_factory_.reset();
484 } 480 }
485 481
486 // Accessors. 482 // Accessors.
487 CaptureTestSourceController* source() { return &controller_; } 483 CaptureTestSourceController* source() { return &controller_; }
488 media::VideoCaptureDevice* device() { return device_.get(); } 484 media::VideoCaptureDevice* device() { return device_.get(); }
489 StubConsumer* consumer() { return &consumer_; } 485 StubConsumer* consumer() { return &consumer_; }
490 486
(...skipping 14 matching lines...) Expand all
505 501
506 void DestroyVideoCaptureDevice() { device_.reset(); } 502 void DestroyVideoCaptureDevice() { device_.reset(); }
507 503
508 private: 504 private:
509 // The consumer is the ultimate recipient of captured pixel data. 505 // The consumer is the ultimate recipient of captured pixel data.
510 StubConsumer consumer_; 506 StubConsumer consumer_;
511 507
512 // The controller controls which pixel patterns to produce. 508 // The controller controls which pixel patterns to produce.
513 CaptureTestSourceController controller_; 509 CaptureTestSourceController controller_;
514 510
515 // We run the UI message loop on the main thread. The capture device
516 // will also spin up its own threads.
517 base::MessageLoopForUI message_loop_;
518 scoped_ptr<TestBrowserThread> ui_thread_;
519
520 // Self-registering RenderProcessHostFactory. 511 // Self-registering RenderProcessHostFactory.
521 scoped_ptr<MockRenderProcessHostFactory> render_process_host_factory_; 512 scoped_ptr<MockRenderProcessHostFactory> render_process_host_factory_;
522 513
523 // Creates capture-capable RenderViewHosts whose pixel content production is 514 // Creates capture-capable RenderViewHosts whose pixel content production is
524 // under the control of |controller_|. 515 // under the control of |controller_|.
525 scoped_ptr<CaptureTestRenderViewHostFactory> render_view_host_factory_; 516 scoped_ptr<CaptureTestRenderViewHostFactory> render_view_host_factory_;
526 517
527 // A mocked-out browser and tab. 518 // A mocked-out browser and tab.
528 scoped_ptr<TestBrowserContext> browser_context_; 519 scoped_ptr<TestBrowserContext> browser_context_;
529 scoped_ptr<WebContents> web_contents_; 520 scoped_ptr<WebContents> web_contents_;
530 521
531 // Finally, the WebContentsVideoCaptureDevice under test. 522 // Finally, the WebContentsVideoCaptureDevice under test.
532 scoped_ptr<media::VideoCaptureDevice> device_; 523 scoped_ptr<media::VideoCaptureDevice> device_;
533 524
534 DISALLOW_COPY_AND_ASSIGN(WebContentsVideoCaptureDeviceTest); 525 TestBrowserThreadBundle thread_bundle_;
535 }; 526 };
536 527
537 TEST_F(WebContentsVideoCaptureDeviceTest, InvalidInitialWebContentsError) { 528 TEST_F(WebContentsVideoCaptureDeviceTest, InvalidInitialWebContentsError) {
538 // Before the installs itself on the UI thread up to start capturing, we'll 529 // Before the installs itself on the UI thread up to start capturing, we'll
539 // delete the web contents. This should trigger an error which can happen in 530 // delete the web contents. This should trigger an error which can happen in
540 // practice; we should be able to recover gracefully. 531 // practice; we should be able to recover gracefully.
541 ResetWebContents(); 532 ResetWebContents();
542 533
543 device()->Allocate(kTestWidth, kTestHeight, kTestFramesPerSecond, consumer()); 534 device()->Allocate(kTestWidth, kTestHeight, kTestFramesPerSecond, consumer());
544 device()->Start(); 535 device()->Start();
545 ASSERT_NO_FATAL_FAILURE(consumer()->WaitForError()); 536 ASSERT_NO_FATAL_FAILURE(consumer()->WaitForError());
546 device()->DeAllocate(); 537 device()->DeAllocate();
547 } 538 }
548 539
549 TEST_F(WebContentsVideoCaptureDeviceTest, WebContentsDestroyed) { 540 TEST_F(WebContentsVideoCaptureDeviceTest, WebContentsDestroyed) {
550 // We'll simulate the tab being closed after the capture pipeline is up and 541 // We'll simulate the tab being closed after the capture pipeline is up and
551 // running. 542 // running.
552 device()->Allocate(kTestWidth, kTestHeight, kTestFramesPerSecond, consumer()); 543 device()->Allocate(kTestWidth, kTestHeight, kTestFramesPerSecond, consumer());
553 device()->Start(); 544 device()->Start();
554 545
555 // Do one capture to prove 546 // Do one capture to prove
556 source()->SetSolidColor(SK_ColorRED); 547 source()->SetSolidColor(SK_ColorRED);
557 SimulateDrawEvent(); 548 SimulateDrawEvent();
558 ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorRED)); 549 ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorRED));
559 550
560 content::RunAllPendingInMessageLoop(); 551 base::RunLoop().RunUntilIdle();
561 552
562 // Post a task to close the tab. We should see an error reported to the 553 // Post a task to close the tab. We should see an error reported to the
563 // consumer. 554 // consumer.
564 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 555 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
565 base::Bind(&WebContentsVideoCaptureDeviceTest::ResetWebContents, 556 base::Bind(&WebContentsVideoCaptureDeviceTest::ResetWebContents,
566 base::Unretained(this))); 557 base::Unretained(this)));
567 ASSERT_NO_FATAL_FAILURE(consumer()->WaitForError()); 558 ASSERT_NO_FATAL_FAILURE(consumer()->WaitForError());
568 device()->DeAllocate(); 559 device()->DeAllocate();
569 } 560 }
570 561
571 TEST_F(WebContentsVideoCaptureDeviceTest, 562 TEST_F(WebContentsVideoCaptureDeviceTest,
572 StopDeviceBeforeCaptureMachineCreation) { 563 StopDeviceBeforeCaptureMachineCreation) {
573 device()->Allocate(kTestWidth, kTestHeight, kTestFramesPerSecond, consumer()); 564 device()->Allocate(kTestWidth, kTestHeight, kTestFramesPerSecond, consumer());
574 device()->Start(); 565 device()->Start();
575 // Make a point of not running the UI messageloop here. 566 // Make a point of not running the UI messageloop here.
576 device()->Stop(); 567 device()->Stop();
577 device()->DeAllocate(); 568 device()->DeAllocate();
578 DestroyVideoCaptureDevice(); 569 DestroyVideoCaptureDevice();
579 570
580 // Currently, there should be CreateCaptureMachineOnUIThread() and 571 // Currently, there should be CreateCaptureMachineOnUIThread() and
581 // DestroyCaptureMachineOnUIThread() tasks pending on the current (UI) message 572 // DestroyCaptureMachineOnUIThread() tasks pending on the current (UI) message
582 // loop. These should both succeed without crashing, and the machine should 573 // loop. These should both succeed without crashing, and the machine should
583 // wind up in the idle state. 574 // wind up in the idle state.
584 content::RunAllPendingInMessageLoop(); 575 base::RunLoop().RunUntilIdle();
585 } 576 }
586 577
587 TEST_F(WebContentsVideoCaptureDeviceTest, StopWithRendererWorkToDo) { 578 TEST_F(WebContentsVideoCaptureDeviceTest, StopWithRendererWorkToDo) {
588 // Set up the test to use RGB copies and an normal 579 // Set up the test to use RGB copies and an normal
589 source()->SetCanCopyToVideoFrame(false); 580 source()->SetCanCopyToVideoFrame(false);
590 source()->SetUseFrameSubscriber(false); 581 source()->SetUseFrameSubscriber(false);
591 device()->Allocate(kTestWidth, kTestHeight, kTestFramesPerSecond, 582 device()->Allocate(kTestWidth, kTestHeight, kTestFramesPerSecond,
592 consumer()); 583 consumer());
593 device()->Start(); 584 device()->Start();
594 // Make a point of not running the UI messageloop here. 585 // Make a point of not running the UI messageloop here.
595 content::RunAllPendingInMessageLoop(); 586 // TODO(ajwong): Why do we care?
587 base::RunLoop().RunUntilIdle();
596 588
597 for (int i = 0; i < 10; ++i) 589 for (int i = 0; i < 10; ++i)
598 SimulateDrawEvent(); 590 SimulateDrawEvent();
599 591
600 device()->Stop(); 592 device()->Stop();
601 device()->DeAllocate(); 593 device()->DeAllocate();
602 // Currently, there should be CreateCaptureMachineOnUIThread() and 594 // Currently, there should be CreateCaptureMachineOnUIThread() and
603 // DestroyCaptureMachineOnUIThread() tasks pending on the current message 595 // DestroyCaptureMachineOnUIThread() tasks pending on the current message
604 // loop. These should both succeed without crashing, and the machine should 596 // loop. These should both succeed without crashing, and the machine should
605 // wind up in the idle state. 597 // wind up in the idle state.
606 ASSERT_FALSE(consumer()->HasError()); 598 ASSERT_FALSE(consumer()->HasError());
607 content::RunAllPendingInMessageLoop(); 599 base::RunLoop().RunUntilIdle();
608 ASSERT_FALSE(consumer()->HasError()); 600 ASSERT_FALSE(consumer()->HasError());
609 } 601 }
610 602
611 TEST_F(WebContentsVideoCaptureDeviceTest, DeviceRestart) { 603 TEST_F(WebContentsVideoCaptureDeviceTest, DeviceRestart) {
612 device()->Allocate(kTestWidth, kTestHeight, kTestFramesPerSecond, consumer()); 604 device()->Allocate(kTestWidth, kTestHeight, kTestFramesPerSecond, consumer());
613 device()->Start(); 605 device()->Start();
614 content::RunAllPendingInMessageLoop(); 606 base::RunLoop().RunUntilIdle();
615 source()->SetSolidColor(SK_ColorRED); 607 source()->SetSolidColor(SK_ColorRED);
616 SimulateDrawEvent(); 608 SimulateDrawEvent();
617 SimulateDrawEvent(); 609 SimulateDrawEvent();
618 ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorRED)); 610 ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorRED));
619 SimulateDrawEvent(); 611 SimulateDrawEvent();
620 SimulateDrawEvent(); 612 SimulateDrawEvent();
621 source()->SetSolidColor(SK_ColorGREEN); 613 source()->SetSolidColor(SK_ColorGREEN);
622 SimulateDrawEvent(); 614 SimulateDrawEvent();
623 ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorGREEN)); 615 ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorGREEN));
624 device()->Stop(); 616 device()->Stop();
625 617
626 // Device is stopped, but content can still be animating. 618 // Device is stopped, but content can still be animating.
627 SimulateDrawEvent(); 619 SimulateDrawEvent();
628 SimulateDrawEvent(); 620 SimulateDrawEvent();
629 content::RunAllPendingInMessageLoop(); 621 base::RunLoop().RunUntilIdle();
630 622
631 device()->Start(); 623 device()->Start();
632 source()->SetSolidColor(SK_ColorBLUE); 624 source()->SetSolidColor(SK_ColorBLUE);
633 SimulateDrawEvent(); 625 SimulateDrawEvent();
634 ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorBLUE)); 626 ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorBLUE));
635 source()->SetSolidColor(SK_ColorYELLOW); 627 source()->SetSolidColor(SK_ColorYELLOW);
636 SimulateDrawEvent(); 628 SimulateDrawEvent();
637 ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorYELLOW)); 629 ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorYELLOW));
638 device()->DeAllocate(); 630 device()->DeAllocate();
639 } 631 }
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
719 ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorGREEN)); 711 ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorGREEN));
720 source()->SetSolidColor(SK_ColorRED); 712 source()->SetSolidColor(SK_ColorRED);
721 ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorRED)); 713 ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorRED));
722 714
723 device()->Stop(); 715 device()->Stop();
724 device()->DeAllocate(); 716 device()->DeAllocate();
725 } 717 }
726 718
727 } // namespace 719 } // namespace
728 } // namespace content 720 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698