Commit 4bfa7d62 authored by Lei Zhang's avatar Lei Zhang Committed by Commit Bot

PDF: Add a FindTextTest.

- Implement a TestDocumentLoader and a TestClient.
- Hook them up to PDFiumEngine to observe its behavior.
- Load a simple 2 page PDF and perform a text search.

Change-Id: I03417880c3b6c3f493f7e08ba07b694272b5b5fc
Reviewed-on: https://chromium-review.googlesource.com/1012976
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: default avatardsinclair <dsinclair@chromium.org>
Cr-Commit-Position: refs/heads/master@{#553836}
parent 5b3d5a34
...@@ -120,6 +120,14 @@ if (enable_pdf) { ...@@ -120,6 +120,14 @@ if (enable_pdf) {
"//testing/gtest", "//testing/gtest",
"//ui/gfx/range", "//ui/gfx/range",
] ]
data = [
"test/data/",
]
if (pdf_engine == 0) {
sources += [ "pdfium/findtext_unittest.cc" ]
}
} }
} else { } else {
# Dummy group when PDF support is disabled so targets can unconditionally # Dummy group when PDF support is disabled so targets can unconditionally
......
// Copyright 2018 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/files/file_util.h"
#include "base/optional.h"
#include "base/path_service.h"
#include "pdf/document_loader.h"
#include "pdf/pdfium/pdfium_engine.h"
#include "pdf/url_loader_wrapper.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::InSequence;
using testing::_;
namespace chrome_pdf {
namespace {
class TestDocumentLoader : public DocumentLoader {
public:
explicit TestDocumentLoader(Client* client) : client_(client) {
base::FilePath pdf_path;
CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &pdf_path));
pdf_path = pdf_path.Append(FILE_PATH_LITERAL("pdf"))
.Append(FILE_PATH_LITERAL("test"))
.Append(FILE_PATH_LITERAL("data"))
.Append(FILE_PATH_LITERAL("hello_world2.pdf"));
CHECK(base::ReadFileToString(pdf_path, &pdf_data_));
}
~TestDocumentLoader() override = default;
// DocumentLoader:
bool Init(std::unique_ptr<URLLoaderWrapper> loader,
const std::string& url) override {
NOTREACHED();
return false;
}
bool GetBlock(uint32_t position, uint32_t size, void* buf) const override {
if (!IsDataAvailable(position, size))
return false;
memcpy(buf, pdf_data_.data() + position, size);
return true;
}
bool IsDataAvailable(uint32_t position, uint32_t size) const override {
return position < pdf_data_.size() && size <= pdf_data_.size() &&
position + size <= pdf_data_.size();
}
void RequestData(uint32_t position, uint32_t size) override {
client_->OnDocumentComplete();
}
bool IsDocumentComplete() const override { return true; }
uint32_t GetDocumentSize() const override { return pdf_data_.size(); }
uint32_t BytesReceived() const override { return pdf_data_.size(); }
private:
Client* const client_;
std::string pdf_data_;
};
std::unique_ptr<DocumentLoader> CreateTestDocumentLoader(
DocumentLoader::Client* client) {
return std::make_unique<TestDocumentLoader>(client);
}
class TestClient : public PDFEngine::Client {
public:
TestClient() = default;
~TestClient() override = default;
// PDFEngine::Client:
MOCK_METHOD2(NotifyNumberOfFindResultsChanged, void(int, bool));
MOCK_METHOD1(NotifySelectedFindResultChanged, void((int)));
bool Confirm(const std::string& message) override { return false; }
std::string Prompt(const std::string& question,
const std::string& default_answer) override {
return std::string();
}
std::string GetURL() override { return std::string(); }
pp::URLLoader CreateURLLoader() override { return pp::URLLoader(); }
std::vector<SearchStringResult> SearchString(const base::char16* string,
const base::char16* term,
bool case_sensitive) override {
EXPECT_TRUE(case_sensitive);
base::string16 haystack = base::string16(string);
base::string16 needle = base::string16(term);
std::vector<SearchStringResult> results;
size_t pos = 0;
while (1) {
pos = haystack.find(needle, pos);
if (pos == base::string16::npos)
break;
SearchStringResult result;
result.length = needle.size();
result.start_index = pos;
results.push_back(result);
pos += needle.size();
}
return results;
}
pp::Instance* GetPluginInstance() override { return nullptr; }
bool IsPrintPreview() override { return false; }
uint32_t GetBackgroundColor() override { return 0; }
float GetToolbarHeightInScreenCoords() override { return 0; }
private:
DISALLOW_COPY_AND_ASSIGN(TestClient);
};
} // namespace
class FindTextTest : public testing::Test {
public:
FindTextTest() = default;
~FindTextTest() override = default;
protected:
void SetUp() override {
InitializePDFium();
PDFiumEngine::SetCreateDocumentLoaderFunctionForTesting(
&CreateTestDocumentLoader);
}
void TearDown() override {
PDFiumEngine::SetCreateDocumentLoaderFunctionForTesting(nullptr);
FPDF_DestroyLibrary();
}
void InitializePDFium() {
FPDF_LIBRARY_CONFIG config;
config.version = 2;
config.m_pUserFontPaths = nullptr;
config.m_pIsolate = nullptr;
config.m_v8EmbedderSlot = 0;
FPDF_InitLibraryWithConfig(&config);
}
DISALLOW_COPY_AND_ASSIGN(FindTextTest);
};
TEST_F(FindTextTest, FindText) {
pp::URLLoader dummy_loader;
TestClient client;
PDFiumEngine engine(&client);
ASSERT_TRUE(engine.New("https://chromium.org/dummy.pdf", ""));
ASSERT_TRUE(engine.HandleDocumentLoad(dummy_loader));
{
InSequence sequence;
for (int i = 0; i < 10; ++i)
EXPECT_CALL(client, NotifyNumberOfFindResultsChanged(i + 1, false));
EXPECT_CALL(client, NotifyNumberOfFindResultsChanged(10, true));
EXPECT_CALL(client, NotifySelectedFindResultChanged(_)).Times(0);
}
engine.StartFind("o", /*case_sensitive=*/true);
}
} // namespace chrome_pdf
...@@ -448,6 +448,9 @@ void Release(FPDF_SYSFONTINFO* sysfontinfo) { ...@@ -448,6 +448,9 @@ void Release(FPDF_SYSFONTINFO* sysfontinfo) {
} }
#endif // defined(OS_LINUX) #endif // defined(OS_LINUX)
PDFiumEngine::CreateDocumentLoaderFunction
g_create_document_loader_for_testing = nullptr;
PDFiumEngine* g_engine_for_unsupported = nullptr; PDFiumEngine* g_engine_for_unsupported = nullptr;
void Unsupported_Handler(UNSUPPORT_INFO*, int type) { void Unsupported_Handler(UNSUPPORT_INFO*, int type) {
...@@ -865,6 +868,12 @@ PDFiumEngine::~PDFiumEngine() { ...@@ -865,6 +868,12 @@ PDFiumEngine::~PDFiumEngine() {
FPDFAvail_Destroy(fpdf_availability_); FPDFAvail_Destroy(fpdf_availability_);
} }
// static
void PDFiumEngine::SetCreateDocumentLoaderFunctionForTesting(
CreateDocumentLoaderFunction function) {
g_create_document_loader_for_testing = function;
}
#if defined(PDF_ENABLE_XFA) #if defined(PDF_ENABLE_XFA)
void PDFiumEngine::Form_EmailTo(FPDF_FORMFILLINFO* param, void PDFiumEngine::Form_EmailTo(FPDF_FORMFILLINFO* param,
...@@ -1223,17 +1232,22 @@ void PDFiumEngine::PostPaint() { ...@@ -1223,17 +1232,22 @@ void PDFiumEngine::PostPaint() {
bool PDFiumEngine::HandleDocumentLoad(const pp::URLLoader& loader) { bool PDFiumEngine::HandleDocumentLoad(const pp::URLLoader& loader) {
password_tries_remaining_ = kMaxPasswordTries; password_tries_remaining_ = kMaxPasswordTries;
process_when_pending_request_complete_ = true; process_when_pending_request_complete_ = true;
auto loader_wrapper =
std::make_unique<URLLoaderWrapperImpl>(GetPluginInstance(), loader); if (g_create_document_loader_for_testing) {
loader_wrapper->SetResponseHeaders(headers_); doc_loader_ = g_create_document_loader_for_testing(this);
} else {
doc_loader_ = std::make_unique<DocumentLoaderImpl>(this); auto loader_wrapper =
if (doc_loader_->Init(std::move(loader_wrapper), url_)) { std::make_unique<URLLoaderWrapperImpl>(GetPluginInstance(), loader);
// request initial data. loader_wrapper->SetResponseHeaders(headers_);
doc_loader_->RequestData(0, 1);
return true; doc_loader_ = std::make_unique<DocumentLoaderImpl>(this);
if (!doc_loader_->Init(std::move(loader_wrapper), url_))
return false;
} }
return false;
// request initial data.
doc_loader_->RequestData(0, 1);
return true;
} }
pp::Instance* PDFiumEngine::GetPluginInstance() { pp::Instance* PDFiumEngine::GetPluginInstance() {
...@@ -2437,6 +2451,13 @@ void PDFiumEngine::StartFind(const std::string& text, bool case_sensitive) { ...@@ -2437,6 +2451,13 @@ void PDFiumEngine::StartFind(const std::string& text, bool case_sensitive) {
if (end_of_search) { if (end_of_search) {
// Send the final notification. // Send the final notification.
client_->NotifyNumberOfFindResultsChanged(find_results_.size(), true); client_->NotifyNumberOfFindResultsChanged(find_results_.size(), true);
return;
}
// In unit tests, PPAPI is not initialized, so just call ContinueFind()
// directly.
if (g_create_document_loader_for_testing) {
ContinueFind(case_sensitive ? 1 : 0);
} else { } else {
pp::CompletionCallback callback = pp::CompletionCallback callback =
find_factory_.NewCallback(&PDFiumEngine::ContinueFind); find_factory_.NewCallback(&PDFiumEngine::ContinueFind);
......
...@@ -46,6 +46,11 @@ class PDFiumEngine : public PDFEngine, ...@@ -46,6 +46,11 @@ class PDFiumEngine : public PDFEngine,
explicit PDFiumEngine(PDFEngine::Client* client); explicit PDFiumEngine(PDFEngine::Client* client);
~PDFiumEngine() override; ~PDFiumEngine() override;
using CreateDocumentLoaderFunction =
std::unique_ptr<DocumentLoader> (*)(DocumentLoader::Client* client);
static void SetCreateDocumentLoaderFunctionForTesting(
CreateDocumentLoaderFunction function);
// PDFEngine implementation. // PDFEngine implementation.
bool New(const char* url, const char* headers) override; bool New(const char* url, const char* headers) override;
void PageOffsetUpdated(const pp::Point& page_offset) override; void PageOffsetUpdated(const pp::Point& page_offset) override;
......
This diff was suppressed by a .gitattributes entry.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment