1414#include <os.h>
1515
1616#include "test_support.h"
17- #include <time.h> /* for time() function */
17+
18+ #include <stdlib.h> /* for getenv(), setenv(), unsetenv() functions */
19+ #include <time.h> /* for localtime(), time(), tzet() functions */
1820
1921/* test os_random */
2022static void test_os_random ( void * * state )
@@ -98,10 +100,11 @@ static void test_os_time_elapsed( void **state )
98100 os_time_sleep ( test_times [i ], OS_FALSE );
99101 os_time_elapsed ( & time_stamp , & time_elapsed );
100102
101- /* depending on clock boundry time may be out by
102- * 1 second */
103- assert_false ( time_elapsed != test_times [i ] &&
104- time_elapsed != test_times [i ] + 1u );
103+ /* depending on clock boundry and system calls, time may be
104+ * out by as much as 5% (+ 1 millisecond) */
105+ assert_in_range ( time_elapsed ,
106+ test_times [i ],
107+ (os_millisecond_t )((double )test_times [i ] * 1.05 ) + 1u );
105108 }
106109}
107110
@@ -110,92 +113,255 @@ static void test_os_time_format( void **state )
110113{
111114 struct symbol_result_table {
112115 const char * symbol ;
113- const char * gmt_result ;
114- const char * local_result ;
116+ const char * result ;
115117 };
118+ unsigned int i = 0u ;
119+ time_t tz_offset = 0 ; /* time zone offset in seconds */
120+ int to_local_time = 0 ;
121+ os_timestamp_t ts = 0u ;
116122
117- unsigned int i ;
118123 struct symbol_result_table tests [] = {
119- { "%%a = %a" , "%a = Thu" , "%a = Wed" },
120- { "%%A = %A" , "%A = Thursday" , "%A = Wednesday" },
121- { "%%b = %b" , "%b = Jan" , "%b = Dec" },
122- { "%%B = %B" , "%B = January" , "%B = December" },
124+ { "%%a = %a" , "%a = Thu" },
125+ { "%%A = %A" , "%A = Thursday" },
126+ { "%%b = %b" , "%b = Jan" },
127+ { "%%B = %B" , "%B = January" },
123128#ifdef _WIN32
124- { "%%c = %c" , "%c = 1/1/1970" , "%c = 12/31/1969" },
129+ { "%%c = %c" , "%c = 1/1/1970" },
125130#else
126- { "%%c = %c" , "%c = Thu Jan 1 00:00:00 1970" , "%c = Wed Dec 31 19:00:00 1969" },
131+ { "%%c = %c" , "%c = Thu Jan 1 00:00:00 1970" },
127132#endif
128- { "%%C = %C" , "%C = 19" , "%C = 19" },
129- { "%%d = %d" , "%d = 01" , "%d = 31" },
130- { "%%D = %D" , "%D = 01/01/70" , "%D = 12/31/69" },
131- { "%%e = %e" , "%e = 1" , "%e = 31" },
132- /* { "%%E = %E", "%E = ", "%E = " }, - modifier symbol */
133- { "%%F = %F" , "%F = 1970-01-01" , "%F = 1969-12-31" },
134- #ifdef _WIN32
135- { "%%G = %G" , "%G = 1970" , "%G = 1969" },
136- { "%%g = %g" , "%g = 70" , "%g = 69" },
133+ { "%%C = %C" , "%C = 19" },
134+ { "%%d = %d" , "%d = 01" },
135+ { "%%D = %D" , "%D = 01/01/70" },
136+ { "%%e = %e" , "%e = 1" },
137+ /* { "%%E = %E", "%E = " }, - modifier symbol */
138+ { "%%F = %F" , "%F = 1970-01-01" },
139+ { "%%G = %G" , "%G = 1970" },
140+ { "%%g = %g" , "%g = 70" },
141+ { "%%h = %h" , "%h = Jan" },
142+ { "%%H = %H" , "%H = 00" },
143+ { "%%I = %I" , "%I = 12" },
144+ { "%%j = %j" , "%j = 001" },
145+ { "%%k = %k" , "%k = 0" },
146+ { "%%l = %l" , "%l = 12" },
147+ { "%%m = %m" , "%m = 01" },
148+ { "%%M = %M" , "%M = 00" },
149+ { "%%n = %n" , "%n = \n" },
150+ /* { "%%O = %O", "%O = " }, - modifier symbol */
151+ { "%%p = %p" , "%p = AM" },
152+ #ifdef __APPLE__
153+ { "%%P = %P" , "%P = P" },
137154#else
138- { "%%G = %G" , "%G = 1970" , "%G = 1970" },
139- { "%%g = %g" , "%g = 70" , "%g = 70" },
155+ { "%%P = %P" , "%P = am" },
140156#endif
141- { "%%h = %h" , "%h = Jan" , "%h = Dec" },
142- { "%%H = %H" , "%H = 00" , "%H = 19" },
143- { "%%I = %I" , "%I = 12" , "%I = 07" },
144- { "%%j = %j" , "%j = 001" , "%j = 365" },
145- { "%%k = %k" , "%k = 0" , "%k = 19" },
146- { "%%l = %l" , "%l = 12" , "%l = 7" },
147- { "%%m = %m" , "%m = 01" , "%m = 12" },
148- { "%%M = %M" , "%M = 00" , "%M = 00" },
149- { "%%n = %n" , "%n = \n" , "%n = \n" },
150- /* { "%%O = %O", "%O = ", "%O = " }, - modifier symbol */
151- { "%%p = %p" , "%p = AM" , "%p = PM" },
152- { "%%P = %P" , "%P = am" , "%P = pm" },
153- { "%%r = %r" , "%r = 12:00:00 AM" , "%r = 07:00:00 PM" },
154- { "%%R = %R" , "%R = 00:00" , "%R = 19:00" },
155- /*{ "%%s = %s", "%s = 18000", "%s = 18000" }, - system offset from epoch using current timestamp */
156- { "%%S = %S" , "%S = 00" , "%S = 00" },
157- { "%%t = %t" , "%t = \t" , "%t = \t" },
158- { "%%T = %T" , "%T = 00:00:00" , "%T = 19:00:00" },
159- { "%%u = %u" , "%u = 4" , "%u = 3" },
160- { "%%U = %U" , "%U = 00" , "%U = 52" },
161- { "%%V = %V" , "%V = 01" , "%V = 01" },
162- { "%%w = %w" , "%w = 4" , "%w = 3" },
163- { "%%W = %W" , "%W = 00" , "%W = 52" },
157+ { "%%r = %r" , "%r = 12:00:00 AM" },
158+ { "%%R = %R" , "%R = 00:00" },
159+ /*{ "%%s = %s", "%s = 18000" }, - system offset from epoch using current timestamp */
160+ { "%%S = %S" , "%S = 00" },
161+ { "%%t = %t" , "%t = \t" },
162+ { "%%T = %T" , "%T = 00:00:00" },
163+ { "%%u = %u" , "%u = 4" },
164+ { "%%U = %U" , "%U = 00" },
165+ { "%%V = %V" , "%V = 01" },
166+ { "%%w = %w" , "%w = 4" },
167+ { "%%W = %W" , "%W = 00" },
164168#ifdef _WIN32
165- { "%%x = %x" , "%x = 1/1/1970" , "%x = 12/31/1969" },
166- { "%%X = %X" , "%X = 12:00:00 AM" , "%X = 7:00:00 PM" },
169+ { "%%x = %x" , "%x = 1/1/1970" },
170+ { "%%X = %X" , "%X = 12:00:00 AM" },
167171#else
168- { "%%x = %x" , "%x = 01/01/70" , "%x = 12/31/69" },
169- { "%%X = %X" , "%X = 00:00:00" , "%X = 19:00:00" },
172+ { "%%x = %x" , "%x = 01/01/70" },
173+ { "%%X = %X" , "%X = 00:00:00" },
170174#endif
171- { "%%y = %y" , "%y = 70" , "%y = 69" },
172- { "%%Y = %Y" , "%Y = 1970" , "%Y = 1969" },
173- { "%%z = %z" , "%z = +0000" , "%z = -0500" },
175+ { "%%y = %y" , "%y = 70" },
176+ { "%%Y = %Y" , "%Y = 1970" },
177+ { "%%z = %z" , "%z = +0000" },
178+ /* { "%%Z = %Z", "%Z = GMT" }, - not consistent on all platforms */
179+ { "%%%% = %%" , "%% = %" }
180+ };
181+
174182#ifdef _WIN32
175- { "%%Z = %Z" , "%Z = GMT" , "%Z = Eastern Standard Time" },
183+ {
184+ TIME_ZONE_INFORMATION tzi ;
185+ if ( GetTimeZoneInformationForYear ( 1970 + (USHORT )(ts / 3.154e+10 ), NULL , & tzi ) )
186+ {
187+ tz_offset = tzi .Bias * -60 ;
188+ }
189+ }
176190#else
177- { "%%Z = %Z" , "%Z = GMT" , "%Z = EST" },
191+ {
192+ time_t gmt_time = (time_t )ts ;
193+ struct tm * local ;
194+ char * tz ;
195+
196+ /* not thread safe (but this is okay) as this program runs in a
197+ * single thread. This calculates the offset for the time zon
198+ */
199+ local = localtime ( & gmt_time );
200+ tz = getenv ( "TZ" );
201+ setenv ( "TZ" , "UTC" , 1 );
202+ tzset ();
203+ tz_offset = mktime ( local );
204+ if ( tz )
205+ setenv ( "TZ" , tz , 1 );
206+ else
207+ unsetenv ("TZ" );
208+ tzset ();
209+ }
178210#endif
179- { "%%%% = %%" , "%% = %" , "%% = %" },
180- };
181- os_timestamp_t ts = 0u ;
182211
183- for ( i = 0u ; i < sizeof ( tests ) / sizeof ( struct symbol_result_table ) ; ++ i )
212+ for ( to_local_time = 0 ; to_local_time < 2 ; ++ to_local_time )
184213 {
185- char buf [ 256u ];
186- os_time_format ( buf , 256u , tests [i ].symbol , ts , OS_FALSE );
187- assert_string_equal ( buf , tests [i ].gmt_result );
188- os_time_format ( buf , 256u , tests [i ].symbol , ts , OS_TRUE );
189- assert_string_equal ( buf , tests [i ].local_result );
214+ if ( to_local_time )
215+ {
216+ unsigned int j = 0 ;
217+ if ( tz_offset < 0 )
218+ {
219+ tests [j ++ ].result = "%a = Wed" ;
220+ tests [j ++ ].result = "%A = Wednesday" ;
221+ tests [j ++ ].result = "%b = Dec" ;
222+ tests [j ++ ].result = "%B = December" ;
223+ #ifdef _WIN32
224+ tests [j ++ ].result = "%c = 12/31/1969" ;
225+ #else
226+ tests [j ++ ].result = "%c = Wed Dec 31 19:00:00 1969" ;
227+ #endif
228+ tests [j ++ ].result = "%C = 19" ;
229+ tests [j ++ ].result = "%d = 31" ;
230+ tests [j ++ ].result = "%D = 12/31/69" ;
231+ tests [j ++ ].result = "%e = 31" ;
232+ /* tests[j++].result = "%E = "; - modifier symbol */
233+ tests [j ++ ].result = "%F = 1969-12-31" ;
234+ #ifdef _WIN32
235+ tests [j ++ ].result = "%G = 1969" ;
236+ tests [j ++ ].result = "%g = 69" ;
237+ #else
238+ /** @todo fix this bug */
239+ tests [j ++ ].result = "%G = 1970" ;
240+ tests [j ++ ].result = "%g = 70" ;
241+ #endif
242+ tests [j ++ ].result = "%h = Dec" ;
243+ tests [j ++ ].result = "%H = 19" ;
244+ tests [j ++ ].result = "%I = 07" ;
245+ tests [j ++ ].result = "%j = 365" ;
246+ tests [j ++ ].result = "%k = 19" ;
247+ tests [j ++ ].result = "%l = 7" ;
248+ tests [j ++ ].result = "%m = 12" ;
249+ tests [j ++ ].result = "%M = 00" ;
250+ tests [j ++ ].result = "%n = \n" ;
251+ /* tests[j++].result = "%O = "; - modifier symbol */
252+ tests [j ++ ].result = "%p = PM" ;
253+ #ifdef __APPLE__
254+ tests [j ++ ].result = "%P = P" ;
255+ #else
256+ tests [j ++ ].result = "%P = pm" ;
257+ #endif
258+ tests [j ++ ].result = "%r = 07:00:00 PM" ;
259+ tests [j ++ ].result = "%R = 19:00" ;
260+ /* tests[j++].result = "%s = 18000"; - modifier symbol */
261+ tests [j ++ ].result = "%S = 00" ;
262+ tests [j ++ ].result = "%t = \t" ;
263+ tests [j ++ ].result = "%T = 19:00:00" ;
264+ tests [j ++ ].result = "%u = 3" ;
265+ tests [j ++ ].result = "%U = 52" ;
266+ tests [j ++ ].result = "%V = 01" ;
267+ tests [j ++ ].result = "%w = 3" ;
268+ tests [j ++ ].result = "%W = 52" ;
269+ #ifdef _WIN32
270+ tests [j ++ ].result = "%x = 12/31/1969" ;
271+ tests [j ++ ].result = "%X = 7:00:00 PM" ;
272+ #else
273+ tests [j ++ ].result = "%x = 12/31/69" ;
274+ tests [j ++ ].result = "%X = 19:00:00" ;
275+ #endif
276+ tests [j ++ ].result = "%y = 69" ;
277+ tests [j ++ ].result = "%Y = 1969" ;
278+ tests [j ++ ].result = "%z = -0500" ;
279+ /* not consistent on all platforms
280+ #ifdef _WIN32
281+ tests[j++].result = "%Z = Eastern Standard Time";
282+ #else
283+ tests[j++].result = "%Z = EST";
284+ #endif
285+ */
286+ tests [j ++ ].result = "%% = %" ;
287+ }
288+ else
289+ {
290+ tests [j ++ ].result = "%a = Thu" ;
291+ tests [j ++ ].result = "%A = Thursday" ;
292+ tests [j ++ ].result = "%b = Jan" ;
293+ tests [j ++ ].result = "%B = January" ;
294+ #ifdef _WIN32
295+ tests [j ++ ].result = "%c = 1/1/1970" ;
296+ #else
297+ tests [j ++ ].result = "%c = Thu Jan 1 00:00:00 1970" ;
298+ #endif
299+ tests [j ++ ].result = "%C = 19" ;
300+ tests [j ++ ].result = "%d = 01" ;
301+ tests [j ++ ].result = "%D = 01/01/70" ;
302+ tests [j ++ ].result = "%e = 1" ;
303+ /* tests[j++].result = "%E = "; - modifier symbol */
304+ tests [j ++ ].result = "%F = 1970-01-01" ;
305+ tests [j ++ ].result = "%G = 1970" ;
306+ tests [j ++ ].result = "%g = 70" ;
307+ tests [j ++ ].result = "%h = Jan" ;
308+ tests [j ++ ].result = "%H = 00" ;
309+ tests [j ++ ].result = "%I = 12" ;
310+ tests [j ++ ].result = "%j = 001" ;
311+ tests [j ++ ].result = "%k = 0" ;
312+ tests [j ++ ].result = "%l = 12" ;
313+ tests [j ++ ].result = "%m = 01" ;
314+ tests [j ++ ].result = "%M = 00" ;
315+ tests [j ++ ].result = "%n = \n" ;
316+ /* tests[j++].result = "%O = "; - modifier symbol */
317+ tests [j ++ ].result = "%p = AM" ;
318+ #ifdef __APPLE__
319+ tests [j ++ ].result = "%P = P" ;
320+ #else
321+ tests [j ++ ].result = "%P = am" ;
322+ #endif
323+ tests [j ++ ].result = "%r = 12:00:00 AM" ;
324+ tests [j ++ ].result = "%R = 00:00" ;
325+ /* tests[j++].result = "%s = 0"; - modifier symbol */
326+ tests [j ++ ].result = "%S = 00" ;
327+ tests [j ++ ].result = "%t = \t" ;
328+ tests [j ++ ].result = "%T = 00:00:00" ;
329+ tests [j ++ ].result = "%u = 4" ;
330+ tests [j ++ ].result = "%U = 00" ;
331+ tests [j ++ ].result = "%V = 01" ;
332+ tests [j ++ ].result = "%w = 4" ;
333+ tests [j ++ ].result = "%W = 00" ;
334+ #ifdef _WIN32
335+ tests [j ++ ].result = "%x = 1/1/1970" ;
336+ tests [j ++ ].result = "%X = 12:00:00 AM" ;
337+ #else
338+ tests [j ++ ].result = "%x = 01/01/70" ;
339+ tests [j ++ ].result = "%X = 00:00:00" ;
340+ #endif
341+ tests [j ++ ].result = "%y = 70" ;
342+ tests [j ++ ].result = "%Y = 1970" ;
343+ tests [j ++ ].result = "%z = +0000" ;
344+ /* tests[j++].result = "%Z = GMT"; not consistent on all platforms */
345+ tests [j ++ ].result = "%% = %" ;
346+ }
347+ }
348+
349+ for ( i = 0u ; i < sizeof ( tests ) / sizeof ( struct symbol_result_table ); ++ i )
350+ {
351+ char buf [ 256u ];
352+ os_time_format ( buf , 256u ,
353+ tests [i ].symbol , ts , to_local_time );
354+ assert_string_equal ( buf , tests [i ].result );
355+ }
356+ }
190357 }
191- }
192358
193- /* test os_time_remaining */
194- static void test_os_time_remaining ( void * * state )
195- {
196- unsigned int i ;
197- os_status_t result ;
198- const os_millisecond_t test_times [] = {
359+ /* test os_time_remaining */
360+ static void test_os_time_remaining ( void * * state )
361+ {
362+ unsigned int i ;
363+ os_status_t result ;
364+ const os_millisecond_t test_times [] = {
199365 0u , /* 0 milliseconds */
200366 500u , /* 500 milliseconds */
201367 1000u , /* 1 second */
0 commit comments