Chromium Code Reviews| Index: blimp/client/core/contents/blimp_contents_impl_unittest.cc |
| diff --git a/blimp/client/core/contents/blimp_contents_impl_unittest.cc b/blimp/client/core/contents/blimp_contents_impl_unittest.cc |
| index 98fa2066246edf05c0c085cd0116196bd5a7edec..64bad1cf9cc5c53b4875ff3b263f63693e146030 100644 |
| --- a/blimp/client/core/contents/blimp_contents_impl_unittest.cc |
| +++ b/blimp/client/core/contents/blimp_contents_impl_unittest.cc |
| @@ -5,11 +5,19 @@ |
| #include "blimp/client/core/contents/blimp_contents_impl.h" |
| #include "base/message_loop/message_loop.h" |
| -#include "blimp/client/core/contents/blimp_contents_impl.h" |
| +#include "blimp/client/core/compositor/compositor_deps_provider.h" |
| #include "blimp/client/core/contents/fake_navigation_feature.h" |
| +#include "blimp/client/core/render_widget/blimp_render_widget.h" |
| +#include "blimp/client/core/render_widget/render_widget_feature.h" |
| #include "blimp/client/public/contents/blimp_contents_observer.h" |
| +#include "cc/proto/compositor_message.pb.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| +#include "third_party/WebKit/public/web/WebInputEvent.h" |
| + |
| +using testing::_; |
| +using testing::InSequence; |
| +using testing::Sequence; |
| namespace blimp { |
| namespace client { |
| @@ -31,36 +39,201 @@ class MockBlimpContentsObserver : public BlimpContentsObserver { |
| DISALLOW_COPY_AND_ASSIGN(MockBlimpContentsObserver); |
| }; |
| -TEST(BlimpContentsImplTest, LoadURLAndNotifyObservers) { |
| - base::MessageLoop loop; |
| - BlimpContentsImpl blimp_contents(kDummyTabId); |
| +class MockRenderWidgetFeature : public RenderWidgetFeature { |
| + public: |
| + MOCK_METHOD3(SendCompositorMessage, |
| + void(const int, const int, const cc::proto::CompositorMessage&)); |
| + MOCK_METHOD3(SendInputEvent, |
| + void(const int, const int, const blink::WebInputEvent&)); |
| + MOCK_METHOD2(SetDelegate, void(int, RenderWidgetFeatureDelegate*)); |
| + MOCK_METHOD1(RemoveDelegate, void(const int)); |
| +}; |
| + |
| +class MockRenderWidget : public BlimpRenderWidget { |
| + public: |
| + MockRenderWidget(int32_t render_widget_id, |
| + CompositorDepsProvider* compositor_deps_provider, |
| + BlimpRenderWidgetDelegate* delegate) |
| + : BlimpRenderWidget(render_widget_id, |
| + compositor_deps_provider, |
| + delegate) {} |
| + |
| + MOCK_METHOD1(SetVisible, void(bool)); |
| + MOCK_METHOD1(SetAcceleratedWidget, void(gfx::AcceleratedWidget)); |
| + |
| + void OnCompositorMessageReceived( |
| + std::unique_ptr<cc::proto::CompositorMessage> message) override { |
| + MockableOnCompositorMessageReceived(*message); |
| + } |
| + MOCK_METHOD1(MockableOnCompositorMessageReceived, |
| + void(const cc::proto::CompositorMessage&)); |
| +}; |
| + |
| +class BlimpContentsImplForTesting : public BlimpContentsImpl { |
| + public: |
| + BlimpContentsImplForTesting(int id, |
| + CompositorDepsProvider* compositor_deps_provider, |
| + RenderWidgetFeature* render_widget_feature) |
| + : BlimpContentsImpl(id, compositor_deps_provider, render_widget_feature) { |
| + } |
| + |
| + protected: |
| + std::unique_ptr<BlimpRenderWidget> CreateBlimpRenderWidget( |
| + int32_t render_widget_id, |
| + CompositorDepsProvider* compositor_deps_provider, |
| + BlimpRenderWidgetDelegate* delegate) override { |
| + return base::MakeUnique<MockRenderWidget>( |
| + render_widget_id, compositor_deps_provider, delegate); |
| + } |
| +}; |
| + |
| +class BlimpContentsImplTest : public testing::Test { |
| + public: |
| + BlimpContentsImplTest() : widget1_(nullptr), widget2_(nullptr) {} |
| + |
| + void SetUpBlimpContents(bool use_direct_rendering) { |
| + compositor_deps_provider_ = |
| + base::MakeUnique<CompositorDepsProvider>(use_direct_rendering); |
| + image_serialization_processor_ = |
| + base::MakeUnique<BlobImageSerializationProcessor>(); |
| + blimp_contents_ = base::MakeUnique<BlimpContentsImplForTesting>( |
| + kDummyTabId, compositor_deps_provider_.get(), &render_widget_feature_); |
| + } |
| + |
| + void SetUpWidgets() { |
| + blimp_contents_->OnRenderWidgetCreated(1); |
| + blimp_contents_->OnRenderWidgetCreated(2); |
| + |
| + widget1_ = |
| + static_cast<MockRenderWidget*>(blimp_contents_->GetWidgetForId(1)); |
| + widget2_ = |
| + static_cast<MockRenderWidget*>(blimp_contents_->GetWidgetForId(2)); |
| + |
| + EXPECT_NE(widget1_, nullptr); |
|
nyquist
2016/08/16 23:14:57
Nit: do you want to flip these to match other EXPE
Khushal
2016/08/18 02:01:46
The macro is expected,actual so you're right. Done
|
| + EXPECT_NE(widget2_, nullptr); |
| + } |
| + |
| + void TearDown() override { |
| + blimp_contents_.reset(); |
| + compositor_deps_provider_.reset(); |
| + image_serialization_processor_.reset(); |
| + widget1_ = nullptr; |
| + widget2_ = nullptr; |
| + } |
| + |
| + base::MessageLoop loop_; |
| + std::unique_ptr<BlimpContentsImpl> blimp_contents_; |
| + std::unique_ptr<CompositorDepsProvider> compositor_deps_provider_; |
| + std::unique_ptr<BlobImageSerializationProcessor> |
| + image_serialization_processor_; |
| + MockRenderWidgetFeature render_widget_feature_; |
| + |
| + MockRenderWidget* widget1_; |
| + MockRenderWidget* widget2_; |
| +}; |
| + |
| +TEST_F(BlimpContentsImplTest, LoadURLAndNotifyObservers) { |
| + SetUpBlimpContents(true); |
| BlimpNavigationControllerImpl& navigation_controller = |
| - blimp_contents.GetNavigationController(); |
| + blimp_contents_->GetNavigationController(); |
| FakeNavigationFeature feature; |
| feature.SetDelegate(1, &navigation_controller); |
| navigation_controller.SetNavigationFeatureForTesting(&feature); |
| - testing::StrictMock<MockBlimpContentsObserver> observer1(&blimp_contents); |
| - testing::StrictMock<MockBlimpContentsObserver> observer2(&blimp_contents); |
| + testing::StrictMock<MockBlimpContentsObserver> observer1( |
| + blimp_contents_.get()); |
| + testing::StrictMock<MockBlimpContentsObserver> observer2( |
| + blimp_contents_.get()); |
| EXPECT_CALL(observer1, OnNavigationStateChanged()); |
| EXPECT_CALL(observer2, OnNavigationStateChanged()).Times(2); |
| navigation_controller.LoadURL(GURL(kExampleURL)); |
| - loop.RunUntilIdle(); |
| + loop_.RunUntilIdle(); |
| EXPECT_EQ(kExampleURL, navigation_controller.GetURL().spec()); |
| // Observer should no longer receive callbacks. |
| - blimp_contents.RemoveObserver(&observer1); |
| + blimp_contents_->RemoveObserver(&observer1); |
| navigation_controller.LoadURL(GURL(kOtherExampleURL)); |
| - loop.RunUntilIdle(); |
| + loop_.RunUntilIdle(); |
| EXPECT_EQ(kOtherExampleURL, navigation_controller.GetURL().spec()); |
| } |
| +TEST_F(BlimpContentsImplTest, ForwardsMessagesToCorrectWidget) { |
| + SetUpBlimpContents(true); |
| + SetUpWidgets(); |
| + |
| + // Ensure that the compositor messages for a render widget are forwarded to |
| + // the correct blimp render widget. |
| + EXPECT_CALL(*widget1_, MockableOnCompositorMessageReceived(_)).Times(2); |
| + EXPECT_CALL(*widget2_, MockableOnCompositorMessageReceived(_)).Times(1); |
| + EXPECT_CALL(*widget1_, SetVisible(false)).Times(1); |
| + EXPECT_CALL(*widget1_, SetAcceleratedWidget(gfx::kNullAcceleratedWidget)) |
| + .Times(1); |
| + |
| + blimp_contents_->OnCompositorMessageReceived( |
| + widget1_->GetId(), base::WrapUnique(new cc::proto::CompositorMessage)); |
| + blimp_contents_->OnRenderWidgetInitialized(widget1_->GetId()); |
| + EXPECT_EQ(widget1_, blimp_contents_->GetActiveWidget()); |
| + |
| + blimp_contents_->OnCompositorMessageReceived( |
| + widget1_->GetId(), base::WrapUnique(new cc::proto::CompositorMessage)); |
| + blimp_contents_->OnCompositorMessageReceived( |
| + widget2_->GetId(), base::WrapUnique(new cc::proto::CompositorMessage)); |
| + |
| + int32_t deleted_id = widget1_->GetId(); |
| + blimp_contents_->OnRenderWidgetDeleted(deleted_id); |
| + EXPECT_EQ(blimp_contents_->GetWidgetForId(deleted_id), nullptr); |
| +} |
| + |
| +TEST_F(BlimpContentsImplTest, ForwardsViewEventsToCorrectWidget) { |
| + InSequence sequence; |
| + SetUpBlimpContents(true); |
| + SetUpWidgets(); |
| + |
| + // Called when the first widget is intialized. |
| + EXPECT_CALL(*widget1_, SetVisible(true)); |
| + EXPECT_CALL(*widget1_, SetAcceleratedWidget(gfx::kNullAcceleratedWidget)); |
| + |
| + // Called when the second widget is initialized. |
| + EXPECT_CALL(*widget1_, SetVisible(false)); |
| + EXPECT_CALL(*widget1_, SetAcceleratedWidget(gfx::kNullAcceleratedWidget)); |
| + EXPECT_CALL(*widget2_, SetVisible(true)); |
| + EXPECT_CALL(*widget2_, SetAcceleratedWidget(gfx::kNullAcceleratedWidget)); |
| + |
| + // Called when the visibility is toggled after the second widget is |
| + // initialized. |
| + EXPECT_CALL(*widget2_, SetVisible(false)); |
| + |
| + // Make the BlimpContents visible while we don't have any render widget |
| + // initialized. |
| + blimp_contents_->SetVisible(true); |
| + blimp_contents_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget); |
| + |
| + // Initialize the first render widget. This should propagate the visibility |
| + // and the accelerated widget to the corresponding widget. |
| + blimp_contents_->OnRenderWidgetInitialized(widget1_->GetId()); |
| + |
| + // Now initialize the second render widget. This should swap the widget |
| + // and make the first one invisible and release the accelerated widget. |
| + blimp_contents_->OnRenderWidgetInitialized(widget2_->GetId()); |
| + |
| + // Now make the BlimpContents invisible. This should make the current render |
| + // widget invisible. |
| + blimp_contents_->SetVisible(false); |
| + |
| + // Destroy all the widgets. We should not be receiving any calls for the view |
| + // events forwarded after this. |
| + blimp_contents_->OnRenderWidgetDeleted(widget1_->GetId()); |
| + blimp_contents_->OnRenderWidgetDeleted(widget2_->GetId()); |
| + |
| + blimp_contents_->SetVisible(true); |
| +} |
| + |
| } // namespace |
| } // namespace client |
| } // namespace blimp |