/* The software in this package is distributed under the GNU General Public License version 2 (with a special exception described below). A copy of GNU General Public License (GPL) is included in this distribution, in the file COPYING.GPL. As a special exception, if other files instantiate templates or use macros or inline functions from this file, or you compile this file and link it with other works to produce a work based on this file, this file does not by itself cause the resulting work to be covered by the GNU General Public License. However the source code for this file must still be made available in accordance with section (3) of the GNU General Public License. This exception does not invalidate any other reasons why a work based on this file might be covered by the GNU General Public License. */ /** @file * @brief unit test for time related functions. * * @copyright Copyright © 2001-2008 by Intra2net AG * */ #include #if (__GLIBC__ <= 2) && (__GLIBC_MINOR__ < 23) /* * Ancient glibc (pre 2015) has a defective implementation of strptime(3) * that doesn’t handle the ‘Z’ modifier of ISO8601 to indicate UTC. It also * parses fractional timezones only partially so e. g. “+11:11” is treated * as “+1100”. */ # define GLIBC_STRPTIME_LACKS_Z #endif #define BOOST_TEST_DYN_LINK #include #include #include #include #include #include #include #include using namespace std; using namespace I2n; using namespace I2n::Time; class TestTimeFuncFixture { protected: typedef std::list< std::string > StringList; std::set used_check_files; struct { std::string env; /* save and restore TZ from envp */ char *name[2]; long zone; int dst; } timezone; std::string get_check_file_path(std::string tag) { std::string result; result= "__unittest__" + tag + ".dat"; used_check_files.insert(result); return result; } // eo get_check_file_path void dump_tz_info (void) { fprintf (stderr, "timezone: %s(%s) %ld, dst: %d\n", tzname[0], tzname[1], ::timezone, daylight); } void remove_check_files() { for (std::set::iterator it= used_check_files.begin(); it != used_check_files.end(); ++it) { std::string filepath(*it); if (path_exists(filepath)) { unlink(filepath); } //TODO } used_check_files.clear(); } // eo remove_check_files void set_tz (const std::string &tzname) { errno = 0; if (setenv ("TZ", tzname.c_str (), 1) == -1) { std::cerr << "error setting environment 'TZ': [" << tzname << "]" << std::endl ; return; } tzset (); } inline void set_utc (void) { this->set_tz ("UTC"); } void set_dst (const bool dst=true) { daylight = dst ? 1 : 0; tzset (); } public: TestTimeFuncFixture() { this->timezone.env = std::string (secure_getenv ("TZ") ?: ""); this->timezone.name[0] = tzname [0]; this->timezone.name[1] = tzname [1]; this->timezone.zone = ::timezone; this->timezone.dst = daylight; } ~TestTimeFuncFixture() { remove_check_files(); /* time zone related cleanup */ daylight = this->timezone.dst; ::timezone = this->timezone.zone; tzname [0] = this->timezone.name[0]; tzname [1] = this->timezone.name[1]; errno = 0; if (setenv ("TZ", this->timezone.env.c_str (), 1) == -1) { std::cerr << "error cleaning up environment 'TZ': [" << this->timezone.env << "]" << std::endl ; } tzset(); } }; BOOST_FIXTURE_TEST_SUITE(TestTimeFunc, TestTimeFuncFixture) BOOST_AUTO_TEST_CASE(AddIntervalsDisjoint) { Intervals intervals; intervals.add( Interval( 10, 100 ) ); intervals.add( Interval( 600, 620 ) ); BOOST_CHECK_EQUAL( false, intervals.empty() ); BOOST_CHECK_EQUAL( 2u, intervals.size() ); BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() ); BOOST_CHECK_EQUAL( 100u, intervals.front().upper_bound() ); BOOST_CHECK_EQUAL( 600u, intervals.back().lower_bound() ); BOOST_CHECK_EQUAL( 620u, intervals.back().upper_bound() ); } // eo AddIntervalsDisjoint() BOOST_AUTO_TEST_CASE(AddIntervalsInclude) { Intervals intervals; intervals.add( Interval( 10, 100 ) ); intervals.add( Interval( 10, 80 ) ); BOOST_CHECK_EQUAL( false, intervals.empty() ); BOOST_CHECK_EQUAL( 1u, intervals.size() ); BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() ); BOOST_CHECK_EQUAL( 100u, intervals.front().upper_bound() ); BOOST_CHECK_EQUAL( false, intervals.front().changed() ); } // eo AddIntervalsInclude() BOOST_AUTO_TEST_CASE(AddIntervalsEmbrace) { Intervals intervals; intervals.add( Interval( 10, 100 ) ); intervals.add( Interval( 5, 120 ) ); BOOST_CHECK_EQUAL( false, intervals.empty() ); BOOST_CHECK_EQUAL( 1u, intervals.size() ); BOOST_CHECK_EQUAL( 5u, intervals.front().lower_bound() ); BOOST_CHECK_EQUAL( 120u, intervals.front().upper_bound() ); BOOST_CHECK_EQUAL( true, intervals.front().changed() ); } // eo AddIntervalsEmbrace() BOOST_AUTO_TEST_CASE(AddIntervalsJoin1) { Intervals intervals; intervals.add( Interval( 10, 100 ) ); intervals.add( Interval( 60, 120 ) ); BOOST_CHECK_EQUAL( false, intervals.empty() ); BOOST_CHECK_EQUAL( 1u, intervals.size() ); BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() ); BOOST_CHECK_EQUAL( 120u, intervals.front().upper_bound() ); BOOST_CHECK_EQUAL( true, intervals.front().changed() ); } // eo AddIntervalsJoin1() BOOST_AUTO_TEST_CASE(AddIntervalsJoin1b) { Intervals intervals; intervals.add( Interval( 10, 100 ) ); intervals.add( Interval( 100, 120 ) ); BOOST_CHECK_EQUAL( false, intervals.empty() ); BOOST_CHECK_EQUAL( 1u, intervals.size() ); BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() ); BOOST_CHECK_EQUAL( 120u, intervals.front().upper_bound() ); BOOST_CHECK_EQUAL( true, intervals.front().changed() ); } // eo AddIntervalsJoin1b() BOOST_AUTO_TEST_CASE(AddIntervalsJoin2) { Intervals intervals; intervals.add( Interval( 10, 100 ) ); intervals.add( Interval( 200, 250 ) ); BOOST_CHECK_EQUAL( false, intervals.empty() ); BOOST_CHECK_EQUAL( 2u, intervals.size() ); BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() ); BOOST_CHECK_EQUAL( 100u, intervals.front().upper_bound() ); BOOST_CHECK_EQUAL( 200u, intervals.back().lower_bound() ); BOOST_CHECK_EQUAL( 250u, intervals.back().upper_bound() ); // now add the gap; the intervals should collapse to one covering all: intervals.add( Interval(100, 200) ); BOOST_CHECK_EQUAL( false, intervals.empty() ); BOOST_CHECK_EQUAL( 1u, intervals.size() ); BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() ); BOOST_CHECK_EQUAL( 250u, intervals.front().upper_bound() ); BOOST_CHECK_EQUAL( true, intervals.front().changed() ); } // eo AddIntervalsJoin2() BOOST_AUTO_TEST_CASE(SubIntervalsDisjoint) { Intervals intervals; intervals.add( Interval(10, 100) ); intervals.sub( Interval(0, 10) ); BOOST_CHECK_EQUAL( false, intervals.empty() ); BOOST_CHECK_EQUAL( 1u, intervals.size() ); BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() ); BOOST_CHECK_EQUAL( 100u, intervals.front().upper_bound() ); BOOST_CHECK_EQUAL( false, intervals.front().changed() ); } // eo SubIntervalsDisjoint() BOOST_AUTO_TEST_CASE(SubIntervalsExact) { Intervals intervals; intervals.add( Interval(10, 100) ); intervals.sub( Interval(10, 100) ); BOOST_CHECK_EQUAL( true, intervals.empty() ); BOOST_CHECK_EQUAL( 0u, intervals.size() ); } // eo SubIntervalsExact() BOOST_AUTO_TEST_CASE(SubIntervalsSplit1) { Intervals intervals; intervals.add( Interval(10, 100) ); intervals.sub( Interval(20, 40) ); BOOST_CHECK_EQUAL( false, intervals.empty() ); BOOST_CHECK_EQUAL( 2u, intervals.size() ); BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() ); BOOST_CHECK_EQUAL( 20u, intervals.front().upper_bound() ); BOOST_CHECK_EQUAL( 40u, intervals.back().lower_bound() ); BOOST_CHECK_EQUAL( 100u, intervals.back().upper_bound() ); BOOST_CHECK_EQUAL( false, intervals.front().changed() ); BOOST_CHECK_EQUAL( true, intervals.back().changed() ); } // eo SubIntervalsSplit1() BOOST_AUTO_TEST_CASE(SubIntervalsCutFront) { Intervals intervals; intervals.add( Interval(10, 100) ); intervals.sub( Interval(10, 20) ); BOOST_CHECK_EQUAL( false, intervals.empty() ); BOOST_CHECK_EQUAL( 1u, intervals.size() ); BOOST_CHECK_EQUAL( 20u, intervals.front().lower_bound() ); BOOST_CHECK_EQUAL( 100u, intervals.front().upper_bound() ); BOOST_CHECK_EQUAL( true, intervals.front().changed() ); } // eo SubIntervalsCutFront() BOOST_AUTO_TEST_CASE(SubIntervalsCutBack) { Intervals intervals; intervals.add( Interval(10, 100) ); intervals.sub( Interval(87, 100) ); BOOST_CHECK_EQUAL( false, intervals.empty() ); BOOST_CHECK_EQUAL( 1u, intervals.size() ); BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() ); BOOST_CHECK_EQUAL( 87u, intervals.front().upper_bound() ); BOOST_CHECK_EQUAL( true, intervals.front().changed() ); } // eo SubIntervalsCutBack() BOOST_AUTO_TEST_CASE(SubIntervalsCutMore) { Intervals intervals; intervals.add( Interval( 10, 100) ); intervals.add( Interval(110, 200) ); intervals.add( Interval(210, 300) ); // this should remove the first 2 intervals and cut the third: intervals.sub( Interval(8, 220) ); BOOST_CHECK_EQUAL( false, intervals.empty() ); BOOST_CHECK_EQUAL( 1u, intervals.size() ); BOOST_CHECK_EQUAL( 220u, intervals.front().lower_bound() ); BOOST_CHECK_EQUAL( 300u, intervals.front().upper_bound() ); BOOST_CHECK_EQUAL( true, intervals.front().changed() ); } // eo SubIntervalsCutMore() BOOST_AUTO_TEST_CASE(IntervalComparisons) { Intervals intervals1; Intervals intervals2; intervals1.add( Interval( 10, 120) ); intervals2.add( Interval( 10, 110 ) ); intervals2.add( Interval( 100, 120 ) ); BOOST_CHECK_EQUAL( 1u, intervals2.size() ); BOOST_CHECK( intervals1 == intervals2 ); BOOST_CHECK_EQUAL( true, intervals1.contains( intervals2 )); BOOST_CHECK_EQUAL( true, intervals2.contains( intervals1 )); intervals2.sub( Interval( 40, 50) ); BOOST_CHECK( intervals1 != intervals2 ); BOOST_CHECK_EQUAL( true, intervals1.contains( intervals2 )); BOOST_CHECK_EQUAL( false, intervals2.contains( intervals1 )); } // eo IntervalComparisons() BOOST_AUTO_TEST_CASE(MonotonicClock) { long sec0, nsec0; long sec1, nsec1; bool res = monotonic_clock_gettime(sec0,nsec0); BOOST_CHECK_EQUAL( true, res ); usleep(250000); res= monotonic_clock_gettime(sec1,nsec1); BOOST_CHECK_EQUAL( true, res); long delta_sec = sec1 - sec0; long delta_nsec= nsec1 - nsec0; long delta_millisec= ( delta_nsec / 1000000L) + delta_sec * 1000L; BOOST_CHECK( delta_millisec >= 250 - /*fuzz*/ 1); BOOST_CHECK( delta_millisec < 300 ); } // eo MonotonicClock() BOOST_AUTO_TEST_CASE(WeekInvalid) { Week week("99999999"); BOOST_CHECK_EQUAL(false, week.is_valid()); BOOST_CHECK_EQUAL(string(""), week.get_displaystring()); } BOOST_AUTO_TEST_CASE(WeekDisplayString1) { Week week(""); BOOST_CHECK_EQUAL(true, week.is_valid()); BOOST_CHECK_EQUAL(string(""), week.get_displaystring()); } BOOST_AUTO_TEST_CASE(WeekDisplayString2) { Week week("0123456"); BOOST_CHECK_EQUAL(true, week.is_valid()); BOOST_CHECK_EQUAL(string("Mon-Sun"), week.get_displaystring()); } BOOST_AUTO_TEST_CASE(WeekDisplayString3) { Week week("123456"); BOOST_CHECK_EQUAL(true, week.is_valid()); BOOST_CHECK_EQUAL(string("Mon-Sat"), week.get_displaystring()); } BOOST_AUTO_TEST_CASE(WeekDisplayString4) { Week week("012345"); BOOST_CHECK_EQUAL(true, week.is_valid()); BOOST_CHECK_EQUAL(string("Mon-Fri, Sun"), week.get_displaystring()); } BOOST_AUTO_TEST_CASE(WeekDisplayString5) { Week week("1256"); BOOST_CHECK_EQUAL(true, week.is_valid()); BOOST_CHECK_EQUAL(string("Mon, Tue, Fri, Sat"), week.get_displaystring()); } BOOST_AUTO_TEST_CASE(WeekDisplayString6) { Week week("0246"); BOOST_CHECK_EQUAL(true, week.is_valid()); BOOST_CHECK_EQUAL(string("Tue, Thu, Sat, Sun"), week.get_displaystring()); } BOOST_AUTO_TEST_CASE(WeekDisplayString7) { Week week("135"); BOOST_CHECK_EQUAL(true, week.is_valid()); BOOST_CHECK_EQUAL(string("Mon, Wed, Fri"), week.get_displaystring()); } BOOST_AUTO_TEST_CASE(WeekDisplayString8) { Week week("15"); BOOST_CHECK_EQUAL(true, week.is_valid()); BOOST_CHECK_EQUAL(string("Mon, Fri"), week.get_displaystring()); } BOOST_AUTO_TEST_CASE(WeekDisplayString9) { Week week("06"); BOOST_CHECK_EQUAL(true, week.is_valid()); BOOST_CHECK_EQUAL(string("Sat, Sun"), week.get_displaystring()); } BOOST_AUTO_TEST_CASE(WeekDisplayString10) { Week week("056"); BOOST_CHECK_EQUAL(true, week.is_valid()); BOOST_CHECK_EQUAL(string("Fri-Sun"), week.get_displaystring()); } BOOST_AUTO_TEST_CASE(WeekDisplayString11) { Week week("0"); BOOST_CHECK_EQUAL(true, week.is_valid()); BOOST_CHECK_EQUAL(string("Sun"), week.get_displaystring()); } BOOST_AUTO_TEST_CASE(WeekDisplayString12) { Week week("6"); BOOST_CHECK_EQUAL(true, week.is_valid()); BOOST_CHECK_EQUAL(string("Sat"), week.get_displaystring()); } BOOST_AUTO_TEST_CASE(WeekDisplayString13) { Week week("123"); BOOST_CHECK_EQUAL(true, week.is_valid()); BOOST_CHECK_EQUAL(string("Mon-Wed"), week.get_displaystring()); } BOOST_AUTO_TEST_CASE(FormatFullTime) { this->set_tz ("CET"); time_t seconds = 1318844005; BOOST_CHECK_EQUAL("17.10.2011 11:33", format_full_time(seconds)); } BOOST_AUTO_TEST_CASE(DateToSeconds1) { this->set_tz ("CET"); // no DST BOOST_CHECK_EQUAL(1325372400, date_to_seconds("2012-01-01")); } BOOST_AUTO_TEST_CASE(DateToSeconds2) { this->set_tz ("CET"); // DST BOOST_CHECK_EQUAL(1341093600, date_to_seconds("2012-07-01")); } BOOST_AUTO_TEST_CASE(FormatISO8601_T) { const time_t moment = 1515492684; BOOST_CHECK_EQUAL("10:11:24", format_iso8601 (moment, true, false, true, false)); } BOOST_AUTO_TEST_CASE(FormatISO8601_TZ_local) { this->set_tz ("CET"); const time_t moment = 1515492684; BOOST_CHECK_EQUAL("11:11:24+0100", format_iso8601 (moment, false, false, true, true)); } BOOST_AUTO_TEST_CASE(FormatISO8601_TZ) { const time_t moment = 1515492684; BOOST_CHECK_EQUAL("10:11:24+0000", format_iso8601 (moment, true, false, true, true)); } BOOST_AUTO_TEST_CASE(FormatISO8601_DTZ_local) { this->set_tz ("CET"); const time_t moment = 1515492684; BOOST_CHECK_EQUAL("2018-01-09T11:11:24+0100", format_iso8601 (moment, false, true, true, true)); } BOOST_AUTO_TEST_CASE(FormatISO8601_DTZ) { const time_t moment = 1515492684; BOOST_CHECK_EQUAL("2018-01-09T10:11:24+0000", format_iso8601 (moment, true, true, true, true)); } BOOST_AUTO_TEST_CASE(FormatISO8601_DT) { const time_t moment = 1515492684; BOOST_CHECK_EQUAL("2018-01-09T10:11:24", format_iso8601 (moment, true, true, true, false)); } BOOST_AUTO_TEST_CASE(FormatISO8601_D) { const time_t moment = 1515492684; BOOST_CHECK_EQUAL("2018-01-09", format_iso8601 (moment, true, true, false, false)); } BOOST_AUTO_TEST_CASE(FormatISO8601_DTZ_struct_tm) { struct tm helau; helau.tm_sec = 11; helau.tm_min = 11; helau.tm_hour = 11; helau.tm_mday = 11; helau.tm_mon = 10; helau.tm_year = 2018 - 1900; helau.tm_wday = 0; helau.tm_yday = 315; helau.tm_isdst = 0; helau.tm_gmtoff = 0; helau.tm_zone = NULL; BOOST_CHECK_EQUAL("2018-11-11T11:11:11+0000", format_iso8601 (helau, true, true, true)); } BOOST_AUTO_TEST_CASE(FormatISO8601_DTZ_struct_timespec) { struct timespec ts = { 1541934671, 11 }; BOOST_CHECK_EQUAL("2018-11-11T11:11:11+0000", format_iso8601 (ts, true, true, true, true)); } BOOST_AUTO_TEST_SUITE(Clock) BOOST_AUTO_TEST_CASE(ctor_simple) { I2n::clock::Time t; BOOST_CHECK_EQUAL(t.get_sec (), 0); BOOST_CHECK_EQUAL(t.get_nsec (), 0); } BOOST_AUTO_TEST_CASE(ctor_type) { I2n::clock::Time t1 (I2n::clock::type::real); I2n::clock::Time t2 (I2n::clock::type::mono); I2n::clock::Time t3 (I2n::clock::type::boot); I2n::clock::Time t4 (I2n::clock::type::cpu); BOOST_CHECK_EQUAL(t1.get_sec (), 0); BOOST_CHECK_EQUAL(t1.get_nsec (), 0); BOOST_CHECK_EQUAL(t2.get_sec (), 0); BOOST_CHECK_EQUAL(t2.get_nsec (), 0); BOOST_CHECK_EQUAL(t3.get_sec (), 0); BOOST_CHECK_EQUAL(t3.get_nsec (), 0); BOOST_CHECK_EQUAL(t4.get_sec (), 0); BOOST_CHECK_EQUAL(t4.get_nsec (), 0); } BOOST_AUTO_TEST_CASE(ctor_variant) { I2n::clock::Time tmc (I2n::clock::type::mono); I2n::clock::Time tmr (I2n::clock::type::mono, I2n::clock::type::raw); I2n::clock::Time tme (I2n::clock::type::mono, I2n::clock::type::exact); I2n::clock::Time trc (I2n::clock::type::real); I2n::clock::Time tre (I2n::clock::type::real, I2n::clock::type::exact); I2n::clock::Time tb (I2n::clock::type::boot); I2n::clock::Time tcp (I2n::clock::type::cpu); I2n::clock::Time tct (I2n::clock::type::cpu, I2n::clock::type::thread); BOOST_CHECK_EQUAL(tmc.get_sec (), 0); /* MONO */ BOOST_CHECK_EQUAL(tmc.get_nsec (), 0); BOOST_CHECK_EQUAL(tmr.get_sec (), 0); BOOST_CHECK_EQUAL(tmr.get_nsec (), 0); BOOST_CHECK_EQUAL(tme.get_sec (), 0); BOOST_CHECK_EQUAL(tme.get_nsec (), 0); BOOST_CHECK_EQUAL(trc.get_sec (), 0); /* REAL */ BOOST_CHECK_EQUAL(trc.get_nsec (), 0); BOOST_CHECK_EQUAL(tre.get_sec (), 0); BOOST_CHECK_EQUAL(tre.get_nsec (), 0); BOOST_CHECK_EQUAL(tb.get_sec (), 0); /* BOOT */ BOOST_CHECK_EQUAL(tb.get_nsec (), 0); BOOST_CHECK_EQUAL(tcp.get_sec (), 0); /* CPU */ BOOST_CHECK_EQUAL(tcp.get_nsec (), 0); BOOST_CHECK_EQUAL(tct.get_sec (), 0); BOOST_CHECK_EQUAL(tct.get_nsec (), 0); } BOOST_AUTO_TEST_CASE(initializer_now) { boost::optional t = I2n::clock::now (); BOOST_CHECK(t); BOOST_CHECK_GT(t->get_sec (), 0); BOOST_CHECK_EQUAL(t->err, 0); } BOOST_AUTO_TEST_CASE(initializer_zero) { I2n::clock::Time stundenull = I2n::clock::zero (); BOOST_CHECK_EQUAL(stundenull.get_sec (), 0); BOOST_CHECK_EQUAL(stundenull.get_nsec (), 0); BOOST_CHECK_EQUAL(stundenull.err, 0); } BOOST_AUTO_TEST_CASE(member_set_now) { I2n::clock::Time t; BOOST_CHECK(t.set ()); BOOST_CHECK_NE(t.get_sec (), 0); } BOOST_AUTO_TEST_CASE(member_set_value) { I2n::clock::Time t; t.set (42, 42); BOOST_CHECK_EQUAL(t.get_sec (), 42); BOOST_CHECK_EQUAL(t.get_nsec (), 42); } BOOST_AUTO_TEST_CASE(member_set_value_type) { I2n::clock::Time t; t.set (42, 42, I2n::clock::type::real, I2n::clock::type::exact); BOOST_CHECK_EQUAL(t.get_sec (), 42); BOOST_CHECK_EQUAL(t.get_nsec (), 42); } BOOST_AUTO_TEST_CASE(member_add_parts) { I2n::clock::Time t; t.set (42, 42); t.add (2187, 2187); BOOST_CHECK_EQUAL(t.get_sec (), 2229); BOOST_CHECK_EQUAL(t.get_nsec (), 2229); } BOOST_AUTO_TEST_CASE(member_sub_parts) { I2n::clock::Time t; t.set (2, 0L); t.subtract (1, 1L); BOOST_CHECK_EQUAL(t.get_sec (), 0); BOOST_CHECK_EQUAL(t.get_nsec (), 999999999); } BOOST_AUTO_TEST_CASE(member_sub_Time) { I2n::clock::Time t1; I2n::clock::Time t2; t1.set (42, 42L); t2.set (42, 0L); t1.subtract (t2); BOOST_CHECK_EQUAL(t1.get_sec (), 0); BOOST_CHECK_EQUAL(t1.get_nsec (), 42L); } BOOST_AUTO_TEST_CASE(member_diff) { static const time_t five = 5 * 365 * 24 * 3600; I2n::clock::Time t1 (42, 1337); I2n::clock::Time t2 = t1 + five;; I2n::clock::Time t3 = t1 - five;; BOOST_CHECK_EQUAL(t2, I2n::clock::Time ((time_t)42 + five, 1337)); BOOST_CHECK_EQUAL(t3, I2n::clock::Time ((time_t)42 - five, 1337)); BOOST_CHECK_EQUAL(t1.difference (t3), t3.difference (t1)); BOOST_CHECK_EQUAL(t3.difference (t3), t3.difference (t3)); } BOOST_AUTO_TEST_CASE(op_copyassign) { I2n::clock::Time t1; I2n::clock::Time t2; BOOST_CHECK(t1.set ()); t2 = t1; BOOST_CHECK_EQUAL(t1.get_sec (), t2.get_sec ()); BOOST_CHECK_EQUAL(t1.get_nsec (), t2.get_nsec ()); } BOOST_AUTO_TEST_CASE(op_equal) { I2n::clock::Time t1; I2n::clock::Time t2; BOOST_CHECK(t1.set ()); t2 = t1; BOOST_CHECK_EQUAL(t1, t2); } BOOST_AUTO_TEST_CASE(op_add_Time) { I2n::clock::Time t1; I2n::clock::Time t2; I2n::clock::Time tsum; t1.set (2187, 2187); t2.set (1337, 1337); tsum = t1 + t2; BOOST_CHECK_EQUAL(tsum.get_sec (), 3524); BOOST_CHECK_EQUAL(tsum.get_nsec (), 3524); } BOOST_AUTO_TEST_CASE(op_add_Time_carry) { I2n::clock::Time t1; I2n::clock::Time t2; I2n::clock::Time tsum; t1.set (2187, 2187); # if LONG_BIT == 32 t2.set (1300, 2L * 1000 * 1000 * 1000 + 1337); # else t2.set (1300, 37L * 1000 * 1000 * 1000 + 1337); # endif tsum = t1 + t2; # if LONG_BIT == 32 BOOST_CHECK_EQUAL(tsum.get_sec (), 3489); BOOST_CHECK_EQUAL(tsum.get_nsec (), 3524); # else BOOST_CHECK_EQUAL(tsum.get_sec (), 3524); BOOST_CHECK_EQUAL(tsum.get_nsec (), 3524); # endif } BOOST_AUTO_TEST_CASE(op_add_time_t) { I2n::clock::Time t1 (2187, 2187); time_t t2 = 1337; I2n::clock::Time tsum; tsum = t1 + t2; BOOST_CHECK_EQUAL(tsum.get_sec (), 3524); BOOST_CHECK_EQUAL(tsum.get_nsec (), 2187); } BOOST_AUTO_TEST_CASE(op_add_time_t_external) { time_t t1 = 1337; I2n::clock::Time t2 (2187, 2187); I2n::clock::Time tsum; tsum = t1 + t2; BOOST_CHECK_EQUAL(tsum.get_sec (), 3524); BOOST_CHECK_EQUAL(tsum.get_nsec (), 2187); } BOOST_AUTO_TEST_CASE(op_incr_Time) { I2n::clock::Time t1 (2187, 2187); I2n::clock::Time t2 (1337, 1337); t1 += t2; BOOST_CHECK_EQUAL(t1.get_sec (), 3524); BOOST_CHECK_EQUAL(t1.get_nsec (), 3524); } BOOST_AUTO_TEST_CASE(op_incr_time_t) { I2n::clock::Time t1 (2187, 2187); time_t t2 = 1337; t1 += t2; BOOST_CHECK_EQUAL(t1.get_sec (), 3524); BOOST_CHECK_EQUAL(t1.get_nsec (), 2187); } BOOST_AUTO_TEST_CASE(op_subtract_Time) { I2n::clock::Time t1; I2n::clock::Time t2; I2n::clock::Time tdiff; t1.set (2187, 2187); t2.set (1337, 1337); tdiff = t1 - t2; BOOST_CHECK_EQUAL(tdiff.get_sec (), 850); BOOST_CHECK_EQUAL(tdiff.get_nsec (), 850); } BOOST_AUTO_TEST_CASE(op_subtract_time_t) { I2n::clock::Time t1 (2187, 2187); time_t t2 = 1337; I2n::clock::Time tdiff; tdiff = t1 - t2; BOOST_CHECK_EQUAL(tdiff.get_sec (), 850); BOOST_CHECK_EQUAL(tdiff.get_nsec (), 2187); } BOOST_AUTO_TEST_CASE(op_subtract_time_t_external) { time_t t1 = 1337; I2n::clock::Time t2 (2187, 2187); I2n::clock::Time tdiff; tdiff = t1 - t2; BOOST_CHECK_EQUAL(tdiff.get_sec (), -851); BOOST_CHECK_EQUAL(tdiff.get_nsec (), 999997813); } BOOST_AUTO_TEST_CASE(op_decr_Time) { I2n::clock::Time t1 (2187, 2187); I2n::clock::Time t2 (1337, 1337); t1 -= t2; BOOST_CHECK_EQUAL(t1.get_sec (), 850); BOOST_CHECK_EQUAL(t1.get_nsec (), 850); } BOOST_AUTO_TEST_CASE(op_decr_time_t) { I2n::clock::Time t1 (2187, 2187); time_t t2 = 1337; t1 -= t2; BOOST_CHECK_EQUAL(t1.get_sec (), 850); BOOST_CHECK_EQUAL(t1.get_nsec (), 2187); } BOOST_AUTO_TEST_CASE(op_mult_scale) { I2n::clock::Time t1; I2n::clock::Time t2; t1.set (1, 1); t2 = t1 * 42; BOOST_CHECK_EQUAL(t2.get_sec (), 42); BOOST_CHECK_EQUAL(t2.get_nsec (), 42); } BOOST_AUTO_TEST_CASE(op_mult_mutate) { I2n::clock::Time t1 ( 42, 42); I2n::clock::Time t2 (1337, 0); t1 *= 2; t2 *= -10; BOOST_CHECK_EQUAL(t1.get_sec (), 84); BOOST_CHECK_EQUAL(t1.get_nsec (), 84); BOOST_CHECK_EQUAL(t2.get_sec (), -13370); } BOOST_AUTO_TEST_CASE(op_mult_scale_carry) { I2n::clock::Time t1; I2n::clock::Time t2; t1.set (1, 500 * 1000 * 1000); t2 = t1 * 3; BOOST_CHECK_EQUAL(t2.get_sec (), 4); BOOST_CHECK_EQUAL(t2.get_nsec (), 500 * 1000 * 1000); } BOOST_AUTO_TEST_CASE(op_equals) { I2n::clock::Time t1; I2n::clock::Time t2; t1.set (50, 50); t2.set (50, 50); BOOST_CHECK_EQUAL(t1, t2); } BOOST_AUTO_TEST_CASE(compare_equal) { I2n::clock::Time t1; I2n::clock::Time t2; t1.set (42, 42); t2.set (42, 42); BOOST_CHECK_EQUAL(I2n::clock::compare (t1, t2), 0); } BOOST_AUTO_TEST_CASE(compare_equal_type) { I2n::clock::Time t1 (42, 42, I2n::clock::type::real); I2n::clock::Time t2 (42, 42, I2n::clock::type::cpu); I2n::clock::Time t3 (42, 0, I2n::clock::type::real); I2n::clock::Time t4 (42, 42, I2n::clock::type::real); BOOST_CHECK_NE(t1, t2); BOOST_CHECK_NE(t1, t3); BOOST_CHECK_EQUAL(t1, t4); } BOOST_AUTO_TEST_CASE(compare_ne_sec) { I2n::clock::Time t1; I2n::clock::Time t2; t1.set ( 42, 42); t2.set (1337, 42); BOOST_CHECK_EQUAL(I2n::clock::compare (t1, t2), -1); BOOST_CHECK_EQUAL(I2n::clock::compare (t2, t1), 1); } BOOST_AUTO_TEST_CASE(compare_ne_nsec) { I2n::clock::Time t1; I2n::clock::Time t2; t1.set (42, 42); t2.set (42, 1337); BOOST_CHECK_EQUAL(I2n::clock::compare (t1, t2), -1); BOOST_CHECK_EQUAL(I2n::clock::compare (t2, t1), 1); } BOOST_AUTO_TEST_CASE(compare_ne_both) { I2n::clock::Time t1; I2n::clock::Time t2; t1.set (42, 2187); t2.set (23, 1337); BOOST_CHECK_EQUAL(I2n::clock::compare (t1, t2), 1); BOOST_CHECK_EQUAL(I2n::clock::compare (t2, t1), -1); } BOOST_AUTO_TEST_CASE(op_ineq_sec) { I2n::clock::Time t1 (1337); I2n::clock::Time t2 (2187); BOOST_CHECK_LT(t1, t2); BOOST_CHECK_GT(t2, t1); } BOOST_AUTO_TEST_CASE(op_ineq_nsec) { I2n::clock::Time t1 (1337, 23); I2n::clock::Time t2 (1337, 42); BOOST_CHECK_LT(t1, t2); BOOST_CHECK_GT(t2, t1); } BOOST_AUTO_TEST_CASE(op_ineq_both) { I2n::clock::Time t1 (2187, 23); I2n::clock::Time t2 (1337, 42); BOOST_CHECK_LT(t2, t1); BOOST_CHECK_GT(t1, t2); } BOOST_AUTO_TEST_CASE(op_eq_time_t) { boost::optional t1 = I2n::clock::now (); const time_t t2 = time (NULL); /* race here */ *t1 -= (time_t)42; BOOST_CHECK_NE(*t1, t2); BOOST_CHECK_LT(*t1, t2); BOOST_CHECK_GT( t2, *t1); } BOOST_AUTO_TEST_CASE(Format_sec_msec) { I2n::clock::Time t1 (42, 42); I2n::clock::Time t2 ( 4, 242424242); I2n::clock::Time t3 ( 0, 133713371); I2n::clock::Time t4 ( 0, 0); std::string s1 = t1.format_sec_msec (); std::string s2 = t2.format_sec_msec (); std::string s3 = t3.format_sec_msec (); std::string s4 = t4.format_sec_msec (); BOOST_CHECK_EQUAL("42s 0ms" , s1); BOOST_CHECK_EQUAL( "4s 242ms", s2); BOOST_CHECK_EQUAL( "0s 133ms", s3); BOOST_CHECK_EQUAL( "0s 0ms" , s4); } BOOST_AUTO_TEST_CASE(Format_min_sec_msec) { I2n::clock::Time t1 (42*60 + 42, 42); I2n::clock::Time t2 ( 4*60 + 42, 242424242); I2n::clock::Time t3 ( 0*60 + 42, 133713371); I2n::clock::Time t4 ( 0 + 0, 0); std::string s1 = *t1.format_min_sec_msec (); std::string s2 = *t2.format_min_sec_msec (); std::string s3 = *t3.format_min_sec_msec (); std::string s4 = *t4.format_min_sec_msec (); BOOST_CHECK_EQUAL("42m42.000s", s1); BOOST_CHECK_EQUAL( "4m42.242s", s2); BOOST_CHECK_EQUAL( "0m42.133s", s3); BOOST_CHECK_EQUAL( "0m0.000s", s4); } BOOST_AUTO_TEST_CASE(FormatISO8601_T) { I2n::clock::Time t (42, 42); boost::optional s = t.format_iso8601 (true, false, true, false); BOOST_CHECK_EQUAL("00:00:42", *s); } BOOST_AUTO_TEST_CASE(FormatISO8601_DT) { I2n::clock::Time t (1541934671, 0); boost::optional s = t.format_iso8601 (true, true, true, false); BOOST_CHECK_EQUAL("2018-11-11T11:11:11", *s); } BOOST_AUTO_TEST_CASE(FormatISO8601_DTZ) { I2n::clock::Time t (1541934671, 0); boost::optional s = t.format_iso8601 (true, true, true, true); BOOST_CHECK_EQUAL("2018-11-11T11:11:11+0000", *s); } BOOST_AUTO_TEST_CASE(Format_make_nice_time) { I2n::clock::Time t (111111, 0); boost::optional s = t.make_nice_time (); BOOST_CHECK_EQUAL("1 day, 06:51:51", *s); } BOOST_AUTO_TEST_CASE(Format_format_full_time) { I2n::clock::Time t (1541934671, 0); /* * brr, the old formatters use localtime without a way to opt out of * it! */ this->set_utc (); boost::optional s = t.format_full_time (); BOOST_CHECK_EQUAL("11.11.2018 11:11", *s); } BOOST_AUTO_TEST_CASE(Format_format_date) { I2n::clock::Time t (1541934671, 0); boost::optional s = t.format_date (); BOOST_CHECK_EQUAL("11.11.2018", *s); } BOOST_AUTO_TEST_CASE(FromString_iso8601_full) { const std::string in1 ("0001-01-01T00:00:00+0000"); const std::string in2 ("2018-11-11T11:11:11+0000"); this->set_utc (); boost::optional t1 = I2n::clock::time_of_iso8601 (in1); boost::optional t2 = I2n::clock::time_of_iso8601 (in2); # if LONG_BIT == 32 BOOST_CHECK(!t1); # else BOOST_CHECK(t1); BOOST_CHECK_EQUAL(*t1->format_iso8601 (), in1); # endif BOOST_CHECK(t2); BOOST_CHECK_EQUAL(*t2->format_iso8601 (), in2); } BOOST_AUTO_TEST_CASE(FromString_iso8601_full_negyear) { const std::string in1 ("-0001-01-01T00:00:00+0000"); const std::string in2 ("-2018-11-11T11:11:11+0000"); this->set_utc (); boost::optional t1 = I2n::clock::time_of_iso8601 (in1); boost::optional t2 = I2n::clock::time_of_iso8601 (in2); # if LONG_BIT == 32 BOOST_CHECK(!t1); BOOST_CHECK(!t2); # else BOOST_CHECK(t1); BOOST_CHECK(t2); BOOST_CHECK_EQUAL(*t1->format_iso8601 (), in1); BOOST_CHECK_EQUAL(*t2->format_iso8601 (), in2); # endif } # ifndef GLIBC_STRPTIME_LACKS_Z BOOST_AUTO_TEST_CASE(FromString_iso8601_Z) { const std::string in1 ("2019-04-25T13:41:47+0000"); const std::string in2 ("2019-04-25T13:41:47Z"); this->set_utc (); boost::optional t1 = I2n::clock::time_of_iso8601 (in1, true, true, true); boost::optional t2 = I2n::clock::time_of_iso8601 (in2, true, true, true); BOOST_CHECK(t1); BOOST_CHECK(t2); BOOST_CHECK_EQUAL(*t1, *t2); BOOST_CHECK_EQUAL(*t1->format_iso8601 (), *t2->format_iso8601 ()); BOOST_CHECK_EQUAL(*t2->format_iso8601 (), in1); } # endif BOOST_AUTO_TEST_CASE(FromString_iso8601_partial) { const std::string in1 ("2018-11-11T11:11:11"); const std::string in2 ("2018-11-11"); this->set_utc (); boost::optional t1 = I2n::clock::time_of_iso8601 (in1, true, true, false); boost::optional t2 = I2n::clock::time_of_iso8601 (in2, true, false, false); BOOST_CHECK(t1); BOOST_CHECK(t2); /* * We test for the difference here which is zero if the number is * correct but causes the difference from the expected value to be * printed in case the test fails. */ BOOST_CHECK_EQUAL(*t1->format_iso8601 (true, true, true, false), in1); BOOST_CHECK_EQUAL(*t2->format_iso8601 (true, true, false, false), in2); } BOOST_AUTO_TEST_CASE(FromString_iso8601_offset) { const std::string in1 ("2019-04-25T13:41:47Z"); const std::string in2 ("2019-04-25T13:41:47+0200"); /* = UTC(in1 + 2h) */ const std::string in3 ("2019-04-25T15:41:47+0000"); /* = UTC(in2) */ this->set_utc (); boost::optional t1 = I2n::clock::time_of_iso8601 (in1, true, true, true); boost::optional t2 = I2n::clock::time_of_iso8601 (in2, true, true, true); boost::optional t3 = I2n::clock::time_of_iso8601 (in3, true, true, true); # ifdef GLIBC_STRPTIME_LACKS_Z BOOST_CHECK(!t1); # else BOOST_CHECK(t1); # endif BOOST_CHECK(t2); BOOST_CHECK(t3); # ifndef GLIBC_STRPTIME_LACKS_Z BOOST_CHECK_EQUAL(*t1->format_iso8601 (), "2019-04-25T13:41:47+0000"); BOOST_CHECK_EQUAL(t1->get_sec (), 1556199707); # endif BOOST_CHECK_EQUAL(*t2->format_iso8601 (), "2019-04-25T15:41:47+0000"); # ifndef GLIBC_STRPTIME_LACKS_Z BOOST_CHECK_EQUAL(t2->get_sec (), t1->get_sec () + 2 * 60 * 60); # endif BOOST_CHECK_EQUAL(*t2, *t3); BOOST_CHECK_EQUAL(*t3->format_iso8601 (), "2019-04-25T15:41:47+0000"); } BOOST_AUTO_TEST_CASE(FromString_iso8601_dst) { const std::string in1 ("2019-03-30T12:42:42"); /* “winter time” */ const std::string in2 ("2019-03-31T12:42:42"); /* “summer time” */ this->set_utc (); boost::optional t1 = I2n::clock::time_of_iso8601 (in1, true, true, false); boost::optional t2 = I2n::clock::time_of_iso8601 (in2, true, true, false); BOOST_CHECK(t1); BOOST_CHECK(t2); BOOST_CHECK_EQUAL(t1->get_sec (), 1553949762); BOOST_CHECK_EQUAL(t2->get_sec (), 1554036162); BOOST_CHECK_EQUAL(*t1->format_iso8601 (), in1 + "+0000"); BOOST_CHECK_EQUAL(*t2->format_iso8601 (), in2 + "+0000"); this->set_tz ("CET"); BOOST_CHECK_EQUAL(*t1->format_iso8601 (false, true, true, true), "2019-03-30T13:42:42+0100"); BOOST_CHECK_EQUAL(*t2->format_iso8601 (false, true, true, true), "2019-03-31T14:42:42+0200"); } BOOST_AUTO_TEST_CASE(FromString_iso8601_tzdiff) { const std::string in ("2019-04-26T13:45:02+0000"); this->set_tz ("UTC"); boost::optional t1 = I2n::clock::time_of_iso8601 (in, true, true, false); this->set_tz ("CET"); boost::optional t2 = I2n::clock::time_of_iso8601 (in, true, true, false); BOOST_CHECK_EQUAL(*t1->format_iso8601 (true, true, true, true), in); BOOST_CHECK_EQUAL(*t2->format_iso8601 (true, true, true, true), "2019-04-26T13:45:02+0000"); } BOOST_AUTO_TEST_CASE(FromString_iso8601_32bit_time_t_err) { const std::string timeless ("11:11:11"); boost::optional untimely = boost::none; this->set_utc (); untimely = I2n::clock::time_of_iso8601 (timeless, false, true, false); # if LONG_BIT == 32 BOOST_CHECK(!untimely); # else BOOST_CHECK(untimely); BOOST_CHECK_EQUAL(*untimely->format_iso8601 (true, false, true, false), timeless); # endif } BOOST_AUTO_TEST_CASE(Ctor_32bit_time_t_err) { boost::optional threw = boost::none; struct tm tm; memset (&tm, 0, sizeof (tm)); tm.tm_sec = 11; tm.tm_min = 11; tm.tm_hour = 11; tm.tm_mday = 11; tm.tm_mon = 10; tm.tm_year = -789; tm.tm_gmtoff = 0; try { I2n::clock::Time untimely (tm); } catch (I2n::clock::conversion_error &exn) { threw = std::string (exn); } # if LONG_BIT == 32 BOOST_CHECK_EQUAL(*threw, "errno=0 [mktime: from struct tm {Sun Nov 11 11:11:11 1111}]"); # else BOOST_CHECK(!threw); # endif } BOOST_AUTO_TEST_CASE(containers_list) { std::list ts; ts.push_back (I2n::clock::zero ()); ts.push_back (I2n::clock::zero ()); BOOST_CHECK_EQUAL(ts.size (), 2); } BOOST_AUTO_TEST_CASE(containers_vec) { std::vector ts; ts.push_back (I2n::clock::zero ()); ts.push_back (I2n::clock::zero ()); BOOST_CHECK_EQUAL(ts.size (), 2); } BOOST_AUTO_TEST_CASE(containers_set) { std::set ts; ts.insert (I2n::clock::zero ()); ts.insert (I2n::clock::Time (42, 2187)); ts.insert (I2n::clock::zero ()); BOOST_CHECK_EQUAL(ts.size (), 2); } BOOST_AUTO_TEST_CASE(containers_list_mean) { std::list ts; ts.push_back (I2n::clock::Time (42, 42)); ts.push_back (I2n::clock::Time (1337, 1337)); BOOST_CHECK_EQUAL(I2n::clock::mean (ts), I2n::clock::Time (689, 500000689)); } BOOST_AUTO_TEST_CASE(containers_list_mean_zero) { std::list ts; ts.push_back (I2n::clock::Time (0, 0)); ts.push_back (I2n::clock::Time (0, 0)); ts.push_back (I2n::clock::Time (0, 0)); ts.push_back (I2n::clock::Time (0, 0)); BOOST_CHECK_EQUAL(I2n::clock::mean (ts), I2n::clock::zero ()); } BOOST_AUTO_TEST_CASE(containers_list_mean_empty) { std::list ts; BOOST_CHECK_EQUAL(I2n::clock::mean (ts), I2n::clock::Time (0, 0)); } BOOST_AUTO_TEST_CASE(containers_set_mean) { std::set ts; ts.insert (I2n::clock::Time (42)); ts.insert (I2n::clock::Time (1337)); ts.insert (I2n::clock::Time (2187)); BOOST_CHECK_EQUAL(I2n::clock::mean (ts), I2n::clock::Time (1188, 666666666)); } BOOST_AUTO_TEST_CASE(containers_set_median_empty) { std::set ts; BOOST_CHECK_EQUAL(I2n::clock::median (ts), I2n::clock::Time (0, 0)); } BOOST_AUTO_TEST_CASE(containers_set_median_one) { std::set ts; ts.insert (I2n::clock::Time (42, 0)); BOOST_CHECK_EQUAL(I2n::clock::median (ts), I2n::clock::Time (42, 0)); } BOOST_AUTO_TEST_CASE(containers_set_median_multi) { std::set ts; ts.insert (I2n::clock::Time (42)); ts.insert (I2n::clock::Time (1337)); ts.insert (I2n::clock::Time (2187)); BOOST_CHECK_EQUAL(I2n::clock::median (ts), I2n::clock::Time (1337)); } BOOST_AUTO_TEST_CASE(containers_vec_median_multi) { std::vector ts; ts.push_back (I2n::clock::Time (42)); ts.push_back (I2n::clock::Time (1337)); ts.push_back (I2n::clock::Time (2187)); BOOST_CHECK_EQUAL(I2n::clock::median (ts), I2n::clock::Time (1337)); } BOOST_AUTO_TEST_CASE(containers_list_median_multi) { std::list ts; ts.push_back (I2n::clock::Time (42)); ts.push_back (I2n::clock::Time (1337)); ts.push_back (I2n::clock::Time (2187)); ts.push_back (I2n::clock::Time (0xdead)); ts.push_back (I2n::clock::Time (0xbeef)); BOOST_CHECK_EQUAL(I2n::clock::median (ts), I2n::clock::Time (2187)); } BOOST_AUTO_TEST_CASE(containers_list_median_multi_evensize) { std::list ts; ts.push_back (I2n::clock::Time (42)); ts.push_back (I2n::clock::Time (1337)); ts.push_back (I2n::clock::Time (2187)); ts.push_back (I2n::clock::Time (0xf00d)); ts.push_back (I2n::clock::Time (0xfeed)); ts.push_back (I2n::clock::Time (0xdeadf0e)); BOOST_CHECK_EQUAL(I2n::clock::median (ts), I2n::clock::Time (0xf00d)); } BOOST_AUTO_TEST_CASE(operator_shift_left) { std::ostringstream os1; std::ostringstream os2; std::ostringstream os3; std::ostringstream os4; os1 << I2n::clock::Time ( 42, 42); os2 << I2n::clock::Time (-42, 42); os3 << I2n::clock::Time ( 42, -42); os4 << I2n::clock::Time (-42, -42); BOOST_CHECK_EQUAL(os1.str (), "42s, 42ns"); BOOST_CHECK_EQUAL(os2.str (), "-42s, 42ns"); BOOST_CHECK_EQUAL(os3.str (), "41s, 999999958ns"); BOOST_CHECK_EQUAL(os4.str (), "-43s, 999999958ns"); } BOOST_AUTO_TEST_SUITE_END() /* [Clock] */ BOOST_AUTO_TEST_SUITE_END()