1290001Sglebius#include <config.h>
2290001Sglebius
3290001Sglebius#include <stdio.h>
4290001Sglebius#include <sys/time.h>
5290001Sglebius
6290001Sglebius#include <ntp_fp.h>
7290001Sglebius#include <timevalops.h>
8290001Sglebius
9290001Sglebius/* microseconds per second */
10290001Sglebius#define MICROSECONDS 1000000
11290001Sglebius
12290001Sglebius
13290001Sglebiusstatic int verbose = 1;        // if not 0, also print results if test passed
14290001Sglebiusstatic int exit_on_err = 0;    // if not 0, exit if test failed
15290001Sglebius
16290001Sglebius
17290001Sglebius/*
18290001Sglebius * Test function calling the old and new code mentioned in
19290001Sglebius * http://bugs.ntp.org/show_bug.cgi?id=2803#c22
20290001Sglebius */
21290001Sglebiusstatic
22290001Sglebiusint do_test( struct timeval timetv, struct timeval tvlast )
23290001Sglebius{
24290001Sglebius	struct timeval tvdiff_old;
25290001Sglebius	struct timeval tvdiff_new;
26290001Sglebius
27290001Sglebius	int cond_old;
28290001Sglebius	int cond_new;
29290001Sglebius	int failed;
30290001Sglebius
31290001Sglebius	cond_old = 0;
32290001Sglebius	cond_new = 0;
33290001Sglebius
34290001Sglebius	// Here is the old code:
35290001Sglebius	tvdiff_old = abs_tval(sub_tval(timetv, tvlast));
36290001Sglebius	if (tvdiff_old.tv_sec > 0) {
37290001Sglebius		cond_old = 1;
38290001Sglebius	}
39290001Sglebius
40290001Sglebius	// Here is the new code:
41290001Sglebius	tvdiff_new = sub_tval(timetv, tvlast);
42290001Sglebius	if (tvdiff_new.tv_sec != 0) {
43290001Sglebius		cond_new = 1;
44290001Sglebius	}
45290001Sglebius
46290001Sglebius	failed = cond_new != cond_old;
47290001Sglebius
48290001Sglebius	if ( failed || verbose )
49290001Sglebius		printf( "timetv %lli|%07li, tvlast  %lli|%07li: tvdiff_old: %lli|%07li -> %i, tvdiff_new: %lli|%07li -> %i, same cond: %s\n",
50290001Sglebius			(long long) timetv.tv_sec, timetv.tv_usec,
51290001Sglebius			(long long) tvlast.tv_sec, tvlast.tv_usec,
52290001Sglebius			(long long) tvdiff_old.tv_sec, tvdiff_old.tv_usec, cond_old,
53290001Sglebius			(long long) tvdiff_new.tv_sec, tvdiff_new.tv_usec, cond_new,
54290001Sglebius			failed ? "NO <<" : "yes" );
55290001Sglebius
56290001Sglebius	return failed ? -1 : 0;
57290001Sglebius}
58290001Sglebius
59290001Sglebius
60290001Sglebius
61290001Sglebius/*
62290001Sglebius * Call the test function in a loop for a given set of parameters.
63290001Sglebius * Both timetv and tvlast iterate over the given range, in all combinations.
64290001Sglebius */
65290001Sglebiusstatic
66290001Sglebiusint test_loop( long long start_sec, long start_usec,
67290001Sglebius	       long long stop_sec, long stop_usec,
68290001Sglebius	       long long step_sec, long step_usec )
69290001Sglebius{
70290001Sglebius	struct timeval timetv;
71290001Sglebius	struct timeval tvlast;
72290001Sglebius
73290001Sglebius	for ( timetv.tv_sec = start_sec; timetv.tv_sec <= stop_sec; timetv.tv_sec += step_sec )
74290001Sglebius	  for ( timetv.tv_usec = start_usec; timetv.tv_usec <= stop_usec; timetv.tv_usec += step_usec )
75290001Sglebius	    for ( tvlast.tv_sec = start_sec; tvlast.tv_sec <= stop_sec; tvlast.tv_sec += step_sec )
76290001Sglebius	      for ( tvlast.tv_usec = start_usec; tvlast.tv_usec <= stop_usec; tvlast.tv_usec += step_usec )
77290001Sglebius	      {
78290001Sglebius		int rc = do_test( timetv, tvlast );
79290001Sglebius		if (rc < 0 && exit_on_err )
80290001Sglebius			return rc;
81290001Sglebius	      }
82290001Sglebius
83290001Sglebius	return 0;
84290001Sglebius}
85290001Sglebius
86290001Sglebius
87290001Sglebius
88290001Sglebiusint main2( void )
89290001Sglebius{
90290001Sglebius
91290001Sglebius	// loop from {0.0} to {1.1000000} stepping by tv_sec by 1 and tv_usec by 100000
92290001Sglebius	test_loop( 0, 0,   1,  MICROSECONDS,   1,  MICROSECONDS / 10 );
93290001Sglebius
94290001Sglebius	// test_loop( 0, 0,   5,  MICROSECONDS,   1,  MICROSECONDS / 1000 );
95290001Sglebius	// test_loop( 0, 0,  -5, -MICROSECONDS,  -1, -MICROSECONDS / 1000 );
96290001Sglebius
97290001Sglebius	return 0;
98290001Sglebius}
99290001Sglebius
100