summaryrefslogtreecommitdiff
path: root/testing
diff options
context:
space:
mode:
authorArtem Strygin <art-snake@yandex-team.ru>2017-09-28 18:46:03 +0300
committerChromium commit bot <commit-bot@chromium.org>2017-09-28 15:59:08 +0000
commit0e60b9ef2b79de52ef62101abae2af7292e879b7 (patch)
tree9f71519f2a364ee6702219a44de7fdb1def18cc7 /testing
parent1ca7173cd85adcd58766fc89f95c3dc163efa17a (diff)
downloadpdfium-0e60b9ef2b79de52ef62101abae2af7292e879b7.tar.xz
Implement FakeFileAccess.
Update embedder tests to simulate unavailable data and download requests. Change-Id: I634fa89d2a0c859243e849752936da87568909f4 Reviewed-on: https://pdfium-review.googlesource.com/11890 Commit-Queue: Art Snake <art-snake@yandex-team.ru> Reviewed-by: dsinclair <dsinclair@chromium.org>
Diffstat (limited to 'testing')
-rw-r--r--testing/embedder_test.cpp97
-rw-r--r--testing/embedder_test.h15
-rw-r--r--testing/fake_file_access.cpp115
-rw-r--r--testing/fake_file_access.h42
-rw-r--r--testing/range_set.cpp74
-rw-r--r--testing/range_set.h45
6 files changed, 337 insertions, 51 deletions
diff --git a/testing/embedder_test.cpp b/testing/embedder_test.cpp
index 82ffb3b825..dab06af50d 100644
--- a/testing/embedder_test.cpp
+++ b/testing/embedder_test.cpp
@@ -19,6 +19,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/test_support.h"
#include "testing/utils/path_service.h"
+#include "third_party/base/ptr_util.h"
#ifdef PDF_ENABLE_V8
#include "v8/include/v8-platform.h"
@@ -36,12 +37,6 @@ v8::StartupData* g_v8_snapshot = nullptr;
#endif // V8_USE_EXTERNAL_STARTUP_DATA
#endif // PDF_ENABLE_V8
-FPDF_BOOL Is_Data_Avail(FX_FILEAVAIL* pThis, size_t offset, size_t size) {
- return true;
-}
-
-void Add_Segment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) {}
-
int GetBitmapBytesPerPixel(FPDF_BITMAP bitmap) {
const int format = FPDFBitmap_GetFormat(bitmap);
switch (format) {
@@ -69,9 +64,7 @@ EmbedderTest::EmbedderTest()
loader_(nullptr),
file_length_(0),
file_contents_(nullptr) {
- memset(&hints_, 0, sizeof(hints_));
memset(&file_access_, 0, sizeof(file_access_));
- memset(&file_avail_, 0, sizeof(file_avail_));
delegate_ = default_delegate_.get();
#ifdef PDF_ENABLE_V8
@@ -151,46 +144,52 @@ bool EmbedderTest::OpenDocument(const std::string& filename,
file_access_.m_FileLen = static_cast<unsigned long>(file_length_);
file_access_.m_GetBlock = TestLoader::GetBlock;
file_access_.m_Param = loader_;
- return OpenDocumentHelper(password, must_linearize, &file_avail_, &hints_,
- &file_access_, &document_, &avail_, &form_handle_);
+ fake_file_access_ = pdfium::MakeUnique<FakeFileAccess>(&file_access_);
+ return OpenDocumentHelper(password, must_linearize, fake_file_access_.get(),
+ &document_, &avail_, &form_handle_);
}
bool EmbedderTest::OpenDocumentHelper(const char* password,
bool must_linearize,
- FX_FILEAVAIL* file_avail,
- FX_DOWNLOADHINTS* hints,
- FPDF_FILEACCESS* file_access,
+ FakeFileAccess* network_simulator,
FPDF_DOCUMENT* document,
FPDF_AVAIL* avail,
FPDF_FORMHANDLE* form_handle) {
- file_avail->version = 1;
- file_avail->IsDataAvail = Is_Data_Avail;
-
- hints->version = 1;
- hints->AddSegment = Add_Segment;
-
- *avail = FPDFAvail_Create(file_avail, file_access);
-
+ network_simulator->AddSegment(0, 1024);
+ network_simulator->SetRequestedDataAvailable();
+ *avail = FPDFAvail_Create(network_simulator->GetFileAvail(),
+ network_simulator->GetFileAccess());
if (FPDFAvail_IsLinearized(*avail) == PDF_LINEARIZED) {
- *document = FPDFAvail_GetDocument(*avail, password);
- if (!*document)
- return false;
-
int32_t nRet = PDF_DATA_NOTAVAIL;
- while (nRet == PDF_DATA_NOTAVAIL)
- nRet = FPDFAvail_IsDocAvail(*avail, hints);
+ while (nRet == PDF_DATA_NOTAVAIL) {
+ network_simulator->SetRequestedDataAvailable();
+ nRet =
+ FPDFAvail_IsDocAvail(*avail, network_simulator->GetDownloadHints());
+ }
if (nRet == PDF_DATA_ERROR)
return false;
- nRet = FPDFAvail_IsFormAvail(*avail, hints);
- if (nRet == PDF_FORM_ERROR || nRet == PDF_FORM_NOTAVAIL)
+ *document = FPDFAvail_GetDocument(*avail, password);
+ if (!*document)
+ return false;
+
+ nRet = PDF_DATA_NOTAVAIL;
+ while (nRet == PDF_DATA_NOTAVAIL) {
+ network_simulator->SetRequestedDataAvailable();
+ nRet =
+ FPDFAvail_IsFormAvail(*avail, network_simulator->GetDownloadHints());
+ }
+ if (nRet == PDF_FORM_ERROR)
return false;
int page_count = FPDF_GetPageCount(*document);
for (int i = 0; i < page_count; ++i) {
nRet = PDF_DATA_NOTAVAIL;
- while (nRet == PDF_DATA_NOTAVAIL)
- nRet = FPDFAvail_IsPageAvail(*avail, i, hints);
+ while (nRet == PDF_DATA_NOTAVAIL) {
+ network_simulator->SetRequestedDataAvailable();
+ nRet = FPDFAvail_IsPageAvail(*avail, i,
+ network_simulator->GetDownloadHints());
+ }
if (nRet == PDF_DATA_ERROR)
return false;
@@ -198,8 +197,9 @@ bool EmbedderTest::OpenDocumentHelper(const char* password,
} else {
if (must_linearize)
return false;
-
- *document = FPDF_LoadCustomDocument(file_access, password);
+ network_simulator->SetWholeFileAvailable();
+ *document =
+ FPDF_LoadCustomDocument(network_simulator->GetFileAccess(), password);
if (!*document)
return false;
}
@@ -248,14 +248,16 @@ void EmbedderTest::DoOpenActions() {
int EmbedderTest::GetFirstPageNum() {
int first_page = FPDFAvail_GetFirstPageNum(document_);
- (void)FPDFAvail_IsPageAvail(avail_, first_page, &hints_);
+ (void)FPDFAvail_IsPageAvail(avail_, first_page,
+ fake_file_access_->GetDownloadHints());
return first_page;
}
int EmbedderTest::GetPageCount() {
int page_count = FPDF_GetPageCount(document_);
for (int i = 0; i < page_count; ++i)
- (void)FPDFAvail_IsPageAvail(avail_, i, &hints_);
+ (void)FPDFAvail_IsPageAvail(avail_, i,
+ fake_file_access_->GetDownloadHints());
return page_count;
}
@@ -314,16 +316,16 @@ void EmbedderTest::TestSaved(int width,
int height,
const char* md5,
const char* password) {
- FPDF_FILEACCESS file_access;
- memset(&file_access, 0, sizeof(file_access));
- file_access.m_FileLen = m_String.size();
- file_access.m_GetBlock = GetBlockFromString;
- file_access.m_Param = &m_String;
- FX_FILEAVAIL file_avail;
- FX_DOWNLOADHINTS hints;
-
- ASSERT_TRUE(OpenDocumentHelper(password, false, &file_avail, &hints,
- &file_access, &m_SavedDocument, &m_SavedAvail,
+ memset(&saved_file_access_, 0, sizeof(saved_file_access_));
+ saved_file_access_.m_FileLen = m_String.size();
+ saved_file_access_.m_GetBlock = GetBlockFromString;
+ saved_file_access_.m_Param = &m_String;
+
+ saved_fake_file_access_ =
+ pdfium::MakeUnique<FakeFileAccess>(&saved_file_access_);
+
+ ASSERT_TRUE(OpenDocumentHelper(password, false, saved_fake_file_access_.get(),
+ &m_SavedDocument, &m_SavedAvail,
&m_SavedForm));
EXPECT_EQ(1, FPDF_GetPageCount(m_SavedDocument));
m_SavedPage = FPDF_LoadPage(m_SavedDocument, 0);
@@ -346,6 +348,11 @@ void EmbedderTest::TestAndCloseSaved(int width, int height, const char* md5) {
CloseSaved();
}
+void EmbedderTest::SetWholeFileAvailable() {
+ ASSERT(fake_file_access_);
+ fake_file_access_->SetWholeFileAvailable();
+}
+
FPDF_PAGE EmbedderTest::Delegate::GetPage(FPDF_FORMFILLINFO* info,
FPDF_DOCUMENT document,
int page_index) {
diff --git a/testing/embedder_test.h b/testing/embedder_test.h
index 878e50bfdd..be89c2a6cd 100644
--- a/testing/embedder_test.h
+++ b/testing/embedder_test.h
@@ -14,6 +14,7 @@
#include "public/fpdf_formfill.h"
#include "public/fpdf_save.h"
#include "public/fpdfview.h"
+#include "testing/fake_file_access.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/test_support.h"
@@ -116,9 +117,7 @@ class EmbedderTest : public ::testing::Test,
protected:
bool OpenDocumentHelper(const char* password,
bool must_linearize,
- FX_FILEAVAIL* file_avail,
- FX_DOWNLOADHINTS* hints,
- FPDF_FILEACCESS* file_access,
+ FakeFileAccess* network_simulator,
FPDF_DOCUMENT* document,
FPDF_AVAIL* avail,
FPDF_FORMHANDLE* form_handle);
@@ -151,14 +150,14 @@ class EmbedderTest : public ::testing::Test,
void CloseSaved();
void TestAndCloseSaved(int width, int height, const char* md5);
+ void SetWholeFileAvailable();
+
Delegate* delegate_;
std::unique_ptr<Delegate> default_delegate_;
FPDF_DOCUMENT document_;
FPDF_FORMHANDLE form_handle_;
FPDF_AVAIL avail_;
- FX_DOWNLOADHINTS hints_;
- FPDF_FILEACCESS file_access_;
- FX_FILEAVAIL file_avail_;
+ FPDF_FILEACCESS file_access_; // must outlive avail_.
#ifdef PDF_ENABLE_V8
v8::Platform* platform_;
#endif // PDF_ENABLE_V8
@@ -172,6 +171,10 @@ class EmbedderTest : public ::testing::Test,
FPDF_PAGE m_SavedPage;
FPDF_FORMHANDLE m_SavedForm;
FPDF_AVAIL m_SavedAvail;
+ FPDF_FILEACCESS saved_file_access_; // must outlive m_SavedAvail.
+ std::unique_ptr<FakeFileAccess> fake_file_access_; // must outlive avail_.
+ std::unique_ptr<FakeFileAccess>
+ saved_fake_file_access_; // must outlive m_SavedAvail.
private:
static void UnsupportedHandlerTrampoline(UNSUPPORT_INFO*, int type);
diff --git a/testing/fake_file_access.cpp b/testing/fake_file_access.cpp
new file mode 100644
index 0000000000..c69f278102
--- /dev/null
+++ b/testing/fake_file_access.cpp
@@ -0,0 +1,115 @@
+// Copyright 2017 PDFium 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 "testing/fake_file_access.h"
+
+#include <algorithm>
+#include <set>
+#include <utility>
+#include <vector>
+
+#include "core/fxcrt/fx_system.h"
+#include "third_party/base/ptr_util.h"
+
+namespace {
+
+class FileAccessWrapper : public FPDF_FILEACCESS {
+ public:
+ explicit FileAccessWrapper(FakeFileAccess* simulator)
+ : simulator_(simulator) {
+ m_FileLen = simulator_->GetFileSize();
+ m_GetBlock = &GetBlockImpl;
+ m_Param = this;
+ }
+
+ static int GetBlockImpl(void* param,
+ unsigned long position,
+ unsigned char* pBuf,
+ unsigned long size) {
+ return static_cast<FileAccessWrapper*>(param)->simulator_->GetBlock(
+ position, pBuf, size);
+ }
+
+ private:
+ fxcrt::UnownedPtr<FakeFileAccess> simulator_;
+};
+
+class FileAvailImpl : public FX_FILEAVAIL {
+ public:
+ explicit FileAvailImpl(FakeFileAccess* simulator) : simulator_(simulator) {
+ version = 1;
+ IsDataAvail = &IsDataAvailImpl;
+ }
+
+ static FPDF_BOOL IsDataAvailImpl(FX_FILEAVAIL* pThis,
+ size_t offset,
+ size_t size) {
+ return static_cast<FileAvailImpl*>(pThis)->simulator_->IsDataAvail(offset,
+ size);
+ }
+
+ private:
+ fxcrt::UnownedPtr<FakeFileAccess> simulator_;
+};
+
+class DownloadHintsImpl : public FX_DOWNLOADHINTS {
+ public:
+ explicit DownloadHintsImpl(FakeFileAccess* simulator)
+ : simulator_(simulator) {
+ version = 1;
+ AddSegment = &AddSegmentImpl;
+ }
+
+ static void AddSegmentImpl(FX_DOWNLOADHINTS* pThis,
+ size_t offset,
+ size_t size) {
+ return static_cast<DownloadHintsImpl*>(pThis)->simulator_->AddSegment(
+ offset, size);
+ }
+
+ private:
+ fxcrt::UnownedPtr<FakeFileAccess> simulator_;
+};
+
+} // namespace
+
+FakeFileAccess::FakeFileAccess(FPDF_FILEACCESS* file_access)
+ : file_access_(file_access),
+ file_access_wrapper_(pdfium::MakeUnique<FileAccessWrapper>(this)),
+ file_avail_(pdfium::MakeUnique<FileAvailImpl>(this)),
+ download_hints_(pdfium::MakeUnique<DownloadHintsImpl>(this)) {
+ ASSERT(file_access_);
+}
+
+FakeFileAccess::~FakeFileAccess() {}
+
+FPDF_BOOL FakeFileAccess::IsDataAvail(size_t offset, size_t size) const {
+ return available_data_.Contains(RangeSet::Range(offset, offset + size));
+}
+
+void FakeFileAccess::AddSegment(size_t offset, size_t size) {
+ requested_data_.Union(RangeSet::Range(offset, offset + size));
+}
+
+unsigned long FakeFileAccess::GetFileSize() {
+ return file_access_->m_FileLen;
+}
+
+int FakeFileAccess::GetBlock(unsigned long position,
+ unsigned char* pBuf,
+ unsigned long size) {
+ if (!IsDataAvail(static_cast<size_t>(position), static_cast<size_t>(size)))
+ return false;
+ return file_access_->m_GetBlock(file_access_->m_Param, position, pBuf, size);
+}
+
+void FakeFileAccess::SetRequestedDataAvailable() {
+ available_data_.Union(requested_data_);
+ requested_data_.Clear();
+}
+
+void FakeFileAccess::SetWholeFileAvailable() {
+ available_data_.Union(RangeSet::Range(0, static_cast<size_t>(GetFileSize())));
+ requested_data_.Clear();
+}
diff --git a/testing/fake_file_access.h b/testing/fake_file_access.h
new file mode 100644
index 0000000000..1328b16392
--- /dev/null
+++ b/testing/fake_file_access.h
@@ -0,0 +1,42 @@
+// Copyright 2017 PDFium 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 TESTING_FAKE_FILE_ACCESS_H_
+#define TESTING_FAKE_FILE_ACCESS_H_
+
+#include <memory>
+
+#include "core/fxcrt/unowned_ptr.h"
+#include "public/fpdf_dataavail.h"
+#include "public/fpdfview.h"
+#include "testing/range_set.h"
+
+class FakeFileAccess {
+ public:
+ explicit FakeFileAccess(FPDF_FILEACCESS* file_access);
+ ~FakeFileAccess();
+
+ FPDF_FILEACCESS* GetFileAccess() const { return file_access_wrapper_.get(); }
+ FX_FILEAVAIL* GetFileAvail() const { return file_avail_.get(); }
+ FX_DOWNLOADHINTS* GetDownloadHints() const { return download_hints_.get(); }
+
+ FPDF_BOOL IsDataAvail(size_t offset, size_t size) const;
+ void AddSegment(size_t offset, size_t size);
+
+ unsigned long GetFileSize();
+
+ int GetBlock(unsigned long position, unsigned char* pBuf, unsigned long size);
+ void SetRequestedDataAvailable();
+ void SetWholeFileAvailable();
+
+ private:
+ fxcrt::UnownedPtr<FPDF_FILEACCESS> file_access_;
+ std::unique_ptr<FPDF_FILEACCESS> file_access_wrapper_;
+ std::unique_ptr<FX_FILEAVAIL> file_avail_;
+ std::unique_ptr<FX_DOWNLOADHINTS> download_hints_;
+ RangeSet available_data_;
+ RangeSet requested_data_;
+};
+
+#endif // TESTING_FAKE_FILE_ACCESS_H_
diff --git a/testing/range_set.cpp b/testing/range_set.cpp
new file mode 100644
index 0000000000..2fc540f17c
--- /dev/null
+++ b/testing/range_set.cpp
@@ -0,0 +1,74 @@
+// Copyright 2017 PDFium 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 "testing/range_set.h"
+
+#include <algorithm>
+
+#include "core/fxcrt/fx_system.h"
+
+RangeSet::RangeSet() {}
+RangeSet::~RangeSet() {}
+
+bool RangeSet::Contains(const Range& range) const {
+ if (IsEmptyRange(range))
+ return false;
+
+ const Range fixed_range = FixDirection(range);
+ auto it = ranges().upper_bound(fixed_range);
+
+ if (it == ranges().begin())
+ return false; // No ranges includes range.first.
+
+ --it; // Now it starts equal or before range.first.
+ return it->second >= fixed_range.second;
+}
+
+void RangeSet::Union(const Range& range) {
+ if (IsEmptyRange(range))
+ return;
+
+ Range fixed_range = FixDirection(range);
+ if (IsEmpty()) {
+ ranges_.insert(fixed_range);
+ return;
+ }
+
+ auto start = ranges_.upper_bound(fixed_range);
+ if (start != ranges_.begin())
+ --start; // start now points to the key equal or lower than offset.
+
+ if (start->second < fixed_range.first)
+ ++start; // start element is entirely before current range, skip it.
+
+ auto end = ranges_.upper_bound(Range(fixed_range.second, fixed_range.second));
+
+ if (start == end) { // No ranges to merge.
+ ranges_.insert(fixed_range);
+ return;
+ }
+
+ --end;
+
+ const int new_start = std::min<size_t>(start->first, fixed_range.first);
+ const int new_end = std::max(end->second, fixed_range.second);
+
+ ranges_.erase(start, ++end);
+ ranges_.insert(Range(new_start, new_end));
+}
+
+void RangeSet::Union(const RangeSet& range_set) {
+ ASSERT(&range_set != this);
+ for (const auto& it : range_set.ranges())
+ Union(it);
+}
+
+RangeSet::Range RangeSet::FixDirection(const Range& range) const {
+ return range.first <= range.second ? range
+ : Range(range.second + 1, range.first + 1);
+}
+
+bool RangeSet::IsEmptyRange(const Range& range) const {
+ return range.first == range.second;
+}
diff --git a/testing/range_set.h b/testing/range_set.h
new file mode 100644
index 0000000000..87cbee910b
--- /dev/null
+++ b/testing/range_set.h
@@ -0,0 +1,45 @@
+// Copyright 2017 PDFium 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 TESTING_RANGE_SET_H_
+#define TESTING_RANGE_SET_H_
+
+#include <set>
+#include <utility>
+
+class RangeSet {
+ public:
+ using Range = std::pair<size_t, size_t>;
+
+ RangeSet();
+ ~RangeSet();
+
+ bool Contains(const Range& range) const;
+
+ void Union(const Range& range);
+
+ void Union(const RangeSet& range_set);
+
+ bool IsEmpty() const { return ranges().empty(); }
+
+ void Clear() { ranges_.clear(); }
+
+ struct range_compare {
+ bool operator()(const Range& lval, const Range& rval) const {
+ return lval.first < rval.first;
+ }
+ };
+
+ using RangesContainer = std::set<Range, range_compare>;
+ const RangesContainer& ranges() const { return ranges_; }
+
+ private:
+ Range FixDirection(const Range& range) const;
+
+ bool IsEmptyRange(const Range& range) const;
+
+ RangesContainer ranges_;
+};
+
+#endif // TESTING_RANGE_SET_H_