xref: /freebsd-src/contrib/ntp/ntpd/check_y2k.c (revision 416ba5c74546f32a993436a99516d35008e9f384)
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