From 16b9d77ceb55e102260bc44cf1c8f519d11d6769 Mon Sep 17 00:00:00 2001 From: Tom Sepez Date: Mon, 17 Apr 2017 09:07:48 -0700 Subject: Add unit test for CFX_SAXReader. Make the pending re-write CL smaller, and back-fill some test. Virtualize the handler interface so that it can be mocked. Change-Id: Icbbc6b6789ba135b73c6fd1bbb90f5aae6ab7649 Reviewed-on: https://pdfium-review.googlesource.com/4250 Commit-Queue: Tom Sepez Reviewed-by: Lei Zhang --- BUILD.gn | 2 + core/fxcrt/xml/cfx_saxreader.h | 29 ++++++- core/fxcrt/xml/cfx_saxreader_unittest.cpp | 132 ++++++++++++++++++++++++++++++ core/fxcrt/xml/cfx_saxreaderhandler.h | 19 ++--- 4 files changed, 169 insertions(+), 13 deletions(-) create mode 100644 core/fxcrt/xml/cfx_saxreader_unittest.cpp 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> 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(str), strlen(str)), + 0, static_cast(-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[] = ""; + 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[] = ""; + 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[] = ""; + 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[] = "biff"; + 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); -- cgit v1.2.3