1c0b746e5SOllivier Robert /* check_y2k.c -- test ntp code constructs for Y2K correctness Y2KFixes [*/
2c0b746e5SOllivier Robert
3c0b746e5SOllivier Robert /*
4c0b746e5SOllivier Robert Code invoked by `make check`. Not part of ntpd and not to be
5c0b746e5SOllivier Robert installed.
6c0b746e5SOllivier Robert
7c0b746e5SOllivier Robert On any code I even wonder about, I've cut and pasted the code
8c0b746e5SOllivier Robert here and ran it as a test case just to be sure.
9c0b746e5SOllivier Robert
10c0b746e5SOllivier Robert For code not in "ntpd" proper, we have tried to call most
11c0b746e5SOllivier Robert repaired functions from herein to properly test them
12c0b746e5SOllivier Robert (something never done before!). This has found several bugs,
13c0b746e5SOllivier Robert not normal Y2K bugs, that will strike in Y2K so repair them
14c0b746e5SOllivier Robert we did.
15c0b746e5SOllivier Robert
16c0b746e5SOllivier Robert Program exits with 0 on success, 1 on Y2K failure (stdout messages).
17c0b746e5SOllivier Robert Exit of 2 indicates internal logic bug detected OR failure of
18c0b746e5SOllivier Robert what should be our correct formulas.
19c0b746e5SOllivier Robert
20c0b746e5SOllivier Robert While "make check" should only check logic for source within that
21c0b746e5SOllivier Robert specific directory, this check goes outside the scope of the local
22c0b746e5SOllivier Robert directory. It's not a perfect world (besides, there is a lot of
23c0b746e5SOllivier Robert interdependence here, and it really needs to be tested in
24c0b746e5SOllivier Robert a controled order).
25c0b746e5SOllivier Robert */
26c0b746e5SOllivier Robert
27c0b746e5SOllivier Robert /* { definitions lifted from ntpd.c to allow us to complie with
28c0b746e5SOllivier Robert "#include ntp.h". I have not taken the time to reduce the clutter. */
29c0b746e5SOllivier Robert
30c0b746e5SOllivier Robert #ifdef HAVE_CONFIG_H
31c0b746e5SOllivier Robert # include <config.h>
32c0b746e5SOllivier Robert #endif
33c0b746e5SOllivier Robert
34224ba2bdSOllivier Robert #include "ntpd.h"
35224ba2bdSOllivier Robert
36c0b746e5SOllivier Robert #ifdef HAVE_UNISTD_H
37c0b746e5SOllivier Robert # include <unistd.h>
38c0b746e5SOllivier Robert #endif
39c0b746e5SOllivier Robert #ifdef HAVE_SYS_STAT_H
40c0b746e5SOllivier Robert # include <sys/stat.h>
41c0b746e5SOllivier Robert #endif
42c0b746e5SOllivier Robert #include <stdio.h>
43c0b746e5SOllivier Robert #include <errno.h>
44c0b746e5SOllivier Robert #ifndef SYS_WINNT
45c0b746e5SOllivier Robert # if !defined(VMS) /*wjm*/
46c0b746e5SOllivier Robert # include <sys/param.h>
47c0b746e5SOllivier Robert # endif /* VMS */
48*9c2daa00SOllivier Robert # if HAVE_SYS_SIGNAL_H
49*9c2daa00SOllivier Robert # include <sys/signal.h>
50*9c2daa00SOllivier Robert # endif /* HAVE_SYS_SIGNAL_H */
51c0b746e5SOllivier Robert # include <sys/signal.h>
52c0b746e5SOllivier Robert # ifdef HAVE_SYS_IOCTL_H
53c0b746e5SOllivier Robert # include <sys/ioctl.h>
54c0b746e5SOllivier Robert # endif /* HAVE_SYS_IOCTL_H */
55c0b746e5SOllivier Robert # if !defined(VMS) /*wjm*/
56c0b746e5SOllivier Robert # include <sys/resource.h>
57c0b746e5SOllivier Robert # endif /* VMS */
58c0b746e5SOllivier Robert #else
59c0b746e5SOllivier Robert # include <signal.h>
60c0b746e5SOllivier Robert # include <process.h>
61c0b746e5SOllivier Robert # include <io.h>
62c0b746e5SOllivier Robert # include "../libntp/log.h"
63c0b746e5SOllivier Robert #endif /* SYS_WINNT */
64c0b746e5SOllivier Robert #if defined(HAVE_RTPRIO)
65c0b746e5SOllivier Robert # ifdef HAVE_SYS_RESOURCE_H
66c0b746e5SOllivier Robert # include <sys/resource.h>
67c0b746e5SOllivier Robert # endif
68c0b746e5SOllivier Robert # ifdef HAVE_SYS_LOCK_H
69c0b746e5SOllivier Robert # include <sys/lock.h>
70c0b746e5SOllivier Robert # endif
71c0b746e5SOllivier Robert # include <sys/rtprio.h>
72c0b746e5SOllivier Robert #else
73c0b746e5SOllivier Robert # ifdef HAVE_PLOCK
74c0b746e5SOllivier Robert # ifdef HAVE_SYS_LOCK_H
75c0b746e5SOllivier Robert # include <sys/lock.h>
76c0b746e5SOllivier Robert # endif
77c0b746e5SOllivier Robert # endif
78c0b746e5SOllivier Robert #endif
79c0b746e5SOllivier Robert #if defined(HAVE_SCHED_SETSCHEDULER)
80c0b746e5SOllivier Robert # ifdef HAVE_SCHED_H
81c0b746e5SOllivier Robert # include <sched.h>
82c0b746e5SOllivier Robert # else
83c0b746e5SOllivier Robert # ifdef HAVE_SYS_SCHED_H
84c0b746e5SOllivier Robert # include <sys/sched.h>
85c0b746e5SOllivier Robert # endif
86c0b746e5SOllivier Robert # endif
87c0b746e5SOllivier Robert #endif
88c0b746e5SOllivier Robert #if defined(HAVE_SYS_MMAN_H)
89c0b746e5SOllivier Robert # include <sys/mman.h>
90c0b746e5SOllivier Robert #endif
91c0b746e5SOllivier Robert
92c0b746e5SOllivier Robert #ifdef HAVE_TERMIOS_H
93c0b746e5SOllivier Robert # include <termios.h>
94c0b746e5SOllivier Robert #endif
95c0b746e5SOllivier Robert
96c0b746e5SOllivier Robert #ifdef SYS_DOMAINOS
97c0b746e5SOllivier Robert # include <apollo/base.h>
98c0b746e5SOllivier Robert #endif /* SYS_DOMAINOS */
99c0b746e5SOllivier Robert
100c0b746e5SOllivier Robert /* } end definitions lifted from ntpd.c */
101c0b746e5SOllivier Robert
102c0b746e5SOllivier Robert #include "ntp_calendar.h"
103c0b746e5SOllivier Robert #include "parse.h"
104c0b746e5SOllivier Robert
105c0b746e5SOllivier Robert #define GoodLeap(Year) (((Year)%4 || (!((Year)%100) && (Year)%400)) ? 0 : 13 )
106c0b746e5SOllivier Robert
107c0b746e5SOllivier Robert char const *progname = "check_y2k";
108c0b746e5SOllivier Robert
109224ba2bdSOllivier Robert long
Days(int Year)110224ba2bdSOllivier Robert Days ( int Year ) /* return number of days since year "0" */
111c0b746e5SOllivier Robert {
112c0b746e5SOllivier Robert long Return;
113c0b746e5SOllivier Robert /* this is a known to be good algorithm */
114c0b746e5SOllivier Robert Return = Year * 365; /* first aproximation to the value */
115c0b746e5SOllivier Robert if ( Year >= 1 )
116c0b746e5SOllivier Robert { /* see notes in libparse/parse.c if you want a PROPER
117c0b746e5SOllivier Robert * **generic algorithm. */
118c0b746e5SOllivier Robert Return += (Year+3) / 4; /* add in (too many) leap days */
119c0b746e5SOllivier Robert Return -= (Year-1) / 100; /* reduce by (too many) centurys */
120c0b746e5SOllivier Robert Return += (Year-1) / 400; /* get final answer */
121c0b746e5SOllivier Robert }
122c0b746e5SOllivier Robert
123c0b746e5SOllivier Robert return Return;
124c0b746e5SOllivier Robert }
125c0b746e5SOllivier Robert
126c0b746e5SOllivier Robert static int year0 = 1900; /* sarting year for NTP time */
127c0b746e5SOllivier Robert static int yearend; /* ending year we test for NTP time.
128c0b746e5SOllivier Robert * 32-bit systems: through 2036, the
129c0b746e5SOllivier Robert **year in which NTP time overflows.
130c0b746e5SOllivier Robert * 64-bit systems: a reasonable upper
131c0b746e5SOllivier Robert **limit (well, maybe somewhat beyond
132c0b746e5SOllivier Robert **reasonable, but well before the
133c0b746e5SOllivier Robert **max time, by which time the earth
134c0b746e5SOllivier Robert **will be dead.) */
135c0b746e5SOllivier Robert static time_t Time;
136c0b746e5SOllivier Robert static struct tm LocalTime;
137c0b746e5SOllivier Robert
138c0b746e5SOllivier Robert #define Error(year) if ( (year)>=2036 && LocalTime.tm_year < 110 ) \
139c0b746e5SOllivier Robert Warnings++; else Fatals++
140c0b746e5SOllivier Robert
141224ba2bdSOllivier Robert int
main(void)142224ba2bdSOllivier Robert main( void )
143c0b746e5SOllivier Robert {
144c0b746e5SOllivier Robert int Fatals;
145c0b746e5SOllivier Robert int Warnings;
146c0b746e5SOllivier Robert int year;
147c0b746e5SOllivier Robert
148c0b746e5SOllivier Robert Time = time( (time_t *)NULL )
149c0b746e5SOllivier Robert #ifdef TESTTIMEOFFSET
150c0b746e5SOllivier Robert + test_time_offset
151c0b746e5SOllivier Robert #endif
152c0b746e5SOllivier Robert ;
153c0b746e5SOllivier Robert LocalTime = *localtime( &Time );
154c0b746e5SOllivier Robert
155c0b746e5SOllivier Robert year = ( sizeof( u_long ) > 4 ) /* save max span using year as temp */
156c0b746e5SOllivier Robert ? ( 400 * 3 ) /* three greater gregorian cycles */
157c0b746e5SOllivier Robert : ((int)(0x7FFFFFFF / 365.242 / 24/60/60)* 2 ); /*32-bit limit*/
158c0b746e5SOllivier Robert /* NOTE: will automacially expand test years on
159c0b746e5SOllivier Robert * 64 bit machines.... this may cause some of the
160c0b746e5SOllivier Robert * existing ntp logic to fail for years beyond
161c0b746e5SOllivier Robert * 2036 (the current 32-bit limit). If all checks
162c0b746e5SOllivier Robert * fail ONLY beyond year 2036 you may ignore such
163c0b746e5SOllivier Robert * errors, at least for a decade or so. */
164c0b746e5SOllivier Robert yearend = year0 + year;
165c0b746e5SOllivier Robert
166c0b746e5SOllivier Robert puts( " internal self check" );
167c0b746e5SOllivier Robert { /* verify our own logic used to verify repairs */
168c0b746e5SOllivier Robert unsigned long days;
169c0b746e5SOllivier Robert
170c0b746e5SOllivier Robert if ( year0 >= yearend )
171c0b746e5SOllivier Robert {
172c0b746e5SOllivier Robert fprintf( stdout, "year0=%d NOT LESS THAN yearend=%d (span=%d)\n",
173c0b746e5SOllivier Robert (int)year0, (int)yearend, (int)year );
174c0b746e5SOllivier Robert exit(2);
175c0b746e5SOllivier Robert }
176c0b746e5SOllivier Robert
177c0b746e5SOllivier Robert {
178c0b746e5SOllivier Robert int save_year;
179c0b746e5SOllivier Robert
180c0b746e5SOllivier Robert save_year = LocalTime.tm_year; /* save current year */
181c0b746e5SOllivier Robert
182c0b746e5SOllivier Robert year = 1980;
183c0b746e5SOllivier Robert LocalTime.tm_year = year - 1900;
184c0b746e5SOllivier Robert Fatals = Warnings = 0;
185c0b746e5SOllivier Robert Error(year); /* should increment Fatals */
186c0b746e5SOllivier Robert if ( Fatals == 0 )
187c0b746e5SOllivier Robert {
188c0b746e5SOllivier Robert fprintf( stdout,
189c0b746e5SOllivier Robert "%4d: %s(%d): FATAL DID NOT INCREMENT (Fatals=%d Warnings=%d)\n",
190c0b746e5SOllivier Robert (int)year, __FILE__, __LINE__, (int)Fatals, (int)Warnings );
191c0b746e5SOllivier Robert exit(2);
192c0b746e5SOllivier Robert }
193c0b746e5SOllivier Robert
194c0b746e5SOllivier Robert year = 2100; /* test year > limit but CURRENT year < limit */
195c0b746e5SOllivier Robert Fatals = Warnings = 0;
196c0b746e5SOllivier Robert Error(year); /* should increment Fatals */
197c0b746e5SOllivier Robert if ( Warnings == 0 )
198c0b746e5SOllivier Robert {
199c0b746e5SOllivier Robert fprintf( stdout,
200c0b746e5SOllivier Robert "%4d: %s(%d): WARNING DID NOT INCREMENT (Fatals=%d Warnings=%d)\n",
201c0b746e5SOllivier Robert (int)year, __FILE__, __LINE__, (int)Fatals, (int)Warnings );
202c0b746e5SOllivier Robert exit(2);
203c0b746e5SOllivier Robert }
204c0b746e5SOllivier Robert Fatals = Warnings = 0;
205c0b746e5SOllivier Robert LocalTime.tm_year = year - 1900; /* everything > limit */
206c0b746e5SOllivier Robert Error(1980); /* should increment Fatals */
207c0b746e5SOllivier Robert if ( Fatals == 0 )
208c0b746e5SOllivier Robert {
209c0b746e5SOllivier Robert fprintf( stdout,
210c0b746e5SOllivier Robert "%4d: %s(%d): FATALS DID NOT INCREMENT (Fatals=%d Warnings=%d)\n",
211c0b746e5SOllivier Robert (int)year, __FILE__, __LINE__, (int)Fatals, (int)Warnings );
212c0b746e5SOllivier Robert exit(2);
213c0b746e5SOllivier Robert }
214c0b746e5SOllivier Robert
215c0b746e5SOllivier Robert LocalTime.tm_year = save_year;
216c0b746e5SOllivier Robert }
217c0b746e5SOllivier Robert
218c0b746e5SOllivier Robert days = 365+1; /* days in year 0 + 1 more day */
219c0b746e5SOllivier Robert for ( year = 1; year <= 2500; year++ )
220c0b746e5SOllivier Robert {
221c0b746e5SOllivier Robert long Test;
222c0b746e5SOllivier Robert Test = Days( year );
223c0b746e5SOllivier Robert if ( days != Test )
224c0b746e5SOllivier Robert {
225c0b746e5SOllivier Robert fprintf( stdout, "%04d: Days() DAY COUNT ERROR: s/b=%ld was=%ld\n",
226c0b746e5SOllivier Robert year, (long)days, (long)Test );
227c0b746e5SOllivier Robert exit(2); /* would throw off many other tests */
228c0b746e5SOllivier Robert }
229c0b746e5SOllivier Robert
230c0b746e5SOllivier Robert Test = julian0(year); /* compare with julian0() macro */
231c0b746e5SOllivier Robert if ( days != Test )
232c0b746e5SOllivier Robert {
233c0b746e5SOllivier Robert fprintf( stdout, "%04d: julian0() DAY COUNT ERROR: s/b=%ld was=%ld\n",
234c0b746e5SOllivier Robert year, (long)days, (long)Test );
235c0b746e5SOllivier Robert exit(2); /* would throw off many other tests */
236c0b746e5SOllivier Robert }
237c0b746e5SOllivier Robert
238c0b746e5SOllivier Robert days += 365;
239c0b746e5SOllivier Robert if ( isleap_4(year) ) days++;
240c0b746e5SOllivier Robert }
241c0b746e5SOllivier Robert
242c0b746e5SOllivier Robert if ( isleap_4(1999) )
243c0b746e5SOllivier Robert {
244c0b746e5SOllivier Robert fprintf( stdout, "isleap_4(1999) REPORTED TRUE\n" );
245c0b746e5SOllivier Robert exit(2);
246c0b746e5SOllivier Robert }
247c0b746e5SOllivier Robert if ( !isleap_4(2000) )
248c0b746e5SOllivier Robert {
249c0b746e5SOllivier Robert fprintf( stdout, "isleap_4(2000) REPORTED FALSE\n" );
250c0b746e5SOllivier Robert exit(2);
251c0b746e5SOllivier Robert }
252c0b746e5SOllivier Robert if ( isleap_4(2001) )
253c0b746e5SOllivier Robert {
254c0b746e5SOllivier Robert fprintf( stdout, "isleap_4(1999) REPORTED TRUE\n" );
255c0b746e5SOllivier Robert exit(2);
256c0b746e5SOllivier Robert }
257c0b746e5SOllivier Robert
258c0b746e5SOllivier Robert if ( !isleap_tm(2000-1900) )
259c0b746e5SOllivier Robert {
260c0b746e5SOllivier Robert fprintf( stdout, "isleap_tm(100) REPORTED FALSE\n" );
261c0b746e5SOllivier Robert exit(2);
262c0b746e5SOllivier Robert }
263c0b746e5SOllivier Robert }
264c0b746e5SOllivier Robert
265c0b746e5SOllivier Robert Fatals = Warnings = 0;
266c0b746e5SOllivier Robert
267c0b746e5SOllivier Robert puts( " include/ntp.h" );
268c0b746e5SOllivier Robert { /* test our new isleap_*() #define "functions" */
269c0b746e5SOllivier Robert
270c0b746e5SOllivier Robert for ( year = 1400; year <= 2200; year++ )
271c0b746e5SOllivier Robert {
272c0b746e5SOllivier Robert int LeapSw;
273c0b746e5SOllivier Robert int IsLeapSw;
274c0b746e5SOllivier Robert
275c0b746e5SOllivier Robert LeapSw = GoodLeap(year);
276c0b746e5SOllivier Robert IsLeapSw = isleap_4(year);
277c0b746e5SOllivier Robert
278c0b746e5SOllivier Robert if ( !!LeapSw != !!IsLeapSw )
279c0b746e5SOllivier Robert {
280c0b746e5SOllivier Robert Error(year);
281c0b746e5SOllivier Robert fprintf( stdout,
282c0b746e5SOllivier Robert " %4d %2d %3d *** ERROR\n", year, LeapSw, IsLeapSw );
283c0b746e5SOllivier Robert break;
284c0b746e5SOllivier Robert }
285c0b746e5SOllivier Robert
286c0b746e5SOllivier Robert IsLeapSw = isleap_tm(year-1900);
287c0b746e5SOllivier Robert
288c0b746e5SOllivier Robert if ( !!LeapSw != !!IsLeapSw )
289c0b746e5SOllivier Robert {
290c0b746e5SOllivier Robert Error(year);
291c0b746e5SOllivier Robert fprintf( stdout,
292c0b746e5SOllivier Robert " %4d %2d %3d *** ERROR\n", year, LeapSw, IsLeapSw );
293c0b746e5SOllivier Robert break;
294c0b746e5SOllivier Robert }
295c0b746e5SOllivier Robert }
296c0b746e5SOllivier Robert }
297c0b746e5SOllivier Robert
298c0b746e5SOllivier Robert puts( " include/ntp_calendar.h" );
299c0b746e5SOllivier Robert { /* I belive this is good, but just to be sure... */
300c0b746e5SOllivier Robert
301c0b746e5SOllivier Robert /* we are testing this #define */
302c0b746e5SOllivier Robert #define is_leapyear(y) (y%4 == 0 && !(y%100 == 0 && !(y%400 == 0)))
303c0b746e5SOllivier Robert
304c0b746e5SOllivier Robert for ( year = 1400; year <= 2200; year++ )
305c0b746e5SOllivier Robert {
306c0b746e5SOllivier Robert int LeapSw;
307c0b746e5SOllivier Robert
308c0b746e5SOllivier Robert LeapSw = GoodLeap(year);
309c0b746e5SOllivier Robert
310c0b746e5SOllivier Robert if ( !(!LeapSw) != !(!is_leapyear(year)) )
311c0b746e5SOllivier Robert {
312c0b746e5SOllivier Robert Error(year);
313c0b746e5SOllivier Robert fprintf( stdout,
314c0b746e5SOllivier Robert " %4d %2d *** ERROR\n", year, LeapSw );
315c0b746e5SOllivier Robert break;
316c0b746e5SOllivier Robert }
317c0b746e5SOllivier Robert }
318c0b746e5SOllivier Robert }
319c0b746e5SOllivier Robert
320c0b746e5SOllivier Robert
321c0b746e5SOllivier Robert puts( " libparse/parse.c" );
322c0b746e5SOllivier Robert {
323c0b746e5SOllivier Robert long Days1970; /* days from 1900 to 1970 */
324c0b746e5SOllivier Robert
325c0b746e5SOllivier Robert struct ParseTime /* womp up a test structure to all cut/paste code */
326c0b746e5SOllivier Robert {
327c0b746e5SOllivier Robert int year;
328c0b746e5SOllivier Robert } Clock_Time, *clock_time;
329c0b746e5SOllivier Robert
330c0b746e5SOllivier Robert clock_time = &Clock_Time;
331c0b746e5SOllivier Robert
332c0b746e5SOllivier Robert /* first test this #define */
333c0b746e5SOllivier Robert #define days_per_year(x) ((x) % 4 ? 365 : ((x % 400) ? ((x % 100) ? 366 : 365) : 366))
334c0b746e5SOllivier Robert
335c0b746e5SOllivier Robert for ( year = 1400; year <= 2200; year++ )
336c0b746e5SOllivier Robert {
337c0b746e5SOllivier Robert int LeapSw;
338c0b746e5SOllivier Robert int DayCnt;
339c0b746e5SOllivier Robert
340c0b746e5SOllivier Robert LeapSw = GoodLeap(year);
341c0b746e5SOllivier Robert DayCnt = (int)days_per_year(year);
342c0b746e5SOllivier Robert
343c0b746e5SOllivier Robert if ( ( LeapSw ? 366 : 365 ) != DayCnt )
344c0b746e5SOllivier Robert {
345c0b746e5SOllivier Robert Error(year);
346c0b746e5SOllivier Robert fprintf( stdout,
347c0b746e5SOllivier Robert " days_per_year() %4d %2d %3d *** ERROR\n",
348c0b746e5SOllivier Robert year, LeapSw, DayCnt );
349c0b746e5SOllivier Robert break;
350c0b746e5SOllivier Robert }
351c0b746e5SOllivier Robert }
352c0b746e5SOllivier Robert
353c0b746e5SOllivier Robert /* test (what is now julian0) calculations */
354c0b746e5SOllivier Robert
355c0b746e5SOllivier Robert Days1970 = Days( 1970 ); /* get days since 1970 using a known good */
356c0b746e5SOllivier Robert
357c0b746e5SOllivier Robert for ( year = 1970; year < yearend; year++ )
358c0b746e5SOllivier Robert {
359c0b746e5SOllivier Robert unsigned long t;
360c0b746e5SOllivier Robert long DaysYear ;
361c0b746e5SOllivier Robert
362c0b746e5SOllivier Robert clock_time->year = year;
363c0b746e5SOllivier Robert
364c0b746e5SOllivier Robert /* here is the code we are testing, cut and pasted out of the source */
365c0b746e5SOllivier Robert #if 0 /* old BUGGY code that has Y2K (and many other) failures */
366c0b746e5SOllivier Robert /* ghealton: this logic FAILED with great frequency when run
367c0b746e5SOllivier Robert * over a period of time, including for year 2000. True, it
368c0b746e5SOllivier Robert * had more successes than failures, but that's not really good
369c0b746e5SOllivier Robert * enough for critical time distribution software.
370c0b746e5SOllivier Robert * It is so awful I wonder if it has had a history of failure
371c0b746e5SOllivier Robert * and fixes? */
372c0b746e5SOllivier Robert t = (clock_time->year - 1970) * 365;
373c0b746e5SOllivier Robert t += (clock_time->year >> 2) - (1970 >> 2);
374c0b746e5SOllivier Robert t -= clock_time->year / 100 - 1970 / 100;
375c0b746e5SOllivier Robert t += clock_time->year / 400 - 1970 / 400;
376c0b746e5SOllivier Robert
377c0b746e5SOllivier Robert /* (immediate feare of rounding errors on integer
378c0b746e5SOllivier Robert * **divisions proved well founded) */
379c0b746e5SOllivier Robert
380c0b746e5SOllivier Robert #else
381c0b746e5SOllivier Robert /* my replacement, based on Days() above */
382c0b746e5SOllivier Robert t = julian0(year) - julian0(1970);
383c0b746e5SOllivier Robert #endif
384c0b746e5SOllivier Robert
385c0b746e5SOllivier Robert /* compare result in t against trusted calculations */
386c0b746e5SOllivier Robert DaysYear = Days( year ); /* get days to this year */
387c0b746e5SOllivier Robert if ( t != DaysYear - Days1970 )
388c0b746e5SOllivier Robert {
389c0b746e5SOllivier Robert Error(year);
390c0b746e5SOllivier Robert fprintf( stdout,
391c0b746e5SOllivier Robert " %4d 1970=%-8ld %4d=%-8ld %-3ld t=%-8ld *** ERROR ***\n",
392c0b746e5SOllivier Robert year, (long)Days1970,
393c0b746e5SOllivier Robert year,
394c0b746e5SOllivier Robert (long)DaysYear,
395c0b746e5SOllivier Robert (long)(DaysYear - Days1970),
396c0b746e5SOllivier Robert (long)t );
397c0b746e5SOllivier Robert }
398c0b746e5SOllivier Robert }
399c0b746e5SOllivier Robert
400c0b746e5SOllivier Robert #if 1 /* { */
401c0b746e5SOllivier Robert {
402c0b746e5SOllivier Robert debug = 1; /* enable debugging */
403c0b746e5SOllivier Robert for ( year = 1970; year < yearend; year++ )
404c0b746e5SOllivier Robert { /* (limited by theory unix 2038 related bug lives by, but
405c0b746e5SOllivier Robert * ends in yearend) */
406c0b746e5SOllivier Robert clocktime_t ct;
407c0b746e5SOllivier Robert time_t Observed;
408c0b746e5SOllivier Robert time_t Expected;
409c0b746e5SOllivier Robert u_long Flag;
410c0b746e5SOllivier Robert unsigned long t;
411c0b746e5SOllivier Robert
412c0b746e5SOllivier Robert ct.day = 1;
413c0b746e5SOllivier Robert ct.month = 1;
414c0b746e5SOllivier Robert ct.year = year;
415c0b746e5SOllivier Robert ct.hour = ct.minute = ct.second = ct.usecond = 0;
416c0b746e5SOllivier Robert ct.utcoffset = 0;
417c0b746e5SOllivier Robert ct.utctime = 0;
418c0b746e5SOllivier Robert ct.flags = 0;
419c0b746e5SOllivier Robert
420c0b746e5SOllivier Robert Flag = 0;
421c0b746e5SOllivier Robert Observed = parse_to_unixtime( &ct, &Flag );
422c0b746e5SOllivier Robert if ( ct.year != year )
423c0b746e5SOllivier Robert {
424c0b746e5SOllivier Robert fprintf( stdout,
425c0b746e5SOllivier Robert "%04d: parse_to_unixtime(,%d) CORRUPTED ct.year: was %d\n",
426c0b746e5SOllivier Robert (int)year, (int)Flag, (int)ct.year );
427c0b746e5SOllivier Robert Error(year);
428c0b746e5SOllivier Robert break;
429c0b746e5SOllivier Robert }
430c0b746e5SOllivier Robert t = julian0(year) - julian0(1970); /* Julian day from 1970 */
431c0b746e5SOllivier Robert Expected = t * 24 * 60 * 60;
432c0b746e5SOllivier Robert if ( Observed != Expected || Flag )
433c0b746e5SOllivier Robert { /* time difference */
434c0b746e5SOllivier Robert fprintf( stdout,
435c0b746e5SOllivier Robert "%04d: parse_to_unixtime(,%d) FAILURE: was=%lu s/b=%lu (%ld)\n",
436c0b746e5SOllivier Robert year, (int)Flag,
437c0b746e5SOllivier Robert (unsigned long)Observed, (unsigned long)Expected,
438c0b746e5SOllivier Robert ((long)Observed - (long)Expected) );
439c0b746e5SOllivier Robert Error(year);
440c0b746e5SOllivier Robert break;
441c0b746e5SOllivier Robert }
442c0b746e5SOllivier Robert
443c0b746e5SOllivier Robert if ( year >= YEAR_PIVOT+1900 )
444c0b746e5SOllivier Robert {
445c0b746e5SOllivier Robert /* check year % 100 code we put into parse_to_unixtime() */
446c0b746e5SOllivier Robert ct.utctime = 0;
447c0b746e5SOllivier Robert ct.year = year % 100;
448c0b746e5SOllivier Robert Flag = 0;
449c0b746e5SOllivier Robert
450c0b746e5SOllivier Robert Observed = parse_to_unixtime( &ct, &Flag );
451c0b746e5SOllivier Robert
452c0b746e5SOllivier Robert if ( Observed != Expected || Flag )
453c0b746e5SOllivier Robert { /* time difference */
454c0b746e5SOllivier Robert fprintf( stdout,
455c0b746e5SOllivier Robert "%04d: parse_to_unixtime(%d,%d) FAILURE: was=%lu s/b=%lu (%ld)\n",
456c0b746e5SOllivier Robert year, (int)ct.year, (int)Flag,
457c0b746e5SOllivier Robert (unsigned long)Observed, (unsigned long)Expected,
458c0b746e5SOllivier Robert ((long)Observed - (long)Expected) );
459c0b746e5SOllivier Robert Error(year);
460c0b746e5SOllivier Robert break;
461c0b746e5SOllivier Robert }
462c0b746e5SOllivier Robert
463c0b746e5SOllivier Robert /* check year - 1900 code we put into parse_to_unixtime() */
464c0b746e5SOllivier Robert ct.utctime = 0;
465c0b746e5SOllivier Robert ct.year = year - 1900;
466c0b746e5SOllivier Robert Flag = 0;
467c0b746e5SOllivier Robert
468c0b746e5SOllivier Robert Observed = parse_to_unixtime( &ct, &Flag );
469c0b746e5SOllivier Robert
470c0b746e5SOllivier Robert if ( Observed != Expected || Flag )
471c0b746e5SOllivier Robert { /* time difference */
472c0b746e5SOllivier Robert fprintf( stdout,
473c0b746e5SOllivier Robert "%04d: parse_to_unixtime(%d,%d) FAILURE: was=%lu s/b=%lu (%ld)\n",
474c0b746e5SOllivier Robert year, (int)ct.year, (int)Flag,
475c0b746e5SOllivier Robert (unsigned long)Observed, (unsigned long)Expected,
476c0b746e5SOllivier Robert ((long)Observed - (long)Expected) );
477c0b746e5SOllivier Robert Error(year);
478c0b746e5SOllivier Robert break;
479c0b746e5SOllivier Robert }
480c0b746e5SOllivier Robert
481c0b746e5SOllivier Robert
482c0b746e5SOllivier Robert }
483c0b746e5SOllivier Robert }
484c0b746e5SOllivier Robert #endif /* } */
485c0b746e5SOllivier Robert }
486c0b746e5SOllivier Robert }
487c0b746e5SOllivier Robert
488c0b746e5SOllivier Robert puts( " libntp/caljulian.c" );
489c0b746e5SOllivier Robert { /* test caljulian() */
490c0b746e5SOllivier Robert struct calendar ot;
491c0b746e5SOllivier Robert u_long ntp_time; /* NTP time */
492c0b746e5SOllivier Robert
493c0b746e5SOllivier Robert year = year0; /* calculate the basic year */
494c0b746e5SOllivier Robert printf( " starting year %04d\n", (int)year0 );
495c0b746e5SOllivier Robert printf( " ending year %04d\n", (int)yearend );
496c0b746e5SOllivier Robert
497c0b746e5SOllivier Robert
498c0b746e5SOllivier Robert ntp_time = julian0( year0 ); /* NTP starts in 1900-01-01 */
499c0b746e5SOllivier Robert #if DAY_NTP_STARTS == 693596
500c0b746e5SOllivier Robert ntp_time -= 365; /* BIAS required for successful test */
501c0b746e5SOllivier Robert #endif
502c0b746e5SOllivier Robert if ( DAY_NTP_STARTS != ntp_time )
503c0b746e5SOllivier Robert {
504c0b746e5SOllivier Robert Error(year);
505c0b746e5SOllivier Robert fprintf( stdout,
506c0b746e5SOllivier Robert "%04d: DAY_NTP_STARTS (%ld) NOT TRUE VALUE OF %ld (%ld)\n",
507c0b746e5SOllivier Robert (int)year0,
508c0b746e5SOllivier Robert (long)DAY_NTP_STARTS, (long)ntp_time,
509c0b746e5SOllivier Robert (long)DAY_NTP_STARTS - (long)ntp_time );
510c0b746e5SOllivier Robert }
511c0b746e5SOllivier Robert
512c0b746e5SOllivier Robert for ( ; year < yearend; year++ )
513c0b746e5SOllivier Robert {
514c0b746e5SOllivier Robert
515c0b746e5SOllivier Robert /* 01-01 for the current year */
516c0b746e5SOllivier Robert ntp_time = Days( year ) - Days( year0 ); /* days into NTP time */
517c0b746e5SOllivier Robert ntp_time *= 24 * 60 * 60; /* convert into seconds */
518c0b746e5SOllivier Robert caljulian( ntp_time, &ot ); /* convert January 1 */
519c0b746e5SOllivier Robert if ( ot.year != year
520c0b746e5SOllivier Robert || ot.month != 1
521c0b746e5SOllivier Robert || ot.monthday != 1 )
522c0b746e5SOllivier Robert {
523c0b746e5SOllivier Robert Error(year);
524c0b746e5SOllivier Robert fprintf( stdout, "%lu: EXPECTED %04d-01-01: FOUND %04d-%02d-%02d\n",
525c0b746e5SOllivier Robert (unsigned long)ntp_time,
526c0b746e5SOllivier Robert year,
527c0b746e5SOllivier Robert (int)ot.year, (int)ot.month, (int)ot.monthday );
528c0b746e5SOllivier Robert break;
529c0b746e5SOllivier Robert }
530c0b746e5SOllivier Robert
531c0b746e5SOllivier Robert ntp_time += (31 + 28-1) * ( 24 * 60 * 60 ); /* advance to 02-28 */
532c0b746e5SOllivier Robert caljulian( ntp_time, &ot ); /* convert Feb 28 */
533c0b746e5SOllivier Robert if ( ot.year != year
534c0b746e5SOllivier Robert || ot.month != 2
535c0b746e5SOllivier Robert || ot.monthday != 28 )
536c0b746e5SOllivier Robert {
537c0b746e5SOllivier Robert Error(year);
538c0b746e5SOllivier Robert fprintf( stdout, "%lu: EXPECTED %04d-02-28: FOUND %04d-%02d-%02d\n",
539c0b746e5SOllivier Robert (unsigned long)ntp_time,
540c0b746e5SOllivier Robert year,
541c0b746e5SOllivier Robert (int)ot.year, (int)ot.month, (int)ot.monthday );
542c0b746e5SOllivier Robert break;
543c0b746e5SOllivier Robert }
544c0b746e5SOllivier Robert
545c0b746e5SOllivier Robert {
546c0b746e5SOllivier Robert int m; /* expected month */
547c0b746e5SOllivier Robert int d; /* expected day */
548c0b746e5SOllivier Robert
549c0b746e5SOllivier Robert m = isleap_4(year) ? 2 : 3;
550c0b746e5SOllivier Robert d = isleap_4(year) ? 29 : 1;
551c0b746e5SOllivier Robert
552c0b746e5SOllivier Robert ntp_time += ( 24 * 60 * 60 ); /* advance to the next day */
553c0b746e5SOllivier Robert caljulian( ntp_time, &ot ); /* convert this day */
554c0b746e5SOllivier Robert if ( ot.year != year
555c0b746e5SOllivier Robert || ot.month != m
556c0b746e5SOllivier Robert || ot.monthday != d )
557c0b746e5SOllivier Robert {
558c0b746e5SOllivier Robert Error(year);
559c0b746e5SOllivier Robert fprintf( stdout, "%lu: EXPECTED %04d-%02d-%02d: FOUND %04d-%02d-%02d\n",
560c0b746e5SOllivier Robert (unsigned long)ntp_time,
561c0b746e5SOllivier Robert year, m, d,
562c0b746e5SOllivier Robert (int)ot.year, (int)ot.month, (int)ot.monthday );
563c0b746e5SOllivier Robert break;
564c0b746e5SOllivier Robert }
565c0b746e5SOllivier Robert
566c0b746e5SOllivier Robert }
567c0b746e5SOllivier Robert }
568c0b746e5SOllivier Robert }
569c0b746e5SOllivier Robert
570c0b746e5SOllivier Robert puts( " libntp/caltontp.c" );
571c0b746e5SOllivier Robert { /* test caltontp() */
572c0b746e5SOllivier Robert struct calendar ot;
573c0b746e5SOllivier Robert u_long ntp_time; /* NTP time */
574c0b746e5SOllivier Robert
575c0b746e5SOllivier Robert year = year0; /* calculate the basic year */
576c0b746e5SOllivier Robert printf( " starting year %04d\n", (int)year0 );
577c0b746e5SOllivier Robert printf( " ending year %04d\n", (int)yearend );
578c0b746e5SOllivier Robert
579c0b746e5SOllivier Robert
580c0b746e5SOllivier Robert for ( ; year < yearend; year++ )
581c0b746e5SOllivier Robert {
582c0b746e5SOllivier Robert u_long ObservedNtp;
583c0b746e5SOllivier Robert
584c0b746e5SOllivier Robert /* 01-01 for the current year */
585c0b746e5SOllivier Robert ot.year = year;
586c0b746e5SOllivier Robert ot.month = ot.monthday = 1; /* unused, but set anyway JIC */
587c0b746e5SOllivier Robert ot.yearday = 1; /* this is the magic value used by caltontp() */
588c0b746e5SOllivier Robert ot.hour = ot.minute = ot.second = 0;
589c0b746e5SOllivier Robert
590c0b746e5SOllivier Robert ntp_time = Days( year ) - Days( year0 ); /* days into NTP time */
591c0b746e5SOllivier Robert ntp_time *= 24 * 60 * 60; /* convert into seconds */
592c0b746e5SOllivier Robert ObservedNtp = caltontp( &ot );
593c0b746e5SOllivier Robert if ( ntp_time != ObservedNtp )
594c0b746e5SOllivier Robert {
595c0b746e5SOllivier Robert Error(year);
596c0b746e5SOllivier Robert fprintf( stdout, "%d: EXPECTED %lu: FOUND %lu (%ld)\n",
597c0b746e5SOllivier Robert (int)year,
598c0b746e5SOllivier Robert (unsigned long)ntp_time, (unsigned long)ObservedNtp ,
599c0b746e5SOllivier Robert (long)ntp_time - (long)ObservedNtp );
600c0b746e5SOllivier Robert
601c0b746e5SOllivier Robert break;
602c0b746e5SOllivier Robert }
603c0b746e5SOllivier Robert
604c0b746e5SOllivier Robert /* now call caljulian as a type of failsafe supercheck */
605c0b746e5SOllivier Robert caljulian( ObservedNtp, &ot ); /* convert January 1 */
606c0b746e5SOllivier Robert if ( ot.year != year
607c0b746e5SOllivier Robert || ot.month != 1
608c0b746e5SOllivier Robert || ot.monthday != 1 )
609c0b746e5SOllivier Robert {
610c0b746e5SOllivier Robert Error(year);
611c0b746e5SOllivier Robert fprintf( stdout, "%lu: caljulian FAILSAFE EXPECTED %04d-01-01: FOUND %04d-%02d-%02d\n",
612c0b746e5SOllivier Robert (unsigned long)ObservedNtp,
613c0b746e5SOllivier Robert year,
614c0b746e5SOllivier Robert (int)ot.year, (int)ot.month, (int)ot.monthday );
615c0b746e5SOllivier Robert break;
616c0b746e5SOllivier Robert }
617c0b746e5SOllivier Robert }
618c0b746e5SOllivier Robert }
619c0b746e5SOllivier Robert
620c0b746e5SOllivier Robert if ( Warnings > 0 )
621c0b746e5SOllivier Robert fprintf( stdout, "%d WARNINGS\n", Warnings );
622c0b746e5SOllivier Robert if ( Fatals > 0 )
623c0b746e5SOllivier Robert fprintf( stdout, "%d FATAL ERRORS\n", Fatals );
624c0b746e5SOllivier Robert return Fatals ? 1 : 0;
625c0b746e5SOllivier Robert }
626c0b746e5SOllivier Robert /* Y2KFixes ] */
627