1 //  Copyright 2011 Vicente J. Botet Escriba
2 //  Copyright (c) Microsoft Corporation 2014
3 //  Distributed under the Boost Software License, Version 1.0.
4 //  See http://www.boost.org/LICENSE_1_0.txt
5 
6 #include <boost/chrono/chrono_io.hpp>
7 #include <sstream>
8 #include <boost/detail/lightweight_test.hpp>
9 #include <boost/chrono/system_clocks.hpp>
10 #include <boost/chrono/thread_clock.hpp>
11 #include <boost/chrono/process_cpu_clocks.hpp>
12 #include <locale>
13 #include <ctime>
14 #include <cstdio>
15 
16 template <typename Clock, typename D>
test_good_prefix(const char * str,D d)17 void test_good_prefix(const char* str, D d)
18 {
19   std::ostringstream out;
20   boost::chrono::time_point<Clock, D> tp(d);
21   out << tp;
22   BOOST_TEST(out.good());
23   //std::cout << "Expected= " << std::string(str) + boost::chrono::clock_string<Clock, char>::since() << std::endl;
24   //std::cout << "Obtained= " << out.str() << std::endl;
25   BOOST_TEST( (out.str() == std::string(str) + boost::chrono::clock_string<Clock, char>::since()));
26 }
27 
28 template <typename D>
test_good_prefix_system_clock(const char * str,D d)29 void test_good_prefix_system_clock(const char* str, D d)
30 {
31   typedef boost::chrono::system_clock Clock;
32 
33   std::ostringstream out;
34   boost::chrono::time_point<Clock, D> tp(d);
35   out << tp;
36   BOOST_TEST(out.good());
37 
38   std::cout << "Expected= " << str << std::endl;
39   std::cout << "Obtained= " << out.str() << std::endl;
40   BOOST_TEST( (out.str() == std::string(str) ));
41 }
42 
43 template <typename Clock, typename D>
test_good_symbol(const char * str,D d)44 void test_good_symbol(const char* str, D d)
45 {
46   std::ostringstream out;
47   boost::chrono::time_point<Clock, D> tp(d);
48 #if BOOST_CHRONO_VERSION>=2
49   out << boost::chrono::duration_fmt(boost::chrono::duration_style::symbol) << tp;
50 #else
51   out << boost::chrono::duration_short << tp;
52 #endif
53   BOOST_TEST(out.good());
54   BOOST_TEST( (out.str() == std::string(str) + boost::chrono::clock_string<Clock, char>::since()));
55 }
56 
57 #if BOOST_CHRONO_VERSION>=2
58 template <typename D>
test_good_symbol_system_clock(const char * str,D d)59 void test_good_symbol_system_clock(const char* str, D d)
60 {
61   typedef boost::chrono::system_clock Clock;
62 
63   std::ostringstream out;
64   boost::chrono::time_point<Clock, D> tp(d);
65   out << boost::chrono::duration_fmt(boost::chrono::duration_style::symbol) << tp;
66   BOOST_TEST(out.good());
67   std::cout << "Expected= " << str << std::endl;
68   std::cout << "Obtained= " << out.str() << std::endl;
69   BOOST_TEST( (out.str() == std::string(str) ));
70 }
71 
72 template <typename D>
test_good_utc_fmt_system_clock(const char * str,const char * fmt,D d)73 void test_good_utc_fmt_system_clock(const char* str, const char* fmt, D d)
74 {
75   typedef boost::chrono::system_clock Clock;
76 
77   std::ostringstream out;
78   boost::chrono::time_point<Clock, D> tp(d);
79   boost::chrono::time_fmt_io_saver<> fmts(out);
80   boost::chrono::timezone_io_saver tzs(out);
81   out << time_fmt(boost::chrono::timezone::utc, fmt)  << tp;
82   BOOST_TEST(out.good());
83   std::cout << "Expected= " << str << std::endl;
84   std::cout << "Obtained= " << out.str() << std::endl;
85   BOOST_TEST_EQ( out.str() , std::string(str) );
86 }
87 
88 template <typename D>
test_good_utc_fmt_system_clock2(const char * str,const char * fmt,D d)89 void test_good_utc_fmt_system_clock2(const char* str, const char* fmt, D d)
90 {
91   typedef boost::chrono::system_clock Clock;
92 
93   std::ostringstream out;
94   boost::chrono::time_point<Clock, D> tp(d);
95   boost::chrono::time_fmt_io_saver<> fmts(out, fmt);
96   boost::chrono::timezone_io_saver tzs(out, boost::chrono::timezone::utc);
97   out << tp;
98   BOOST_TEST(out.good());
99   std::cout << "Expected= " << str << std::endl;
100   std::cout << "Obtained= " << out.str() << std::endl;
101   BOOST_TEST_EQ( out.str() , std::string(str) );
102 }
103 
104 template<typename Clock, typename D>
test_good(const char * str,D d,boost::chrono::duration_style style)105 void test_good(const char* str, D d, boost::chrono::duration_style style)
106 {
107   std::ostringstream out;
108   boost::chrono::time_point<Clock,D> tp(d);
109   out << boost::chrono::duration_fmt(style) << tp;
110   BOOST_TEST(out.good());
111   BOOST_TEST((out.str() == std::string(str)+boost::chrono::clock_string<Clock,char>::since()));
112 }
113 
114 template<typename D>
test_good_system_clock(const char * str,D d,boost::chrono::duration_style style)115 void test_good_system_clock(const char* str, D d, boost::chrono::duration_style style)
116 {
117   typedef boost::chrono::system_clock Clock;
118 
119   std::ostringstream out;
120   boost::chrono::time_point<Clock,D> tp(d);
121   out << boost::chrono::duration_fmt(style) << tp;
122   BOOST_TEST(out.good());
123   std::cout << "Expected= " << str << std::endl;
124   std::cout << "Obtained= " << out.str() << std::endl;
125   BOOST_TEST((out.str() == std::string(str) ));
126 }
127 #endif
128 
129 template <typename Clock>
check_all()130 void check_all()
131 {
132   using namespace boost::chrono;
133   using namespace boost;
134 
135 #if BOOST_CHRONO_VERSION>=2
136   test_good<Clock>("2 hours", hours(2), duration_style::prefix);
137   test_good<Clock>("2 h", hours(2), duration_style::symbol);
138 #endif
139 
140   test_good_prefix<Clock> ("2 hours", hours(2));
141   test_good_prefix<Clock> ("2 minutes", minutes(2));
142   test_good_prefix<Clock> ("2 seconds", seconds(2));
143   test_good_prefix<Clock> ("1 second", seconds(1));
144   test_good_prefix<Clock> ("-1 second", seconds(-1));
145   test_good_prefix<Clock> ("0 seconds", seconds(0));
146   test_good_prefix<Clock> ("2 milliseconds", milliseconds(2));
147   test_good_prefix<Clock> ("2 microseconds", microseconds(2));
148   test_good_prefix<Clock> ("2 nanoseconds", nanoseconds(2));
149   test_good_prefix<Clock> ("2 deciseconds", duration<boost::int_least64_t, deci> (2));
150   test_good_prefix<Clock> ("2 [1/30]seconds", duration<boost::int_least64_t, ratio<1, 30> > (2));
151 
152   test_good_symbol<Clock> ("2 h", hours(2));
153 #if BOOST_CHRONO_VERSION>=2
154   test_good_symbol<Clock>("2 min", minutes(2));
155 #else
156   test_good_symbol<Clock> ("2 m", minutes(2));
157 #endif
158   test_good_symbol<Clock> ("2 s", seconds(2));
159   test_good_symbol<Clock> ("2 ms", milliseconds(2));
160   test_good_symbol<Clock> ("2 ns", nanoseconds(2));
161   test_good_symbol<Clock> ("2 ds", duration<boost::int_least64_t, deci> (2));
162   test_good_symbol<Clock> ("2 [1/30]s", duration<boost::int_least64_t, ratio<1, 30> > (2));
163 }
164 
165 #if BOOST_CHRONO_VERSION >= 2
check_all_system_clock()166 void check_all_system_clock()
167 {
168   using namespace boost::chrono;
169   using namespace boost;
170 
171   test_good_system_clock("1970-01-01 02:00:00.000000000 +0000", hours(2), duration_style::prefix);
172   test_good_system_clock("1970-01-01 02:00:00.000000000 +0000", hours(2), duration_style::symbol);
173 
174   test_good_prefix_system_clock("1970-01-01 02:00:00.000000000 +0000", hours(2));
175   test_good_prefix_system_clock("1970-01-01 00:02:00.000000000 +0000", minutes(2));
176   test_good_prefix_system_clock("1970-01-01 00:00:02.000000000 +0000", seconds(2));
177   test_good_prefix_system_clock("1970-01-01 00:00:01.000000000 +0000", seconds(1));
178   test_good_prefix_system_clock("1969-12-31 23:59:59.000000000 +0000", seconds(-1));
179   test_good_prefix_system_clock("1970-01-01 00:00:00.000000000 +0000", seconds(0));
180   test_good_prefix_system_clock("1970-01-01 00:00:00.002000000 +0000", milliseconds(2));
181   test_good_prefix_system_clock("1970-01-01 00:00:00.000002000 +0000", microseconds(2));
182   test_good_prefix_system_clock("1970-01-01 00:00:00.000000002 +0000", nanoseconds(2));
183   test_good_prefix_system_clock("1970-01-01 00:00:00.200000000 +0000", duration<boost::int_least64_t, deci> (2));
184   test_good_prefix_system_clock("1970-01-01 00:00:00.066666667 +0000", duration<boost::int_least64_t, ratio<1, 30> > (2));
185 
186   test_good_symbol_system_clock("1970-01-01 02:00:00.000000000 +0000", hours(2));
187   test_good_symbol_system_clock("1970-01-01 00:02:00.000000000 +0000", minutes(2));
188   test_good_symbol_system_clock("1970-01-01 00:00:02.000000000 +0000", seconds(2));
189   test_good_symbol_system_clock("1970-01-01 00:00:00.002000000 +0000", milliseconds(2));
190   test_good_symbol_system_clock("1970-01-01 00:00:00.000000002 +0000", nanoseconds(2));
191   test_good_symbol_system_clock("1970-01-01 00:00:00.200000000 +0000", duration<boost::int_least64_t, deci> (2));
192   test_good_symbol_system_clock("1970-01-01 00:00:00.066666667 +0000", duration<boost::int_least64_t, ratio<1, 30> > (2));
193 
194   test_good_utc_fmt_system_clock("1970-01-01 02:00:00", "%Y-%m-%d %H:%M:%S", hours(2));
195   test_good_utc_fmt_system_clock("1970-01-01 02", "%Y-%m-%d %H", hours(2));
196 #if ! defined(BOOST_CHRONO_WINDOWS_API)
197   test_good_utc_fmt_system_clock ("1970-01-01 02:00:00", "%Y-%m-%d %T", hours(2));
198   test_good_utc_fmt_system_clock ("1970-01-01 02:00", "%Y-%m-%d %R", hours(2));
199   test_good_utc_fmt_system_clock ("% 1970-01-01 02:00", "%% %Y-%m-%d %R", hours(2));
200   test_good_utc_fmt_system_clock ("1970-01-01 02:00 Thursday January", "%Y-%m-%d %R %A %B", hours(2));
201 #endif
202   test_good_utc_fmt_system_clock2("1970-01-01 02:00:00", "%Y-%m-%d %H:%M:%S", hours(2));
203   test_good_utc_fmt_system_clock2("1970-01-01 02", "%Y-%m-%d %H", hours(2));
204 #if ! defined(BOOST_CHRONO_WINDOWS_API)
205   test_good_utc_fmt_system_clock2 ("1970-01-01 02:00:00", "%Y-%m-%d %T", hours(2));
206   test_good_utc_fmt_system_clock2 ("1970-01-01 02:00", "%Y-%m-%d %R", hours(2));
207   test_good_utc_fmt_system_clock2 ("% 1970-01-01 02:00", "%% %Y-%m-%d %R", hours(2));
208   test_good_utc_fmt_system_clock2 ("1970-01-01 02:00 Thursday January", "%Y-%m-%d %R %A %B", hours(2));
209 #endif
210 }
211 
212 
213 #endif
214 #if defined  BOOST_CHRONO_INTERNAL_GMTIME
215 #elif BOOST_CHRONO_VERSION == 2
test_gmtime(std::time_t t)216 void test_gmtime(std::time_t t)
217 {
218   std::cout << "t    " << t << std::endl;
219   std::puts(ctime(&t));
220   std::tm tm;
221   std::memset(&tm, 0, sizeof(std::tm));
222   if (boost::chrono::detail::internal_gmtime(&t, &tm))
223   {
224     tm.tm_isdst = -1;
225     (void)mktime(&tm);
226     std::tm tm2;
227     std::memset(&tm2, 0, sizeof(std::tm));
228     if (gmtime_r(&t, &tm2))
229     {
230       tm2.tm_isdst = -1;
231       (void)mktime(&tm2);
232 
233       BOOST_TEST_EQ( tm.tm_year , tm2.tm_year );
234       BOOST_TEST_EQ( tm.tm_mon , tm2.tm_mon );
235       BOOST_TEST_EQ( tm.tm_mday , tm2.tm_mday );
236       BOOST_TEST_EQ( tm.tm_hour , tm2.tm_hour);
237       BOOST_TEST_EQ( tm.tm_min , tm2.tm_min );
238       BOOST_TEST_EQ( tm.tm_sec , tm2.tm_sec );
239       BOOST_TEST_EQ( tm.tm_wday , tm2.tm_wday );
240       BOOST_TEST_EQ( tm.tm_yday , tm2.tm_yday );
241       BOOST_TEST_EQ( tm.tm_isdst , tm2.tm_isdst );
242     }
243   }
244 
245 }
246 #endif
247 
248 
main()249 int main()
250 {
251 #if defined BOOST_CHRONO_INTERNAL_GMTIME
252 #elif BOOST_CHRONO_VERSION == 2
253   test_gmtime(  0 );
254   test_gmtime( -1  );
255   test_gmtime( +1  );
256   test_gmtime(  0 - (3600 * 24) );
257   test_gmtime( -1 - (3600 * 24) );
258   test_gmtime( +1 - (3600 * 24) );
259   test_gmtime(  0 + (3600 * 24) );
260   test_gmtime( -1 + (3600 * 24) );
261   test_gmtime( +1 + (3600 * 24) );
262   test_gmtime(  0 + 365*(3600 * 24) );
263   test_gmtime(  0 + 10LL*365*(3600 * 24) );
264   test_gmtime(  0 + 15LL*365*(3600 * 24) );
265   test_gmtime(  0 + 17LL*365*(3600 * 24) );
266   test_gmtime(  0 + 18LL*365*(3600 * 24) );
267   test_gmtime(  0 + 19LL*365*(3600 * 24) );
268   test_gmtime(  0 + 19LL*365*(3600 * 24)+ (3600 * 24));
269   test_gmtime(  0 + 19LL*365*(3600 * 24)+ 3*(3600 * 24));
270   test_gmtime(  0 + 19LL*365*(3600 * 24)+ 4*(3600 * 24));
271   test_gmtime(  0 + 20LL*365*(3600 * 24) );
272   test_gmtime(  0 + 40LL*365*(3600 * 24) );
273 #endif
274 
275   std::cout << "high_resolution_clock=" << std::endl;
276   check_all<boost::chrono::high_resolution_clock> ();
277 #ifdef BOOST_CHRONO_HAS_CLOCK_STEADY
278   std::cout << "steady_clock=" << std::endl;
279   check_all<boost::chrono::steady_clock> ();
280 #endif
281   std::cout << "system_clock=" << std::endl;
282 #if BOOST_CHRONO_VERSION >= 2  && defined BOOST_CHRONO_PROVIDES_DATE_IO_FOR_SYSTEM_CLOCK_TIME_POINT
283   check_all_system_clock();
284 #else
285   check_all<boost::chrono::system_clock> ();
286 #endif
287 
288 #if defined(BOOST_CHRONO_HAS_THREAD_CLOCK)
289   std::cout << "thread_clock="<< std::endl;
290   check_all<boost::chrono::thread_clock>();
291 #endif
292 
293 #if defined(BOOST_CHRONO_HAS_PROCESS_CLOCKS)
294   std::cout << "process_real_cpu_clock=" << std::endl;
295   check_all<boost::chrono::process_real_cpu_clock> ();
296 #if ! BOOST_OS_WINDOWS || BOOST_PLAT_WINDOWS_DESKTOP
297   std::cout << "process_user_cpu_clock=" << std::endl;
298   check_all<boost::chrono::process_user_cpu_clock> ();
299   std::cout << "process_system_cpu_clock=" << std::endl;
300   check_all<boost::chrono::process_system_cpu_clock> ();
301   std::cout << "process_cpu_clock=" << std::endl;
302   check_all<boost::chrono::process_cpu_clock> ();
303 #endif
304 #endif
305 
306 #if defined BOOST_CHRONO_INTERNAL_GMTIME
307 #elif BOOST_CHRONO_VERSION == 2
308   boost::chrono::system_clock::time_point tp = boost::chrono::system_clock::now();
309   std::cout << tp << std::endl;
310   time_t t = boost::chrono::system_clock::to_time_t(tp);
311   test_gmtime(  t );
312 #endif
313 
314   return boost::report_errors();
315 
316 }
317 
318