From b761b5a0dc82ef53e1dc1b7fa50eb196fdd0a4a0 Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Sat, 28 Apr 2018 12:16:52 +0200 Subject: [PATCH] Bug 795377 - Reads and saves Gnucash 2.6.19 XML file, then can't reread it, due to bad date in old file This commit contains another round of cleanups in the timespec to time64 conversion. There were a number of false assumptions that time64 = 0 would be a bad date in the xml parser. This commit corrects enough of them to eliminate the bug. Further cleanup is probably advised but can be done at a later stage. --- .../backend/xml/sixtp-dom-generators.cpp | 2 +- libgnucash/backend/xml/sixtp-dom-parsers.cpp | 8 ++-- .../backend/xml/test/test-dom-converters1.cpp | 8 ++-- libgnucash/engine/gnc-date.cpp | 6 +-- libgnucash/engine/test/test-gnc-date.c | 46 +++++++------------ 5 files changed, 29 insertions(+), 41 deletions(-) diff --git a/libgnucash/backend/xml/sixtp-dom-generators.cpp b/libgnucash/backend/xml/sixtp-dom-generators.cpp index 3f4c8deed6..ce7bc5baa1 100644 --- a/libgnucash/backend/xml/sixtp-dom-generators.cpp +++ b/libgnucash/backend/xml/sixtp-dom-generators.cpp @@ -141,7 +141,7 @@ xmlNodePtr time64_to_dom_tree (const char* tag, const time64 time) { xmlNodePtr ret; - g_return_val_if_fail (time, NULL); + g_return_val_if_fail (time != INT64_MAX, NULL); auto date_str = time64_to_string (time); if (!date_str) return NULL; diff --git a/libgnucash/backend/xml/sixtp-dom-parsers.cpp b/libgnucash/backend/xml/sixtp-dom-parsers.cpp index 7e4ae97a05..0ef82e9f39 100644 --- a/libgnucash/backend/xml/sixtp-dom-parsers.cpp +++ b/libgnucash/backend/xml/sixtp-dom-parsers.cpp @@ -526,7 +526,7 @@ dom_tree_to_gnc_numeric (xmlNodePtr node) static time64 time_parse_failure () { - return 0; + return INT64_MAX; } @@ -544,7 +544,7 @@ dom_tree_to_time64 (xmlNodePtr node) undefined. The XML is valid if it has at least one of or and no more than one of each. Order is irrelevant. */ - time64 ret {0}; + time64 ret {INT64_MAX}; gboolean seen_s = FALSE; gboolean seen_ns = FALSE; xmlNodePtr n; @@ -865,9 +865,9 @@ dom_tree_generic_parse (xmlNodePtr node, struct dom_tree_handler* handlers, gboolean dom_tree_valid_time64 (time64 val, const xmlChar * name) { - if (val) + if (val != INT64_MAX) return TRUE; g_warning ("Invalid timestamp in data file. Look for a '%s' entry " - "with a date of 1969-12-31 or 1970-01-01.", name); + "with a year outside of the valie range: 1400..10000", name); return FALSE; } diff --git a/libgnucash/backend/xml/test/test-dom-converters1.cpp b/libgnucash/backend/xml/test/test-dom-converters1.cpp index a6124d85ad..29182d1942 100644 --- a/libgnucash/backend/xml/test/test-dom-converters1.cpp +++ b/libgnucash/backend/xml/test/test-dom-converters1.cpp @@ -127,7 +127,7 @@ test_dom_tree_to_text (void) static void -test_dom_tree_to_timespec (void) +test_dom_tree_to_time64 (void) { int i; for (i = 0; i < 20; i++) @@ -146,11 +146,11 @@ test_dom_tree_to_timespec (void) } else if (test_spec1 == test_spec2) { - success ("dom_tree_to_timespec"); + success ("dom_tree_to_time64"); } else { - failure ("dom_tree_to_timespec"); + failure ("dom_tree_to_time64"); printf ("Node looks like:\n"); xmlElemDump (stdout, NULL, test_node); printf ("\n"); @@ -266,7 +266,7 @@ main (int argc, char** argv) fflush (stdout); test_dom_tree_to_text (); fflush (stdout); - test_dom_tree_to_timespec (); + test_dom_tree_to_time64 (); fflush (stdout); test_dom_tree_to_gnc_numeric (); fflush (stdout); diff --git a/libgnucash/engine/gnc-date.cpp b/libgnucash/engine/gnc-date.cpp index 1b37ede086..881c090fef 100644 --- a/libgnucash/engine/gnc-date.cpp +++ b/libgnucash/engine/gnc-date.cpp @@ -1202,7 +1202,7 @@ time64 gnc_iso8601_to_time64_gmt(const char *cstr) { time64 time; - if (!cstr) return 0; + if (!cstr) return INT64_MAX; try { GncDateTime gncdt(cstr); @@ -1211,12 +1211,12 @@ gnc_iso8601_to_time64_gmt(const char *cstr) catch(std::logic_error& err) { PWARN("Error processing %s: %s", cstr, err.what()); - return 0; + return INT64_MAX; } catch(std::runtime_error& err) { PWARN("Error processing time64 %s: %s", cstr, err.what()); - return 0; + return INT64_MAX; } } diff --git a/libgnucash/engine/test/test-gnc-date.c b/libgnucash/engine/test/test-gnc-date.c index a86bfb3ed3..b262ff688f 100644 --- a/libgnucash/engine/test/test-gnc-date.c +++ b/libgnucash/engine/test/test-gnc-date.c @@ -1633,40 +1633,28 @@ get_nanoseconds (GDateTime *gdt) } static void -test_gnc_iso8601_to_timespec_gmt (FixtureA *f, gconstpointer pData) +test_gnc_iso8601_to_time64_gmt (FixtureA *f, gconstpointer pData) { - Timespec t = {gnc_iso8601_to_time64_gmt (NULL), 0}; - g_assert_cmpint (t.tv_sec, ==, 0); - g_assert_cmpint (t.tv_nsec, ==, 0); + time64 t = gnc_iso8601_to_time64_gmt (NULL); + g_assert_cmpint (t, ==, INT64_MAX); - t.tv_sec = gnc_iso8601_to_time64_gmt (""); - g_assert_cmpint (t.tv_sec, ==, 0); - g_assert_cmpint (t.tv_nsec, ==, 0); + t = gnc_iso8601_to_time64_gmt (""); + g_assert_cmpint (t, ==, 0); - t.tv_sec = gnc_iso8601_to_time64_gmt ("1989-03-27 13:43:27"); - g_assert_cmpint (t.tv_sec, ==, f->ts1.tv_sec); - /* MinGW has some precision issues in the last microsecond digit */ -#ifdef G_OS_WIN32 - g_assert_cmpint (t.tv_nsec - 2000, <=, f->ts1.tv_nsec); - g_assert_cmpint (t.tv_nsec + 2000, >=, f->ts1.tv_nsec); -#else - g_assert_cmpint (t.tv_nsec, ==, f->ts1.tv_nsec); -#endif - t.tv_sec = gnc_iso8601_to_time64_gmt ("2020-11-07 06:21:19 -05"); - g_assert_cmpint (t.tv_sec, ==, f->ts2.tv_sec); - g_assert_cmpint (t.tv_nsec, ==, f->ts2.tv_nsec); + t = gnc_iso8601_to_time64_gmt ("1989-03-27 13:43:27"); + g_assert_cmpint (t, ==, f->ts1.tv_sec); + + t = gnc_iso8601_to_time64_gmt ("2020-11-07 06:21:19 -05"); + g_assert_cmpint (t, ==, f->ts2.tv_sec); - t.tv_sec = gnc_iso8601_to_time64_gmt ("2012-07-04 19:27:44.0+08:40"); - g_assert_cmpint (t.tv_sec, ==, f->ts3.tv_sec); - g_assert_cmpint (t.tv_nsec, ==, f->ts3.tv_nsec); + t = gnc_iso8601_to_time64_gmt ("2012-07-04 19:27:44.0+08:40"); + g_assert_cmpint (t, ==, f->ts3.tv_sec); - t.tv_sec = gnc_iso8601_to_time64_gmt ("1961-09-22 17:53:19 -05"); - g_assert_cmpint (t.tv_sec, ==, f->ts4.tv_sec); - g_assert_cmpint (t.tv_nsec, ==, f->ts4.tv_nsec); + t = gnc_iso8601_to_time64_gmt ("1961-09-22 17:53:19 -05"); + g_assert_cmpint (t, ==, f->ts4.tv_sec); - t.tv_sec = gnc_iso8601_to_time64_gmt ("2061-01-25 23:21:19.0 -05:00"); - g_assert_cmpint (t.tv_sec, ==, f->ts5.tv_sec); - g_assert_cmpint (t.tv_nsec, ==, f->ts5.tv_nsec); + t = gnc_iso8601_to_time64_gmt ("2061-01-25 23:21:19.0 -05:00"); + g_assert_cmpint (t, ==, f->ts5.tv_sec); } /* gnc_timespec_to_iso8601_buff char * @@ -2269,7 +2257,7 @@ test_suite_gnc_date (void) // GNC_TEST_ADD_FUNC (suitename, "qof format time", test_qof_format_time); // GNC_TEST_ADD_FUNC (suitename, "qof strftime", test_qof_strftime); GNC_TEST_ADD_FUNC (suitename, "gnc_date_timestamp", test_gnc_date_timestamp); - GNC_TEST_ADD (suitename, "gnc iso8601 to timespec gmt", FixtureA, NULL, setup, test_gnc_iso8601_to_timespec_gmt, NULL); + GNC_TEST_ADD (suitename, "gnc iso8601 to time64 gmt", FixtureA, NULL, setup, test_gnc_iso8601_to_time64_gmt, NULL); GNC_TEST_ADD (suitename, "gnc timespec to iso8601 buff", FixtureA, NULL, setup, test_gnc_timespec_to_iso8601_buff, NULL); GNC_TEST_ADD (suitename, "gnc timespec2dmy", FixtureA, NULL, setup, test_gnc_timespec2dmy, NULL); // GNC_TEST_ADD_FUNC (suitename, "gnc dmy2timespec internal", test_gnc_dmy2timespec_internal);