/* predicate: returns TRUE if the nanoseconds are in nominal range */
#define timespec_isnormal(x) \
- ((u_long)(x)->tv_nsec < 1000000000)
+ ((x)->tv_nsec >= 0 && (x)->tv_nsec < 1000000000)
/* predicate: returns TRUE if the nanoseconds are out-of-bounds */
#define timespec_isdenormal(x) (!timespec_isnormal(x))
--- /dev/null
+/*
+ * timetoa.h -- time_t related string formatting
+ *
+ * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project.
+ * The contents of 'html/copyright.html' apply.
+ *
+ * Printing a 'time_t' has some portability pitfalls, due to it's opaque
+ * base type. The only requirement imposed by the standard is that it
+ * must be a numeric type. For all practical purposes it's a signed int,
+ * and 32 bits are common.
+ *
+ * Since the UN*X time epoch will cause a signed integer overflow for
+ * 32-bit signed int values in the year 2038, implementations slowly
+ * move to 64bit base types for time_t, even in 32-bit environments. In
+ * such an environment sizeof(time_t) could be bigger than sizeof(long)
+ * and the commonly used idiom of casting to long leads to truncation.
+ *
+ * As the printf() family has no standardised type specifier for time_t,
+ * guessing the right output format specifier is a bit troublesome and
+ * best done with the help of the preprocessor and "config.h".
+ */
+#ifndef TIMETOA_H
+#define TIMETOA_H
+
+#include "config.h"
+#include "ntp_fp.h"
+#include "ntp_stdlib.h"
+#include "ntp_unixtime.h"
+
+/*
+ * Given the size of time_t, guess what can be used as an unsigned value
+ * to hold a time_t and the printf() format specifcation.
+ *
+ * These should be used with the string constant concatenation feature
+ * of the compiler like this:
+ *
+ * printf("a time stamp: %" TIME_FORMAT " and more\n", a_time_t_value);
+ *
+ * It's not exactly nice, but there's not much leeway once we want to
+ * use the printf() family on time_t values.
+ */
+
+#if SIZEOF_TIME_T <= SIZEOF_INT
+
+typedef unsigned int u_time;
+#define TIME_FORMAT "d"
+#define UTIME_FORMAT "u"
+
+#elif SIZEOF_TIME_T <= SIZEOF_LONG
+
+typedef unsigned long u_time;
+#define TIME_FORMAT "ld"
+#define UTIME_FORMAT "lu"
+
+#elif defined(SIZEOF_LONG_LONG) && SIZEOF_TIME_T <= SIZEOF_LONG_LONG
+
+typedef unsigned long long u_time;
+#define TIME_FORMAT "lld"
+#define UTIME_FORMAT "llu"
+
+#else
+#include "GRONK: what size has a time_t here?"
+#endif
+
+/* general fractional time stamp formatting.
+ *
+ * secs - integral seconds of time stamp
+ * frac - fractional units
+ * prec - log10 of units per second (3=miliseconds, 6=microseconds,..)
+ * or in other words: the number decimal digits required.
+ * If prec is < 0, abs(prec) is taken and for the precision
+ * and 'secs' is treated as an unsigned value.
+ *
+ * abs(prec) must be in [1 .. 9], or only the seconds are formatted.
+ *
+ * The function will eventually normalise the fraction and adjust the
+ * seconds accordingly.
+ *
+ * This function uses the string buffer library for the return value,
+ * so do not keep the resulting pointers around.
+ */
+extern const char *
+format_time_fraction(time_t secs, long frac, int prec);
+
+#endif /* !defined(TIMETOA_H) */
* use like: int timeval_isnormal(const struct timeval *x)
*/
#define timeval_isnormal(x) \
- ((u_long)(x)->tv_usec < 1000000)
+ ((x)->tv_usec >= 0 && (x)->tv_usec < 1000000)
/*
* predicate: returns TRUE if the microseconds are out-of-bounds
strdup.c \
syssignal.c \
timespecops.c \
+ timetoa.c \
timevalops.c \
tsftomsu.c \
tstotv.c \
--- /dev/null
+/*
+ * timetoa.c -- time_t related string formatting
+ *
+ * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project.
+ * The contents of 'html/copyright.html' apply.
+ *
+ * Printing a 'time_t' has a lot of portability pitfalls, due to it's
+ * opaque base type. The only requirement imposed by the standard is
+ * that it must be a numeric type. For all practical purposes it's a
+ * signed int, and 32 bits are common.
+ *
+ * Since the UN*X time epoch will cause a signed integer overflow for
+ * 32-bit signed int in the year 2038, implementations slowly move to
+ * 64bit base types for time_t, even in 32-bit environments.
+ *
+ * As the printf() family has no standardised type specifier for time_t,
+ * guessing the right output format specifier is a bit troublesome and
+ * best done with the help of the preprocessor and "config.h".
+ */
+
+#include "config.h"
+
+#include "timetoa.h"
+#include "lib_strbuf.h"
+#include <stdio.h>
+
+/*
+ * Formatting to string needs at max 40 bytes (even with 64 bit time_t),
+ * so we check LIB_BUFLENGTH is big enough for our pupose.
+ */
+#if LIB_BUFLENGTH < 40
+# include "GRONK: LIB_BUFLENGTH is not sufficient"
+#endif
+
+/*
+ * general fractional timestamp formatting
+ *
+ * Many pieces of ntpd require a machine with two's complement
+ * representation of signed integers, so we don't go through the whole
+ * rigamarole of creating fully portable code here. But we have to stay
+ * away from signed integer overflow, as this might cause trouble even
+ * with two's complement representation.
+ */
+const char *
+format_time_fraction(
+ time_t secs,
+ long frac,
+ int prec
+ )
+{
+ static const long limit[10] = {
+ 1,
+ 10, 100, 1000,
+ 10000, 100000, 1000000,
+ 10000000, 100000000, 1000000000
+ };
+
+ char * cp;
+ u_time ttmp; /* unsigned storage for seconds */
+ int notneg; /* flag for non-negative value */
+ const char * fmt;
+
+ LIB_GETBUF(cp);
+ ttmp = (u_time)secs;
+ fmt = "-%" UTIME_FORMAT ".%0*ld";
+
+ /* check if we need signed or unsigned mode */
+ notneg = (prec < 0);
+ prec = abs(prec);
+ if (prec <= 0 || prec > 9) {
+ if (notneg)
+ fmt = "%" UTIME_FORMAT;
+ else
+ fmt = "%" TIME_FORMAT;
+ snprintf(cp, LIB_BUFLENGTH, fmt, secs);
+ return (cp);
+ }
+
+ /*
+ * Since conversion to string uses lots of divisions anyway,
+ * there's no big extra penalty for normalisation. We do it for
+ * consistency.
+ */
+ if (frac < 0 || frac >= limit[prec]) {
+ ldiv_t qr;
+ qr = ldiv(frac, limit[prec]);
+ if (qr.rem < 0) {
+ qr.quot--;
+ qr.rem += limit[prec];
+ }
+ ttmp += (time_t)qr.quot;
+ frac = qr.rem;
+ }
+
+ /*
+ * Get the absolute value of the time stamp.
+ */
+ notneg = notneg || ((time_t)ttmp >= 0);
+ if (notneg == 0) {
+ ttmp = ~ttmp;
+ if (frac != 0)
+ frac = limit[prec] - frac;
+ else
+ ttmp += 1;
+ } else
+ fmt++; /* skip sign char in format string */
+
+ /* finally format the data and return the result */
+ snprintf(cp, LIB_BUFLENGTH, fmt, ttmp, prec, frac);
+
+ return (cp);
+}
#include <config.h>
#include <math.h>
-#include "lib_strbuf.h"
-#include "ntp_calendar.h"
-
#include "timevalops.h"
-/* formatting to string needs at max 29 bytes (even with 64 bit time_t),
- * so we check LIB_BUFLENGTH is big enough for our pupose.
- */
-#if LIB_BUFLENGTH < 29
-#error LIB_BUFLENGTH not big enough
-#endif
+#include "timetoa.h"
+#include "ntp_calendar.h"
/* make sure we have the right definition for MICROSECONDS */
#undef MICROSECONDS
# define MYTVUTOF(tvu, tsf) TVUTOTSF(tvu, tsf)
#endif
-/* using snprintf is troublesome with time_t. Try to resolve it. */
-#if SIZEOF_TIME_T <= SIZEOF_INT
-typedef unsigned int u_time;
-#define TIMEFMT ""
-#elif SIZEOF_TIME_T <= SIZEOF_LONG
-typedef unsigned long u_time;
-#define TIMEFMT "l"
-#elif defined(SIZEOF_LONG_LONG) && SIZEOF_TIME_T <= SIZEOF_LONG_LONG
-typedef unsigned long long u_time;
-#define TIMEFMT "ll"
-#else
-#include "GRONK: what size has a time_t here?"
-#endif
-
/* copy and normalise. Used often enough to warrant a macro. */
#define COPYNORM(dst, src) \
do { \
* to do first partial normalisation. The normalisation loops
* following will do the remaining cleanup. Since the size of
* tv_usec has a peculiar definition by the standard the range
- * check is coded manualla.
+ * check is coded manually.
*/
if (x->tv_usec < -3l * MICROSECONDS ||
x->tv_usec > 3l * MICROSECONDS ) {
const struct timeval *x
)
{
- /* see timespecops.c for rationale -- this needs refactoring
- *
- * Even with 64 bit time_t, 32 chars will suffice. Hopefully,
- * LIB_BUFLENGTH is big enough; the current definiton checks
- * this by the preprocessor just at the top of this file. */
- static const char *fmt = "-%" TIMEFMT "u.%06lu";
-
- struct timeval v;
- char * cp;
- int notneg;
- u_time itmp;
- u_long ftmp;
-
- /* normalise and get absolute value into unsigned values. Since
- * the negation of TIME_T_MIN (if it existed) is implementation
- * defined, we try to avoid it. */
- COPYNORM(&v, x);
- notneg = v.tv_sec >= 0;
- if (notneg != 0) {
- itmp = (u_time)v.tv_sec;
- ftmp = (u_long)v.tv_usec;
- } else if (v.tv_usec != 0) {
- itmp = (u_time)-(v.tv_sec + 1);
- ftmp = (u_long)(MICROSECONDS - v.tv_usec);
- } else {
- itmp = ((u_time) -(v.tv_sec + 1)) + 1;
- ftmp = 0;
- }
-
- /* get buffer and format data */
- LIB_GETBUF(cp);
- snprintf(cp, LIB_BUFLENGTH, fmt + notneg, itmp, ftmp);
-
- return cp;
+ return format_time_fraction(x->tv_sec, x->tv_usec, 6);
}
void
ssl_init.cpp \
statestr.cpp \
strtolfp.cpp \
+ timestructs.cpp \
tspecops.cpp \
tvalops.cpp \
tsftomsu.cpp \
--- /dev/null
+/*
+ * timestructs.cpp -- test bed adaptors for time structs.
+ *
+ * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project.
+ * The contents of 'html/copyright.html' apply.
+ */
+#include "libntptest.h"
+#include "timestructs.h"
+
+extern "C" {
+#include "ntp_unixtime.h"
+#include "timetoa.h"
+#include "ntp_fp.h"
+
+#include "timevalops.h"
+}
+
+std::ostream&
+operator << (std::ostream& os, const timeStruct::l_fp_wrap& val)
+{
+ // raw data formatting
+ os << "0x" << std::hex << val.V.l_ui << ':'
+ << std::setfill('0') << std::setw(8) << val.V.l_uf
+ << std::dec;
+ // human-readable format
+ os << '[' << dolfptoa(val.V.l_ui, val.V.l_uf, 0, 10, 0) << ']';
+ return os;
+}
+
+std::ostream&
+operator << (std::ostream& os, const timeStruct::timeval_wrap& val)
+{
+ // raw data formatting
+ os << val.V.tv_sec << ':' << val.V.tv_usec;
+ // human-readable format
+ os << '['
+ << format_time_fraction(val.V.tv_sec, val.V.tv_usec, 6)
+ << ']';
+ return os;
+}
+
+std::ostream&
+operator << (std::ostream& os, const timeStruct::timespec_wrap& val)
+{
+ // raw data formatting
+ os << val.V.tv_sec << ':' << val.V.tv_nsec;
+ // human-readable format
+ os << '['
+ << format_time_fraction(val.V.tv_sec, val.V.tv_nsec, 9)
+ << ']';
+ return os;
+}
+
+namespace timeStruct {
+
+// Implementation of the l_fp closeness predicate
+
+AssertFpClose::AssertFpClose(
+ u_int32 hi,
+ u_int32 lo
+ )
+{
+ limit.l_ui = hi;
+ limit.l_uf = lo;
+}
+
+::testing::AssertionResult
+AssertFpClose::operator()(
+ const char* m_expr,
+ const char* n_expr,
+ const l_fp & m,
+ const l_fp & n
+ )
+{
+ l_fp diff;
+
+ if (L_ISGEQ(&m, &n)) {
+ diff = m;
+ L_SUB(&diff, &n);
+ } else {
+ diff = n;
+ L_SUB(&diff, &m);
+ }
+ if (L_ISGEQ(&limit, &diff))
+ return ::testing::AssertionSuccess();
+
+ return ::testing::AssertionFailure()
+ << m_expr << " which is " << l_fp_wrap(m)
+ << "\nand\n"
+ << n_expr << " which is " << l_fp_wrap(n)
+ << "\nare not close; diff=" << l_fp_wrap(diff);
+}
+
+// Implementation of the timeval closeness predicate
+
+AssertTimevalClose::AssertTimevalClose(
+ time_t hi,
+ int32 lo
+ )
+{
+ limit.tv_sec = hi;
+ limit.tv_usec = lo;
+}
+
+::testing::AssertionResult
+AssertTimevalClose::operator()(
+ const char* m_expr,
+ const char* n_expr,
+ const struct timeval & m,
+ const struct timeval & n
+ )
+{
+ struct timeval diff;
+
+ timeval_sub(&diff, &m, &n);
+ timeval_abs(&diff, &diff);
+ if (timeval_cmp(&limit, &diff) >= 0)
+ return ::testing::AssertionSuccess();
+
+ return ::testing::AssertionFailure()
+ << m_expr << " which is " << timeval_wrap(m)
+ << "\nand\n"
+ << n_expr << " which is " << timeval_wrap(n)
+ << "\nare not close; diff=" << timeval_wrap(diff);
+}
+
+} // namespace timeStruct
--- /dev/null
+/*
+ * timestructs.h -- test bed adaptors for time structs.
+ *
+ * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project.
+ * The contents of 'html/copyright.html' apply.
+ *
+ * Some wrapper classes and a closeness predicate that are used to
+ * bridge the gap between the goggletest framework and the structs used
+ * for representing time stamps (l_fp, struct timeval, struct timespec).
+ *
+ * Some ostream conversion operators are provided to give diagnostic
+ * output on errors. The normal string conversion functions will give
+ * HRVs (human readable values) but we might also be interested in the
+ * machine representation for diagnostic purposes.
+ */
+#ifndef TIMESTRUCTS_H
+#define TIMESTRUCTS_H
+
+extern "C" {
+#include "ntp_types.h"
+#include "ntp_fp.h"
+}
+
+namespace timeStruct {
+
+// wrap a l_fp struct with common operations
+class l_fp_wrap {
+ public:
+ l_fp V;
+
+ l_fp_wrap()
+ { ZERO(V); }
+ l_fp_wrap(u_int32 hi, u_int32 lo)
+ { V.l_ui = hi; V.l_uf = lo; }
+ l_fp_wrap(const l_fp &rhs)
+ { V = rhs; }
+ bool operator == (const l_fp_wrap& rhs) const
+ { return L_ISEQU(&V, &rhs.V); }
+ operator l_fp* ()
+ { return &V; }
+ operator l_fp& ()
+ { return V; }
+ l_fp_wrap & operator = (const l_fp_wrap& rhs)
+ { V = rhs.V; return *this; }
+ l_fp_wrap& operator = (const l_fp& rhs)
+ { V = rhs; return *this; }
+ };
+
+// wrap a 'struct timeval' with common operations
+class timeval_wrap {
+public:
+ struct timeval V;
+
+ timeval_wrap()
+ { ZERO(V); }
+ timeval_wrap(time_t hi, long lo)
+ { V.tv_sec = hi; V.tv_usec = lo; }
+ timeval_wrap(const struct timeval & rhs)
+ { V = rhs; }
+ bool operator == (const timeval_wrap& rhs) const
+ { return V.tv_sec == rhs.V.tv_sec &&
+ V.tv_usec == rhs.V.tv_usec ; }
+ bool valid() const
+ { return V.tv_usec >= 0 && V.tv_usec < 1000000; }
+ operator struct timeval* ()
+ { return &V; }
+ operator struct timeval& ()
+ { return V; }
+ timeval_wrap& operator = (const timeval_wrap& rhs)
+ { V = rhs.V; return *this; }
+ timeval_wrap& operator = (const struct timeval& rhs)
+ { V = rhs; return *this; }
+};
+
+// wrap a 'struct timespec' with common operations
+class timespec_wrap {
+public:
+ struct timespec V;
+
+ timespec_wrap()
+ { ZERO(V); }
+ timespec_wrap(time_t hi, long lo)
+ { V.tv_sec = hi; V.tv_nsec = lo; }
+ timespec_wrap(const struct timespec & rhs)
+ { V = rhs; }
+ bool operator == (const timespec_wrap& rhs) const
+ { return V.tv_sec == rhs.V.tv_sec &&
+ V.tv_nsec == rhs.V.tv_nsec ; }
+ bool valid() const
+ { return V.tv_nsec >= 0 && V.tv_nsec < 1000000000; }
+ operator struct timespec* ()
+ { return &V; }
+ operator struct timespec& ()
+ { return V; }
+ timespec_wrap& operator = (const timespec_wrap& rhs)
+ { V = rhs.V; return *this; }
+ timespec_wrap& operator = (const struct timespec& rhs)
+ { V = rhs; return *this; }
+};
+
+// l_fp closeness testing predicate
+//
+// This predicate is used for the closeness ('near') testing of l_fp
+// values. Once constructed with a limit, it can be used to check the
+// absolute difference of two l_fp structs against that limit; if the
+// difference is less or equal to this limit, the test passes.
+class AssertFpClose {
+private:
+ l_fp limit;
+
+public:
+ AssertFpClose(u_int32 hi, u_int32 lo);
+
+ ::testing::AssertionResult
+ operator()(const char* m_expr, const char* n_expr,
+ const l_fp & m, const l_fp & n);
+};
+
+
+// timeval closeness testing predicate
+//
+// CAVEAT: This class uses the timevalops functions
+// - timeval_sub
+// - timeval_abs
+// - timeval_cmp
+//
+// This creates a dependency loop of sorts. The loop is defused by the
+// fact that these basic operations can be tested by exact value tests,
+// so once the basic timeval operations passed it's safe to use this
+// predicate.
+class AssertTimevalClose {
+private:
+ struct timeval limit;
+
+public:
+ // note: (hi,lo) should be a positive normalised timeval;
+ // the constructor does not normalise the values!
+ AssertTimevalClose(time_t hi, int32 lo);
+
+ ::testing::AssertionResult
+ operator()(const char* m_expr, const char* n_expr,
+ const struct timeval & m, const struct timeval & n);
+};
+
+
+} // namespace timeStruct
+
+// since googletest wants to string format items, we declare the
+// necessary operators. Since all adaptors have only public members
+// there is need for friend declarations anywhere.
+
+extern std::ostream& operator << (std::ostream& os,
+ const timeStruct::l_fp_wrap& val);
+extern std::ostream& operator << (std::ostream& os,
+ const timeStruct::timeval_wrap& val);
+extern std::ostream& operator << (std::ostream& os,
+ const timeStruct::timespec_wrap& val);
+
+#endif // TIMESTRUCTS_H
#include "libntptest.h"
+#include "timestructs.h"
extern "C" {
#include <math.h>
#include <string>
#include <sstream>
+using namespace timeStruct;
+
class timevalTest : public libntptest {
protected:
+
+ static u_int32 my_tick_to_tsf(u_int32 ticks);
+ static u_int32 my_tsf_to_tick(u_int32 tsf);
+
static const long MICROSECONDS;
// that's it...
struct lfpfracdata {
static const lfpfracdata fdata[];
};
+u_int32
+timevalTest::my_tick_to_tsf(
+ u_int32 ticks
+ )
+{
+ // convert microseconds to l_fp fractional units, using double
+ // precision float calculations or, if available, 64bit integer
+ // arithmetic. This should give the precise fraction, rounded to
+ // the nearest representation.
+#if SIZEOF_LONG >= 8
+ return (u_int32)((((u_long)ticks << 32) + 500000) / 1000000);
+#else
+ return (u_int32)floor((double)ticks * 4294.967296 + 0.5);
+#endif
+ // And before you ask: if ticks >= 1000000, the result is
+ // truncated nonsense, so don't use it out-of-bounds.
+}
+
+u_int32
+timevalTest::my_tsf_to_tick(
+ u_int32 tsf
+ )
+{
+ // Inverse operation: converts fraction to microseconds.
+#if SIZEOF_LONG >= 8
+ return (u_int32)(((u_long)tsf * 1000000 + 0x80000000) >> 32);
+#else
+ return (u_int32)floor((double)ticks / 4294.967296 + 0.5);
+#endif
+ // Beware: The result might be 10^6 due to rounding!
+}
+
+
const long timevalTest::MICROSECONDS = 1000000;
const timevalTest::lfpfracdata timevalTest::fdata [] = {
{ 0, 0x00000000 }, { 7478, 0x01ea1405 },
};
-class TVAL {
-public:
- struct timeval V;
-
- TVAL()
- { ZERO(V); }
- TVAL(time_t hi, long lo)
- { V.tv_sec = hi; V.tv_usec = lo; }
- bool operator == (const TVAL& rhs) const
- { return timeval_cmp(&V, &rhs.V) == 0; }
- bool valid() const
- { return timeval_isnormal(&V); }
- operator struct timeval* ()
- { return &V; }
- operator struct timeval& ()
- { return V; }
- TVAL& operator = (const TVAL& rhs)
- { V = rhs.V; return *this; }
- TVAL& operator = (const struct timeval& rhs)
- { V = rhs; return *this; }
-};
-
-std::ostream&
-operator << (std::ostream& os, const TVAL& val)
-{
- os << timeval_tostr(&val.V);
- return os;
-}
+// and the global predicate instances we're using here
+static AssertFpClose FpClose(0, 1);
-class LFP {
-public:
- l_fp V;
-
- LFP()
- { ZERO(V); }
- LFP(u_int32 hi, u_int32 lo)
- { V.l_ui = hi; V.l_uf = lo; }
- bool operator == (const LFP& rhs) const
- { return L_ISEQU(&V, &rhs.V); }
- operator l_fp* ()
- { return &V; }
- operator l_fp& ()
- { return V; }
- LFP& operator = (const LFP& rhs)
- { V = rhs.V; return *this; }
- LFP& operator = (const l_fp& rhs)
- { V = rhs; return *this; }
-};
-
-static std::ostream&
-operator << (std::ostream& os, const LFP& val)
-{
- os << ulfptoa(&val.V, 10);
- return os;
-}
-
+static AssertTimevalClose TimevalClose(0, 1);
// ---------------------------------------------------------------------
// test support stuff
TEST_F(timevalTest, Normalise) {
for (long ns = -2000000000; ns <= 2000000000; ns += 10000000) {
- TVAL x(0, ns);
+ timeval_wrap x(0, ns);
timeval_norm(x);
ASSERT_TRUE(x.valid());
TEST_F(timevalTest, SignNoFrac) {
// sign test, no fraction
for (int i = -4; i <= 4; ++i) {
- TVAL a(i, 0);
- int E = (i > 0) - (i < 0);
- int r = timeval_test(a);
+ timeval_wrap a(i, 0);
+ int E = (i > 0) - (i < 0);
+ int r = timeval_test(a);
ASSERT_EQ(E, r);
}
TEST_F(timevalTest, SignWithFrac) {
// sign test, with fraction
for (int i = -4; i <= 4; ++i) {
- TVAL a(i, 10);
- int E = (i >= 0) - (i < 0);
- int r = timeval_test(a);
+ timeval_wrap a(i, 10);
+ int E = (i >= 0) - (i < 0);
+ int r = timeval_test(a);
ASSERT_EQ(E, r);
}
// fractions are equal
for (int i = -4; i <= 4; ++i)
for (int j = -4; j <= 4; ++j) {
- TVAL a(i, 200);
- TVAL b(j, 200);
- int E = (i > j) - (i < j);
- int r = timeval_cmp(a, b);
+ timeval_wrap a(i, 200);
+ timeval_wrap b(j, 200);
+ int E = (i > j) - (i < j);
+ int r = timeval_cmp(a, b);
ASSERT_EQ(E, r);
}
// fraction a bigger fraction b
for (int i = -4; i <= 4; ++i)
for (int j = -4; j <= 4; ++j) {
- TVAL a( i , 999800);
- TVAL b( j , 200);
- int E = (i >= j) - (i < j);
- int r = timeval_cmp(a, b);
+ timeval_wrap a( i , 999800);
+ timeval_wrap b( j , 200);
+ int E = (i >= j) - (i < j);
+ int r = timeval_cmp(a, b);
ASSERT_EQ(E, r);
}
// fraction a less fraction b
for (int i = -4; i <= 4; ++i)
for (int j = -4; j <= 4; ++j) {
- TVAL a(i, 200);
- TVAL b(j, 999800);
- int E = (i > j) - (i <= j);
- int r = timeval_cmp(a, b);
+ timeval_wrap a(i, 200);
+ timeval_wrap b(j, 999800);
+ int E = (i > j) - (i <= j);
+ int r = timeval_cmp(a, b);
ASSERT_EQ(E, r);
}
TEST_F(timevalTest, AddFullNorm) {
for (int i = -4; i <= 4; ++i)
for (int j = -4; j <= 4; ++j) {
- TVAL a(i, 200);
- TVAL b(j, 400);
- TVAL E(i + j, 200 + 400);
- TVAL c;
+ timeval_wrap a(i, 200);
+ timeval_wrap b(j, 400);
+ timeval_wrap E(i + j, 200 + 400);
+ timeval_wrap c;
timeval_add(c, a, b);
ASSERT_EQ(E, c);
TEST_F(timevalTest, AddFullOflow1) {
for (int i = -4; i <= 4; ++i)
for (int j = -4; j <= 4; ++j) {
- TVAL a(i, 200);
- TVAL b(j, 999900);
- TVAL E(i + j + 1, 100);
- TVAL c;
+ timeval_wrap a(i, 200);
+ timeval_wrap b(j, 999900);
+ timeval_wrap E(i + j + 1, 100);
+ timeval_wrap c;
timeval_add(c, a, b);
ASSERT_EQ(E, c);
}
TEST_F(timevalTest, AddUsecNorm) {
for (int i = -4; i <= 4; ++i) {
- TVAL a(i, 200);
- TVAL E(i, 600);
- TVAL c;
+ timeval_wrap a(i, 200);
+ timeval_wrap E(i, 600);
+ timeval_wrap c;
timeval_addus(c, a, 400);
ASSERT_EQ(E, c);
TEST_F(timevalTest, AddUsecOflow1) {
for (int i = -4; i <= 4; ++i) {
- TVAL a(i, 200);
- TVAL E(i + 1, 100);
- TVAL c;
+ timeval_wrap a(i, 200);
+ timeval_wrap E(i + 1, 100);
+ timeval_wrap c;
timeval_addus(c, a, MICROSECONDS - 100);
ASSERT_EQ(E, c);
TEST_F(timevalTest, SubFullNorm) {
for (int i = -4; i <= 4; ++i)
for (int j = -4; j <= 4; ++j) {
- TVAL a(i, 600);
- TVAL b(j, 400);
- TVAL E(i - j, 600 - 400);
- TVAL c;
+ timeval_wrap a(i, 600);
+ timeval_wrap b(j, 400);
+ timeval_wrap E(i - j, 600 - 400);
+ timeval_wrap c;
timeval_sub(c, a, b);
ASSERT_EQ(E, c);
TEST_F(timevalTest, SubFullOflow) {
for (int i = -4; i <= 4; ++i)
for (int j = -4; j <= 4; ++j) {
- TVAL a(i, 100);
- TVAL b(j, 999900);
- TVAL E(i - j - 1, 200);
- TVAL c;
+ timeval_wrap a(i, 100);
+ timeval_wrap b(j, 999900);
+ timeval_wrap E(i - j - 1, 200);
+ timeval_wrap c;
timeval_sub(c, a, b);
ASSERT_EQ(E, c);
TEST_F(timevalTest, SubUsecNorm) {
for (int i = -4; i <= 4; ++i) {
- TVAL a(i, 600);
- TVAL E(i, 200);
- TVAL c;
+ timeval_wrap a(i, 600);
+ timeval_wrap E(i, 200);
+ timeval_wrap c;
timeval_subus(c, a, 600 - 200);
ASSERT_EQ(E, c);
TEST_F(timevalTest, SubUsecOflow) {
for (int i = -4; i <= 4; ++i) {
- TVAL a(i, 100);
- TVAL E(i - 1, 200);
- TVAL c;
+ timeval_wrap a(i, 100);
+ timeval_wrap E(i - 1, 200);
+ timeval_wrap c;
timeval_subus(c, a, MICROSECONDS - 100);
ASSERT_EQ(E, c);
// test negation
TEST_F(timevalTest, Neg) {
for (int i = -4; i <= 4; ++i) {
- TVAL a(i, 100);
- TVAL b;
- TVAL c;
+ timeval_wrap a(i, 100);
+ timeval_wrap b;
+ timeval_wrap c;
+
timeval_neg(b, a);
timeval_add(c, a, b);
ASSERT_EQ(0, timeval_test(c));
// test abs value
TEST_F(timevalTest, AbsNoFrac) {
for (int i = -4; i <= 4; ++i) {
- TVAL a(i, 0);
- TVAL b;
- int c;
+ timeval_wrap a(i, 0);
+ timeval_wrap b;
+ int c;
c = timeval_abs(b, a);
ASSERT_EQ((i < 0), c);
TEST_F(timevalTest, AbsWithFrac) {
for (int i = -4; i <= 4; ++i) {
- TVAL a(i, 100);
- TVAL b;
- int c;
+ timeval_wrap a(i, 100);
+ timeval_wrap b;
+ int c;
c = timeval_abs(b, a);
ASSERT_EQ((i < 0), c);
}
// conversion to l_fp
+TEST_F(timevalTest, ToLFPbittest) {
+ for (u_int32 i = 0; i < 1000000; i++) {
+ timeval_wrap a(1, i);
+ l_fp_wrap E(1, my_tick_to_tsf(i));
+ l_fp_wrap r;
+
+ timeval_reltolfp(r, a);
+ ASSERT_PRED_FORMAT2(FpClose, E, r);
+ }
+}
+
TEST_F(timevalTest, ToLFPrelPos) {
for (int i = 0; i < COUNTOF(fdata); i++) {
- TVAL a(1, fdata[i].usec);
- LFP E(1, fdata[i].frac);
- LFP r;
- double Ef;
- double rf;
+ timeval_wrap a(1, fdata[i].usec);
+ l_fp_wrap E(1, fdata[i].frac);
+ l_fp_wrap r;
timeval_reltolfp(r, a);
- LFPTOD(&E.V, Ef);
- LFPTOD(&r.V, rf);
- ASSERT_NEAR(Ef, rf, 1. / MICROSECONDS);
+ ASSERT_PRED_FORMAT2(FpClose, E, r);
}
}
TEST_F(timevalTest, ToLFPrelNeg) {
for (int i = 0; i < COUNTOF(fdata); i++) {
- TVAL a(-1, fdata[i].usec);
- LFP E(~0, fdata[i].frac);
- LFP r;
- double Ef;
- double rf;
+ timeval_wrap a(-1, fdata[i].usec);
+ l_fp_wrap E(~0, fdata[i].frac);
+ l_fp_wrap r;
timeval_reltolfp(r, a);
- LFPTOD(&E.V, Ef);
- LFPTOD(&r.V, rf);
- ASSERT_NEAR(Ef, rf, 1. / MICROSECONDS);
+ ASSERT_PRED_FORMAT2(FpClose, E, r);
}
}
TEST_F(timevalTest, ToLFPabs) {
for (int i = 0; i < COUNTOF(fdata); i++) {
- TVAL a(1, fdata[i].usec);
- LFP E(1 + JAN_1970, fdata[i].frac);
- LFP r;
- double Ef;
- double rf;
+ timeval_wrap a(1, fdata[i].usec);
+ l_fp_wrap E(1 + JAN_1970, fdata[i].frac);
+ l_fp_wrap r;
timeval_abstolfp(r, a);
- LFPTOD(&E.V, Ef);
- LFPTOD(&r.V, rf);
- ASSERT_NEAR(Ef, rf, 1. / MICROSECONDS);
+ ASSERT_PRED_FORMAT2(FpClose, E, r);
+ }
+}
+
+// conversion from l_fp
+TEST_F(timevalTest, FromLFPbittest) {
+ // Not *exactly* a bittest, because 2**32 tests would take a
+ // really long time even on very fast machines! So we do test
+ // every 1000 fractional units.
+ for (u_int32 tsf = 0; tsf < ~u_int32(1000); tsf += 1000) {
+ timeval_wrap E(1, my_tsf_to_tick(tsf));
+ l_fp_wrap a(1, tsf);
+ timeval_wrap r;
+
+ timeval_relfromlfp(r, a);
+
+ // The conversion might be off by one microsecond when
+ // comparing to calculated value; the table-driven
+ // conversion does not use all bits from the FP fraction
+ // and this truncation will affect the rounding.
+ ASSERT_PRED_FORMAT2(TimevalClose, E, r);
+ }
+}
+
+// usec -> frac -> usec roundtrip
+TEST_F(timevalTest, LFProundtrip) {
+ for (u_int32 i = 0; i < 1000000; i++) {
+ timeval_wrap E(1, i);
+ l_fp_wrap a;
+ timeval_wrap r;
+
+ timeval_reltolfp(a, E);
+ timeval_relfromlfp(r, a);
+ ASSERT_EQ(E, r);
}
}
TEST_F(timevalTest, ToString) {
static const struct {
- time_t sec;
- long usec;
- const char * repr;
+ time_t sec;
+ long usec;
+ const char * repr;
} data [] = {
{ 0, 0, "0.000000" },
{ 2, 0, "2.000000" },
{-1, 1, "-0.999999" }
};
for (int i = 0; i < COUNTOF(data); ++i) {
- TVAL a(data[i].sec, data[i].usec);
- std::string E(data[i].repr);
- std::string r(timeval_tostr(a));
+ timeval_wrap a(data[i].sec, data[i].usec);
+ std::string E(data[i].repr);
+ std::string r(timeval_tostr(a));
ASSERT_EQ(E, r);
}