From 6c5ea100a7d2531576037b17d5631dde42846b84 Mon Sep 17 00:00:00 2001 From: Dan Sinclair Date: Mon, 5 Jun 2017 09:53:06 -0400 Subject: Add start of CFGAS_FormatString tests This CL adds tests for the date parsing and formatting code in CFGAS_FormatString. Change-Id: I9989cdd1b3f92c90d46ee2c3f7838fe1de255be2 Reviewed-on: https://pdfium-review.googlesource.com/6178 Commit-Queue: dsinclair Reviewed-by: Tom Sepez --- BUILD.gn | 1 + core/fxcrt/cfx_datetime.cpp | 6 ++ core/fxcrt/cfx_datetime.h | 2 + testing/fx_string_testhelpers.cpp | 10 +++ testing/fx_string_testhelpers.h | 4 + xfa/fgas/crt/cfgas_formatstring.cpp | 4 +- xfa/fgas/crt/cfgas_formatstring_unittest.cpp | 114 +++++++++++++++++++++++++++ 7 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 xfa/fgas/crt/cfgas_formatstring_unittest.cpp diff --git a/BUILD.gn b/BUILD.gn index b1774d63b6..ecc8f6a51e 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1944,6 +1944,7 @@ test("pdfium_unittests") { "xfa/fde/css/cfde_cssdeclaration_unittest.cpp", "xfa/fde/css/cfde_cssstylesheet_unittest.cpp", "xfa/fde/css/cfde_cssvaluelistparser_unittest.cpp", + "xfa/fgas/crt/cfgas_formatstring_unittest.cpp", "xfa/fgas/layout/cfx_rtfbreak_unittest.cpp", "xfa/fwl/cfx_barcode_unittest.cpp", "xfa/fxfa/app/cxfa_ffbarcode_unittest.cpp", diff --git a/core/fxcrt/cfx_datetime.cpp b/core/fxcrt/cfx_datetime.cpp index dcf25d5463..833fe58907 100644 --- a/core/fxcrt/cfx_datetime.cpp +++ b/core/fxcrt/cfx_datetime.cpp @@ -127,3 +127,9 @@ int32_t CFX_DateTime::GetDayOfWeek() const { v += 7; return v; } + +bool CFX_DateTime::operator==(const CFX_DateTime& other) const { + return year_ == other.year_ && month_ == other.month_ && day_ == other.day_ && + hour_ == other.hour_ && minute_ == other.minute_ && + second_ == other.second_ && millisecond_ == other.millisecond_; +} diff --git a/core/fxcrt/cfx_datetime.h b/core/fxcrt/cfx_datetime.h index 2de75c4e38..272c2496cc 100644 --- a/core/fxcrt/cfx_datetime.h +++ b/core/fxcrt/cfx_datetime.h @@ -79,6 +79,8 @@ class CFX_DateTime { uint16_t GetMillisecond() const { return millisecond_; } int32_t GetDayOfWeek() const; + bool operator==(const CFX_DateTime& other) const; + private: int32_t year_; uint8_t month_; diff --git a/testing/fx_string_testhelpers.cpp b/testing/fx_string_testhelpers.cpp index 934dd680e4..00a13f5b57 100644 --- a/testing/fx_string_testhelpers.cpp +++ b/testing/fx_string_testhelpers.cpp @@ -6,6 +6,7 @@ #include #include +#include namespace { @@ -46,3 +47,12 @@ std::ostream& operator<<(std::ostream& out, const CFX_WideStringC& str) { std::ostream& operator<<(std::ostream& out, const CFX_WideString& str) { return output_string(out, str); } + +std::ostream& operator<<(std::ostream& os, const CFX_DateTime& dt) { + os << dt.GetYear() << "-" << std::to_string(dt.GetMonth()) << "-" + << std::to_string(dt.GetDay()) << " " << std::to_string(dt.GetHour()) + << ":" << std::to_string(dt.GetMinute()) << ":" + << std::to_string(dt.GetSecond()) << "." + << std::to_string(dt.GetMillisecond()); + return os; +} diff --git a/testing/fx_string_testhelpers.h b/testing/fx_string_testhelpers.h index 82552d7227..caa233049a 100644 --- a/testing/fx_string_testhelpers.h +++ b/testing/fx_string_testhelpers.h @@ -7,6 +7,7 @@ #include +#include "core/fxcrt/cfx_datetime.h" #include "core/fxcrt/fx_string.h" // Output stream operator so GTEST macros work with FX strings. @@ -15,4 +16,7 @@ std::ostream& operator<<(std::ostream& out, const CFX_ByteString& str); std::ostream& operator<<(std::ostream& out, const CFX_WideStringC& str); std::ostream& operator<<(std::ostream& out, const CFX_WideString& str); +// Output stream operator so GTEST macros work with CFX_DateTime objects. +std::ostream& operator<<(std::ostream& os, const CFX_DateTime& dt); + #endif // TESTING_FX_STRING_TESTHELPERS_H_ diff --git a/xfa/fgas/crt/cfgas_formatstring.cpp b/xfa/fgas/crt/cfgas_formatstring.cpp index aa8f53aaf0..d0cb479d26 100644 --- a/xfa/fgas/crt/cfgas_formatstring.cpp +++ b/xfa/fgas/crt/cfgas_formatstring.cpp @@ -1984,7 +1984,6 @@ bool CFGAS_FormatString::ParseDateTime(const CFX_WideString& wsSrcDateTime, FX_DATETIMETYPE eDateTimeType, CFX_DateTime* dtValue) { dtValue->Reset(); - if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty()) return false; @@ -2592,7 +2591,8 @@ bool CFGAS_FormatString::FormatDateTime(const CFX_WideString& wsSrcDateTime, if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty()) return false; - CFX_WideString wsDatePattern, wsTimePattern; + CFX_WideString wsDatePattern; + CFX_WideString wsTimePattern; IFX_Locale* pLocale = nullptr; FX_DATETIMETYPE eCategory = GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern); diff --git a/xfa/fgas/crt/cfgas_formatstring_unittest.cpp b/xfa/fgas/crt/cfgas_formatstring_unittest.cpp new file mode 100644 index 0000000000..066391914f --- /dev/null +++ b/xfa/fgas/crt/cfgas_formatstring_unittest.cpp @@ -0,0 +1,114 @@ +// 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. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fgas/crt/cfgas_formatstring.h" + +#include + +#include "core/fpdfapi/cpdf_modulemgr.h" +#include "testing/fx_string_testhelpers.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_localemgr.h" + +class CFGAS_FormatStringTest : public testing::Test { + public: + CFGAS_FormatStringTest() { CPDF_ModuleMgr::Get()->Init(); } + + ~CFGAS_FormatStringTest() override { CPDF_ModuleMgr::Get()->Destroy(); } + + void TearDown() override { + fmt_.reset(); + mgr_.reset(); + } + + // Note, this re-creates the fmt on each call. If you need to multiple + // times store it locally. + CFGAS_FormatString* fmt(const CFX_WideString& locale) { + mgr_ = pdfium::MakeUnique(nullptr, locale); + fmt_ = pdfium::MakeUnique(mgr_.get()); + return fmt_.get(); + } + + protected: + std::unique_ptr mgr_; + std::unique_ptr fmt_; +}; + +// TODO(dsinclair): Looks like the formatter/parser does not handle the various +// 'g' flags. +TEST_F(CFGAS_FormatStringTest, DateFormat) { + struct { + const wchar_t* locale; + const wchar_t* input; + const wchar_t* pattern; + const wchar_t* output; + } tests[] = { + {L"en", L"2002-10-25", L"MMMM DD, YYYY", L"October 25, 2002"}, + // Note, this is in the doc as 5 but it's wrong and should be 3 by the + // example in the Picture Clause Reference section. + {L"en", L"20040722", L"'Week of the month is' w", + L"Week of the month is 3"}, + {L"en", L"20040722", L"e 'days after Sunday'", L"4 days after Sunday"}, + {L"en", L"20040722", L"YYYY-'W'WW-e", L"2004-W30-4"}, + {L"en", L"20040722", L"E 'days after Saturday'", + L"5 days after Saturday"}, + {L"en", L"2000-01-01", L"EEEE, 'the' D 'of' MMMM, YYYY", + L"Saturday, the 1 of January, 2000"}, + {L"en", L"19991202", L"MM/D/YY", L"12/2/99"}, + {L"en", L"19990110", L"MMM D, YYYY", L"Jan 10, 1999"}, + {L"de_CH", L"20041030", L"D. MMMM YYYY", L"30. Oktober 2004"}, + {L"fr_CA", L"20041030", L"D MMMM YYYY", L"30 octobre 2004"}, + // {L"ja", L"2003-11-03", L"gY/M/D", L"H15/11/3"}, + // {L"ja", L"1989-01-08", L"ggY-M-D", L"\u5e731-1-8"}, + // {L"ja", L"1989-11-03", L"gggYY/MM/DD", L"\u5e73\u621089/11/03"}, + // {L"ja", L"1989-01-08", L"\u0067\u0067YY/MM/DD", L"\u337b89/01/08"} + }; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + CFX_WideString result; + EXPECT_TRUE(fmt(tests[i].locale) + ->FormatDateTime(tests[i].input, tests[i].pattern, result, + FX_DATETIMETYPE_Date)); + EXPECT_STREQ(tests[i].output, result.c_str()) << " TEST: " << i; + } +} + +TEST_F(CFGAS_FormatStringTest, DateParse) { + struct { + const wchar_t* locale; + const wchar_t* input; + const wchar_t* pattern; + CFX_DateTime output; + } tests[] = { + {L"en", L"12/2/99", L"MM/D/YY", CFX_DateTime(1999, 12, 2, 0, 0, 0, 0)}, + {L"en", L"Jan 10, 1999", L"MMM D, YYYY", + CFX_DateTime(1999, 1, 10, 0, 0, 0, 0)}, + {L"en", L"October 25, 2002", L"MMMM DD, YYYY", + CFX_DateTime(2002, 10, 25, 0, 0, 0, 0)}, + {L"de_CH", L"30. Oktober 2004", L"D. MMMM YYYY", + CFX_DateTime(2004, 10, 30, 0, 0, 0, 0)}, + {L"fr_CA", L"30 octobre 2004", L"D MMMM YYYY", + CFX_DateTime(2004, 10, 30, 0, 0, 0, 0)}, + {L"en", L"Saturday, the 1 of January, 2000", + L"EEEE, 'the' D 'of' MMMM, YYYY", CFX_DateTime(2000, 1, 1, 0, 0, 0, 0)}, + // {L"ja", L"H15/11/3", L"gY/M/D", CFX_DateTime(2003, 11, 3, 0, 0, 0, 0)}, + // {L"ja", L"\u5e731-1-8", L"ggY-M-D", CFX_DateTime(1989, 1, 8, 0, 0, 0, + // 0)}, {L"ja", L"\u5e73\u621089/11/03", L"gggYY/MM/DD", + // CFX_DateTime(1989, 11, 3, 0, 0, 0, 0)}, + // {L"ja", L"u337b99/01/08", L"\u0067\u0067YY/MM/DD", + // CFX_DateTime(1999, 1, 8, 0, 0, 0, 0)} + }; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + CFX_DateTime result; + EXPECT_TRUE(fmt(tests[i].locale) + ->ParseDateTime(tests[i].input, tests[i].pattern, + FX_DATETIMETYPE_Date, &result)); + EXPECT_EQ(tests[i].output, result) << " TEST: " << i; + } +} -- cgit v1.2.3