summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BUILD.gn2
-rw-r--r--core/fxcrt/xml/cfx_saxreader.h29
-rw-r--r--core/fxcrt/xml/cfx_saxreader_unittest.cpp132
-rw-r--r--core/fxcrt/xml/cfx_saxreaderhandler.h19
4 files changed, 169 insertions, 13 deletions
diff --git a/BUILD.gn b/BUILD.gn
index 77bdeb5e77..9b879f5b1b 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1878,12 +1878,14 @@ test("pdfium_unittests") {
deps = [
":pdfium",
":test_support",
+ "//testing/gmock",
"//testing/gtest",
"//testing/gtest:gtest_main",
]
include_dirs = []
if (pdf_enable_xfa) {
sources += [
+ "core/fxcrt/xml/cfx_saxreader_unittest.cpp",
"fxbarcode/pdf417/BC_PDF417HighLevelEncoder_unittest.cpp",
"xfa/fde/cfde_txtedtbuf_unittest.cpp",
"xfa/fde/css/cfde_cssdeclaration_unittest.cpp",
diff --git a/core/fxcrt/xml/cfx_saxreader.h b/core/fxcrt/xml/cfx_saxreader.h
index af3c26f94a..6c76016110 100644
--- a/core/fxcrt/xml/cfx_saxreader.h
+++ b/core/fxcrt/xml/cfx_saxreader.h
@@ -14,7 +14,6 @@
class CFX_SAXCommentContext;
class CFX_SAXContext;
-class CFX_SAXReaderHandler;
enum class CFX_SaxMode;
class CFX_SAXItem {
@@ -70,6 +69,30 @@ enum CFX_SaxParseMode {
class CFX_SAXReader {
public:
+ class HandlerIface {
+ public:
+ virtual ~HandlerIface() {}
+ virtual CFX_SAXContext* OnTagEnter(const CFX_ByteStringC& bsTagName,
+ CFX_SAXItem::Type eType,
+ uint32_t dwStartPos) = 0;
+ virtual void OnTagAttribute(CFX_SAXContext* pTag,
+ const CFX_ByteStringC& bsAttri,
+ const CFX_ByteStringC& bsValue) = 0;
+ virtual void OnTagBreak(CFX_SAXContext* pTag) = 0;
+ virtual void OnTagData(CFX_SAXContext* pTag,
+ CFX_SAXItem::Type eType,
+ const CFX_ByteStringC& bsData,
+ uint32_t dwStartPos) = 0;
+ virtual void OnTagClose(CFX_SAXContext* pTag, uint32_t dwEndPos) = 0;
+ virtual void OnTagEnd(CFX_SAXContext* pTag,
+ const CFX_ByteStringC& bsTagName,
+ uint32_t dwEndPos) = 0;
+ virtual void OnTargetData(CFX_SAXContext* pTag,
+ CFX_SAXItem::Type eType,
+ const CFX_ByteStringC& bsData,
+ uint32_t dwStartPos) = 0;
+ };
+
CFX_SAXReader();
~CFX_SAXReader();
@@ -79,7 +102,7 @@ class CFX_SAXReader {
uint32_t dwParseMode = 0);
int32_t ContinueParse(IFX_Pause* pPause = nullptr);
void SkipCurrentNode();
- void SetHandler(CFX_SAXReaderHandler* pHandler) { m_pHandler = pHandler; }
+ void SetHandler(HandlerIface* pHandler) { m_pHandler = pHandler; }
void AppendData(uint8_t ch);
void AppendName(uint8_t ch);
void ParseText();
@@ -117,7 +140,7 @@ class CFX_SAXReader {
void ParseChar(uint8_t ch);
CFX_SAXFile m_File;
- CFX_SAXReaderHandler* m_pHandler;
+ HandlerIface* m_pHandler;
int32_t m_iState;
std::stack<std::unique_ptr<CFX_SAXItem>> m_Stack;
uint32_t m_dwItemID;
diff --git a/core/fxcrt/xml/cfx_saxreader_unittest.cpp b/core/fxcrt/xml/cfx_saxreader_unittest.cpp
new file mode 100644
index 0000000000..f79b82c3cc
--- /dev/null
+++ b/core/fxcrt/xml/cfx_saxreader_unittest.cpp
@@ -0,0 +1,132 @@
+// Copyright 2017 The 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 "core/fxcrt/xml/cfx_saxreader.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/test_support.h"
+
+using testing::_;
+using testing::Eq;
+using testing::Return;
+
+namespace {
+
+class MockHandler : public CFX_SAXReader::HandlerIface {
+ public:
+ MOCK_METHOD3(OnTagEnter,
+ CFX_SAXContext*(const CFX_ByteStringC& bsTagName,
+ CFX_SAXItem::Type eType,
+ uint32_t dwStartPos));
+ MOCK_METHOD3(OnTagAttribute,
+ void(CFX_SAXContext* pTag,
+ const CFX_ByteStringC& bsAttri,
+ const CFX_ByteStringC& bsValue));
+ MOCK_METHOD1(OnTagBreak, void(CFX_SAXContext* pTag));
+ MOCK_METHOD4(OnTagData,
+ void(CFX_SAXContext* pTag,
+ CFX_SAXItem::Type eType,
+ const CFX_ByteStringC& bsData,
+ uint32_t dwStartPos));
+ MOCK_METHOD2(OnTagClose, void(CFX_SAXContext* pTag, uint32_t dwEndPos));
+ MOCK_METHOD3(OnTagEnd,
+ void(CFX_SAXContext* pTag,
+ const CFX_ByteStringC& bsTagName,
+ uint32_t dwEndPos));
+ MOCK_METHOD4(OnTargetData,
+ void(CFX_SAXContext* pTag,
+ CFX_SAXItem::Type eType,
+ const CFX_ByteStringC& bsData,
+ uint32_t dwStartPos));
+};
+
+} // namespace
+
+class CFX_SAXReaderTest : public pdfium::FPDF_Test {
+ public:
+ void SetHandler(CFX_SAXReader::HandlerIface* handler) {
+ reader_.SetHandler(handler);
+ }
+
+ bool StartParse(char* str) {
+ return reader_.StartParse(IFX_MemoryStream::Create(
+ reinterpret_cast<uint8_t*>(str), strlen(str)),
+ 0, static_cast<uint32_t>(-1),
+ CFX_SaxParseMode_NotSkipSpace) >= 0;
+ }
+
+ int32_t ContinueParse() {
+ int32_t ret;
+ do {
+ ret = reader_.ContinueParse(nullptr);
+ } while (ret >= 0 && ret < 100);
+ return ret;
+ }
+
+ private:
+ CFX_SAXReader reader_;
+};
+
+TEST_F(CFX_SAXReaderTest, Null) {
+ char data[] = "";
+ ASSERT_FALSE(StartParse(data));
+}
+
+TEST_F(CFX_SAXReaderTest, SimpleText) {
+ MockHandler mock;
+ SetHandler(&mock);
+
+ char data[] = "clams";
+ ASSERT_TRUE(StartParse(data));
+ EXPECT_EQ(100, ContinueParse());
+}
+
+TEST_F(CFX_SAXReaderTest, SimpleTag) {
+ MockHandler mock;
+ EXPECT_CALL(mock, OnTagEnter(Eq("clams"), _, _));
+ EXPECT_CALL(mock, OnTagBreak(_));
+ SetHandler(&mock);
+
+ char data[] = "<clams>";
+ ASSERT_TRUE(StartParse(data));
+ EXPECT_EQ(100, ContinueParse());
+}
+
+TEST_F(CFX_SAXReaderTest, AttributeTag) {
+ MockHandler mock;
+ EXPECT_CALL(mock, OnTagEnter(Eq("clams"), _, _));
+ EXPECT_CALL(mock, OnTagAttribute(_, Eq("size"), Eq("small")));
+ EXPECT_CALL(mock, OnTagAttribute(_, Eq("color"), Eq("red")));
+ EXPECT_CALL(mock, OnTagBreak(_));
+ SetHandler(&mock);
+
+ char data[] = "<clams size='small' color='red'>";
+ ASSERT_TRUE(StartParse(data));
+ EXPECT_EQ(100, ContinueParse());
+}
+
+TEST_F(CFX_SAXReaderTest, AttributeEntityTag) {
+ MockHandler mock;
+ EXPECT_CALL(mock, OnTagEnter(Eq("clams"), _, _));
+ EXPECT_CALL(mock, OnTagAttribute(_, Eq("predicate"), Eq("1 < 2")));
+ EXPECT_CALL(mock, OnTagBreak(_));
+ SetHandler(&mock);
+
+ char data[] = "<clams predicate='1 &lt; 2'>";
+ ASSERT_TRUE(StartParse(data));
+ EXPECT_EQ(100, ContinueParse());
+}
+
+TEST_F(CFX_SAXReaderTest, TextWithinTag) {
+ MockHandler mock;
+ EXPECT_CALL(mock, OnTagEnter(Eq("b"), _, _));
+ EXPECT_CALL(mock, OnTagBreak(_));
+ EXPECT_CALL(mock, OnTagData(_, _, Eq("biff"), _));
+ EXPECT_CALL(mock, OnTagEnd(_, Eq("b"), _));
+ SetHandler(&mock);
+
+ char data[] = "<b>biff</b>";
+ ASSERT_TRUE(StartParse(data));
+ EXPECT_EQ(100, ContinueParse());
+}
diff --git a/core/fxcrt/xml/cfx_saxreaderhandler.h b/core/fxcrt/xml/cfx_saxreaderhandler.h
index bfedf03846..c5e1dc28b6 100644
--- a/core/fxcrt/xml/cfx_saxreaderhandler.h
+++ b/core/fxcrt/xml/cfx_saxreaderhandler.h
@@ -13,31 +13,30 @@
class CFX_ChecksumContext;
-class CFX_SAXReaderHandler {
+class CFX_SAXReaderHandler : public CFX_SAXReader::HandlerIface {
public:
explicit CFX_SAXReaderHandler(CFX_ChecksumContext* pContext);
- ~CFX_SAXReaderHandler();
+ ~CFX_SAXReaderHandler() override;
CFX_SAXContext* OnTagEnter(const CFX_ByteStringC& bsTagName,
CFX_SAXItem::Type eType,
- uint32_t dwStartPos);
+ uint32_t dwStartPos) override;
void OnTagAttribute(CFX_SAXContext* pTag,
const CFX_ByteStringC& bsAttri,
- const CFX_ByteStringC& bsValue);
- void OnTagBreak(CFX_SAXContext* pTag);
+ const CFX_ByteStringC& bsValue) override;
+ void OnTagBreak(CFX_SAXContext* pTag) override;
void OnTagData(CFX_SAXContext* pTag,
CFX_SAXItem::Type eType,
const CFX_ByteStringC& bsData,
- uint32_t dwStartPos);
- void OnTagClose(CFX_SAXContext* pTag, uint32_t dwEndPos);
+ uint32_t dwStartPos) override;
+ void OnTagClose(CFX_SAXContext* pTag, uint32_t dwEndPos) override;
void OnTagEnd(CFX_SAXContext* pTag,
const CFX_ByteStringC& bsTagName,
- uint32_t dwEndPos);
-
+ uint32_t dwEndPos) override;
void OnTargetData(CFX_SAXContext* pTag,
CFX_SAXItem::Type eType,
const CFX_ByteStringC& bsData,
- uint32_t dwStartPos);
+ uint32_t dwStartPos) override;
private:
void UpdateChecksum(bool bCheckSpace);