From 706e187ed8be44eb50bdf7024674930a4e10fa45 Mon Sep 17 00:00:00 2001 From: Tom Sepez Date: Mon, 22 Oct 2018 19:34:53 +0000 Subject: Fix timezone inconsistency in document methods test. We do this by adding an override that forces GM time on everyone when run from the test harness. Generalize presubmit warnings so that the new function passes. De-duplicate lambda capture in place of static function. Change-Id: I15b34bea558baf1763476b36f0bca76614984107 Reviewed-on: https://pdfium-review.googlesource.com/c/44390 Reviewed-by: Lei Zhang Commit-Queue: Tom Sepez --- core/fxcrt/fx_extension.cpp | 27 +++++++++++++++-- core/fxcrt/fx_extension.h | 7 +++++ fpdfsdk/fpdf_editpage.cpp | 2 +- fpdfsdk/fpdf_ext.cpp | 5 ++++ fpdfsdk/fpdf_view_c_api_test.c | 1 + fxjs/cfxjse_formcalc_context.cpp | 2 +- fxjs/js_define.cpp | 12 ++++---- public/fpdf_ext.h | 15 ++++++++-- samples/pdfium_test.cc | 3 +- testing/resources/javascript/public_methods.in | 4 +-- .../javascript/public_methods_expected.txt | 4 +-- .../resources/javascript/util_printd_expected.txt | 34 +++++++++++----------- testing/tools/api_check.py | 4 +-- 13 files changed, 81 insertions(+), 39 deletions(-) diff --git a/core/fxcrt/fx_extension.cpp b/core/fxcrt/fx_extension.cpp index 8e78e4d789..443e301630 100644 --- a/core/fxcrt/fx_extension.cpp +++ b/core/fxcrt/fx_extension.cpp @@ -12,7 +12,20 @@ #include "third_party/base/compiler_specific.h" -time_t (*time_func)() = []() -> time_t { return time(nullptr); }; +namespace { + +time_t DefaultTimeFunction() { + return time(nullptr); +} + +struct tm* DefaultLocaltimeFunction(const time_t* tp) { + return localtime(tp); +} + +time_t (*g_time_func)() = DefaultTimeFunction; +struct tm* (*g_localtime_func)(const time_t*) = DefaultLocaltimeFunction; + +} // namespace float FXSYS_wcstof(const wchar_t* pwsStr, int32_t iLength, int32_t* pUsedLen) { ASSERT(pwsStr); @@ -171,12 +184,20 @@ size_t FXSYS_ToUTF16BE(uint32_t unicode, char* buf) { } void FXSYS_SetTimeFunction(time_t (*func)()) { - time_func = func ? func : []() -> time_t { return time(nullptr); }; + g_time_func = func ? func : DefaultTimeFunction; +} + +void FXSYS_SetLocaltimeFunction(struct tm* (*func)(const time_t*)) { + g_localtime_func = func ? func : DefaultLocaltimeFunction; } time_t FXSYS_time(time_t* tloc) { - time_t ret_val = time_func(); + time_t ret_val = g_time_func(); if (tloc) *tloc = ret_val; return ret_val; } + +struct tm* FXSYS_localtime(const time_t* tp) { + return g_localtime_func(tp); +} diff --git a/core/fxcrt/fx_extension.h b/core/fxcrt/fx_extension.h index c1cd188c81..38f9fd5993 100644 --- a/core/fxcrt/fx_extension.h +++ b/core/fxcrt/fx_extension.h @@ -7,6 +7,8 @@ #ifndef CORE_FXCRT_FX_EXTENSION_H_ #define CORE_FXCRT_FX_EXTENSION_H_ +#include + #include #include #include @@ -106,7 +108,12 @@ bool FXSYS_SafeLT(const T& lhs, const T& rhs) { return lhs < rhs; } +// Override time/localtime functions for test consistency. void FXSYS_SetTimeFunction(time_t (*func)()); +void FXSYS_SetLocaltimeFunction(struct tm* (*func)(const time_t*)); + +// Replacements for time/localtime that respect overrides. time_t FXSYS_time(time_t* tloc); +struct tm* FXSYS_localtime(const time_t* tp); #endif // CORE_FXCRT_FX_EXTENSION_H_ diff --git a/fpdfsdk/fpdf_editpage.cpp b/fpdfsdk/fpdf_editpage.cpp index dcb3d5e1f0..585e7e1740 100644 --- a/fpdfsdk/fpdf_editpage.cpp +++ b/fpdfsdk/fpdf_editpage.cpp @@ -164,7 +164,7 @@ FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_CreateNewDocument() { ByteString DateStr; if (FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS)) { if (FXSYS_time(¤tTime) != -1) { - tm* pTM = localtime(¤tTime); + tm* pTM = FXSYS_localtime(¤tTime); if (pTM) { DateStr = ByteString::Format( "D:%04d%02d%02d%02d%02d%02d", pTM->tm_year + 1900, pTM->tm_mon + 1, diff --git a/fpdfsdk/fpdf_ext.cpp b/fpdfsdk/fpdf_ext.cpp index 1ff27cc94d..9f7b24b60f 100644 --- a/fpdfsdk/fpdf_ext.cpp +++ b/fpdfsdk/fpdf_ext.cpp @@ -83,6 +83,11 @@ FPDF_EXPORT void FPDF_CALLCONV FSDK_SetTimeFunction(time_t (*func)()) { FXSYS_SetTimeFunction(func); } +FPDF_EXPORT void FPDF_CALLCONV +FSDK_SetLocaltimeFunction(struct tm* (*func)(const time_t* tp)) { + FXSYS_SetLocaltimeFunction(func); +} + FPDF_EXPORT int FPDF_CALLCONV FPDFDoc_GetPageMode(FPDF_DOCUMENT document) { CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc) diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c index ab184cc519..9cf037685e 100644 --- a/fpdfsdk/fpdf_view_c_api_test.c +++ b/fpdfsdk/fpdf_view_c_api_test.c @@ -216,6 +216,7 @@ int CheckPDFiumCApi() { // fpdf_ext.h CHK(FPDFDoc_GetPageMode); + CHK(FSDK_SetLocaltimeFunction); CHK(FSDK_SetTimeFunction); CHK(FSDK_SetUnSpObjProcessHandler); diff --git a/fxjs/cfxjse_formcalc_context.cpp b/fxjs/cfxjse_formcalc_context.cpp index f95ee831a7..d77453ef72 100644 --- a/fxjs/cfxjse_formcalc_context.cpp +++ b/fxjs/cfxjse_formcalc_context.cpp @@ -959,7 +959,7 @@ void GetLocalTimeZone(int32_t* pHour, int32_t* pMin, int32_t* pSec) { FXSYS_time(&now); struct tm* pGmt = gmtime(&now); - struct tm* pLocal = localtime(&now); + struct tm* pLocal = FXSYS_localtime(&now); *pHour = pLocal->tm_hour - pGmt->tm_hour; *pMin = pLocal->tm_min - pGmt->tm_min; *pSec = pLocal->tm_sec - pGmt->tm_sec; diff --git a/fxjs/js_define.cpp b/fxjs/js_define.cpp index 54bd8e1c3a..b4e0197b54 100644 --- a/fxjs/js_define.cpp +++ b/fxjs/js_define.cpp @@ -24,7 +24,7 @@ double GetLocalTZA() { return 0; time_t t = 0; FXSYS_time(&t); - localtime(&t); + FXSYS_localtime(&t); #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ // In gcc 'timezone' is a global variable declared in time.h. In VC++, that // variable was removed in VC++ 2015, with _get_timezone replacing it. @@ -38,7 +38,7 @@ int GetDaylightSavingTA(double d) { if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS)) return 0; time_t t = (time_t)(d / 1000); - struct tm* tmp = localtime(&t); + struct tm* tmp = FXSYS_localtime(&t); if (!tmp) return 0; if (tmp->tm_isdst > 0) @@ -175,12 +175,10 @@ void JSDestructor(v8::Local obj) { double JS_GetDateTime() { if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS)) return 0; - time_t t = FXSYS_time(nullptr); - struct tm* pTm = localtime(&t); - - int year = pTm->tm_year + 1900; - double t1 = TimeFromYear(year); + time_t t = FXSYS_time(nullptr); + struct tm* pTm = FXSYS_localtime(&t); + double t1 = TimeFromYear(pTm->tm_year + 1900); return t1 + pTm->tm_yday * 86400000.0 + pTm->tm_hour * 3600000.0 + pTm->tm_min * 60000.0 + pTm->tm_sec * 1000.0; } diff --git a/public/fpdf_ext.h b/public/fpdf_ext.h index a531f1407e..b1784dd66f 100644 --- a/public/fpdf_ext.h +++ b/public/fpdf_ext.h @@ -69,14 +69,25 @@ typedef struct _UNSUPPORT_INFO { FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FSDK_SetUnSpObjProcessHandler(UNSUPPORT_INFO* unsp_info); -// Sets generator function for calls to time. +// Set replacement function for calls to time(). // // This API is intended to be used only for testing, thus may cause PDFium to // behave poorly in production environments. // -// func - Function pointer to alternate implementation of time. +// func - Function pointer to alternate implementation of time(), or +// NULL to restore to actual time() call itself. FPDF_EXPORT void FPDF_CALLCONV FSDK_SetTimeFunction(time_t (*func)()); +// Set replacement function for calls to localtime(). +// +// This API is intended to be used only for testing, thus may cause PDFium to +// behave poorly in production environments. +// +// func - Function pointer to alternate implementation of localtime(), or +// NULL to restore to actual localtime() call itself. +FPDF_EXPORT void FPDF_CALLCONV +FSDK_SetLocaltimeFunction(struct tm* (*func)(const time_t*)); + // Unknown page mode. #define PAGEMODE_UNKNOWN -1 // Document outline, and thumbnails hidden. diff --git a/samples/pdfium_test.cc b/samples/pdfium_test.cc index ac24bcc326..6f70c34644 100644 --- a/samples/pdfium_test.cc +++ b/samples/pdfium_test.cc @@ -963,7 +963,8 @@ int main(int argc, const char* argv[]) { // This must be a static var to avoid explicit capture, so the lambda can be // converted to a function ptr. static time_t time_ret = options.time; - FSDK_SetTimeFunction([]() -> time_t { return time_ret; }); + FSDK_SetTimeFunction([]() { return time_ret; }); + FSDK_SetLocaltimeFunction([](const time_t* tp) { return gmtime(tp); }); } for (const std::string& filename : files) { diff --git a/testing/resources/javascript/public_methods.in b/testing/resources/javascript/public_methods.in index 4b70375b91..07797671b9 100644 --- a/testing/resources/javascript/public_methods.in +++ b/testing/resources/javascript/public_methods.in @@ -166,7 +166,7 @@ endobj expectError(undefined, "AFParseDateEx()"); expectError(undefined, "AFParseDateEx(1, 2, 3)"); - expect(undefined, "AFParseDateEx(1, 2)", "1399646930000"); + expect(undefined, "AFParseDateEx(1, 2)", "1399672130000"); app.alert("**********************"); @@ -223,7 +223,7 @@ endobj expectError(undefined, "AFTime_Format()"); expectError(undefined, "AFTime_Format(1, 2)"); - expectEventValue(undefined, "AFTime_Format(1)", "2:48 pm"); + expectEventValue(undefined, "AFTime_Format(1)", "9:48 pm"); app.alert("**********************"); diff --git a/testing/resources/javascript/public_methods_expected.txt b/testing/resources/javascript/public_methods_expected.txt index 12e8496af5..48928f51b9 100644 --- a/testing/resources/javascript/public_methods_expected.txt +++ b/testing/resources/javascript/public_methods_expected.txt @@ -55,7 +55,7 @@ Alert: PASS: AFNumber_Keystroke(1, 2, 3) = 123 Alert: ********************** Alert: PASS: AFParseDateEx() threw AFParseDateEx: Incorrect number of parameters passed to function. Alert: PASS: AFParseDateEx(1, 2, 3) threw AFParseDateEx: Incorrect number of parameters passed to function. -Alert: PASS: AFParseDateEx(1, 2) = 1399646930000 +Alert: PASS: AFParseDateEx(1, 2) = 1399672130000 Alert: ********************** Alert: PASS: AFPercent_Format() threw AFPercent_Format: Incorrect number of parameters passed to function. Alert: PASS: AFPercent_Format(1, 2, 3) threw AFPercent_Format: Incorrect number of parameters passed to function. @@ -96,7 +96,7 @@ Alert: PASS: AFSpecial_KeystrokeEx('999999') = 12 Alert: ********************** Alert: PASS: AFTime_Format() threw AFTime_Format: Incorrect number of parameters passed to function. Alert: PASS: AFTime_Format(1, 2) threw AFTime_Format: Incorrect number of parameters passed to function. -Alert: PASS: AFTime_Format(1) = 2:48 pm +Alert: PASS: AFTime_Format(1) = 9:48 pm Alert: ********************** Alert: PASS: AFTime_FormatEx() threw AFTime_FormatEx: Incorrect number of parameters passed to function. Alert: PASS: AFTime_FormatEx('blooey', 42) threw AFTime_FormatEx: Incorrect number of parameters passed to function. diff --git a/testing/resources/javascript/util_printd_expected.txt b/testing/resources/javascript/util_printd_expected.txt index 2f077fc5fd..c609e34d1b 100644 --- a/testing/resources/javascript/util_printd_expected.txt +++ b/testing/resources/javascript/util_printd_expected.txt @@ -1,7 +1,7 @@ -Alert: mm/dd/yyyy HH:MM:ss: 07/04/2014 15:59:58 -Alert: 0: D:20140704155958 -Alert: 1: 2014.07.04 15:59:58 -Alert: 2: 2014/07/04 15:59:58 +Alert: mm/dd/yyyy HH:MM:ss: 07/04/2014 14:59:58 +Alert: 0: D:20140704145958 +Alert: 1: 2014.07.04 14:59:58 +Alert: 2: 2014/07/04 14:59:58 Alert: 3: Caught error: util.printd: Incorrect parameter value. Alert: mmmm: July Alert: mmm: Jul @@ -13,9 +13,9 @@ Alert: dd: 04 Alert: d: 4 Alert: yyyy: 2014 Alert: yy: 14 -Alert: HH: 15 -Alert: H: 15 -Alert: hh: 03 +Alert: HH: 14 +Alert: H: 14 +Alert: hh: 02 Alert: MM: 59 Alert: M: 59 Alert: ss: 58 @@ -23,7 +23,7 @@ Alert: s: 58 Alert: t: t Alert: abc.efg.i.kl.nopqr..uvwxyzABC.EFG.I.KL.NOPQR..UVWXYZ0123456780: abc.efg.i.kl.nopqr..uvwxyzABC.EFG.I.KL.NOPQR..UVWXYZ0123456780 Alert: !@#$^&*()-_<>[];:~: !@#$^&*()-_<>[];:~ -Alert: %z %d %%z %%d %%%z %%%d %%% hh:MM: z 4 z 4 z 4 03:59 +Alert: %z %d %%z %%d %%%z %%%d %%% hh:MM: z 4 z 4 z 4 02:59 Alert: : Alert: mm/dd/yyyy: 07/04/2014 Alert: mm/dd/yyyy: 12/31/1849 @@ -39,16 +39,16 @@ Alert: clams,3: Caught error: util.printd: Incorrect parameter type. Alert: mm: 07 Alert: mm: Caught error: util.printd: Operation not supported. Alert: mm/dd/yyyy HH:MM:ss: 07/03/1900 15:59:58 -Alert: mm/dd/yyyy HH:MM:ss: 09/04/2015 15:59:58 +Alert: mm/dd/yyyy HH:MM:ss: 09/04/2015 14:59:58 Alert: mm/dd/yyyy HH:MM:ss: 12/09/2015 15:59:58 -Alert: mm/dd/yyyy HH:MM:ss: 07/06/2014 02:59:58 -Alert: mm/dd/yyyy HH:MM:ss: 07/05/2014 11:34:58 -Alert: mm/dd/yyyy HH:MM:ss: 07/04/2014 16:00:05 -Alert: mm/dd/yyyy HH:MM:ss: 05/01/2014 15:59:58 +Alert: mm/dd/yyyy HH:MM:ss: 07/06/2014 01:59:58 +Alert: mm/dd/yyyy HH:MM:ss: 07/05/2014 10:34:58 +Alert: mm/dd/yyyy HH:MM:ss: 07/04/2014 15:00:05 +Alert: mm/dd/yyyy HH:MM:ss: 05/01/2014 14:59:58 Alert: mm/dd/yyyy HH:MM:ss: 03/02/2014 15:59:58 Alert: mm/dd/yyyy HH:MM:ss: Caught error: util.printd: Incorrect parameter value. Alert: mm/dd/yyyy HH:MM:ss: 12/30/2013 15:59:58 -Alert: mm/dd/yyyy HH:MM:ss: 06/29/2014 15:59:58 -Alert: mm/dd/yyyy HH:MM:ss: 07/03/2014 23:59:58 -Alert: mm/dd/yyyy HH:MM:ss: 07/04/2014 14:59:58 -Alert: mm/dd/yyyy HH:MM:ss: 07/04/2014 15:58:59 +Alert: mm/dd/yyyy HH:MM:ss: 06/29/2014 14:59:58 +Alert: mm/dd/yyyy HH:MM:ss: 07/03/2014 22:59:58 +Alert: mm/dd/yyyy HH:MM:ss: 07/04/2014 13:59:58 +Alert: mm/dd/yyyy HH:MM:ss: 07/04/2014 14:58:59 diff --git a/testing/tools/api_check.py b/testing/tools/api_check.py index 934577b21b..da2869f2fe 100755 --- a/testing/tools/api_check.py +++ b/testing/tools/api_check.py @@ -20,9 +20,7 @@ import sys def _IsValidFunctionName(function, filename): if function.startswith('FPDF'): return True - if function == 'FSDK_SetUnSpObjProcessHandler' and filename == 'fpdf_ext.h': - return True - if function == 'FSDK_SetTimeFunction' and filename == 'fpdf_ext.h': + if function.startswith('FSDK_') and filename == 'fpdf_ext.h': return True if function.startswith('FORM_') and filename == 'fpdf_formfill.h': return True -- cgit v1.2.3