/** * Common code for UTCTime and GeneralizedTime converters that normalizes the * converted time and checks that the input values doesn't change. * * @returns IPRT status code. * @param pCursor The cursor to use when reporting an error. * @param pThis The time to normalize and check. * @param pszType The type name. * @param pszErrorTag The error tag. */ static int rtAsn1Time_NormalizeTime(PRTASN1CURSOR pCursor, PRTASN1TIME pThis, const char *pszType, const char *pszErrorTag) { int rc; if ( pThis->Time.u8Month > 0 && pThis->Time.u8Month <= 12 && pThis->Time.u8Hour < 24 && pThis->Time.u8Minute < 60 && pThis->Time.u8Second < 60) /** @todo what about leap seconds? */ { RTTIME const TimeCopy = pThis->Time; if (RTTimeNormalize(&pThis->Time)) { if ( TimeCopy.u8MonthDay == pThis->Time.u8MonthDay && TimeCopy.u8Month == pThis->Time.u8Month && TimeCopy.i32Year == pThis->Time.i32Year && TimeCopy.u8Hour == pThis->Time.u8Hour && TimeCopy.u8Minute == pThis->Time.u8Minute && TimeCopy.u8Second == pThis->Time.u8Second) return VINF_SUCCESS; rc = RTAsn1CursorSetInfo(pCursor, VERR_ASN1_TIME_NORMALIZE_MISMATCH, "%s: Normalized result not the same as %s: '%.*s'", pszErrorTag, pszType, pThis->Asn1Core.cb, pThis->Asn1Core.uData.pch); } else rc = RTAsn1CursorSetInfo(pCursor, VERR_ASN1_TIME_NORMALIZE_ERROR, "%s: RTTimeNormalize failed on %s: '%.*s'", pszErrorTag, pszType, pThis->Asn1Core.cb, pThis->Asn1Core.uData.pch); } else rc = RTAsn1CursorSetInfo(pCursor, VERR_ASN1_TIME_BAD_NORMALIZE_INPUT, "%s: Bad %s values: '%.*s'; mth=%u h=%u min=%u sec=%u", pszErrorTag, pszType, pThis->Asn1Core.cb, pThis->Asn1Core.uData.pch, pThis->Time.u8Month, pThis->Time.u8Hour, pThis->Time.u8Minute, pThis->Time.u8Second); return rc; }
int main() { RTTIMESPEC Now; RTTIMESPEC Ts1; RTTIMESPEC Ts2; RTTIME T1; RTTIME T2; #ifdef RTTIME_INCL_TIMEVAL struct timeval Tv1; struct timeval Tv2; struct timespec Tsp1; struct timespec Tsp2; #endif RTTEST hTest; int rc = RTTestInitAndCreate("tstRTTimeSpec", &hTest); if (rc) return rc; /* * Simple test with current time. */ RTTestSub(hTest, "Current time (UTC)"); CHECK_NZ(RTTimeNow(&Now)); CHECK_NZ(RTTimeExplode(&T1, &Now)); RTTestIPrintf(RTTESTLVL_ALWAYS, " %RI64 ns - %s\n", RTTimeSpecGetNano(&Now), ToString(&T1)); CHECK_NZ(RTTimeImplode(&Ts1, &T1)); if (!RTTimeSpecIsEqual(&Ts1, &Now)) RTTestIFailed("%RI64 != %RI64\n", RTTimeSpecGetNano(&Ts1), RTTimeSpecGetNano(&Now)); /* * Simple test with current local time. */ RTTestSub(hTest, "Current time (local)"); CHECK_NZ(RTTimeLocalNow(&Now)); CHECK_NZ(RTTimeExplode(&T1, &Now)); RTTestIPrintf(RTTESTLVL_ALWAYS, " %RI64 ns - %s\n", RTTimeSpecGetNano(&Now), ToString(&T1)); CHECK_NZ(RTTimeImplode(&Ts1, &T1)); if (!RTTimeSpecIsEqual(&Ts1, &Now)) RTTestIFailed("%RI64 != %RI64\n", RTTimeSpecGetNano(&Ts1), RTTimeSpecGetNano(&Now)); /* * Some simple tests with fixed dates (just checking for smoke). */ RTTestSub(hTest, "Smoke"); TEST_NS(INT64_C(0)); CHECK_TIME(&T1, 1970,01,01, 00,00,00, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); TEST_NS(INT64_C(86400000000000)); CHECK_TIME(&T1, 1970,01,02, 00,00,00, 0, 2, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); TEST_NS(INT64_C(1)); CHECK_TIME(&T1, 1970,01,01, 00,00,00, 1, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); TEST_NS(INT64_C(-1)); CHECK_TIME(&T1, 1969,12,31, 23,59,59,999999999, 365, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* * Test the limits. */ RTTestSub(hTest, "Extremes"); TEST_NS(INT64_MAX); TEST_NS(INT64_MIN); TEST_SEC(1095379198); CHECK_TIME(&T1, 2004, 9,16, 23,59,58, 0, 260, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); TEST_SEC(1095379199); CHECK_TIME(&T1, 2004, 9,16, 23,59,59, 0, 260, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); TEST_SEC(1095379200); CHECK_TIME(&T1, 2004, 9,17, 00,00,00, 0, 261, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); TEST_SEC(1095379201); CHECK_TIME(&T1, 2004, 9,17, 00,00,01, 0, 261, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); /* * Test normalization (UTC). */ RTTestSub(hTest, "Normalization (UTC)"); /* simple */ CHECK_NZ(RTTimeNow(&Now)); CHECK_NZ(RTTimeExplode(&T1, &Now)); T2 = T1; CHECK_NZ(RTTimeNormalize(&T1)); if (memcmp(&T1, &T2, sizeof(T1))) RTTestIFailed("simple normalization failed\n"); CHECK_NZ(RTTimeImplode(&Ts1, &T1)); CHECK_NZ(RTTimeSpecIsEqual(&Ts1, &Now)); /* a few partial dates. */ memset(&T1, 0, sizeof(T1)); SET_TIME( &T1, 1970,01,01, 00,00,00, 0, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1970,01,01, 00,00,00, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1970,00,00, 00,00,00, 1, 1, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1970,01,01, 00,00,00, 1, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2007,12,06, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1968,01,30, 00,19,24, 5, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1968,01,30, 00,19,24, 5, 30, 1, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); SET_TIME( &T1, 1969,01,31, 00, 9, 2, 7, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,01,31, 00, 9, 2, 7, 31, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,03,31, 00, 9, 2, 7, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,03,31, 00, 9, 2, 7, 90, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,31, 00,00,00, 9, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,31, 00,00,00, 9, 365, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,30, 00,00,00, 30, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,30, 00,00,00, 30, 364, 1, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,00,00, 00,00,00, 30, 363, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,29, 00,00,00, 30, 363, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,00,00, 00,00,00, 30, 362, 6, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,28, 00,00,00, 30, 362, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,27, 00,00,00, 30, 0, 5, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,27, 00,00,00, 30, 361, 5, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,00,00, 00,00,00, 30, 360, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,26, 00,00,00, 30, 360, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,25, 00,00,00, 12, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,25, 00,00,00, 12, 359, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,24, 00,00,00, 16, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,24, 00,00,00, 16, 358, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* outside the year table range */ SET_TIME( &T1, 1200,01,30, 00,00,00, 2, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1200,01,30, 00,00,00, 2, 30, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); SET_TIME( &T1, 2555,11,29, 00,00,00, 2, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2555,11,29, 00,00,00, 2, 333, 5, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2555,00,00, 00,00,00, 3, 333, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2555,11,29, 00,00,00, 3, 333, 5, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* time overflow */ SET_TIME( &T1, 1969,12,30, 255,255,255, UINT32_MAX, 364, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1970,01, 9, 19,19,19,294967295, 9, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* date overflow */ SET_TIME( &T1, 2007,11,36, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2007,10,67, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2007,10,98, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2008,01,06, 02,15,23, 1, 6, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); SET_TIME( &T1, 2006,24,06, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2003,60,37, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2008,01,06, 02,15,23, 1, 6, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); SET_TIME( &T1, 2003,00,00, 02,15,23, 1,1801, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* * Conversions. */ #define CHECK_NSEC(Ts1, T2) \ do { \ RTTIMESPEC TsTmp; \ RTTESTI_CHECK_MSG( RTTimeSpecGetNano(&(Ts1)) == RTTimeSpecGetNano(RTTimeImplode(&TsTmp, &(T2))), \ ("line %d: %RI64, %RI64\n", __LINE__, \ RTTimeSpecGetNano(&(Ts1)), RTTimeSpecGetNano(RTTimeImplode(&TsTmp, &(T2)))) ); \ } while (0) RTTestSub(hTest, "Conversions, positive"); SET_TIME(&T1, 1980,01,01, 00,00,00, 0, 1, 1, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); RTTESTI_CHECK(RTTimeSpecSetDosSeconds(&Ts2, 0) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetDosSeconds(&Ts2) == 0); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1980,01,01, 00,00,00, 0, 1, 1, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); RTTESTI_CHECK(RTTimeSpecSetNtTime(&Ts2, INT64_C(119600064000000000)) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetNtTime(&Ts2) == INT64_C(119600064000000000)); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1970,01,01, 00,00,01, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); RTTESTI_CHECK(RTTimeSpecSetSeconds(&Ts2, 1) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetSeconds(&Ts2) == 1); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1970,01,01, 00,00,01, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); RTTESTI_CHECK(RTTimeSpecSetMilli(&Ts2, 1000) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetMilli(&Ts2) == 1000); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1970,01,01, 00,00,01, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); RTTESTI_CHECK(RTTimeSpecSetMicro(&Ts2, 1000000) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetMicro(&Ts2) == 1000000); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1970,01,01, 00,00,01, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); RTTESTI_CHECK(RTTimeSpecSetNano(&Ts2, 1000000000) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetNano(&Ts2) == 1000000000); CHECK_NSEC(Ts2, T1); #ifdef RTTIME_INCL_TIMEVAL SET_TIME(&T1, 1970,01,01, 00,00,01, 5000, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); Tv1.tv_sec = 1; Tv1.tv_usec = 5; RTTESTI_CHECK(RTTimeSpecSetTimeval(&Ts2, &Tv1) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetMicro(&Ts2) == 1000005); CHECK_NSEC(Ts2, T1); RTTESTI_CHECK(RTTimeSpecGetTimeval(&Ts2, &Tv2) == &Tv2); RTTESTI_CHECK(Tv1.tv_sec == Tv2.tv_sec); RTTESTI_CHECK(Tv1.tv_usec == Tv2.tv_usec); #endif #ifdef RTTIME_INCL_TIMESPEC SET_TIME(&T1, 1970,01,01, 00,00,01, 5, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); Tsp1.tv_sec = 1; Tsp1.tv_nsec = 5; RTTESTI_CHECK(RTTimeSpecSetTimespec(&Ts2, &Tsp1) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetNano(&Ts2) == 1000000005); CHECK_NSEC(Ts2, T1); RTTESTI_CHECK(RTTimeSpecGetTimespec(&Ts2, &Tsp2) == &Tsp2); RTTESTI_CHECK(Tsp1.tv_sec == Tsp2.tv_sec); RTTESTI_CHECK(Tsp1.tv_nsec == Tsp2.tv_nsec); #endif RTTestSub(hTest, "Conversions, negative"); #ifdef RTTIME_INCL_TIMEVAL SET_TIME(&T1, 1969,12,31, 23,59,58,999995000, 365, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); Tv1.tv_sec = -2; Tv1.tv_usec = 999995; RTTESTI_CHECK(RTTimeSpecSetTimeval(&Ts2, &Tv1) == &Ts2); RTTESTI_CHECK_MSG(RTTimeSpecGetMicro(&Ts2) == -1000005, ("%RI64\n", RTTimeSpecGetMicro(&Ts2))); CHECK_NSEC(Ts2, T1); RTTESTI_CHECK(RTTimeSpecGetTimeval(&Ts2, &Tv2) == &Tv2); RTTESTI_CHECK(Tv1.tv_sec == Tv2.tv_sec); RTTESTI_CHECK(Tv1.tv_usec == Tv2.tv_usec); #endif #ifdef RTTIME_INCL_TIMESPEC SET_TIME(&T1, 1969,12,31, 23,59,58,999999995, 365, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); Tsp1.tv_sec = -2; Tsp1.tv_nsec = 999999995; RTTESTI_CHECK(RTTimeSpecSetTimespec(&Ts2, &Tsp1) == &Ts2); RTTESTI_CHECK_MSG(RTTimeSpecGetNano(&Ts2) == -1000000005, ("%RI64\n", RTTimeSpecGetMicro(&Ts2))); CHECK_NSEC(Ts2, T1); RTTESTI_CHECK(RTTimeSpecGetTimespec(&Ts2, &Tsp2) == &Tsp2); RTTESTI_CHECK(Tsp1.tv_sec == Tsp2.tv_sec); RTTESTI_CHECK(Tsp1.tv_nsec == Tsp2.tv_nsec); #endif /* * Summary */ return RTTestSummaryAndDestroy(hTest); }