|
|
#define _XOPEN_SOURCE 600 |
|
|
|
|
|
#include <stdlib.h> |
|
|
#include <stdio.h> |
|
|
#include <string.h> |
|
|
#include <errno.h> |
|
|
|
|
|
#include "casprintf.h" |
|
|
#include "girstring.h" |
|
|
|
|
|
#include "xmlrpc_config.h" |
|
|
|
|
|
#include "xmlrpc-c/base.h" |
|
|
#include "xmlrpc-c/string_int.h" |
|
|
|
|
|
#include "testtool.h" |
|
|
|
|
|
#include "value_datetime.h" |
|
|
|
|
|
|
|
|
|
|
|
static const char * |
|
|
truncateFracSec(const char * const datestring) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char * buffer; |
|
|
unsigned int i; |
|
|
|
|
|
buffer = strdup(datestring); |
|
|
|
|
|
for (i = 0; i < strlen(buffer); ++i) { |
|
|
if (buffer[i] == '.') |
|
|
buffer[i] = '\0'; |
|
|
} |
|
|
return buffer; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#if XMLRPC_HAVE_TIMEVAL |
|
|
|
|
|
static struct timeval |
|
|
makeTv(time_t const secs, |
|
|
unsigned int const usecs) { |
|
|
|
|
|
struct timeval retval; |
|
|
|
|
|
retval.tv_sec = secs; |
|
|
retval.tv_usec = usecs; |
|
|
|
|
|
return retval; |
|
|
} |
|
|
|
|
|
static bool |
|
|
tvIsEqual(struct timeval const comparand, |
|
|
struct timeval const comparator) { |
|
|
return |
|
|
comparand.tv_sec == comparator.tv_sec && |
|
|
comparand.tv_usec == comparator.tv_usec; |
|
|
} |
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if XMLRPC_HAVE_TIMESPEC |
|
|
|
|
|
static struct timespec |
|
|
makeTs(time_t const secs, |
|
|
unsigned int const usecs) { |
|
|
|
|
|
struct timespec retval; |
|
|
|
|
|
retval.tv_sec = secs; |
|
|
retval.tv_nsec = usecs * 1000; |
|
|
|
|
|
return retval; |
|
|
} |
|
|
|
|
|
static bool |
|
|
tsIsEqual(struct timespec const comparand, |
|
|
struct timespec const comparator) { |
|
|
return |
|
|
comparand.tv_sec == comparator.tv_sec && |
|
|
comparand.tv_nsec == comparator.tv_nsec; |
|
|
} |
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
static const char * |
|
|
make8601(time_t const seconds, |
|
|
unsigned int const usec) { |
|
|
|
|
|
struct tm const tm = *gmtime(&seconds); |
|
|
|
|
|
const char * retval; |
|
|
|
|
|
xmlrpc_asprintf(&retval, "%04u%02u%02uT%02u%02u%02u,%06uZ", |
|
|
1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday, |
|
|
tm.tm_hour, tm.tm_min, tm.tm_sec, |
|
|
usec); |
|
|
|
|
|
return retval; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
test_value_datetime_varytime(const char * const datestring, |
|
|
time_t const datetime, |
|
|
unsigned int const usec) { |
|
|
|
|
|
xmlrpc_value * v; |
|
|
xmlrpc_env env; |
|
|
const char * readBackString; |
|
|
time_t readBackDt; |
|
|
unsigned int readBackUsec; |
|
|
const char * datestringSec; |
|
|
#if XMLRPC_HAVE_TIMEVAL |
|
|
struct timeval const dtTimeval = makeTv(datetime, usec); |
|
|
struct timeval readBackTv; |
|
|
#endif |
|
|
#if XMLRPC_HAVE_TIMESPEC |
|
|
struct timespec const dtTimespec = makeTs(datetime, usec); |
|
|
struct timespec readBackTs; |
|
|
#endif |
|
|
const char * const dt8601 = make8601(datetime, usec); |
|
|
const char * readBack8601; |
|
|
|
|
|
datestringSec = truncateFracSec(datestring); |
|
|
|
|
|
xmlrpc_env_init(&env); |
|
|
|
|
|
|
|
|
v = xmlrpc_datetime_new_str(&env, datestring); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(XMLRPC_TYPE_DATETIME == xmlrpc_value_type(v)); |
|
|
|
|
|
xmlrpc_read_datetime_sec(&env, v, &readBackDt); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(readBackDt == datetime); |
|
|
|
|
|
xmlrpc_read_datetime_usec(&env, v, &readBackDt, &readBackUsec); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(readBackDt == datetime); |
|
|
TEST(readBackUsec == usec); |
|
|
|
|
|
#if XMLRPC_HAVE_TIMEVAL |
|
|
xmlrpc_read_datetime_timeval(&env, v, &readBackTv); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(tvIsEqual(dtTimeval, readBackTv)); |
|
|
#endif |
|
|
|
|
|
#if XMLRPC_HAVE_TIMESPEC |
|
|
xmlrpc_read_datetime_timespec(&env, v, &readBackTs); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(tsIsEqual(dtTimespec, readBackTs)); |
|
|
#endif |
|
|
|
|
|
xmlrpc_read_datetime_8601(&env, v, &readBack8601); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(xmlrpc_streq(dt8601, readBack8601)); |
|
|
strfree(readBack8601); |
|
|
|
|
|
xmlrpc_DECREF(v); |
|
|
|
|
|
|
|
|
v = xmlrpc_datetime_new_sec(&env, datetime); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(XMLRPC_TYPE_DATETIME == xmlrpc_value_type(v)); |
|
|
|
|
|
xmlrpc_read_datetime_str(&env, v, &readBackString); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(streq(readBackString, datestringSec)); |
|
|
strfree(readBackString); |
|
|
|
|
|
xmlrpc_DECREF(v); |
|
|
|
|
|
|
|
|
v = xmlrpc_datetime_new_usec(&env, datetime, usec); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(XMLRPC_TYPE_DATETIME == xmlrpc_value_type(v)); |
|
|
|
|
|
xmlrpc_read_datetime_str(&env, v, &readBackString); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(streq(readBackString, datestring)); |
|
|
strfree(readBackString); |
|
|
|
|
|
xmlrpc_DECREF(v); |
|
|
|
|
|
#if XMLRPC_HAVE_TIMEVAL |
|
|
|
|
|
v = xmlrpc_datetime_new_timeval(&env, dtTimeval); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(XMLRPC_TYPE_DATETIME == xmlrpc_value_type(v)); |
|
|
|
|
|
xmlrpc_read_datetime_str(&env, v, &readBackString); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(streq(readBackString, datestring)); |
|
|
strfree(readBackString); |
|
|
|
|
|
xmlrpc_DECREF(v); |
|
|
#endif |
|
|
|
|
|
#if XMLRPC_HAVE_TIMESPEC |
|
|
|
|
|
v = xmlrpc_datetime_new_timespec(&env, dtTimespec); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(XMLRPC_TYPE_DATETIME == xmlrpc_value_type(v)); |
|
|
|
|
|
xmlrpc_read_datetime_str(&env, v, &readBackString); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(streq(readBackString, datestring)); |
|
|
strfree(readBackString); |
|
|
|
|
|
xmlrpc_DECREF(v); |
|
|
#endif |
|
|
|
|
|
xmlrpc_env_clean(&env); |
|
|
strfree(datestringSec); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
test_value_datetime_not_unix(const char * const datestring) { |
|
|
|
|
|
xmlrpc_value * v; |
|
|
xmlrpc_env env; |
|
|
time_t dt; |
|
|
|
|
|
xmlrpc_env_init(&env); |
|
|
|
|
|
v = xmlrpc_datetime_new_str(&env, datestring); |
|
|
TEST_NO_FAULT(&env); |
|
|
|
|
|
xmlrpc_read_datetime_sec(&env, v, &dt); |
|
|
TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR); |
|
|
|
|
|
xmlrpc_DECREF(v); |
|
|
|
|
|
xmlrpc_env_clean(&env); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
test_value_datetime_str_invalid1(const char * const datestring) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
xmlrpc_value * v; |
|
|
xmlrpc_env env; |
|
|
time_t dt; |
|
|
|
|
|
xmlrpc_env_init(&env); |
|
|
|
|
|
v = xmlrpc_datetime_new_str(&env, datestring); |
|
|
TEST_NO_FAULT(&env); |
|
|
|
|
|
xmlrpc_read_datetime_sec(&env, v, &dt); |
|
|
TEST_FAULT(&env, XMLRPC_PARSE_ERROR); |
|
|
|
|
|
xmlrpc_DECREF(v); |
|
|
|
|
|
xmlrpc_env_clean(&env); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
test_value_datetime_str_invalid2(const char * const datestring) { |
|
|
|
|
|
xmlrpc_env env; |
|
|
|
|
|
xmlrpc_env_init(&env); |
|
|
|
|
|
xmlrpc_datetime_new_str(&env, datestring); |
|
|
TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR); |
|
|
|
|
|
xmlrpc_env_clean(&env); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
test_build_decomp_datetime(void) { |
|
|
|
|
|
const char * datestring = "19980717T14:08:55"; |
|
|
time_t const datetime = 900684535; |
|
|
|
|
|
xmlrpc_env env; |
|
|
xmlrpc_value * v; |
|
|
time_t dt; |
|
|
const char * ds; |
|
|
|
|
|
xmlrpc_env_init(&env); |
|
|
|
|
|
v = xmlrpc_build_value(&env, "t", datetime); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(v != NULL); |
|
|
TEST(xmlrpc_value_type(v) == XMLRPC_TYPE_DATETIME); |
|
|
|
|
|
dt = 0; |
|
|
xmlrpc_read_datetime_sec(&env, v, &dt); |
|
|
TEST(dt == datetime); |
|
|
|
|
|
dt = 0; |
|
|
xmlrpc_decompose_value(&env, v, "t", &dt); |
|
|
xmlrpc_DECREF(v); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(dt == datetime); |
|
|
|
|
|
v = xmlrpc_int_new(&env, 9); |
|
|
TEST_NO_FAULT(&env); |
|
|
xmlrpc_decompose_value(&env, v, "t", &dt); |
|
|
TEST_FAULT(&env, XMLRPC_TYPE_ERROR); |
|
|
xmlrpc_env_clean(&env); |
|
|
xmlrpc_env_init(&env); |
|
|
xmlrpc_decompose_value(&env, v, "8", &ds); |
|
|
TEST_FAULT(&env, XMLRPC_TYPE_ERROR); |
|
|
xmlrpc_env_clean(&env); |
|
|
xmlrpc_env_init(&env); |
|
|
xmlrpc_DECREF(v); |
|
|
|
|
|
v = xmlrpc_build_value(&env, "8", datestring); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(v != NULL); |
|
|
TEST(xmlrpc_value_type(v) == XMLRPC_TYPE_DATETIME); |
|
|
xmlrpc_decompose_value(&env, v, "8", &ds); |
|
|
xmlrpc_DECREF(v); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(streq(ds, datestring)); |
|
|
strfree(ds); |
|
|
|
|
|
xmlrpc_env_clean(&env); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
test_value_datetime_basic(void) { |
|
|
|
|
|
xmlrpc_value * v; |
|
|
xmlrpc_env env; |
|
|
xmlrpc_datetime dt; |
|
|
xmlrpc_datetime readBackDt; |
|
|
|
|
|
xmlrpc_env_init(&env); |
|
|
|
|
|
dt.Y = 2001; |
|
|
dt.M = 12; |
|
|
dt.D = 25; |
|
|
dt.h = 1; |
|
|
dt.m = 2; |
|
|
dt.s = 3; |
|
|
dt.u = 4; |
|
|
|
|
|
v = xmlrpc_datetime_new(&env, dt); |
|
|
|
|
|
xmlrpc_read_datetime(&env, v, &readBackDt); |
|
|
TEST_NO_FAULT(&env); |
|
|
TEST(readBackDt.Y = dt.Y); |
|
|
TEST(readBackDt.M = dt.M); |
|
|
TEST(readBackDt.D = dt.D); |
|
|
TEST(readBackDt.h = dt.h); |
|
|
TEST(readBackDt.m = dt.m); |
|
|
TEST(readBackDt.s = dt.s); |
|
|
TEST(readBackDt.u = dt.u); |
|
|
|
|
|
xmlrpc_env_clean(&env); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
test_value_datetime(void) { |
|
|
|
|
|
const char * datestring = "19980717T14:08:55"; |
|
|
time_t const datetime = 900684535; |
|
|
|
|
|
xmlrpc_env env; |
|
|
|
|
|
printf("\n Running datetime value tests"); |
|
|
|
|
|
xmlrpc_env_init(&env); |
|
|
|
|
|
TEST(streq(xmlrpc_type_name(XMLRPC_TYPE_DATETIME), "DATETIME")); |
|
|
|
|
|
test_value_datetime_basic(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
test_value_datetime_varytime(datestring, datetime, 0); |
|
|
|
|
|
|
|
|
test_value_datetime_varytime("20000301T00:00:00.654321", |
|
|
951868800, 654321); |
|
|
test_value_datetime_varytime("20040229T23:59:59.123000", |
|
|
1078099199, 123000); |
|
|
test_value_datetime_varytime("20000229T23:59:59.000123", |
|
|
951868799, 123); |
|
|
|
|
|
|
|
|
test_value_datetime_varytime("20000229T23:59:59", 951868799, 0); |
|
|
test_value_datetime_varytime("20000301T00:00:00", 951868800, 0); |
|
|
test_value_datetime_varytime("20010228T23:59:59", 983404799, 0); |
|
|
test_value_datetime_varytime("20010301T00:00:00", 983404800, 0); |
|
|
test_value_datetime_varytime("20040229T23:59:59", 1078099199, 0); |
|
|
test_value_datetime_varytime("20040301T00:00:00", 1078099200, 0); |
|
|
|
|
|
|
|
|
test_value_datetime_not_unix("19691231T23:59:59"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
test_value_datetime_str_invalid1("19700101T25:00:00"); |
|
|
test_value_datetime_str_invalid1("19700101T10:61:01"); |
|
|
test_value_datetime_str_invalid1("19700101T10:59:61"); |
|
|
test_value_datetime_str_invalid1("19700001T10:00:00"); |
|
|
test_value_datetime_str_invalid1("19701301T10:00:00"); |
|
|
test_value_datetime_str_invalid1("19700132T10:00:00"); |
|
|
test_value_datetime_str_invalid2("19700132T10:00:00."); |
|
|
test_value_datetime_str_invalid2("19700132T10:00:00,123"); |
|
|
|
|
|
test_build_decomp_datetime(); |
|
|
|
|
|
xmlrpc_env_clean(&env); |
|
|
|
|
|
printf("\n"); |
|
|
printf(" datetime value tests done.\n"); |
|
|
} |
|
|
|