From 1a3595cbeb6b6cb3b5771d0e303c0139949169aa Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Fri, 28 Apr 2017 16:42:54 +0200 Subject: [PATCH] Convert gnc_dmy2timespec{,_end,_neutral} to use the equivalent GncDateTime constructor This required a couple of tweaks to the tests because: - the invalid date returned for impossible conversions is different between the old implementation and the cpp edition - unhandled glib warnings caused the tests to abort --- src/engine/test/test-date.cpp | 6 ++- src/engine/test/utest-gnc-pricedb.c | 7 +++ src/libqof/qof/gnc-date.cpp | 78 ++++++++--------------------- src/libqof/qof/test/test-gnc-date.c | 45 +++++++++++++---- 4 files changed, 67 insertions(+), 69 deletions(-) diff --git a/src/engine/test/test-date.cpp b/src/engine/test/test-date.cpp index 6efc39bbb9..3600e3e630 100644 --- a/src/engine/test/test-date.cpp +++ b/src/engine/test/test-date.cpp @@ -99,8 +99,10 @@ check_conversion (const char * str, Timespec expected_ts) || (g_date_get_year(&d1) != year)) { fprintf (stderr, - "\nmis-converted \"%s\" to GDate\n", - str); + "\nmis-converted \"%s\" to GDate. " + "Got d1(Y-M-D) = %i-%i-%i, d2(Y-M-D) = %i-%i-%i\n", + str, year, month, day, + g_date_get_year(&d2), g_date_get_month(&d2), g_date_get_day(&d2)); failure ("misconverted timespec"); return FALSE; } diff --git a/src/engine/test/utest-gnc-pricedb.c b/src/engine/test/utest-gnc-pricedb.c index 691e4bf1be..b8f5d8569b 100644 --- a/src/engine/test/utest-gnc-pricedb.c +++ b/src/engine/test/utest-gnc-pricedb.c @@ -968,6 +968,11 @@ gnc_pricedb_lookup_day(GNCPriceDB *db,// C: 4 in 2 SCM: 2 in 1 Local: 1:0:0 static void test_gnc_pricedb_lookup_day (PriceDBFixture *fixture, gconstpointer pData) { + gchar *msg1 = "[gnc_dmy2timespec_internal()] Date computation error from Y-M-D 12-11-18: Year is out of valid range: 1400..10000"; + gint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL; + gchar *logdomain = "qof.engine"; + TestErrorStruct check = {loglevel, logdomain, msg1, 0}; + GLogFunc hdlr = g_log_set_default_handler ((GLogFunc)test_null_handler, &check); Timespec t = gnc_dmy2timespec(17, 11, 2012); GNCPrice *price = gnc_pricedb_lookup_day(fixture->pricedb, fixture->com->usd, @@ -978,11 +983,13 @@ test_gnc_pricedb_lookup_day (PriceDBFixture *fixture, gconstpointer pData) fixture->com->usd, fixture->com->gbp, t); g_assert_cmpstr(GET_COM_NAME(price), ==, "GBP"); + g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, &check); t = gnc_dmy2timespec(18, 11, 12); price = gnc_pricedb_lookup_day(fixture->pricedb, fixture->com->usd, fixture->com->gbp, t); g_assert(price == NULL); + g_log_set_default_handler (hdlr, 0); } // Not Used diff --git a/src/libqof/qof/gnc-date.cpp b/src/libqof/qof/gnc-date.cpp index 066a34a8dd..b078da8bfe 100644 --- a/src/libqof/qof/gnc-date.cpp +++ b/src/libqof/qof/gnc-date.cpp @@ -1255,65 +1255,12 @@ gnc_timespec2dmy (Timespec t, int *day, int *month, int *year) #define THIRTY_TWO_YEARS 0x3c30fc00LL static Timespec -gnc_dmy2timespec_internal (int day, int month, int year, gboolean start_of_day) +gnc_dmy2timespec_internal (int day, int month, int year, DayPart day_part) { - Timespec result; - struct tm date; - long long secs = 0; - - date.tm_year = year - 1900; - date.tm_mon = month - 1; - date.tm_mday = day; - - if (start_of_day) - gnc_tm_set_day_start(&date); - else - gnc_tm_set_day_end(&date); - - /* compute number of seconds */ - secs = gnc_mktime (&date); - - result.tv_sec = secs; - result.tv_nsec = 0; - - return result; -} - - -Timespec -gnc_dmy2timespec (int day, int month, int year) -{ - return gnc_dmy2timespec_internal (day, month, year, TRUE); -} - -Timespec -gnc_dmy2timespec_end (int day, int month, int year) -{ - return gnc_dmy2timespec_internal (day, month, year, FALSE); -} - -Timespec -gnc_dmy2timespec_neutral (int day, int month, int year) -{ - struct tm date; - memset (&date, 0, sizeof(struct tm)); - date.tm_year = year - 1900; - date.tm_mon = month - 1; - date.tm_mday = day; - date.tm_hour = 10; - date.tm_min = 59; - date.tm_sec = 0; - try { - GncDateTime gncdt(date); - auto offset = gncdt.offset() / 3600; - if (offset < -11) - date.tm_hour = -offset; - if (offset > 13) - date.tm_hour = 23 - offset; - - return {gnc_timegm(&date), 0}; + auto date = GncDate(year, month, day); + return { static_cast(GncDateTime (date, day_part)), 0 }; } catch(const std::logic_error& err) { @@ -1328,6 +1275,25 @@ gnc_dmy2timespec_neutral (int day, int month, int year) return {INT64_MAX, 0}; } } + + +Timespec +gnc_dmy2timespec (int day, int month, int year) +{ + return gnc_dmy2timespec_internal (day, month, year, DayPart::start); +} + +Timespec +gnc_dmy2timespec_end (int day, int month, int year) +{ + return gnc_dmy2timespec_internal (day, month, year, DayPart::end); +} + +Timespec +gnc_dmy2timespec_neutral (int day, int month, int year) +{ + return gnc_dmy2timespec_internal (day, month, year, DayPart::neutral); +} /********************************************************************\ \********************************************************************/ void diff --git a/src/libqof/qof/test/test-gnc-date.c b/src/libqof/qof/test/test-gnc-date.c index 3e00d8c120..489bf9bc31 100644 --- a/src/libqof/qof/test/test-gnc-date.c +++ b/src/libqof/qof/test/test-gnc-date.c @@ -114,10 +114,10 @@ setup_begin(FixtureB *f, gconstpointer pData) f->test[1] = (TimeMap){1918, 3, 31, INT64_C(-1633305600)}; f->test[2] = (TimeMap){1918, 4, 1, INT64_C(-1633219200)}; f->test[3] = (TimeMap){2057, 11, 20, INT64_C(2773440000)}; - f->test[4] = (TimeMap){1257, 07, 02, INT64_C(21695385600)}; /*invalid year*/ - f->test[5] = (TimeMap){2017, 02, 29, INT64_C(1488326400)}; /*invalid day*/ - f->test[6] = (TimeMap){2017, 02, 33, INT64_C(1488672000)}; /*invalid day*/ - f->test[7] = (TimeMap){2017, 13, 29, INT64_C(1517184000)}; /*invalid month*/ + f->test[4] = (TimeMap){1257, 07, 02, INT64_MAX}; /*invalid year*/ + f->test[5] = (TimeMap){2017, 02, 29, INT64_MAX}; /*invalid day*/ + f->test[6] = (TimeMap){2017, 02, 33, INT64_MAX}; /*invalid day*/ + f->test[7] = (TimeMap){2017, 13, 29, INT64_MAX}; /*invalid month*/ f->test[8] = (TimeMap){2017, 03, 16, INT64_C(1489622400)}; } @@ -142,10 +142,10 @@ setup_end(FixtureB *f, gconstpointer pData) f->test[1] = (TimeMap){1918, 3, 31, INT64_C(-1633219201)}; f->test[2] = (TimeMap){1918, 4, 1, INT64_C(-1633132801)}; f->test[3] = (TimeMap){2057, 11, 20, INT64_C(2773526399)}; - f->test[4] = (TimeMap){1257, 07, 02, INT64_C(21695471999)}; - f->test[5] = (TimeMap){2017, 02, 29, INT64_C(1488412799)}; - f->test[6] = (TimeMap){2017, 02, 33, INT64_C(1488758399)}; - f->test[7] = (TimeMap){2017, 13, 29, INT64_C(1517270399)}; + f->test[4] = (TimeMap){1257, 07, 02, INT64_MAX}; + f->test[5] = (TimeMap){2017, 02, 29, INT64_MAX}; + f->test[6] = (TimeMap){2017, 02, 33, INT64_MAX}; + f->test[7] = (TimeMap){2017, 13, 29, INT64_MAX}; f->test[8] = (TimeMap){2017, 03, 16, INT64_C(1489708799)}; } @@ -1807,7 +1807,12 @@ gnc_dmy2timespec (int day, int month, int year)// C: 8 in 5 Local: 1:0:0 static void test_gnc_dmy2timespec (FixtureB *f, gconstpointer pData) { - + gchar *msg1 = "[qof_dmy2timespec()] Date computation error from Y-M-D 1257-7-2: Time value is outside the supported year range."; + gint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL; + gchar *logdomain = "qof.engine"; + TestErrorStruct check = {loglevel, logdomain, msg1, 0}; + GLogFunc hdlr = g_log_set_default_handler ((GLogFunc)test_null_handler, &check); + g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, &check); for (int i = 0; i < sizeof(f->test)/sizeof(TimeMap); ++i) { #ifdef HAVE_STRUCT_TM_GMTOFF @@ -1820,8 +1825,14 @@ test_gnc_dmy2timespec (FixtureB *f, gconstpointer pData) Timespec r_t = gnc_dmy2timespec (f->test[i].day, f->test[i].mon, f->test[i].yr); int offset = gnc_mktime(&tm) - gnc_timegm(&tm); - g_assert_cmpint (r_t.tv_sec, ==, f->test[i].secs + offset); + if (f->test[i].secs == INT64_MAX) + /* We use INT64_MAX as invalid timespec.secs. + * As we can't *add* to the max, we can ignore the tz offset in this case. */ + g_assert_cmpint (r_t.tv_sec, ==, INT64_MAX); + else + g_assert_cmpint (r_t.tv_sec, ==, f->test[i].secs + offset); } + g_log_set_default_handler (hdlr, 0); } /* gnc_dmy2timespec_end Timespec @@ -1830,6 +1841,12 @@ gnc_dmy2timespec_end (int day, int month, int year)// C: 1 Local: 0:0:0 static void test_gnc_dmy2timespec_end (FixtureB *f, gconstpointer pData) { + gchar *msg1 = "[qof_dmy2timespec_end()] Date computation error from Y-M-D 1257-7-2: Time value is outside the supported year range."; + gint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL; + gchar *logdomain = "qof.engine"; + TestErrorStruct check = {loglevel, logdomain, msg1, 0}; + GLogFunc hdlr = g_log_set_default_handler ((GLogFunc)test_null_handler, &check); + g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, &check); for (int i = 0; i < sizeof(f->test)/sizeof(TimeMap); ++i) { #ifdef HAVE_STRUCT_TM_GMTOFF @@ -1842,8 +1859,14 @@ test_gnc_dmy2timespec_end (FixtureB *f, gconstpointer pData) Timespec r_t = gnc_dmy2timespec_end (f->test[i].day, f->test[i].mon, f->test[i].yr); int offset = gnc_mktime(&tm) - gnc_timegm(&tm); - g_assert_cmpint (r_t.tv_sec, ==, f->test[i].secs + offset); + if (f->test[i].secs == INT64_MAX) + /* We use INT64_MAX as invalid timespec.secs. + * As we can't *add* to the max, we can ignore the tz offset in this case. */ + g_assert_cmpint (r_t.tv_sec, ==, INT64_MAX); + else + g_assert_cmpint (r_t.tv_sec, ==, f->test[i].secs + offset); } + g_log_set_default_handler (hdlr, 0); } static GDateTime*