diff options
author | hbono@chromium.org <hbono@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-23 03:09:52 +0000 |
---|---|---|
committer | hbono@chromium.org <hbono@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-23 03:09:52 +0000 |
commit | fa8a2b1b050009d67e03cf03a26d7d558afe0ecb (patch) | |
tree | 09108ff8271c1ca005d439213db16a784977175f /chrome/renderer | |
parent | b6b60c9b2afa70010fe38ed7c753f4c8e37e7131 (diff) | |
download | chromium_src-fa8a2b1b050009d67e03cf03a26d7d558afe0ecb.zip chromium_src-fa8a2b1b050009d67e03cf03a26d7d558afe0ecb.tar.gz chromium_src-fa8a2b1b050009d67e03cf03a26d7d558afe0ecb.tar.bz2 |
Adds a RenderViewTest.PrintLayoutTest.
This change adds a new test 'RenderViewTest.PrintLayoutTest', which prints an HTML page and verify its output.
To process a print job and verify its output, this change adds a pseudo-printer device "MockPrinter" into the MockRenderThread object. This MockPrinter object receives print-related IPC messages, process print jobs, and store the MD5 checksum of the output data.
The current RenderViewTest.PrintLayoutTest retrieves the MD5 checksum values and just compare them with expected values. Nevertheless, please feel free to give me your ideas to improve this test.
Finally, this change is inspired by PrintingLayoutTextTests (created by maruel) and a RenderViewTest.OnPrintPages (created by Mohamed Mansour). I would like to express my best gratitude to them.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/100255
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16834 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r-- | chrome/renderer/mock_printer.cc | 214 | ||||
-rw-r--r-- | chrome/renderer/mock_printer.h | 155 | ||||
-rw-r--r-- | chrome/renderer/mock_printer_driver_win.cc | 125 | ||||
-rw-r--r-- | chrome/renderer/mock_printer_driver_win.h | 25 | ||||
-rw-r--r-- | chrome/renderer/mock_render_thread.cc | 40 | ||||
-rw-r--r-- | chrome/renderer/mock_render_thread.h | 13 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 1 | ||||
-rw-r--r-- | chrome/renderer/render_view_unittest.cc | 88 |
8 files changed, 650 insertions, 11 deletions
diff --git a/chrome/renderer/mock_printer.cc b/chrome/renderer/mock_printer.cc new file mode 100644 index 0000000..88f9909 --- /dev/null +++ b/chrome/renderer/mock_printer.cc @@ -0,0 +1,214 @@ +// 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 "chrome/renderer/mock_printer.h" + +#include "base/file_util.h" +#include "base/gfx/png_encoder.h" +#include "base/logging.h" +#include "base/md5.h" +#include "base/shared_memory.h" +#include "chrome/common/ipc_message_utils.h" +#include "chrome/common/render_messages.h" +#include "testing/gtest/include/gtest/gtest.h" + +MockPrinter::MockPrinter() + : printable_width_(0), + printable_height_(0), + dpi_(72), + max_shrink_(2.0), + min_shrink_(1.25), + desired_dpi_(72), + document_cookie_(-1), + current_document_cookie_(0), + printer_status_(PRINTER_READY), + number_pages_(0), + page_number_(0) { + printable_width_ = static_cast<int>(dpi_ * 8.5); + printable_height_ = static_cast<int>(dpi_ * 11.0); +} + +MockPrinter::~MockPrinter() { +} + +void MockPrinter::ResetPrinter() { + printer_status_ = PRINTER_READY; + document_cookie_ = -1; +} + +void MockPrinter::GetDefaultPrintSettings(ViewMsg_Print_Params* params) { + // Verify this printer is not processing a job. + // Sorry, this mock printer is very fragile. + EXPECT_EQ(-1, document_cookie_); + + // Assign a unit document cookie and set the print settings. + document_cookie_ = CreateDocumentCookie(); + memset(params, 0, sizeof(ViewMsg_Print_Params)); + params->dpi = dpi_; + params->max_shrink = max_shrink_; + params->min_shrink = min_shrink_; + params->desired_dpi = desired_dpi_; + params->document_cookie = document_cookie_; + params->printable_size.set_width(printable_width_); + params->printable_size.set_height(printable_height_); +} + +void MockPrinter::SetDefaultPrintSettings(const ViewMsg_Print_Params& params) { + dpi_ = params.dpi; + max_shrink_ = params.max_shrink; + min_shrink_ = params.min_shrink; + desired_dpi_ = params.desired_dpi; + printable_width_ = params.printable_size.width(); + printable_height_ = params.printable_size.height(); +} + +void MockPrinter::ScriptedPrint(int cookie, + int expected_pages_count, + ViewMsg_PrintPages_Params* settings) { + // Verify the input parameters. + EXPECT_EQ(document_cookie_, cookie); + + memset(settings, 0, sizeof(ViewMsg_PrintPages_Params)); + settings->params.dpi = dpi_; + settings->params.max_shrink = max_shrink_; + settings->params.min_shrink = min_shrink_; + settings->params.desired_dpi = desired_dpi_; + settings->params.document_cookie = document_cookie_; + settings->params.printable_size.set_width(printable_width_); + settings->params.printable_size.set_height(printable_height_); + printer_status_ = PRINTER_PRINTING; +} + +void MockPrinter::SetPrintedPagesCount(int cookie, int number_pages) { + // Verify the input parameter and update the printer status so that the + // RenderViewTest class can verify the this function finishes without errors. + EXPECT_EQ(document_cookie_, cookie); + EXPECT_EQ(PRINTER_PRINTING, printer_status_); + EXPECT_EQ(0, number_pages_); + EXPECT_EQ(0, page_number_); + + // Initialize the job status. + number_pages_ = number_pages; + page_number_ = 0; + pages_.clear(); +} + +void MockPrinter::PrintPage(const ViewHostMsg_DidPrintPage_Params& params) { + // Verify the input parameter and update the printer status so that the + // RenderViewTest class can verify the this function finishes without errors. + EXPECT_EQ(PRINTER_PRINTING, printer_status_); + EXPECT_EQ(document_cookie_, params.document_cookie); + EXPECT_EQ(page_number_, params.page_number); + EXPECT_LE(params.page_number, number_pages_); + +#if defined(OS_WIN) + // Load the EMF data sent from a RenderView object and create a PageData + // object. + // We duplicate the given file handle when creating a base::SharedMemory + // instance so that its destructor closes the copy. + EXPECT_GT(params.data_size, 0U); + base::SharedMemory emf_data(params.emf_data_handle, true, + GetCurrentProcess()); + emf_data.Map(params.data_size); + MockPrinterPage* page_data = driver_.LoadSource(emf_data.memory(), + params.data_size); + if (!page_data) { + printer_status_ = PRINTER_ERROR; + return; + } + + scoped_refptr<MockPrinterPage> page(page_data); + pages_.push_back(page); +#endif + + // We finish printing a printing job. + // Reset the job status and the printer status. + ++page_number_; + if (number_pages_ == page_number_) + ResetPrinter(); +} + +int MockPrinter::GetPrintedPages() const { + if (printer_status_ != PRINTER_READY) + return -1; + return page_number_; +} + +int MockPrinter::GetWidth(size_t page) const { + if (printer_status_ != PRINTER_READY || page >= pages_.size()) + return -1; + return pages_[page]->width(); +} + +int MockPrinter::GetHeight(size_t page) const { + if (printer_status_ != PRINTER_READY || page >= pages_.size()) + return -1; + return pages_[page]->height(); +} + +bool MockPrinter::GetSourceChecksum(size_t page, std::string* checksum) const { + if (printer_status_ != PRINTER_READY || page >= pages_.size()) + return false; + return GetChecksum(pages_[page]->source_data(), pages_[page]->source_size(), + checksum); +} + +bool MockPrinter::GetBitmapChecksum(size_t page, std::string* checksum) const { + if (printer_status_ != PRINTER_READY || page >= pages_.size()) + return false; + return GetChecksum(pages_[page]->bitmap_data(), pages_[page]->bitmap_size(), + checksum); +} + +bool MockPrinter::GetBitmap(size_t page, + const void** data, + size_t* size) const { + if (printer_status_ != PRINTER_READY || page >= pages_.size()) + return false; + *data = pages_[page]->bitmap_data(); + *size = pages_[page]->bitmap_size(); + return true; +} + +bool MockPrinter::SaveSource(size_t page, + const std::wstring& filename) const { + if (printer_status_ != PRINTER_READY || page >= pages_.size()) + return false; + const uint8* source_data = pages_[page]->source_data(); + size_t source_size = pages_[page]->source_size(); + file_util::WriteFile(filename, reinterpret_cast<const char*>(source_data), + source_size); + return true; +} + +bool MockPrinter::SaveBitmap(size_t page, + const std::wstring& filename) const { + if (printer_status_ != PRINTER_READY || page >= pages_.size()) + return false; + int width = pages_[page]->width(); + int height = pages_[page]->height(); + int row_byte_width = width * 4; + const uint8* bitmap_data = pages_[page]->bitmap_data(); + std::vector<unsigned char> compressed; + PNGEncoder::Encode(bitmap_data, + PNGEncoder::FORMAT_BGRA, width, height, + row_byte_width, true, &compressed); + file_util::WriteFile(filename, + reinterpret_cast<char*>(&*compressed.begin()), + compressed.size()); + return true; +} + +int MockPrinter::CreateDocumentCookie() { + return ++current_document_cookie_; +} + +bool MockPrinter::GetChecksum(const void* data, + size_t size, + std::string* checksum) const { + MD5Digest digest; + MD5Sum(data, size, &digest); + checksum->assign(HexEncode(&digest, sizeof(digest))); + return true; +} diff --git a/chrome/renderer/mock_printer.h b/chrome/renderer/mock_printer.h new file mode 100644 index 0000000..bf318c1 --- /dev/null +++ b/chrome/renderer/mock_printer.h @@ -0,0 +1,155 @@ +// 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. + +#ifndef CHROME_RENDERER_MOCK_PRINTER_H_ +#define CHROME_RENDERER_MOCK_PRINTER_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/ref_counted.h" +#include "base/scoped_ptr.h" + +#if defined(OS_WIN) +#include "chrome/renderer/mock_printer_driver_win.h" +#endif + +struct ViewMsg_Print_Params; +struct ViewMsg_PrintPages_Params; +struct ViewHostMsg_DidPrintPage_Params; + +// A class which represents an output page used in the MockPrinter class. +// The MockPrinter class stores output pages in a vector, so, this class +// inherits the base::RefCounted<> class so that the MockPrinter class can use +// a smart pointer of this object (i.e. scoped_refptr<>). +class MockPrinterPage : public base::RefCounted<MockPrinterPage> { + public: + MockPrinterPage() + : width_(0), + height_(0), + source_size_(0), + bitmap_size_(0) { + } + + MockPrinterPage(int width, + int height, + const void* source_data, + size_t source_size, + const void* bitmap_data, + size_t bitmap_size) + : width_(width), + height_(height), + source_size_(source_size), + bitmap_size_(bitmap_size) { + // Create copies of the source data and the bitmap data. + source_data_.reset(new uint8[source_size]); + if (source_data_.get()) + memcpy(source_data_.get(), source_data, source_size); + bitmap_data_.reset(new uint8[bitmap_size]); + if (bitmap_data_.get()) + memcpy(bitmap_data_.get(), bitmap_data, bitmap_size); + } + + ~MockPrinterPage() { + } + + int width() { return width_; } + int height() { return height_; } + const uint8* source_data() { return source_data_.get(); } + const size_t source_size() { return source_size_; } + const uint8* bitmap_data() { return bitmap_data_.get(); } + const size_t bitmap_size() { return bitmap_size_; } + + private: + int width_; + int height_; + size_t source_size_; + scoped_array<uint8> source_data_; + size_t bitmap_size_; + scoped_array<uint8> bitmap_data_; + + DISALLOW_COPY_AND_ASSIGN(MockPrinterPage); +}; + +// A class which implements a pseudo-printer object used by the RenderViewTest +// class. +// This class consists of three parts: +// 1. An IPC-message hanlder sent from the RenderView class; +// 2. A renderer that creates a printing job into bitmaps, and; +// 3. A vector which saves the output pages of a printing job. +// A user who writes RenderViewTest cases only use the functions which +// retrieve output pages from this vector to verify them with expected results. +class MockPrinter { + public: + enum Status { + PRINTER_READY, + PRINTER_PRINTING, + PRINTER_ERROR, + }; + + MockPrinter(); + ~MockPrinter(); + + // Functions that changes settings of a pseudo printer. + void ResetPrinter(); + void SetDefaultPrintSettings(const ViewMsg_Print_Params& params); + + // Functions that handles IPC events. + void GetDefaultPrintSettings(ViewMsg_Print_Params* params); + void ScriptedPrint(int cookie, + int expected_pages_count, + ViewMsg_PrintPages_Params* settings); + void SetPrintedPagesCount(int cookie, int number_pages); + void PrintPage(const ViewHostMsg_DidPrintPage_Params& params); + + // Functions that retrieve the output pages. + Status GetPrinterStatus() const { return printer_status_; } + int GetPrintedPages() const; + int GetWidth(size_t page) const; + int GetHeight(size_t page) const; + bool GetSourceChecksum(size_t page, std::string* checksum) const; + bool GetBitmapChecksum(size_t page, std::string* checksum) const; + bool GetSource(size_t page, const void** data, size_t* size) const; + bool GetBitmap(size_t page, const void** data, size_t* size) const; + bool SaveSource(size_t page, const std::wstring& filename) const; + bool SaveBitmap(size_t page, const std::wstring& filename) const; + + protected: + int CreateDocumentCookie(); + bool GetChecksum(const void* data, size_t size, std::string* checksum) const; + + private: + // In pixels according to dpi_x and dpi_y. + int printable_width_; + int printable_height_; + + // Specifies dots per inch. + double dpi_; + double max_shrink_; + double min_shrink_; + + // Desired apparent dpi on paper. + int desired_dpi_; + + // Cookie for the document to ensure correctness. + int document_cookie_; + int current_document_cookie_; + + // The current status of this printer. + Status printer_status_; + + // The output of a printing job. + int number_pages_; + int page_number_; + std::vector<scoped_refptr<MockPrinterPage> > pages_; + +#if defined(OS_WIN) + MockPrinterDriverWin driver_; +#endif + + DISALLOW_COPY_AND_ASSIGN(MockPrinter); +}; + +#endif // CHROME_RENDERER_MOCK_PRINTER_H_ diff --git a/chrome/renderer/mock_printer_driver_win.cc b/chrome/renderer/mock_printer_driver_win.cc new file mode 100644 index 0000000..4232019 --- /dev/null +++ b/chrome/renderer/mock_printer_driver_win.cc @@ -0,0 +1,125 @@ +// 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 "chrome/renderer/mock_printer_driver_win.h" + +#include "base/gfx/gdi_util.h" +#include "base/logging.h" +#include "chrome/common/gfx/emf.h" +#include "chrome/renderer/mock_printer.h" +#include "skia/ext/platform_device.h" + +namespace { + +// A simple class which temporarily overrides system settings. +// The bitmap image rendered via the PlayEnhMetaFile() function depends on +// some system settings. +// As a workaround for such dependency, this class saves the system settings +// and changes them. This class also restore the saved settings in its +// destructor. +class SystemSettingsOverride { + public: + SystemSettingsOverride() : font_smoothing_(0) { + } + + ~SystemSettingsOverride() { + SystemParametersInfo(SPI_SETFONTSMOOTHING, font_smoothing_, NULL, 0); + } + + BOOL Init(BOOL font_smoothing) { + if (!SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &font_smoothing_, 0)) + return FALSE; + return SystemParametersInfo(SPI_SETFONTSMOOTHING, font_smoothing, NULL, 0); + } + + private: + BOOL font_smoothing_; +}; + +// A class which renders an EMF data and returns a raw bitmap data. +// The bitmap data returned from Create() is deleted in the destructor of this +// class. So, we need to create a copy of this bitmap data if it is used after +// this object is deleted, +class EmfRenderer { + public: + EmfRenderer() : dc_(NULL), bitmap_(NULL) { + } + + ~EmfRenderer() { + if (bitmap_) { + DeleteObject(bitmap_); + bitmap_ = NULL; + } + if (dc_) { + DeleteDC(dc_); + dc_ = NULL; + } + } + + const void* Create(int width, int height, const gfx::Emf* emf) { + CHECK(!dc_ && !bitmap_); + + BITMAPV4HEADER header; + gfx::CreateBitmapV4Header(width, height, &header); + + dc_ = CreateCompatibleDC(NULL); + if (!dc_) + return NULL; + + void* bits; + bitmap_ = CreateDIBSection(dc_, reinterpret_cast<BITMAPINFO*>(&header), 0, + &bits, NULL, 0); + if (!bitmap_ || !bits) + return NULL; + + SelectObject(dc_, bitmap_); + + skia::PlatformDeviceWin::InitializeDC(dc_); + emf->Playback(dc_, NULL); + + return reinterpret_cast<uint8*>(bits); + } + + private: + HDC dc_; + HBITMAP bitmap_; +}; + +} // namespace + +MockPrinterDriverWin::MockPrinterDriverWin() { +} + +MockPrinterDriverWin::~MockPrinterDriverWin() { +} + +MockPrinterPage* MockPrinterDriverWin::LoadSource(const void* source_data, + size_t source_size) { + // This code is mostly copied from the Image::LoadEMF() function in + // "src/chrome/browser/printing/printing_layout_uitest.cc". + gfx::Emf emf; + emf.CreateFromData(source_data, source_size); + gfx::Rect rect(emf.GetBounds()); + + // Create a temporary DC and bitmap to retrieve the renderered data. + if (rect.width() <= 0 || rect.height() <= 0) + return NULL; + + // Disable the font-smoothing feature of Windows. + SystemSettingsOverride system_settings; + system_settings.Init(FALSE); + + // Render the EMF data and create a bitmap. + EmfRenderer renderer; + const void* bitmap_data = renderer.Create(rect.width(), rect.height(), &emf); + if (!bitmap_data) + return NULL; + + // Create a new MockPrinterPage instance and return it. + size_t row_byte_width = rect.width() * 4; + size_t bitmap_size = row_byte_width * rect.height(); + return new MockPrinterPage(rect.width(), rect.height(), + source_data, source_size, + bitmap_data, bitmap_size); +} diff --git a/chrome/renderer/mock_printer_driver_win.h b/chrome/renderer/mock_printer_driver_win.h new file mode 100644 index 0000000..117aa16 --- /dev/null +++ b/chrome/renderer/mock_printer_driver_win.h @@ -0,0 +1,25 @@ +// 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. + +#ifndef CHROME_RENDERER_MOCK_PRINTER_DRIVER_WIN_H_ +#define CHROME_RENDERER_MOCK_PRINTER_DRIVER_WIN_H_ + +#include "base/basictypes.h" + +class MockPrinterPage; + +// Implements the platform-dependent part of a pseudo printer object. +// This class renders a platform-dependent input and creates a MockPrinterPage +// instance. +class MockPrinterDriverWin { + public: + MockPrinterDriverWin(); + ~MockPrinterDriverWin(); + + MockPrinterPage* LoadSource(const void* data, size_t size); + + DISALLOW_COPY_AND_ASSIGN(MockPrinterDriverWin); +}; + +#endif // CHROME_RENDERER_MOCK_PRINTER_DRIVER_WIN_H_ diff --git a/chrome/renderer/mock_render_thread.cc b/chrome/renderer/mock_render_thread.cc index 7812b31..8ff04a9 100644 --- a/chrome/renderer/mock_render_thread.cc +++ b/chrome/renderer/mock_render_thread.cc @@ -12,7 +12,8 @@ MockRenderThread::MockRenderThread() : routing_id_(0), opener_id_(0), widget_(NULL), - reply_deserializer_(NULL) { + reply_deserializer_(NULL), + printer_(new MockPrinter) { } MockRenderThread::~MockRenderThread() { @@ -78,6 +79,10 @@ void MockRenderThread::OnMessageReceived(const IPC::Message& msg) { OnGetDefaultPrintSettings); IPC_MESSAGE_HANDLER(ViewHostMsg_ScriptedPrint, OnScriptedPrint); + IPC_MESSAGE_HANDLER(ViewHostMsg_DidGetPrintedPagesCount, + OnDidGetPrintedPagesCount) + IPC_MESSAGE_HANDLER(ViewHostMsg_DidPrintPage, OnDidPrintPage) + IPC_MESSAGE_HANDLER(ViewHostMsg_DuplicateSection, OnDuplicateSection) #endif IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP_EX() @@ -96,21 +101,34 @@ void MockRenderThread::OnMsgOpenChannelToExtension( *channel_id = 0; } +void MockRenderThread::OnDuplicateSection( + base::SharedMemoryHandle renderer_handle, + base::SharedMemoryHandle* browser_handle) { + // We don't have to duplicate the input handles since RenderViewTest does not + // separate a browser process from a renderer process. + *browser_handle = renderer_handle; +} + void MockRenderThread::OnGetDefaultPrintSettings(ViewMsg_Print_Params* params) { - memset(params, 0, sizeof(ViewMsg_Print_Params)); - params->dpi = 72; - params->desired_dpi = 72; - params->document_cookie = 1; - params->printable_size = gfx::Size(500, 500); + if (printer_.get()) + printer_->GetDefaultPrintSettings(params); } void MockRenderThread::OnScriptedPrint(gfx::NativeViewId host_window, int cookie, int expected_pages_count, ViewMsg_PrintPages_Params* settings) { - memset(settings, 0, sizeof(ViewMsg_PrintPages_Params)); - settings->params.dpi = 72; - settings->params.document_cookie = 1; - settings->params.desired_dpi = 72; - settings->params.printable_size = gfx::Size(500, 500); + if (printer_.get()) + printer_->ScriptedPrint(cookie, expected_pages_count, settings); +} + +void MockRenderThread::OnDidGetPrintedPagesCount(int cookie, int number_pages) { + if (printer_.get()) + printer_->SetPrintedPagesCount(cookie, number_pages); +} + +void MockRenderThread::OnDidPrintPage( + const ViewHostMsg_DidPrintPage_Params& params) { + if (printer_.get()) + printer_->PrintPage(params); } diff --git a/chrome/renderer/mock_render_thread.h b/chrome/renderer/mock_render_thread.h index e4f2403..ebca0df 100644 --- a/chrome/renderer/mock_render_thread.h +++ b/chrome/renderer/mock_render_thread.h @@ -9,6 +9,7 @@ #include <vector> #include "chrome/common/ipc_test_sink.h" +#include "chrome/renderer/mock_printer.h" #include "chrome/renderer/render_thread.h" struct ViewMsg_Print_Params; @@ -64,6 +65,9 @@ class MockRenderThread : public RenderThreadBase { // state. void SendCloseMessage(); + // Returns the pseudo-printer instance. + const MockPrinter* printer() const { return printer_.get(); } + private: // This function operates as a regular IPC listener. void OnMessageReceived(const IPC::Message& msg); @@ -78,6 +82,9 @@ class MockRenderThread : public RenderThreadBase { const std::string& extension_id, int* channel_id); + void OnDuplicateSection(base::SharedMemoryHandle renderer_handle, + base::SharedMemoryHandle* browser_handle); + // The RenderView expects default print settings. void OnGetDefaultPrintSettings(ViewMsg_Print_Params* setting); @@ -87,6 +94,9 @@ class MockRenderThread : public RenderThreadBase { int expected_pages_count, ViewMsg_PrintPages_Params* settings); + void OnDidGetPrintedPagesCount(int cookie, int number_pages); + void OnDidPrintPage(const ViewHostMsg_DidPrintPage_Params& params); + IPC::TestSink sink_; // Routing id what will be assigned to the Widget. @@ -101,6 +111,9 @@ class MockRenderThread : public RenderThreadBase { // The last known good deserializer for sync messages. scoped_ptr<IPC::MessageReplyDeserializer> reply_deserializer_; + + // A mock printer device used for printing tests. + scoped_ptr<MockPrinter> printer_; }; #endif // CHROME_RENDERER_MOCK_RENDER_THREAD_H_ diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 4de8bb3..744ef73 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -398,6 +398,7 @@ class RenderView : public RenderWidget, FRIEND_TEST(RenderViewTest, ImeComposition); FRIEND_TEST(RenderViewTest, OnSetTextDirection); FRIEND_TEST(RenderViewTest, OnPrintPages); + FRIEND_TEST(RenderViewTest, PrintLayoutTest); FRIEND_TEST(RenderViewTest, OnHandleKeyboardEvent); FRIEND_TEST(RenderViewTest, InsertCharacters); diff --git a/chrome/renderer/render_view_unittest.cc b/chrome/renderer/render_view_unittest.cc index 8537583..781c62a 100644 --- a/chrome/renderer/render_view_unittest.cc +++ b/chrome/renderer/render_view_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/file_util.h" #include "chrome/common/native_web_keyboard_event.h" #include "chrome/common/render_messages.h" #include "chrome/test/render_view_test.h" @@ -311,6 +312,93 @@ TEST_F(RenderViewTest, OnPrintPages) { #endif } +// Tests if we can print a page and verify its results. +// This test prints HTML pages into a pseudo printer and check their outputs, +// i.e. a simplified version of the PrintingLayoutTextTest UI test. +namespace { +// Test cases used in this test. +const struct { + const char* page; + int printed_pages; + int width; + int height; + const char* checksum; + const wchar_t* file; +} kTestPages[] = { + {"<html>" + "<head>" + "<meta" + " http-equiv=\"Content-Type\"" + " content=\"text/html; charset=utf-8\"/>" + "<title>Test 1</title>" + "</head>" + "<body style=\"background-color: white;\">" + "<p style=\"font-family: arial;\">Hello World!</p>" + "</body>", + 1, 764, 42, + NULL, + NULL, + }, +}; +} // namespace + +TEST_F(RenderViewTest, PrintLayoutTest) { +#if defined(OS_WIN) + bool baseline = false; + + EXPECT_TRUE(render_thread_.printer() != NULL); + for (size_t i = 0; i < arraysize(kTestPages); ++i) { + // Load an HTML page and print it. + LoadHTML(kTestPages[i].page); + view_->OnPrintPages(); + + // MockRenderThread::Send() just calls MockRenderThread::OnMsgReceived(). + // So, all IPC messages sent in the above RenderView::OnPrintPages() call + // has been handled by the MockPrinter object, i.e. this printing job + // has been already finished. + // So, we can start checking the output pages of this printing job. + // Retrieve the number of pages actually printed. + size_t pages = render_thread_.printer()->GetPrintedPages(); + EXPECT_EQ(kTestPages[i].printed_pages, pages); + + // Retrieve the width and height of the output page. + int width = render_thread_.printer()->GetWidth(0); + int height = render_thread_.printer()->GetHeight(0); + EXPECT_EQ(kTestPages[i].width, width); + EXPECT_EQ(kTestPages[i].height, height); + + // Retrieve the checksum of the bitmap data from the pseudo printer and + // compare it with the expected result. + std::string bitmap_actual; + EXPECT_TRUE(render_thread_.printer()->GetBitmapChecksum(0, &bitmap_actual)); + if (kTestPages[i].checksum) + EXPECT_EQ(kTestPages[i].checksum, bitmap_actual); + + // Retrieve the bitmap data from the pseudo printer. + // TODO(hbono): implement a function which retrieves an expected result + // from a file and compares it with this bitmap data. + const void* bitmap_data; + size_t bitmap_size; + EXPECT_TRUE(render_thread_.printer()->GetBitmap(0, &bitmap_data, + &bitmap_size)); + + if (baseline) { + // Save the source data and the bitmap data into temporary files to + // create base-line results. + FilePath source_path; + file_util::CreateTemporaryFileName(&source_path); + render_thread_.printer()->SaveSource(0, source_path.value()); + + FilePath bitmap_path; + file_util::CreateTemporaryFileName(&bitmap_path); + render_thread_.printer()->SaveBitmap(0, bitmap_path.value()); + } + } +#else + NOTIMPLEMENTED(); +#endif +} + // Test that we can receive correct DOM events when we send input events // through the RenderWidget::OnHandleInputEvent() function. TEST_F(RenderViewTest, OnHandleKeyboardEvent) { |