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