08ac8ef25d4e79ed303db38ebedaa266062f61b7
[libi2ncommon] / test / test_timefunc.cpp
1 /*
2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
4
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
7
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
13
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
16
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
19 */
20 /** @file
21  * @brief unit test for time related functions.
22  *
23  * @copyright Copyright © 2001-2008 by Intra2net AG
24  *
25  */
26
27 #define BOOST_TEST_DYN_LINK
28 #include <boost/test/unit_test.hpp>
29
30 #include <timefunc.hxx>
31 #include <filefunc.hxx>
32
33 #include <unistd.h>
34 #include <set>
35
36 using namespace std;
37 using namespace I2n;
38 using namespace I2n::Time;
39
40 class TestTimeFuncFixture
41 {
42 protected:
43    typedef std::list< std::string > StringList;
44    std::set<std::string>  used_check_files;
45
46    std::string get_check_file_path(std::string tag)
47    {
48       std::string result;
49       result= "__unittest__" + tag + ".dat";
50       used_check_files.insert(result);
51       return result;
52    } // eo get_check_file_path
53
54    void remove_check_files()
55    {
56       for (std::set<std::string>::iterator it= used_check_files.begin();
57             it != used_check_files.end();
58             ++it)
59       {
60          std::string filepath(*it);
61          if (path_exists(filepath))
62          {
63             unlink(filepath);
64          }
65          //TODO
66       }
67       used_check_files.clear();
68    } // eo remove_check_files
69
70 public:
71     TestTimeFuncFixture()
72     {
73     }
74
75     ~TestTimeFuncFixture()
76     {
77         remove_check_files();
78     }
79 };
80
81 BOOST_FIXTURE_TEST_SUITE(TestTimeFunc, TestTimeFuncFixture)
82
83 BOOST_AUTO_TEST_CASE(AddIntervalsDisjoint)
84 {
85     Intervals intervals;
86
87     intervals.add( Interval( 10, 100 ) );
88     intervals.add( Interval( 600, 620 ) );
89
90     BOOST_CHECK_EQUAL( false, intervals.empty() );
91     BOOST_CHECK_EQUAL( 2u, intervals.size() );
92
93     BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() );
94     BOOST_CHECK_EQUAL( 100u, intervals.front().upper_bound() );
95
96     BOOST_CHECK_EQUAL( 600u, intervals.back().lower_bound() );
97     BOOST_CHECK_EQUAL( 620u, intervals.back().upper_bound() );
98 } // eo AddIntervalsDisjoint()
99
100
101
102 BOOST_AUTO_TEST_CASE(AddIntervalsInclude)
103 {
104     Intervals intervals;
105
106     intervals.add( Interval( 10, 100 ) );
107     intervals.add( Interval( 10, 80 ) );
108
109     BOOST_CHECK_EQUAL( false, intervals.empty() );
110     BOOST_CHECK_EQUAL( 1u, intervals.size() );
111
112     BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() );
113     BOOST_CHECK_EQUAL( 100u, intervals.front().upper_bound() );
114     BOOST_CHECK_EQUAL( false, intervals.front().changed() );
115 } // eo AddIntervalsInclude()
116
117
118
119 BOOST_AUTO_TEST_CASE(AddIntervalsEmbrace)
120 {
121     Intervals intervals;
122
123     intervals.add( Interval( 10, 100 ) );
124     intervals.add( Interval( 5, 120 ) );
125
126     BOOST_CHECK_EQUAL( false, intervals.empty() );
127     BOOST_CHECK_EQUAL( 1u, intervals.size() );
128
129     BOOST_CHECK_EQUAL( 5u, intervals.front().lower_bound() );
130     BOOST_CHECK_EQUAL( 120u, intervals.front().upper_bound() );
131     BOOST_CHECK_EQUAL( true, intervals.front().changed() );
132 } // eo AddIntervalsEmbrace()
133
134
135
136 BOOST_AUTO_TEST_CASE(AddIntervalsJoin1)
137 {
138     Intervals intervals;
139
140     intervals.add( Interval( 10, 100 ) );
141     intervals.add( Interval( 60, 120 ) );
142
143     BOOST_CHECK_EQUAL( false, intervals.empty() );
144     BOOST_CHECK_EQUAL( 1u, intervals.size() );
145
146     BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() );
147     BOOST_CHECK_EQUAL( 120u, intervals.front().upper_bound() );
148     BOOST_CHECK_EQUAL( true, intervals.front().changed() );
149 } // eo AddIntervalsJoin1()
150
151
152
153 BOOST_AUTO_TEST_CASE(AddIntervalsJoin1b)
154 {
155     Intervals intervals;
156
157     intervals.add( Interval( 10, 100 ) );
158     intervals.add( Interval( 100, 120 ) );
159
160     BOOST_CHECK_EQUAL( false, intervals.empty() );
161     BOOST_CHECK_EQUAL( 1u, intervals.size() );
162
163     BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() );
164     BOOST_CHECK_EQUAL( 120u, intervals.front().upper_bound() );
165     BOOST_CHECK_EQUAL( true, intervals.front().changed() );
166 } // eo AddIntervalsJoin1b()
167
168
169
170 BOOST_AUTO_TEST_CASE(AddIntervalsJoin2)
171 {
172     Intervals intervals;
173
174     intervals.add( Interval( 10, 100 ) );
175     intervals.add( Interval( 200, 250 ) );
176
177     BOOST_CHECK_EQUAL( false, intervals.empty() );
178     BOOST_CHECK_EQUAL( 2u, intervals.size() );
179
180     BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() );
181     BOOST_CHECK_EQUAL( 100u, intervals.front().upper_bound() );
182     BOOST_CHECK_EQUAL( 200u, intervals.back().lower_bound() );
183     BOOST_CHECK_EQUAL( 250u, intervals.back().upper_bound() );
184
185     // now add the gap; the intervals should collapse to one covering all:
186     intervals.add( Interval(100, 200) );
187
188     BOOST_CHECK_EQUAL( false, intervals.empty() );
189     BOOST_CHECK_EQUAL( 1u, intervals.size() );
190
191     BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() );
192     BOOST_CHECK_EQUAL( 250u, intervals.front().upper_bound() );
193     BOOST_CHECK_EQUAL( true, intervals.front().changed() );
194 } // eo AddIntervalsJoin2()
195
196
197
198 BOOST_AUTO_TEST_CASE(SubIntervalsDisjoint)
199 {
200     Intervals intervals;
201
202     intervals.add( Interval(10, 100) );
203     intervals.sub( Interval(0, 10) );
204
205     BOOST_CHECK_EQUAL( false, intervals.empty() );
206     BOOST_CHECK_EQUAL( 1u, intervals.size() );
207
208     BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() );
209     BOOST_CHECK_EQUAL( 100u, intervals.front().upper_bound() );
210     BOOST_CHECK_EQUAL( false, intervals.front().changed() );
211 } // eo SubIntervalsDisjoint()
212
213
214
215 BOOST_AUTO_TEST_CASE(SubIntervalsExact)
216 {
217     Intervals intervals;
218
219     intervals.add( Interval(10, 100) );
220     intervals.sub( Interval(10, 100) );
221
222     BOOST_CHECK_EQUAL( true, intervals.empty() );
223     BOOST_CHECK_EQUAL( 0u, intervals.size() );
224 } // eo SubIntervalsExact()
225
226
227
228 BOOST_AUTO_TEST_CASE(SubIntervalsSplit1)
229 {
230     Intervals intervals;
231
232     intervals.add( Interval(10, 100) );
233     intervals.sub( Interval(20, 40) );
234
235     BOOST_CHECK_EQUAL( false, intervals.empty() );
236     BOOST_CHECK_EQUAL( 2u, intervals.size() );
237
238     BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() );
239     BOOST_CHECK_EQUAL( 20u, intervals.front().upper_bound() );
240
241     BOOST_CHECK_EQUAL( 40u, intervals.back().lower_bound() );
242     BOOST_CHECK_EQUAL( 100u, intervals.back().upper_bound() );
243     BOOST_CHECK_EQUAL( false, intervals.front().changed() );
244     BOOST_CHECK_EQUAL( true, intervals.back().changed() );
245 } // eo SubIntervalsSplit1()
246
247
248 BOOST_AUTO_TEST_CASE(SubIntervalsCutFront)
249 {
250     Intervals intervals;
251
252     intervals.add( Interval(10, 100) );
253     intervals.sub( Interval(10, 20) );
254
255     BOOST_CHECK_EQUAL( false, intervals.empty() );
256     BOOST_CHECK_EQUAL( 1u, intervals.size() );
257
258     BOOST_CHECK_EQUAL( 20u, intervals.front().lower_bound() );
259     BOOST_CHECK_EQUAL( 100u, intervals.front().upper_bound() );
260     BOOST_CHECK_EQUAL( true, intervals.front().changed() );
261 } // eo SubIntervalsCutFront()
262
263
264 BOOST_AUTO_TEST_CASE(SubIntervalsCutBack)
265 {
266     Intervals intervals;
267
268     intervals.add( Interval(10, 100) );
269     intervals.sub( Interval(87, 100) );
270
271     BOOST_CHECK_EQUAL( false, intervals.empty() );
272     BOOST_CHECK_EQUAL( 1u, intervals.size() );
273
274     BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() );
275     BOOST_CHECK_EQUAL( 87u, intervals.front().upper_bound() );
276     BOOST_CHECK_EQUAL( true, intervals.front().changed() );
277 } // eo SubIntervalsCutBack()
278
279
280
281 BOOST_AUTO_TEST_CASE(SubIntervalsCutMore)
282 {
283     Intervals intervals;
284
285     intervals.add( Interval( 10, 100) );
286     intervals.add( Interval(110, 200) );
287     intervals.add( Interval(210, 300) );
288
289     // this should remove the first 2 intervals and cut the third:
290     intervals.sub( Interval(8, 220) );
291
292     BOOST_CHECK_EQUAL( false, intervals.empty() );
293     BOOST_CHECK_EQUAL( 1u, intervals.size() );
294
295     BOOST_CHECK_EQUAL( 220u, intervals.front().lower_bound() );
296     BOOST_CHECK_EQUAL( 300u, intervals.front().upper_bound() );
297     BOOST_CHECK_EQUAL( true, intervals.front().changed() );
298 } // eo SubIntervalsCutMore()
299
300
301 BOOST_AUTO_TEST_CASE(IntervalComparisons)
302 {
303     Intervals intervals1;
304     Intervals intervals2;
305
306     intervals1.add( Interval( 10, 120) );
307
308     intervals2.add( Interval( 10, 110 ) );
309     intervals2.add( Interval( 100, 120 ) );
310
311     BOOST_CHECK_EQUAL( 1u, intervals2.size() );
312
313     BOOST_CHECK( intervals1 == intervals2 );
314     BOOST_CHECK_EQUAL( true, intervals1.contains( intervals2 ));
315     BOOST_CHECK_EQUAL( true, intervals2.contains( intervals1 ));
316
317     intervals2.sub( Interval( 40, 50) );
318
319     BOOST_CHECK( intervals1 != intervals2 );
320     BOOST_CHECK_EQUAL( true, intervals1.contains( intervals2 ));
321     BOOST_CHECK_EQUAL( false, intervals2.contains( intervals1 ));
322 } // eo IntervalComparisons()
323
324
325
326 BOOST_AUTO_TEST_CASE(MonotonicClock)
327 {
328     long sec0, nsec0;
329     long sec1, nsec1;
330
331     bool res = monotonic_clock_gettime(sec0,nsec0);
332     BOOST_CHECK_EQUAL( true, res );
333
334     usleep(250000);
335     res= monotonic_clock_gettime(sec1,nsec1);
336     BOOST_CHECK_EQUAL( true, res);
337
338     long delta_sec = sec1 - sec0;
339     long delta_nsec= nsec1 - nsec0;
340
341     long delta_millisec= ( delta_nsec / 1000000L) + delta_sec * 1000L;
342
343     BOOST_CHECK( delta_millisec >= 250 - /*fuzz*/ 1);
344     BOOST_CHECK( delta_millisec < 300 );
345 } // eo MonotonicClock()
346
347 BOOST_AUTO_TEST_CASE(WeekInvalid)
348 {
349     Week week("99999999");
350     BOOST_CHECK_EQUAL(false, week.is_valid());
351     BOOST_CHECK_EQUAL(string(""), week.get_displaystring());
352 }
353
354 BOOST_AUTO_TEST_CASE(WeekDisplayString1)
355 {
356     Week week("");
357     BOOST_CHECK_EQUAL(true, week.is_valid());
358     BOOST_CHECK_EQUAL(string(""), week.get_displaystring());
359 }
360
361 BOOST_AUTO_TEST_CASE(WeekDisplayString2)
362 {
363     Week week("0123456");
364     BOOST_CHECK_EQUAL(true, week.is_valid());
365     BOOST_CHECK_EQUAL(string("Mon-Sun"), week.get_displaystring());
366 }
367
368 BOOST_AUTO_TEST_CASE(WeekDisplayString3)
369 {
370     Week week("123456");
371     BOOST_CHECK_EQUAL(true, week.is_valid());
372     BOOST_CHECK_EQUAL(string("Mon-Sat"), week.get_displaystring());
373 }
374
375 BOOST_AUTO_TEST_CASE(WeekDisplayString4)
376 {
377     Week week("012345");
378     BOOST_CHECK_EQUAL(true, week.is_valid());
379     BOOST_CHECK_EQUAL(string("Mon-Fri, Sun"), week.get_displaystring());
380 }
381
382 BOOST_AUTO_TEST_CASE(WeekDisplayString5)
383 {
384     Week week("1256");
385     BOOST_CHECK_EQUAL(true, week.is_valid());
386     BOOST_CHECK_EQUAL(string("Mon, Tue, Fri, Sat"), week.get_displaystring());
387 }
388
389 BOOST_AUTO_TEST_CASE(WeekDisplayString6)
390 {
391     Week week("0246");
392     BOOST_CHECK_EQUAL(true, week.is_valid());
393     BOOST_CHECK_EQUAL(string("Tue, Thu, Sat, Sun"), week.get_displaystring());
394 }
395
396 BOOST_AUTO_TEST_CASE(WeekDisplayString7)
397 {
398     Week week("135");
399     BOOST_CHECK_EQUAL(true, week.is_valid());
400     BOOST_CHECK_EQUAL(string("Mon, Wed, Fri"), week.get_displaystring());
401 }
402
403 BOOST_AUTO_TEST_CASE(WeekDisplayString8)
404 {
405     Week week("15");
406     BOOST_CHECK_EQUAL(true, week.is_valid());
407     BOOST_CHECK_EQUAL(string("Mon, Fri"), week.get_displaystring());
408 }
409
410 BOOST_AUTO_TEST_CASE(WeekDisplayString9)
411 {
412     Week week("06");
413     BOOST_CHECK_EQUAL(true, week.is_valid());
414     BOOST_CHECK_EQUAL(string("Sat, Sun"), week.get_displaystring());
415 }
416
417 BOOST_AUTO_TEST_CASE(WeekDisplayString10)
418 {
419     Week week("056");
420     BOOST_CHECK_EQUAL(true, week.is_valid());
421     BOOST_CHECK_EQUAL(string("Fri-Sun"), week.get_displaystring());
422 }
423
424 BOOST_AUTO_TEST_CASE(WeekDisplayString11)
425 {
426     Week week("0");
427     BOOST_CHECK_EQUAL(true, week.is_valid());
428     BOOST_CHECK_EQUAL(string("Sun"), week.get_displaystring());
429 }
430
431 BOOST_AUTO_TEST_CASE(WeekDisplayString12)
432 {
433     Week week("6");
434     BOOST_CHECK_EQUAL(true, week.is_valid());
435     BOOST_CHECK_EQUAL(string("Sat"), week.get_displaystring());
436 }
437
438 BOOST_AUTO_TEST_CASE(WeekDisplayString13)
439 {
440     Week week("123");
441     BOOST_CHECK_EQUAL(true, week.is_valid());
442     BOOST_CHECK_EQUAL(string("Mon-Wed"), week.get_displaystring());
443 }
444
445 BOOST_AUTO_TEST_CASE(FormatFullTime)
446 {
447     time_t seconds = 1318844005;
448
449     BOOST_CHECK_EQUAL("17.10.2011 11:33", format_full_time(seconds));
450 }
451
452 BOOST_AUTO_TEST_CASE(DateToSeconds1)
453 {
454     // no DST
455     BOOST_CHECK_EQUAL(1325372400, date_to_seconds("2012-01-01"));
456 }
457
458 BOOST_AUTO_TEST_CASE(DateToSeconds2)
459 {
460     // DST
461     BOOST_CHECK_EQUAL(1341093600, date_to_seconds("2012-07-01"));
462 }
463
464 BOOST_AUTO_TEST_CASE(FormatISO8601_T)
465 {
466     const time_t moment = 1515492684;
467     BOOST_CHECK_EQUAL("10:11:24",
468                       format_iso8601 (moment, true, false, true, false));
469 }
470
471 BOOST_AUTO_TEST_CASE(FormatISO8601_TZ_local)
472 {
473     const time_t moment = 1515492684;
474     BOOST_CHECK_EQUAL("11:11:24Z+0100",
475                       format_iso8601 (moment, false, false, true, true));
476 }
477
478 BOOST_AUTO_TEST_CASE(FormatISO8601_TZ)
479 {
480     const time_t moment = 1515492684;
481     BOOST_CHECK_EQUAL("10:11:24Z+0000",
482                       format_iso8601 (moment, true, false, true, true));
483 }
484
485 BOOST_AUTO_TEST_CASE(FormatISO8601_DTZ_local)
486 {
487     const time_t moment = 1515492684;
488     BOOST_CHECK_EQUAL("2018-01-09T11:11:24Z+0100",
489                       format_iso8601 (moment, false, true, true, true));
490 }
491
492 BOOST_AUTO_TEST_CASE(FormatISO8601_DTZ)
493 {
494     const time_t moment = 1515492684;
495     BOOST_CHECK_EQUAL("2018-01-09T10:11:24Z+0000",
496                       format_iso8601 (moment, true, true, true, true));
497 }
498
499 BOOST_AUTO_TEST_CASE(FormatISO8601_DT)
500 {
501     const time_t moment = 1515492684;
502     BOOST_CHECK_EQUAL("2018-01-09T10:11:24",
503                       format_iso8601 (moment, true, true, true, false));
504 }
505
506 BOOST_AUTO_TEST_CASE(FormatISO8601_D)
507 {
508     const time_t moment = 1515492684;
509     BOOST_CHECK_EQUAL("2018-01-09",
510                       format_iso8601 (moment, true, true, false, false));
511 }
512
513 BOOST_AUTO_TEST_CASE(FormatISO8601_DTZ_struct_tm)
514 {
515     struct tm helau;
516     helau.tm_sec    = 11;
517     helau.tm_min    = 11;
518     helau.tm_hour   = 11;
519     helau.tm_mday   = 11;
520     helau.tm_mon    = 10;
521     helau.tm_year   = 2018 - 1900;
522     helau.tm_wday   = 0;
523     helau.tm_yday   = 315;
524     helau.tm_isdst  = 0;
525     helau.tm_gmtoff = 0;
526     helau.tm_zone   = NULL;
527
528     BOOST_CHECK_EQUAL("2018-11-11T11:11:11Z+0000",
529                       format_iso8601 (helau, true, true, true));
530 }
531
532 BOOST_AUTO_TEST_CASE(FormatISO8601_DTZ_struct_timespec)
533 {
534     struct timespec ts = { 1541934671, 11 };
535
536     BOOST_CHECK_EQUAL("2018-11-11T11:11:11Z+0000",
537                       format_iso8601 (ts, true, true, true, true));
538 }
539
540 BOOST_AUTO_TEST_SUITE(Clock)
541
542     BOOST_AUTO_TEST_CASE(ctor_simple)
543     {
544         I2n::clock::Time t;
545
546         BOOST_CHECK_EQUAL(t.get_sec  (), 0);
547         BOOST_CHECK_EQUAL(t.get_nsec (), 0);
548     }
549
550     BOOST_AUTO_TEST_CASE(ctor_type)
551     {
552         I2n::clock::Time t (I2n::clock::type::real);
553
554         BOOST_CHECK_EQUAL(t.get_sec  (), 0);
555         BOOST_CHECK_EQUAL(t.get_nsec (), 0);
556     }
557
558     BOOST_AUTO_TEST_CASE(ctor_variant)
559     {
560         I2n::clock::Time t (I2n::clock::type::cpu,
561                             I2n::clock::type::thread);
562
563         BOOST_CHECK_EQUAL(t.get_sec  (), 0);
564         BOOST_CHECK_EQUAL(t.get_nsec (), 0);
565     }
566
567     BOOST_AUTO_TEST_CASE(initializer_now)
568     {
569         boost::optional<I2n::clock::Time> t = I2n::clock::now ();
570
571         BOOST_CHECK(t);
572         BOOST_CHECK_GT(t->get_sec (), 0);
573         BOOST_CHECK_EQUAL(t->err, 0);
574     }
575
576     BOOST_AUTO_TEST_CASE(initializer_zero)
577     {
578         I2n::clock::Time stundenull = I2n::clock::zero ();
579
580         BOOST_CHECK_EQUAL(stundenull.get_sec  (), 0);
581         BOOST_CHECK_EQUAL(stundenull.get_nsec (), 0);
582         BOOST_CHECK_EQUAL(stundenull.err, 0);
583     }
584
585     BOOST_AUTO_TEST_CASE(member_set_now)
586     {
587         I2n::clock::Time t;
588
589         BOOST_CHECK(t.set ());
590
591         BOOST_CHECK_NE(t.get_sec (), 0);
592     }
593
594     BOOST_AUTO_TEST_CASE(member_set_value)
595     {
596         I2n::clock::Time t;
597
598         t.set (42, 42);
599
600         BOOST_CHECK_EQUAL(t.get_sec  (), 42);
601         BOOST_CHECK_EQUAL(t.get_nsec (), 42);
602     }
603
604     BOOST_AUTO_TEST_CASE(member_set_value_type)
605     {
606         I2n::clock::Time t;
607
608         t.set (42, 42, I2n::clock::type::real, I2n::clock::type::exact);
609
610         BOOST_CHECK_EQUAL(t.get_sec  (), 42);
611         BOOST_CHECK_EQUAL(t.get_nsec (), 42);
612     }
613
614     BOOST_AUTO_TEST_CASE(member_add_parts)
615     {
616         I2n::clock::Time t;
617
618         t.set (42, 42);
619         t.add (2187, 2187);
620
621         BOOST_CHECK_EQUAL(t.get_sec  (), 2229);
622         BOOST_CHECK_EQUAL(t.get_nsec (), 2229);
623     }
624
625     BOOST_AUTO_TEST_CASE(member_sub_parts)
626     {
627         I2n::clock::Time t;
628
629         t.set (2, 0L);
630         t.subtract (1, 1L);
631
632         BOOST_CHECK_EQUAL(t.get_sec  (), 0);
633         BOOST_CHECK_EQUAL(t.get_nsec (), 999999999);
634     }
635
636     BOOST_AUTO_TEST_CASE(member_sub_Time)
637     {
638         I2n::clock::Time t1;
639         I2n::clock::Time t2;
640
641         t1.set (42, 42L);
642         t2.set (42,  0L);
643
644         t1.subtract (t2);
645
646         BOOST_CHECK_EQUAL(t1.get_sec  (),  0);
647         BOOST_CHECK_EQUAL(t1.get_nsec (), 42L);
648     }
649
650     BOOST_AUTO_TEST_CASE(member_diff)
651     {
652         static const time_t five = 5 * 365 * 24 * 3600;
653
654         I2n::clock::Time t1 (42, 1337);
655         I2n::clock::Time t2 = t1 + five;;
656         I2n::clock::Time t3 = t1 - five;;
657
658         BOOST_CHECK_EQUAL(t2, I2n::clock::Time ((time_t)42 + five, 1337));
659         BOOST_CHECK_EQUAL(t3, I2n::clock::Time ((time_t)42 - five, 1337));
660         BOOST_CHECK_EQUAL(t1.difference (t3), t3.difference (t1));
661         BOOST_CHECK_EQUAL(t3.difference (t3), t3.difference (t3));
662     }
663
664     BOOST_AUTO_TEST_CASE(op_copyassign)
665     {
666         I2n::clock::Time t1;
667         I2n::clock::Time t2;
668
669         BOOST_CHECK(t1.set ());
670
671         t2 = t1;
672
673         BOOST_CHECK_EQUAL(t1.get_sec  (), t2.get_sec  ());
674         BOOST_CHECK_EQUAL(t1.get_nsec (), t2.get_nsec ());
675     }
676
677     BOOST_AUTO_TEST_CASE(op_equal)
678     {
679         I2n::clock::Time t1;
680         I2n::clock::Time t2;
681
682         BOOST_CHECK(t1.set ());
683         t2 = t1;
684
685         BOOST_CHECK_EQUAL(t1, t2);
686     }
687
688     BOOST_AUTO_TEST_CASE(op_add_Time)
689     {
690         I2n::clock::Time t1;
691         I2n::clock::Time t2;
692         I2n::clock::Time tsum;
693
694         t1.set (2187, 2187);
695         t2.set (1337, 1337);
696         tsum = t1 + t2;
697
698         BOOST_CHECK_EQUAL(tsum.get_sec  (), 3524);
699         BOOST_CHECK_EQUAL(tsum.get_nsec (), 3524);
700     }
701
702     BOOST_AUTO_TEST_CASE(op_add_Time_carry)
703     {
704         I2n::clock::Time t1;
705         I2n::clock::Time t2;
706         I2n::clock::Time tsum;
707
708         t1.set (2187, 2187);
709         t2.set (1300, 37L * 1000 * 1000 * 1000 + 1337);
710
711         tsum = t1 + t2;
712
713         BOOST_CHECK_EQUAL(tsum.get_sec  (), 3524);
714         BOOST_CHECK_EQUAL(tsum.get_nsec (), 3524);
715     }
716
717     BOOST_AUTO_TEST_CASE(op_add_time_t)
718     {
719         I2n::clock::Time t1 (2187, 2187);
720         time_t           t2 = 1337;
721         I2n::clock::Time tsum;
722
723         tsum = t1 + t2;
724
725         BOOST_CHECK_EQUAL(tsum.get_sec  (), 3524);
726         BOOST_CHECK_EQUAL(tsum.get_nsec (), 2187);
727     }
728
729     BOOST_AUTO_TEST_CASE(op_add_time_t_external)
730     {
731         time_t           t1 = 1337;
732         I2n::clock::Time t2 (2187, 2187);
733         I2n::clock::Time tsum;
734
735         tsum = t1 + t2;
736
737         BOOST_CHECK_EQUAL(tsum.get_sec  (), 3524);
738         BOOST_CHECK_EQUAL(tsum.get_nsec (), 2187);
739     }
740
741     BOOST_AUTO_TEST_CASE(op_incr_Time)
742     {
743         I2n::clock::Time t1 (2187, 2187);
744         I2n::clock::Time t2 (1337, 1337);
745
746         t1 += t2;
747
748         BOOST_CHECK_EQUAL(t1.get_sec  (), 3524);
749         BOOST_CHECK_EQUAL(t1.get_nsec (), 3524);
750     }
751
752     BOOST_AUTO_TEST_CASE(op_incr_time_t)
753     {
754         I2n::clock::Time t1 (2187, 2187);
755         time_t           t2 = 1337;
756
757         t1 += t2;
758
759         BOOST_CHECK_EQUAL(t1.get_sec  (), 3524);
760         BOOST_CHECK_EQUAL(t1.get_nsec (), 2187);
761     }
762
763     BOOST_AUTO_TEST_CASE(op_subtract_Time)
764     {
765         I2n::clock::Time t1;
766         I2n::clock::Time t2;
767         I2n::clock::Time tdiff;
768
769         t1.set (2187, 2187);
770         t2.set (1337, 1337);
771         tdiff = t1 - t2;
772
773         BOOST_CHECK_EQUAL(tdiff.get_sec  (), 850);
774         BOOST_CHECK_EQUAL(tdiff.get_nsec (), 850);
775     }
776
777     BOOST_AUTO_TEST_CASE(op_subtract_time_t)
778     {
779         I2n::clock::Time t1 (2187, 2187);
780         time_t           t2 = 1337;
781         I2n::clock::Time tdiff;
782
783         tdiff = t1 - t2;
784
785         BOOST_CHECK_EQUAL(tdiff.get_sec  (), 850);
786         BOOST_CHECK_EQUAL(tdiff.get_nsec (), 2187);
787     }
788
789     BOOST_AUTO_TEST_CASE(op_subtract_time_t_external)
790     {
791         time_t           t1 = 1337;
792         I2n::clock::Time t2 (2187, 2187);
793         I2n::clock::Time tdiff;
794
795         tdiff = t1 - t2;
796
797         BOOST_CHECK_EQUAL(tdiff.get_sec  (), -851);
798         BOOST_CHECK_EQUAL(tdiff.get_nsec (), 999997813);
799     }
800
801     BOOST_AUTO_TEST_CASE(op_decr_Time)
802     {
803         I2n::clock::Time t1 (2187, 2187);
804         I2n::clock::Time t2 (1337, 1337);
805
806         t1 -= t2;
807
808         BOOST_CHECK_EQUAL(t1.get_sec  (), 850);
809         BOOST_CHECK_EQUAL(t1.get_nsec (), 850);
810     }
811
812     BOOST_AUTO_TEST_CASE(op_decr_time_t)
813     {
814         I2n::clock::Time t1 (2187, 2187);
815         time_t           t2 = 1337;
816
817         t1 -= t2;
818
819         BOOST_CHECK_EQUAL(t1.get_sec  (), 850);
820         BOOST_CHECK_EQUAL(t1.get_nsec (), 2187);
821     }
822
823     BOOST_AUTO_TEST_CASE(op_mult_scale)
824     {
825         I2n::clock::Time t1;
826         I2n::clock::Time t2;
827
828         t1.set (1, 1);
829         t2 = t1 * 42;
830
831         BOOST_CHECK_EQUAL(t2.get_sec  (), 42);
832         BOOST_CHECK_EQUAL(t2.get_nsec (), 42);
833     }
834
835     BOOST_AUTO_TEST_CASE(op_mult_mutate)
836     {
837         I2n::clock::Time t1 (  42, 42);
838         I2n::clock::Time t2 (1337,  0);
839
840         t1 *=   2;
841         t2 *= -10;
842
843         BOOST_CHECK_EQUAL(t1.get_sec  (),     84);
844         BOOST_CHECK_EQUAL(t1.get_nsec (),     84);
845         BOOST_CHECK_EQUAL(t2.get_sec  (), -13370);
846     }
847
848     BOOST_AUTO_TEST_CASE(op_mult_scale_carry)
849     {
850         I2n::clock::Time t1;
851         I2n::clock::Time t2;
852
853         t1.set (1, 500 * 1000 * 1000);
854         t2 = t1 * 3;
855
856         BOOST_CHECK_EQUAL(t2.get_sec  (),  4);
857         BOOST_CHECK_EQUAL(t2.get_nsec (),  500 * 1000 * 1000);
858     }
859
860     BOOST_AUTO_TEST_CASE(op_equals)
861     {
862         I2n::clock::Time t1;
863         I2n::clock::Time t2;
864
865         t1.set (50, 50);
866         t2.set (50, 50);
867
868         BOOST_CHECK_EQUAL(t1, t2);
869     }
870
871     BOOST_AUTO_TEST_CASE(compare_equal)
872     {
873         I2n::clock::Time t1;
874         I2n::clock::Time t2;
875
876         t1.set (42, 42);
877         t2.set (42, 42);
878
879         BOOST_CHECK_EQUAL(I2n::clock::compare (t1, t2), 0);
880     }
881
882     BOOST_AUTO_TEST_CASE(compare_equal_type)
883     {
884         I2n::clock::Time t1 (42, 42, I2n::clock::type::real);
885         I2n::clock::Time t2 (42, 42, I2n::clock::type::cpu);
886         I2n::clock::Time t3 (42,  0, I2n::clock::type::real);
887         I2n::clock::Time t4 (42, 42, I2n::clock::type::real);
888
889         BOOST_CHECK_NE(t1, t2);
890         BOOST_CHECK_NE(t1, t3);
891         BOOST_CHECK_EQUAL(t1, t4);
892     }
893
894     BOOST_AUTO_TEST_CASE(compare_ne_sec)
895     {
896         I2n::clock::Time t1;
897         I2n::clock::Time t2;
898
899         t1.set (  42, 42);
900         t2.set (1337, 42);
901
902         BOOST_CHECK_EQUAL(I2n::clock::compare (t1, t2), -1);
903         BOOST_CHECK_EQUAL(I2n::clock::compare (t2, t1),  1);
904     }
905
906     BOOST_AUTO_TEST_CASE(compare_ne_nsec)
907     {
908         I2n::clock::Time t1;
909         I2n::clock::Time t2;
910
911         t1.set (42,   42);
912         t2.set (42, 1337);
913
914         BOOST_CHECK_EQUAL(I2n::clock::compare (t1, t2), -1);
915         BOOST_CHECK_EQUAL(I2n::clock::compare (t2, t1),  1);
916     }
917
918     BOOST_AUTO_TEST_CASE(compare_ne_both)
919     {
920         I2n::clock::Time t1;
921         I2n::clock::Time t2;
922
923         t1.set (42, 2187);
924         t2.set (23, 1337);
925
926         BOOST_CHECK_EQUAL(I2n::clock::compare (t1, t2),  1);
927         BOOST_CHECK_EQUAL(I2n::clock::compare (t2, t1), -1);
928     }
929
930     BOOST_AUTO_TEST_CASE(op_ineq_sec)
931     {
932         I2n::clock::Time t1 (1337);
933         I2n::clock::Time t2 (2187);
934
935         BOOST_CHECK_LT(t1, t2);
936         BOOST_CHECK_GT(t2, t1);
937     }
938
939     BOOST_AUTO_TEST_CASE(op_ineq_nsec)
940     {
941         I2n::clock::Time t1 (1337, 23);
942         I2n::clock::Time t2 (1337, 42);
943
944         BOOST_CHECK_LT(t1, t2);
945         BOOST_CHECK_GT(t2, t1);
946     }
947
948     BOOST_AUTO_TEST_CASE(op_ineq_both)
949     {
950         I2n::clock::Time t1 (2187, 23);
951         I2n::clock::Time t2 (1337, 42);
952
953         BOOST_CHECK_LT(t2, t1);
954         BOOST_CHECK_GT(t1, t2);
955     }
956
957     BOOST_AUTO_TEST_CASE(op_eq_time_t)
958     {
959         boost::optional<I2n::clock::Time> t1  = I2n::clock::now ();
960         const time_t                      t2  = time (NULL); /* race here */
961
962         *t1 -= (time_t)42;
963
964         BOOST_CHECK_NE(*t1,  t2);
965         BOOST_CHECK_LT(*t1,  t2);
966         BOOST_CHECK_GT( t2, *t1);
967     }
968
969     BOOST_AUTO_TEST_CASE(containers_list)
970     {
971         std::list<I2n::clock::Time> ts;
972
973         ts.push_back (I2n::clock::zero ());
974         ts.push_back (I2n::clock::zero ());
975
976         BOOST_CHECK_EQUAL(ts.size (), 2);
977     }
978
979     BOOST_AUTO_TEST_CASE(containers_vec)
980     {
981         std::vector<I2n::clock::Time> ts;
982
983         ts.push_back (I2n::clock::zero ());
984         ts.push_back (I2n::clock::zero ());
985
986         BOOST_CHECK_EQUAL(ts.size (), 2);
987     }
988
989     BOOST_AUTO_TEST_CASE(containers_set)
990     {
991         std::set<I2n::clock::Time> ts;
992
993         ts.insert (I2n::clock::zero ());
994         ts.insert (I2n::clock::Time (42, 2187));
995         ts.insert (I2n::clock::zero ());
996
997         BOOST_CHECK_EQUAL(ts.size (), 2);
998     }
999
1000     BOOST_AUTO_TEST_CASE(FormatISO8601_T)
1001     {
1002         I2n::clock::Time t (42, 42);
1003         boost::optional<std::string> s = t.format_iso8601 (true, false, true, false);
1004
1005         BOOST_CHECK_EQUAL("00:00:42", *s);
1006     }
1007
1008     BOOST_AUTO_TEST_CASE(FormatISO8601_DT)
1009     {
1010         I2n::clock::Time t (1541934671, 0);
1011         boost::optional<std::string> s = t.format_iso8601 (true, true, true, false);
1012
1013         BOOST_CHECK_EQUAL("2018-11-11T11:11:11", *s);
1014     }
1015
1016     BOOST_AUTO_TEST_CASE(FormatISO8601_DTZ)
1017     {
1018         I2n::clock::Time t (1541934671, 0);
1019         boost::optional<std::string> s = t.format_iso8601 (true, true, true, true);
1020
1021         BOOST_CHECK_EQUAL("2018-11-11T11:11:11Z+0000", *s);
1022     }
1023
1024     BOOST_AUTO_TEST_CASE(Format_make_nice_time)
1025     {
1026         I2n::clock::Time t (111111, 0);
1027         boost::optional<std::string> s = t.make_nice_time ();
1028
1029         BOOST_CHECK_EQUAL("1 day, 06:51:51", *s);
1030     }
1031
1032     BOOST_AUTO_TEST_CASE(Format_format_full_time)
1033     {
1034         I2n::clock::Time t (1541934671, 0);
1035         /*
1036          * brr, the old formatters use localtime without a way to opt out of
1037          * it!
1038          */
1039         setenv ("TZ", "UTC", 1);
1040         tzset();
1041         boost::optional<std::string> s = t.format_full_time ();
1042
1043         BOOST_CHECK_EQUAL("11.11.2018 11:11", *s);
1044     }
1045
1046     BOOST_AUTO_TEST_CASE(Format_format_date)
1047     {
1048         I2n::clock::Time t (1541934671, 0);
1049         boost::optional<std::string> s = t.format_date ();
1050
1051         BOOST_CHECK_EQUAL("11.11.2018", *s);
1052     }
1053
1054     BOOST_AUTO_TEST_CASE(FromString_iso8601_full)
1055     {
1056         const std::string in1 ("0001-01-01T00:00:00Z+0000");
1057         const std::string in2 ("2018-11-11T11:11:11Z+0000");
1058
1059         boost::optional<I2n::clock::Time> t1 = I2n::clock::time_of_iso8601 (in1);
1060         boost::optional<I2n::clock::Time> t2 = I2n::clock::time_of_iso8601 (in2);
1061
1062         BOOST_CHECK(t1);
1063         BOOST_CHECK(t2);
1064
1065         BOOST_CHECK_EQUAL(*t1->format_iso8601 (), in1);
1066         BOOST_CHECK_EQUAL(*t2->format_iso8601 (), in2);
1067     }
1068
1069     BOOST_AUTO_TEST_CASE(FromString_iso8601_full_negyear)
1070     {
1071         const std::string in1 ("-0001-01-01T00:00:00Z+0000");
1072         const std::string in2 ("-2018-11-11T11:11:11Z+0000");
1073
1074         boost::optional<I2n::clock::Time> t1 = I2n::clock::time_of_iso8601 (in1);
1075         boost::optional<I2n::clock::Time> t2 = I2n::clock::time_of_iso8601 (in2);
1076
1077         BOOST_CHECK(t1);
1078         BOOST_CHECK(t2);
1079
1080         BOOST_CHECK_EQUAL(*t1->format_iso8601 (), in1);
1081         BOOST_CHECK_EQUAL(*t2->format_iso8601 (), in2);
1082     }
1083
1084     BOOST_AUTO_TEST_CASE(FromString_iso8601_partial)
1085     {
1086         const std::string in1 ("2018-11-11T11:11:11");
1087         const std::string in2 ("2018-11-11");
1088         const std::string in3 ("11:11:11");
1089
1090         boost::optional<I2n::clock::Time> t1 =
1091             I2n::clock::time_of_iso8601 (in1, true, true, false);
1092         boost::optional<I2n::clock::Time> t2 =
1093             I2n::clock::time_of_iso8601 (in2, true, false, false);
1094         boost::optional<I2n::clock::Time> t3 =
1095             I2n::clock::time_of_iso8601 (in3, false, true, false);
1096
1097         BOOST_CHECK(t1);
1098         BOOST_CHECK(t2);
1099         BOOST_CHECK(t3);
1100         /*
1101          * We test for the difference here which is zero if the number is
1102          * correct but causes the difference from the expected value to be
1103          * printed in case the test fails.
1104          */
1105         BOOST_CHECK_EQUAL(*t1->format_iso8601 (true,  true,  true, false), in1);
1106         BOOST_CHECK_EQUAL(*t2->format_iso8601 (true,  true, false, false), in2);
1107         BOOST_CHECK_EQUAL(*t3->format_iso8601 (true, false,  true, false), in3);
1108     }
1109
1110 BOOST_AUTO_TEST_SUITE_END() /* [Clock] */
1111
1112 BOOST_AUTO_TEST_SUITE_END()