diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-28 17:45:19 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-28 17:45:19 +0000 |
commit | 99796bd00ef99bb38f651e62e640989b17ab0bf6 (patch) | |
tree | b8e6182770e99dff83adc095281e41111887c4b9 /chrome | |
parent | b026f4aeb159244e47d3b55c5faad7bb3247fd55 (diff) | |
download | chromium_src-99796bd00ef99bb38f651e62e640989b17ab0bf6.zip chromium_src-99796bd00ef99bb38f651e62e640989b17ab0bf6.tar.gz chromium_src-99796bd00ef99bb38f651e62e640989b17ab0bf6.tar.bz2 |
Write some basic RenderWidgetHost unittests for the more tricky behavior.
Review URL: http://codereview.chromium.org/19419
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8806 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/renderer_host/mock_render_process_host.cc | 2 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host.h | 4 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_unittest.cc | 299 | ||||
-rw-r--r-- | chrome/common/ipc_test_sink.h | 8 | ||||
-rw-r--r-- | chrome/test/unit/unit_tests.scons | 2 | ||||
-rw-r--r-- | chrome/test/unit/unittests.vcproj | 4 |
6 files changed, 318 insertions, 1 deletions
diff --git a/chrome/browser/renderer_host/mock_render_process_host.cc b/chrome/browser/renderer_host/mock_render_process_host.cc index 525f726..c1c9ae9 100644 --- a/chrome/browser/renderer_host/mock_render_process_host.cc +++ b/chrome/browser/renderer_host/mock_render_process_host.cc @@ -31,7 +31,7 @@ void MockRenderProcessHost::CrossSiteClosePageACK( bool MockRenderProcessHost::WaitForPaintMsg(int render_widget_id,
const base::TimeDelta& max_delay,
IPC::Message* msg) {
- return true;
+ return false;
}
void MockRenderProcessHost::ReceivedBadMessage(uint16 msg_type) {
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h index 70d6cf5..d61320b 100644 --- a/chrome/browser/renderer_host/render_widget_host.h +++ b/chrome/browser/renderer_host/render_widget_host.h @@ -12,6 +12,7 @@ #include "base/gfx/size.h" #include "base/timer.h" #include "chrome/common/ipc_channel.h" +#include "testing/gtest/include/gtest/gtest_prod.h" namespace gfx { class Rect; @@ -229,6 +230,9 @@ class RenderWidgetHost : public IPC::Channel::Listener { virtual void NotifyRendererResponsive() {} private: + FRIEND_TEST(RenderWidgetHostTest, Resize); + FRIEND_TEST(RenderWidgetHostTest, HiddenPaint); + // Tell this object to destroy itself. void Destroy(); diff --git a/chrome/browser/renderer_host/render_widget_host_unittest.cc b/chrome/browser/renderer_host/render_widget_host_unittest.cc new file mode 100644 index 0000000..166efb9 --- /dev/null +++ b/chrome/browser/renderer_host/render_widget_host_unittest.cc @@ -0,0 +1,299 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/basictypes.h" +#include "base/scoped_ptr.h" +#include "base/shared_memory.h" +#include "build/build_config.h" +#include "chrome/browser/renderer_host/test_render_view_host.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +// RenderWidgetHostProcess ----------------------------------------------------- + +class RenderWidgetHostProcess : public MockRenderProcessHost { + public: + RenderWidgetHostProcess(Profile* profile) + : MockRenderProcessHost(profile), + current_paint_buf_(NULL), + paint_msg_should_reply_(false), + paint_msg_reply_flags_(0) { + // DANGER! This is a hack. The RenderWidgetHost checks the channel to see + // if the process is still alive, but it doesn't actually dereference it. + // An IPC::SyncChannel is nontrivial, so we just fake it here. If you end up + // crashing by dereferencing 1, then you'll have to make a real channel. + channel_.reset(reinterpret_cast<IPC::SyncChannel*>(0x1)); + } + ~RenderWidgetHostProcess() { + // We don't want to actually delete the channel, since it's not a real + // pointer. + channel_.release(); + } + + void set_paint_msg_should_reply(bool reply) { + paint_msg_should_reply_ = reply; + } + void set_paint_msg_reply_flags(int flags) { + paint_msg_reply_flags_ = flags; + } + + // Fills the given paint parameters with resonable default values. + void InitPaintRectParams(ViewHostMsg_PaintRect_Params* params); + + protected: + virtual bool WaitForPaintMsg(int render_widget_id, + const base::TimeDelta& max_delay, + IPC::Message* msg); + + scoped_ptr<base::SharedMemory> current_paint_buf_; + + // Set to true when WaitForPaintMsg should return a successful paint messaage + // reply. False implies timeout. + bool paint_msg_should_reply_; + + // Indicates the flags that should be sent with a the repaint request. This + // only has an effect when paint_msg_should_reply_ is true. + int paint_msg_reply_flags_; + + DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostProcess); +}; + +void RenderWidgetHostProcess::InitPaintRectParams( + ViewHostMsg_PaintRect_Params* params) { + // Create the shared backing store. + const int w = 100, h = 100; + int pixel_size = w * h * 4; + current_paint_buf_.reset(new base::SharedMemory()); + ASSERT_TRUE(current_paint_buf_->Create(std::wstring(), false, true, + pixel_size)); + + params->bitmap = current_paint_buf_->handle(); + params->bitmap_rect = gfx::Rect(0, 0, w, h); + params->view_size = gfx::Size(w, h); + params->flags = paint_msg_reply_flags_; +} + +bool RenderWidgetHostProcess::WaitForPaintMsg(int render_widget_id, + const base::TimeDelta& max_delay, + IPC::Message* msg) { + if (!paint_msg_should_reply_) + return false; + + // Construct a fake paint reply. + ViewHostMsg_PaintRect_Params params; + InitPaintRectParams(¶ms); + + ViewHostMsg_PaintRect message(render_widget_id, params); + *msg = message; + return true; +} + +// TestView -------------------------------------------------------------------- + +// This test view allows us to specify the size. +class TestView : public TestRenderWidgetHostView { + public: + TestView() {} + + // Sets the bounds returned by GetViewBounds. + void set_bounds(const gfx::Rect& bounds) { + bounds_ = bounds; + } + + // RenderWidgetHostView override. + virtual gfx::Rect GetViewBounds() const { + return bounds_; + } + + protected: + gfx::Rect bounds_; + DISALLOW_COPY_AND_ASSIGN(TestView); +}; + +// RenderWidgetHostTest -------------------------------------------------------- + +class RenderWidgetHostTest : public testing::Test { + public: + RenderWidgetHostTest() : process_(NULL) { + } + ~RenderWidgetHostTest() { + } + + protected: + // testing::Test + void SetUp() { + profile_.reset(new TestingProfile()); + process_ = new RenderWidgetHostProcess(profile_.get()); + host_.reset(new RenderWidgetHost(process_, 1)); + view_.reset(new TestView); + host_->set_view(view_.get()); + } + void TearDown() { + view_.reset(); + host_.reset(); + process_ = NULL; + profile_.reset(); + + // Process all pending tasks to avoid leaks. + MessageLoop::current()->RunAllPending(); + } + + MessageLoopForUI message_loop_; + + scoped_ptr<TestingProfile> profile_; + RenderWidgetHostProcess* process_; // Deleted automatically by the widget. + scoped_ptr<RenderWidgetHost> host_; + scoped_ptr<TestView> view_; + + DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostTest); +}; + +} // namespace + +// ----------------------------------------------------------------------------- + +TEST_F(RenderWidgetHostTest, Resize) { + // The initial bounds is the empty rect, so setting it to the same thing + // should do nothing. + view_->set_bounds(gfx::Rect()); + host_->WasResized(); + EXPECT_FALSE(host_->resize_ack_pending_); + EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID)); + + // Setting the bounds to a "real" rect should send out the notification. + gfx::Rect original_size(0, 0, 100, 100); + process_->sink().ClearMessages(); + view_->set_bounds(original_size); + host_->WasResized(); + EXPECT_TRUE(host_->resize_ack_pending_); + EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID)); + + // Send out a paint that's not a resize ack. This should not clean the + // resize ack pending flag. + ViewHostMsg_PaintRect_Params params; + process_->InitPaintRectParams(¶ms); + host_->OnMsgPaintRect(params); + EXPECT_TRUE(host_->resize_ack_pending_); + + // Sending out a new notification should NOT send out a new IPC message since + // a resize ACK is pending. + gfx::Rect second_size(0, 0, 90, 90); + process_->sink().ClearMessages(); + view_->set_bounds(second_size); + host_->WasResized(); + EXPECT_TRUE(host_->resize_ack_pending_); + EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID)); + + // Send a paint that's a resize ack, but for the original_size we sent. Since + // this isn't the second_size, the message handler should immediately send + // a new resize message for the new size to the renderer. + process_->sink().ClearMessages(); + params.flags = ViewHostMsg_PaintRect_Flags::IS_RESIZE_ACK; + params.view_size = original_size.size(); + host_->OnMsgPaintRect(params); + EXPECT_TRUE(host_->resize_ack_pending_); + ASSERT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID)); + + // Send the resize ack for the latest size. + process_->sink().ClearMessages(); + params.view_size = second_size.size(); + host_->OnMsgPaintRect(params); + EXPECT_FALSE(host_->resize_ack_pending_); + ASSERT_FALSE(process_->sink().GetFirstMessageMatching(ViewMsg_Resize::ID)); + + // Now clearing the bounds should send out a notification but we shouldn't + // expect a resize ack (since the renderer won't ack empty sizes). The message + // should contain the new size (0x0) and not the previous one that we skipped + process_->sink().ClearMessages(); + view_->set_bounds(gfx::Rect()); + host_->WasResized(); + EXPECT_FALSE(host_->resize_ack_pending_); + EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID)); +} + +// Tests getting the backing store with the renderer not setting repaint ack +// flags. +TEST_F(RenderWidgetHostTest, GetBackingStore_NoRepaintAck) { + // We don't currently have a backing store, and if the renderer doesn't send + // one in time, we should get nothing. + process_->set_paint_msg_should_reply(false); + BackingStore* backing = host_->GetBackingStore(); + EXPECT_FALSE(backing); + // The widget host should have sent a request for a repaint, and there should + // be no paint ACK. + EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID)); + EXPECT_FALSE(process_->sink().GetUniqueMessageMatching( + ViewMsg_PaintRect_ACK::ID)); + + // Allowing the renderer to reply in time should give is a backing store. + process_->sink().ClearMessages(); + process_->set_paint_msg_should_reply(true); + process_->set_paint_msg_reply_flags(0); + backing = host_->GetBackingStore(); + EXPECT_TRUE(backing); + // The widget host should NOT have sent a request for a repaint, since there + // was an ACK already pending. + EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID)); + EXPECT_TRUE(process_->sink().GetUniqueMessageMatching( + ViewMsg_PaintRect_ACK::ID)); +} + +// Tests getting the backing store with the renderer sending a repaint ack. +TEST_F(RenderWidgetHostTest, GetBackingStore_RepaintAck) { + // Doing a request request with the paint message allowed should work and + // the repaint ack should work. + process_->set_paint_msg_should_reply(true); + process_->set_paint_msg_reply_flags( + ViewHostMsg_PaintRect_Flags::IS_REPAINT_ACK); + BackingStore* backing = host_->GetBackingStore(); + EXPECT_TRUE(backing); + // We still should not have sent out a repaint request since the last flags + // didn't have the repaint ack set, and the pending flag will still be set. + EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID)); + EXPECT_TRUE(process_->sink().GetUniqueMessageMatching( + ViewMsg_PaintRect_ACK::ID)); + + // Asking again for the backing store should just re-use the existing one + // and not send any messagse. + process_->sink().ClearMessages(); + backing = host_->GetBackingStore(); + EXPECT_TRUE(backing); + EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID)); + EXPECT_FALSE(process_->sink().GetUniqueMessageMatching( + ViewMsg_PaintRect_ACK::ID)); +} + +// Test that we don't paint when we're hidden, but we still send the ACK. Most +// of the rest of the painting is tested in the GetBackingStore* ones. +TEST_F(RenderWidgetHostTest, HiddenPaint) { + // Hide the widget, it should have sent out a message to the renderer. + EXPECT_FALSE(host_->is_hidden_); + host_->WasHidden(); + EXPECT_TRUE(host_->is_hidden_); + EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_WasHidden::ID)); + + // Send it a paint as from the renderer. + process_->sink().ClearMessages(); + ViewHostMsg_PaintRect_Params params; + process_->InitPaintRectParams(¶ms); + host_->OnMsgPaintRect(params); + + // It should have sent out the ACK. + EXPECT_TRUE(process_->sink().GetUniqueMessageMatching( + ViewMsg_PaintRect_ACK::ID)); + + // Now unhide. + process_->sink().ClearMessages(); + host_->WasRestored(); + EXPECT_FALSE(host_->is_hidden_); + + // It should have sent out a restored message with a request to paint. + const IPC::Message* restored = process_->sink().GetUniqueMessageMatching( + ViewMsg_WasRestored::ID); + ASSERT_TRUE(restored); + bool needs_repaint; + ViewMsg_WasRestored::Read(restored, &needs_repaint); + EXPECT_TRUE(needs_repaint); +} diff --git a/chrome/common/ipc_test_sink.h b/chrome/common/ipc_test_sink.h index db4096d..9403deb 100644 --- a/chrome/common/ipc_test_sink.h +++ b/chrome/common/ipc_test_sink.h @@ -27,6 +27,14 @@ namespace IPC { // // ...and no start load messages.
// EXPECT_FALSE(test_sink.GetFirstMessageMatching(ViewHostMsg_Start::ID));
//
+// // Now inspect a message. This assumes a message that was declared like
+// // this: IPC_MESSAGE_ROUTED2(ViewMsg_Foo, bool, int)
+// IPC::Message* msg = test_sink.GetFirstMessageMatching(ViewMsg_Foo::ID));
+// ASSERT_TRUE(msg);
+// bool first_param;
+// int second_param;
+// ViewMsg_Foo::Read(msg, &first_param, &second_param);
+//
// // Go on to the next phase of the test.
// test_sink.ClearMessages();
//
diff --git a/chrome/test/unit/unit_tests.scons b/chrome/test/unit/unit_tests.scons index adf72e7..bae1094 100644 --- a/chrome/test/unit/unit_tests.scons +++ b/chrome/test/unit/unit_tests.scons @@ -197,6 +197,7 @@ input_files = ChromeFileList([ '$CHROME_DIR/browser/webdata/web_database_unittest.cc', '$CHROME_DIR/browser/printing/win_printing_context_unittest.cc', '$CHROME_DIR/browser/window_sizer_unittest.cc', + '$CHROME_DIR/browser/renderer_host/render_widget_host_unittests.cc', # test_infrastructure '$CHROME_DIR/test/browser_with_test_window_test.cc', @@ -411,6 +412,7 @@ if not env.Bit('windows'): '$CHROME_DIR/browser/metrics/metrics_log_unittest.cc', '$CHROME_DIR/browser/renderer_host/mock_render_process_host.cc', '$CHROME_DIR/browser/renderer_host/mock_render_process_host.h', + '$CHROME_DIR/browser/renderer_host/render_widget_host_unittests.cc', '$CHROME_DIR/browser/navigation_controller_unittest.cc', '$CHROME_DIR/browser/net/dns_master_unittest.cc', '$CHROME_DIR/browser/password_manager/encryptor_unittest.cc', diff --git a/chrome/test/unit/unittests.vcproj b/chrome/test/unit/unittests.vcproj index 3e44d38..d5d5e95 100644 --- a/chrome/test/unit/unittests.vcproj +++ b/chrome/test/unit/unittests.vcproj @@ -571,6 +571,10 @@ > </File> <File + RelativePath="..\..\browser\renderer_host\render_widget_host_unittest.cc" + > + </File> + <File RelativePath="..\..\browser\renderer_host\renderer_security_policy_unittest.cc" > </File> |