Resolves: RHEL-108555,RHEL-108568,RHEL-108576,RHEL-108584,RHEL-108596,RHEL-108598,RHEL-109096,RHEL-109488,RHEL-111065,RHEL-31756,RHEL-50103
445 lines
23 KiB
Diff
445 lines
23 KiB
Diff
From 05b4623cb23c6f083a5bee9769e5cd22d8ff4e16 Mon Sep 17 00:00:00 2001
|
|
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
|
Date: Sun, 12 Feb 2023 05:30:49 +0900
|
|
Subject: [PATCH] test: add tests for format_timestamp() and parse_timestamp()
|
|
with various timezone
|
|
|
|
(cherry picked from commit 8b51c41fd0796b1299f3b7f2f11eaf4efae8c2db)
|
|
|
|
Related: RHEL-109488
|
|
---
|
|
src/test/test-time-util.c | 378 ++++++++++++++++++++++++++++++++++++--
|
|
1 file changed, 366 insertions(+), 12 deletions(-)
|
|
|
|
diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
|
|
index 6b546fb9f5..3fbf7bf3d0 100644
|
|
--- a/src/test/test-time-util.c
|
|
+++ b/src/test/test-time-util.c
|
|
@@ -1,6 +1,9 @@
|
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
|
|
+#include "dirent-util.h"
|
|
#include "env-util.h"
|
|
+#include "fd-util.h"
|
|
+#include "fileio.h"
|
|
#include "random-util.h"
|
|
#include "serialize.h"
|
|
#include "string-util.h"
|
|
@@ -8,6 +11,8 @@
|
|
#include "tests.h"
|
|
#include "time-util.h"
|
|
|
|
+#define TRIAL 100u
|
|
+
|
|
TEST(parse_sec) {
|
|
usec_t u;
|
|
|
|
@@ -334,11 +339,11 @@ TEST(usec_sub_signed) {
|
|
}
|
|
|
|
TEST(format_timestamp) {
|
|
- for (unsigned i = 0; i < 100; i++) {
|
|
+ for (unsigned i = 0; i < TRIAL; i++) {
|
|
char buf[CONST_MAX(FORMAT_TIMESTAMP_MAX, FORMAT_TIMESPAN_MAX)];
|
|
usec_t x, y;
|
|
|
|
- x = random_u64_range(2147483600 * USEC_PER_SEC) + 1;
|
|
+ x = random_u64_range(USEC_TIMESTAMP_FORMATTABLE_MAX - USEC_PER_SEC) + USEC_PER_SEC;
|
|
|
|
assert_se(format_timestamp(buf, sizeof(buf), x));
|
|
log_debug("%s", buf);
|
|
@@ -377,20 +382,91 @@ TEST(format_timestamp) {
|
|
}
|
|
}
|
|
|
|
+static void test_format_timestamp_impl(usec_t x) {
|
|
+ bool success;
|
|
+ const char *xx, *yy;
|
|
+ usec_t y;
|
|
+
|
|
+ xx = FORMAT_TIMESTAMP(x);
|
|
+ assert_se(xx);
|
|
+ assert_se(parse_timestamp(xx, &y) >= 0);
|
|
+ yy = FORMAT_TIMESTAMP(y);
|
|
+ assert_se(yy);
|
|
+
|
|
+ success = (x / USEC_PER_SEC == y / USEC_PER_SEC) && streq(xx, yy);
|
|
+ log_full(success ? LOG_DEBUG : LOG_ERR, "@" USEC_FMT " → %s → @" USEC_FMT " → %s", x, xx, y, yy);
|
|
+ assert_se(x / USEC_PER_SEC == y / USEC_PER_SEC);
|
|
+ assert_se(streq(xx, yy));
|
|
+}
|
|
+
|
|
+static void test_format_timestamp_loop(void) {
|
|
+ test_format_timestamp_impl(USEC_PER_SEC);
|
|
+
|
|
+ for (unsigned i = 0; i < TRIAL; i++) {
|
|
+ usec_t x;
|
|
+
|
|
+ x = random_u64_range(USEC_TIMESTAMP_FORMATTABLE_MAX - USEC_PER_SEC) + USEC_PER_SEC;
|
|
+ test_format_timestamp_impl(x);
|
|
+ }
|
|
+}
|
|
+
|
|
TEST(FORMAT_TIMESTAMP) {
|
|
- for (unsigned i = 0; i < 100; i++) {
|
|
- _cleanup_free_ char *buf;
|
|
- usec_t x, y;
|
|
+ test_format_timestamp_loop();
|
|
+}
|
|
|
|
- x = random_u64_range(2147483600 * USEC_PER_SEC) + 1;
|
|
+static void test_format_timestamp_with_tz_one(const char *name1, const char *name2) {
|
|
+ _cleanup_free_ char *buf = NULL, *tz = NULL;
|
|
+ const char *name, *saved_tz;
|
|
|
|
- /* strbuf() is to test the macro in an argument to a function call. */
|
|
- assert_se(buf = strdup(FORMAT_TIMESTAMP(x)));
|
|
- log_debug("%s", buf);
|
|
- assert_se(parse_timestamp(buf, &y) >= 0);
|
|
- assert_se(x / USEC_PER_SEC == y / USEC_PER_SEC);
|
|
+ if (name2)
|
|
+ assert_se(buf = path_join(name1, name2));
|
|
+ name = buf ?: name1;
|
|
+
|
|
+ if (!timezone_is_valid(name, LOG_DEBUG))
|
|
+ return;
|
|
|
|
- assert_se(streq(FORMAT_TIMESTAMP(x), buf));
|
|
+ log_info("/* %s(%s) */", __func__, name);
|
|
+
|
|
+ saved_tz = getenv("TZ");
|
|
+
|
|
+ assert_se(tz = strjoin(":", name));
|
|
+ assert_se(setenv("TZ", tz, 1) >= 0);
|
|
+ tzset();
|
|
+ log_debug("%s: tzname[0]=%s, tzname[1]=%s", tz, strempty(tzname[0]), strempty(tzname[1]));
|
|
+
|
|
+ test_format_timestamp_loop();
|
|
+
|
|
+ assert_se(set_unset_env("TZ", saved_tz, true) == 0);
|
|
+ tzset();
|
|
+}
|
|
+
|
|
+TEST(FORMAT_TIMESTAMP_with_tz) {
|
|
+ if (!slow_tests_enabled())
|
|
+ return (void) log_tests_skipped("slow tests are disabled");
|
|
+
|
|
+ _cleanup_closedir_ DIR *dir = opendir("/usr/share/zoneinfo");
|
|
+ if (!dir)
|
|
+ return (void) log_tests_skipped_errno(errno, "Failed to open /usr/share/zoneinfo");
|
|
+
|
|
+ FOREACH_DIRENT(de, dir, break) {
|
|
+ if (de->d_type == DT_REG)
|
|
+ test_format_timestamp_with_tz_one(de->d_name, NULL);
|
|
+
|
|
+ else if (de->d_type == DT_DIR) {
|
|
+ if (streq(de->d_name, "right"))
|
|
+ /* The test does not support timezone with leap second info. */
|
|
+ continue;
|
|
+
|
|
+ _cleanup_closedir_ DIR *subdir = xopendirat(dirfd(dir), de->d_name, 0);
|
|
+ if (!subdir) {
|
|
+ log_notice_errno(errno, "Failed to open /usr/share/zoneinfo/%s, ignoring: %m", de->d_name);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ FOREACH_DIRENT(subde, subdir, break)
|
|
+ if (subde->d_type == DT_REG)
|
|
+ test_format_timestamp_with_tz_one(de->d_name, subde->d_name);
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -490,6 +566,219 @@ TEST(format_timestamp_utc) {
|
|
test_format_timestamp_utc_one(USEC_INFINITY, NULL);
|
|
}
|
|
|
|
+static void test_parse_timestamp_one(const char *str, usec_t max_diff, usec_t expected) {
|
|
+ usec_t usec;
|
|
+
|
|
+ log_debug("/* %s(%s) */", __func__, str);
|
|
+ assert_se(parse_timestamp(str, &usec) >= 0);
|
|
+ assert_se(usec >= expected);
|
|
+ assert_se(usec_sub_unsigned(usec, expected) <= max_diff);
|
|
+}
|
|
+
|
|
+TEST(parse_timestamp) {
|
|
+ usec_t today, now_usec;
|
|
+
|
|
+ /* UTC */
|
|
+ test_parse_timestamp_one("Thu 1970-01-01 00:01 UTC", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("Thu 1970-01-01 00:00:01 UTC", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("Thu 1970-01-01 00:00:01.001 UTC", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("Thu 1970-01-01 00:00:01.0010 UTC", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("Thu 70-01-01 00:01 UTC", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("Thu 70-01-01 00:00:01 UTC", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("Thu 70-01-01 00:00:01.001 UTC", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("Thu 70-01-01 00:00:01.0010 UTC", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("1970-01-01 00:01 UTC", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("1970-01-01 00:00:01 UTC", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("1970-01-01 00:00:01.001 UTC", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("1970-01-01 00:00:01.0010 UTC", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("70-01-01 00:01 UTC", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("70-01-01 00:00:01 UTC", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("70-01-01 00:00:01.001 UTC", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("70-01-01 00:00:01.0010 UTC", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ if (timezone_is_valid("Asia/Tokyo", LOG_DEBUG)) {
|
|
+ /* Asia/Tokyo (+0900) */
|
|
+ test_parse_timestamp_one("Thu 1970-01-01 09:01 Asia/Tokyo", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("Thu 1970-01-01 09:00:01 Asia/Tokyo", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("Thu 1970-01-01 09:00:01.001 Asia/Tokyo", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("Thu 1970-01-01 09:00:01.0010 Asia/Tokyo", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("Thu 70-01-01 09:01 Asia/Tokyo", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("Thu 70-01-01 09:00:01 Asia/Tokyo", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("Thu 70-01-01 09:00:01.001 Asia/Tokyo", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("Thu 70-01-01 09:00:01.0010 Asia/Tokyo", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("1970-01-01 09:01 Asia/Tokyo", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("1970-01-01 09:00:01 Asia/Tokyo", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("1970-01-01 09:00:01.001 Asia/Tokyo", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("1970-01-01 09:00:01.0010 Asia/Tokyo", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("70-01-01 09:01 Asia/Tokyo", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("70-01-01 09:00:01 Asia/Tokyo", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("70-01-01 09:00:01.001 Asia/Tokyo", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("70-01-01 09:00:01.0010 Asia/Tokyo", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ const char *saved_tz = getenv("TZ");
|
|
+ assert_se(setenv("TZ", ":Asia/Tokyo", 1) >= 0);
|
|
+
|
|
+ /* JST (+0900) */
|
|
+ test_parse_timestamp_one("Thu 1970-01-01 09:01 JST", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("Thu 1970-01-01 09:00:01 JST", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("Thu 1970-01-01 09:00:01.001 JST", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("Thu 1970-01-01 09:00:01.0010 JST", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("Thu 70-01-01 09:01 JST", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("Thu 70-01-01 09:00:01 JST", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("Thu 70-01-01 09:00:01.001 JST", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("Thu 70-01-01 09:00:01.0010 JST", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("1970-01-01 09:01 JST", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("1970-01-01 09:00:01 JST", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("1970-01-01 09:00:01.001 JST", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("1970-01-01 09:00:01.0010 JST", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("70-01-01 09:01 JST", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("70-01-01 09:00:01 JST", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("70-01-01 09:00:01.001 JST", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("70-01-01 09:00:01.0010 JST", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ assert_se(set_unset_env("TZ", saved_tz, true) == 0);
|
|
+ }
|
|
+
|
|
+ if (timezone_is_valid("America/New_York", LOG_DEBUG)) {
|
|
+ /* America/New_York (-0500) */
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 19:01 America/New_York", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 19:00:01 America/New_York", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 19:00:01.001 America/New_York", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 19:00:01.0010 America/New_York", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("Wed 69-12-31 19:01 America/New_York", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("Wed 69-12-31 19:00:01 America/New_York", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("Wed 69-12-31 19:00:01.001 America/New_York", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("Wed 69-12-31 19:00:01.0010 America/New_York", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("1969-12-31 19:01 America/New_York", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("1969-12-31 19:00:01 America/New_York", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("1969-12-31 19:00:01.001 America/New_York", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("1969-12-31 19:00:01.0010 America/New_York", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("69-12-31 19:01 America/New_York", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("69-12-31 19:00:01 America/New_York", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("69-12-31 19:00:01.001 America/New_York", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("69-12-31 19:00:01.0010 America/New_York", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ const char *saved_tz = getenv("TZ");
|
|
+ assert_se(setenv("TZ", ":America/New_York", 1) >= 0);
|
|
+
|
|
+ /* EST (-0500) */
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 19:01 EST", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 19:00:01 EST", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 19:00:01.001 EST", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 19:00:01.0010 EST", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("Wed 69-12-31 19:01 EST", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("Wed 69-12-31 19:00:01 EST", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("Wed 69-12-31 19:00:01.001 EST", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("Wed 69-12-31 19:00:01.0010 EST", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("1969-12-31 19:01 EST", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("1969-12-31 19:00:01 EST", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("1969-12-31 19:00:01.001 EST", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("1969-12-31 19:00:01.0010 EST", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("69-12-31 19:01 EST", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("69-12-31 19:00:01 EST", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("69-12-31 19:00:01.001 EST", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("69-12-31 19:00:01.0010 EST", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ assert_se(set_unset_env("TZ", saved_tz, true) == 0);
|
|
+ }
|
|
+
|
|
+ /* -06 */
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 18:01 -06", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 18:00:01 -06", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 18:00:01.001 -06", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 18:00:01.0010 -06", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("Wed 69-12-31 18:01 -06", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("Wed 69-12-31 18:00:01 -06", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("Wed 69-12-31 18:00:01.001 -06", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("Wed 69-12-31 18:00:01.0010 -06", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("1969-12-31 18:01 -06", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("1969-12-31 18:00:01 -06", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("1969-12-31 18:00:01.001 -06", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("1969-12-31 18:00:01.0010 -06", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("69-12-31 18:01 -06", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("69-12-31 18:00:01 -06", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("69-12-31 18:00:01.001 -06", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("69-12-31 18:00:01.0010 -06", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ /* -0600 */
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 18:01 -0600", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 18:00:01 -0600", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 18:00:01.001 -0600", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 18:00:01.0010 -0600", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("Wed 69-12-31 18:01 -0600", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("Wed 69-12-31 18:00:01 -0600", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("Wed 69-12-31 18:00:01.001 -0600", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("Wed 69-12-31 18:00:01.0010 -0600", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("1969-12-31 18:01 -0600", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("1969-12-31 18:00:01 -0600", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("1969-12-31 18:00:01.001 -0600", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("1969-12-31 18:00:01.0010 -0600", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("69-12-31 18:01 -0600", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("69-12-31 18:00:01 -0600", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("69-12-31 18:00:01.001 -0600", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("69-12-31 18:00:01.0010 -0600", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ /* -06:00 */
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 18:01 -06:00", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 18:00:01 -06:00", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 18:00:01.001 -06:00", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("Wed 1969-12-31 18:00:01.0010 -06:00", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("Wed 69-12-31 18:01 -06:00", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("Wed 69-12-31 18:00:01 -06:00", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("Wed 69-12-31 18:00:01.001 -06:00", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("Wed 69-12-31 18:00:01.0010 -06:00", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("1969-12-31 18:01 -06:00", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("1969-12-31 18:00:01 -06:00", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("1969-12-31 18:00:01.001 -06:00", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("1969-12-31 18:00:01.0010 -06:00", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ test_parse_timestamp_one("69-12-31 18:01 -06:00", 0, USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("69-12-31 18:00:01 -06:00", 0, USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("69-12-31 18:00:01.001 -06:00", 0, USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("69-12-31 18:00:01.0010 -06:00", 0, USEC_PER_SEC + 1000);
|
|
+
|
|
+ /* without date */
|
|
+ assert_se(parse_timestamp("today", &today) == 0);
|
|
+ test_parse_timestamp_one("00:01", 0, today + USEC_PER_MINUTE);
|
|
+ test_parse_timestamp_one("00:00:01", 0, today + USEC_PER_SEC);
|
|
+ test_parse_timestamp_one("00:00:01.001", 0, today + USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("00:00:01.0010", 0, today + USEC_PER_SEC + 1000);
|
|
+ test_parse_timestamp_one("tomorrow", 0, today + USEC_PER_DAY);
|
|
+ test_parse_timestamp_one("yesterday", 0, today - USEC_PER_DAY);
|
|
+
|
|
+ /* relative */
|
|
+ assert_se(parse_timestamp("now", &now_usec) == 0);
|
|
+ test_parse_timestamp_one("+5hours", USEC_PER_MINUTE, now_usec + 5 * USEC_PER_HOUR);
|
|
+ if (now_usec >= 10 * USEC_PER_DAY)
|
|
+ test_parse_timestamp_one("-10days", USEC_PER_MINUTE, now_usec - 10 * USEC_PER_DAY);
|
|
+ test_parse_timestamp_one("2weeks left", USEC_PER_MINUTE, now_usec + 2 * USEC_PER_WEEK);
|
|
+ if (now_usec >= 30 * USEC_PER_MINUTE)
|
|
+ test_parse_timestamp_one("30minutes ago", USEC_PER_MINUTE, now_usec - 30 * USEC_PER_MINUTE);
|
|
+}
|
|
+
|
|
TEST(deserialize_dual_timestamp) {
|
|
int r;
|
|
dual_timestamp t;
|
|
@@ -613,6 +902,71 @@ TEST(map_clock_usec) {
|
|
}
|
|
}
|
|
|
|
+static void test_timezone_offset_change_one(const char *utc, const char *pretty) {
|
|
+ usec_t x, y, z;
|
|
+ char *s;
|
|
+
|
|
+ assert_se(parse_timestamp(utc, &x) >= 0);
|
|
+
|
|
+ s = FORMAT_TIMESTAMP_STYLE(x, TIMESTAMP_UTC);
|
|
+ assert_se(parse_timestamp(s, &y) >= 0);
|
|
+ log_debug("%s -> " USEC_FMT " -> %s -> " USEC_FMT, utc, x, s, y);
|
|
+ assert_se(streq(s, utc));
|
|
+ assert_se(x == y);
|
|
+
|
|
+ assert_se(parse_timestamp(pretty, &y) >= 0);
|
|
+ s = FORMAT_TIMESTAMP_STYLE(y, TIMESTAMP_PRETTY);
|
|
+ assert_se(parse_timestamp(s, &z) >= 0);
|
|
+ log_debug("%s -> " USEC_FMT " -> %s -> " USEC_FMT, pretty, y, s, z);
|
|
+ assert_se(streq(s, pretty));
|
|
+ assert_se(x == y);
|
|
+ assert_se(x == z);
|
|
+}
|
|
+
|
|
+TEST(timezone_offset_change) {
|
|
+ const char *tz = getenv("TZ");
|
|
+
|
|
+ /* See issue #26370. */
|
|
+
|
|
+ if (timezone_is_valid("Africa/Casablanca", LOG_DEBUG)) {
|
|
+ assert_se(setenv("TZ", ":Africa/Casablanca", 1) >= 0);
|
|
+ tzset();
|
|
+ log_debug("Africa/Casablanca: tzname[0]=%s, tzname[1]=%s", strempty(tzname[0]), strempty(tzname[1]));
|
|
+
|
|
+ test_timezone_offset_change_one("Sun 2015-10-25 01:59:59 UTC", "Sun 2015-10-25 02:59:59 +01");
|
|
+ test_timezone_offset_change_one("Sun 2015-10-25 02:00:00 UTC", "Sun 2015-10-25 02:00:00 +00");
|
|
+ test_timezone_offset_change_one("Sun 2018-06-17 01:59:59 UTC", "Sun 2018-06-17 01:59:59 +00");
|
|
+ test_timezone_offset_change_one("Sun 2018-06-17 02:00:00 UTC", "Sun 2018-06-17 03:00:00 +01");
|
|
+ test_timezone_offset_change_one("Sun 2018-10-28 01:59:59 UTC", "Sun 2018-10-28 02:59:59 +01");
|
|
+ test_timezone_offset_change_one("Sun 2018-10-28 02:00:00 UTC", "Sun 2018-10-28 03:00:00 +01");
|
|
+ }
|
|
+
|
|
+ if (timezone_is_valid("Asia/Atyrau", LOG_DEBUG)) {
|
|
+ assert_se(setenv("TZ", ":Asia/Atyrau", 1) >= 0);
|
|
+ tzset();
|
|
+ log_debug("Asia/Atyrau: tzname[0]=%s, tzname[1]=%s", strempty(tzname[0]), strempty(tzname[1]));
|
|
+
|
|
+ test_timezone_offset_change_one("Sat 2004-03-27 21:59:59 UTC", "Sun 2004-03-28 01:59:59 +04");
|
|
+ test_timezone_offset_change_one("Sat 2004-03-27 22:00:00 UTC", "Sun 2004-03-28 03:00:00 +05");
|
|
+ test_timezone_offset_change_one("Sat 2004-10-30 21:59:59 UTC", "Sun 2004-10-31 02:59:59 +05");
|
|
+ test_timezone_offset_change_one("Sat 2004-10-30 22:00:00 UTC", "Sun 2004-10-31 03:00:00 +05");
|
|
+ }
|
|
+
|
|
+ if (timezone_is_valid("Chile/EasterIsland", LOG_DEBUG)) {
|
|
+ assert_se(setenv("TZ", ":Chile/EasterIsland", 1) >= 0);
|
|
+ tzset();
|
|
+ log_debug("Chile/EasterIsland: tzname[0]=%s, tzname[1]=%s", strempty(tzname[0]), strempty(tzname[1]));
|
|
+
|
|
+ test_timezone_offset_change_one("Sun 1981-10-11 03:59:59 UTC", "Sat 1981-10-10 20:59:59 -07");
|
|
+ test_timezone_offset_change_one("Sun 1981-10-11 04:00:00 UTC", "Sat 1981-10-10 22:00:00 -06");
|
|
+ test_timezone_offset_change_one("Sun 1982-03-14 02:59:59 UTC", "Sat 1982-03-13 20:59:59 -06");
|
|
+ test_timezone_offset_change_one("Sun 1982-03-14 03:00:00 UTC", "Sat 1982-03-13 21:00:00 -06");
|
|
+ }
|
|
+
|
|
+ assert_se(set_unset_env("TZ", tz, true) == 0);
|
|
+ tzset();
|
|
+}
|
|
+
|
|
static int intro(void) {
|
|
log_info("realtime=" USEC_FMT "\n"
|
|
"monotonic=" USEC_FMT "\n"
|