Commit 6e6ad6d3 authored by Mark Andrews's avatar Mark Andrews

Merge branch '2190-in-new-yaml-output-when-truncation-is-query-time-usec' into 'main'

dig: print timestamps with microsecond precision if "-u" is used in YAML output mode

Closes #2190

See merge request isc-projects/bind9!4193
parents f2762acd b7512e87
5511. [bug] 'dig -u +yaml' failed to display timestamps to the
microsecond. [GL #2190]
5510. [bug] Implement the attach/detach semantics for dns_message_t
to fix a data race in accessing already destroyed
fctx->rmessage. [GL #2124]
......
......@@ -675,15 +675,25 @@ printmessage(dig_query_t *query, const isc_buffer_t *msgbuf, dns_message_t *msg,
if (!isc_time_isepoch(&query->time_sent)) {
char tbuf[100];
isc_time_formatISO8601ms(&query->time_sent, tbuf,
sizeof(tbuf));
if (query->lookup->use_usec) {
isc_time_formatISO8601us(&query->time_sent,
tbuf, sizeof(tbuf));
} else {
isc_time_formatISO8601ms(&query->time_sent,
tbuf, sizeof(tbuf));
}
printf(" query_time: !!timestamp %s\n", tbuf);
}
if (!isquery && !isc_time_isepoch(&query->time_recv)) {
char tbuf[100];
isc_time_formatISO8601ms(&query->time_recv, tbuf,
sizeof(tbuf));
if (query->lookup->use_usec) {
isc_time_formatISO8601us(&query->time_recv,
tbuf, sizeof(tbuf));
} else {
isc_time_formatISO8601ms(&query->time_recv,
tbuf, sizeof(tbuf));
}
printf(" response_time: !!timestamp %s\n", tbuf);
}
......
......@@ -963,6 +963,40 @@ if [ -x "$DIG" ] ; then
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
n=$((n+1))
echo_i "check that dig without -u displays 'Query time' in millseconds ($n)"
ret=0
dig_with_opts @10.53.0.3 a.example > dig.out.test$n 2>&1 || ret=1
grep ';; Query time: [0-9][0-9]* msec' dig.out.test$n >/dev/null || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
n=$((n+1))
echo_i "check that dig -u displays 'Query time' in microseconds ($n)"
ret=0
dig_with_opts -u @10.53.0.3 a.example > dig.out.test$n 2>&1 || ret=1
grep ';; Query time: [0-9][0-9]* usec' dig.out.test$n >/dev/null || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
n=$((n+1))
echo_i "check that dig +yaml without -u displays timestamps in milliseconds ($n)"
ret=0
dig_with_opts +yaml @10.53.0.3 a.example > dig.out.test$n 2>&1 || ret=1
grep 'query_time: !!timestamp ....-..-..T..:..:..\....Z' dig.out.test$n >/dev/null || ret=1
grep 'response_time: !!timestamp ....-..-..T..:..:..\....Z' dig.out.test$n >/dev/null || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
n=$((n+1))
echo_i "check that dig -u +yaml displays timestamps in microseconds ($n)"
ret=0
dig_with_opts -u +yaml @10.53.0.3 a.example > dig.out.test$n 2>&1 || ret=1
grep 'query_time: !!timestamp ....-..-..T..:..:..\.......Z' dig.out.test$n >/dev/null || ret=1
grep 'response_time: !!timestamp ....-..-..T..:..:..\.......Z' dig.out.test$n >/dev/null || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
else
echo_i "$DIG is needed, so skipping these dig tests"
fi
......
......@@ -118,6 +118,43 @@ isc_time_formatISO8601ms_test(void **state) {
assert_string_equal(buf, "2015-12-13T09:46:40.123Z");
}
/* print UTC in ISO8601 with microseconds */
static void
isc_time_formatISO8601us_test(void **state) {
isc_result_t result;
isc_time_t t;
char buf[64];
UNUSED(state);
setenv("TZ", "America/Los_Angeles", 1);
result = isc_time_now(&t);
assert_int_equal(result, ISC_R_SUCCESS);
/* check formatting: yyyy-mm-ddThh:mm:ss.ssssssZ */
memset(buf, 'X', sizeof(buf));
isc_time_formatISO8601us(&t, buf, sizeof(buf));
assert_int_equal(strlen(buf), 27);
assert_int_equal(buf[4], '-');
assert_int_equal(buf[7], '-');
assert_int_equal(buf[10], 'T');
assert_int_equal(buf[13], ':');
assert_int_equal(buf[16], ':');
assert_int_equal(buf[19], '.');
assert_int_equal(buf[26], 'Z');
/* check time conversion correctness */
memset(buf, 'X', sizeof(buf));
isc_time_settoepoch(&t);
isc_time_formatISO8601us(&t, buf, sizeof(buf));
assert_string_equal(buf, "1970-01-01T00:00:00.000000Z");
memset(buf, 'X', sizeof(buf));
isc_time_set(&t, 1450000000, 123456000);
isc_time_formatISO8601us(&t, buf, sizeof(buf));
assert_string_equal(buf, "2015-12-13T09:46:40.123456Z");
}
/* print local time in ISO8601 */
static void
isc_time_formatISO8601L_test(void **state) {
......@@ -189,6 +226,42 @@ isc_time_formatISO8601Lms_test(void **state) {
assert_string_equal(buf, "2015-12-13T01:46:40.123");
}
/* print local time in ISO8601 with microseconds */
static void
isc_time_formatISO8601Lus_test(void **state) {
isc_result_t result;
isc_time_t t;
char buf[64];
UNUSED(state);
setenv("TZ", "America/Los_Angeles", 1);
result = isc_time_now(&t);
assert_int_equal(result, ISC_R_SUCCESS);
/* check formatting: yyyy-mm-ddThh:mm:ss.ssssss */
memset(buf, 'X', sizeof(buf));
isc_time_formatISO8601Lus(&t, buf, sizeof(buf));
assert_int_equal(strlen(buf), 26);
assert_int_equal(buf[4], '-');
assert_int_equal(buf[7], '-');
assert_int_equal(buf[10], 'T');
assert_int_equal(buf[13], ':');
assert_int_equal(buf[16], ':');
assert_int_equal(buf[19], '.');
/* check time conversion correctness */
memset(buf, 'X', sizeof(buf));
isc_time_settoepoch(&t);
isc_time_formatISO8601Lus(&t, buf, sizeof(buf));
assert_string_equal(buf, "1969-12-31T16:00:00.000000");
memset(buf, 'X', sizeof(buf));
isc_time_set(&t, 1450000000, 123456000);
isc_time_formatISO8601Lus(&t, buf, sizeof(buf));
assert_string_equal(buf, "2015-12-13T01:46:40.123456");
}
/* print UTC time as yyyymmddhhmmsssss */
static void
isc_time_formatshorttimestamp_test(void **state) {
......@@ -225,8 +298,10 @@ main(void) {
cmocka_unit_test(isc_time_parsehttptimestamp_test),
cmocka_unit_test(isc_time_formatISO8601_test),
cmocka_unit_test(isc_time_formatISO8601ms_test),
cmocka_unit_test(isc_time_formatISO8601us_test),
cmocka_unit_test(isc_time_formatISO8601L_test),
cmocka_unit_test(isc_time_formatISO8601Lms_test),
cmocka_unit_test(isc_time_formatISO8601Lus_test),
cmocka_unit_test(isc_time_formatshorttimestamp_test),
};
......
......@@ -355,6 +355,20 @@ isc_time_formatISO8601Lms(const isc_time_t *t, char *buf, unsigned int len);
*
*/
void
isc_time_formatISO8601Lus(const isc_time_t *t, char *buf, unsigned int len);
/*%<
* Format the time 't' into the buffer 'buf' of length 'len',
* using the ISO8601 format: "yyyy-mm-ddThh:mm:ss.ssssss"
* If the text does not fit in the buffer, the result is indeterminate,
* but is always guaranteed to be null terminated.
*
* Requires:
*\li 'len' > 0
*\li 'buf' points to an array of at least len chars
*
*/
void
isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len);
/*%<
......@@ -383,6 +397,20 @@ isc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len);
*
*/
void
isc_time_formatISO8601us(const isc_time_t *t, char *buf, unsigned int len);
/*%<
* Format the time 't' into the buffer 'buf' of length 'len',
* using the ISO8601 format: "yyyy-mm-ddThh:mm:ss.ssssssZ"
* If the text does not fit in the buffer, the result is indeterminate,
* but is always guaranteed to be null terminated.
*
* Requires:
*\li 'len' > 0
*\li 'buf' points to an array of at least len chars
*
*/
void
isc_time_formatshorttimestamp(const isc_time_t *t, char *buf, unsigned int len);
/*%<
......
......@@ -429,6 +429,26 @@ isc_time_formatISO8601Lms(const isc_time_t *t, char *buf, unsigned int len) {
}
}
void
isc_time_formatISO8601Lus(const isc_time_t *t, char *buf, unsigned int len) {
time_t now;
unsigned int flen;
struct tm tm;
REQUIRE(t != NULL);
INSIST(t->nanoseconds < NS_PER_S);
REQUIRE(buf != NULL);
REQUIRE(len > 0);
now = (time_t)t->seconds;
flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%S", localtime_r(&now, &tm));
INSIST(flen < len);
if (flen > 0U && len - flen >= 6) {
snprintf(buf + flen, len - flen, ".%06u",
t->nanoseconds / NS_PER_US);
}
}
void
isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) {
time_t now;
......@@ -466,6 +486,27 @@ isc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len) {
}
}
void
isc_time_formatISO8601us(const isc_time_t *t, char *buf, unsigned int len) {
time_t now;
unsigned int flen;
struct tm tm;
REQUIRE(t != NULL);
INSIST(t->nanoseconds < NS_PER_S);
REQUIRE(buf != NULL);
REQUIRE(len > 0);
now = (time_t)t->seconds;
flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime_r(&now, &tm));
INSIST(flen < len);
if (flen > 0U && len - flen >= 5) {
flen -= 1; /* rewind one character (Z) */
snprintf(buf + flen, len - flen, ".%06uZ",
t->nanoseconds / NS_PER_US);
}
}
void
isc_time_formatshorttimestamp(const isc_time_t *t, char *buf,
unsigned int len) {
......
......@@ -344,6 +344,20 @@ isc_time_formatISO8601Lms(const isc_time_t *t, char *buf, unsigned int len);
*
*/
void
isc_time_formatISO8601Lus(const isc_time_t *t, char *buf, unsigned int len);
/*%<
* Format the time 't' into the buffer 'buf' of length 'len',
* using the ISO8601 format: "yyyy-mm-ddThh:mm:ss.ssssss"
* If the text does not fit in the buffer, the result is indeterminate,
* but is always guaranteed to be null terminated.
*
* Requires:
*\li 'len' > 0
*\li 'buf' points to an array of at least len chars
*
*/
void
isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len);
/*%<
......@@ -372,6 +386,20 @@ isc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len);
*
*/
void
isc_time_formatISO8601us(const isc_time_t *t, char *buf, unsigned int len);
/*%<
* Format the time 't' into the buffer 'buf' of length 'len',
* using the ISO8601 format: "yyyy-mm-ddThh:mm:ss.ssssssZ"
* If the text does not fit in the buffer, the result is indeterminate,
* but is always guaranteed to be null terminated.
*
* Requires:
*\li 'len' > 0
*\li 'buf' points to an array of at least len chars
*
*/
void
isc_time_formatshorttimestamp(const isc_time_t *t, char *buf, unsigned int len);
/*%<
......
......@@ -667,7 +667,11 @@ isc_thread_setname
isc_time_add
isc_time_compare
isc_time_formatISO8601
isc_time_formatISO8601L
isc_time_formatISO8601Lms
isc_time_formatISO8601Lus
isc_time_formatISO8601ms
isc_time_formatISO8601us
isc_time_formathttptimestamp
isc_time_formatshorttimestamp
isc_time_formattimestamp
......
......@@ -403,6 +403,35 @@ isc_time_formatISO8601Lms(const isc_time_t *t, char *buf, unsigned int len) {
}
}
void
isc_time_formatISO8601Lus(const isc_time_t *t, char *buf, unsigned int len) {
SYSTEMTIME st;
char DateBuf[50];
char TimeBuf[50];
/* strtime() format: "%Y-%m-%dT%H:%M:%S.SSSSSS" */
REQUIRE(t != NULL);
REQUIRE(buf != NULL);
REQUIRE(len > 0);
if (FileTimeToSystemTime(&t->absolute, &st)) {
ULARGE_INTEGER i;
GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, "yyyy-MM-dd",
DateBuf, 50);
GetTimeFormat(LOCALE_USER_DEFAULT,
TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &st,
"hh':'mm':'ss", TimeBuf, 50);
i.LowPart = t->absolute.dwLowDateTime;
i.HighPart = t->absolute.dwHighDateTime;
snprintf(buf, len, "%sT%s.%06u", DateBuf, TimeBuf,
(uint32_t)(i.QuadPart % 10000000) / 10);
} else {
buf[0] = 0;
}
}
void
isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) {
SYSTEMTIME st;
......@@ -452,6 +481,35 @@ isc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len) {
}
}
void
isc_time_formatISO8601us(const isc_time_t *t, char *buf, unsigned int len) {
SYSTEMTIME st;
char DateBuf[50];
char TimeBuf[50];
/* strtime() format: "%Y-%m-%dT%H:%M:%S.SSSSSSZ" */
REQUIRE(t != NULL);
REQUIRE(buf != NULL);
REQUIRE(len > 0);
if (FileTimeToSystemTime(&t->absolute, &st)) {
ULARGE_INTEGER i;
GetDateFormat(LOCALE_NEUTRAL, 0, &st, "yyyy-MM-dd", DateBuf,
50);
GetTimeFormat(LOCALE_NEUTRAL,
TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &st,
"hh':'mm':'ss", TimeBuf, 50);
i.LowPart = t->absolute.dwLowDateTime;
i.HighPart = t->absolute.dwHighDateTime;
snprintf(buf, len, "%sT%s.%06uZ", DateBuf, TimeBuf,
(uint32_t)(i.QuadPart % 10000000) / 10);
} else {
buf[0] = 0;
}
}
void
isc_time_formatshorttimestamp(const isc_time_t *t, char *buf,
unsigned int len) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment