1284990Scy#include <config.h>
2284990Scy
3284990Scy#include <stdio.h>
4284990Scy#include <sys/time.h>
5284990Scy
6284990Scy#include <ntp_fp.h>
7284990Scy#include <timevalops.h>
8284990Scy
9284990Scy/* microseconds per second */
10284990Scy#define MICROSECONDS 1000000
11284990Scy
12284990Scy
13284990Scystatic int verbose = 1;        // if not 0, also print results if test passed
14284990Scystatic int exit_on_err = 0;    // if not 0, exit if test failed
15284990Scy
16284990Scy
17284990Scy/*
18284990Scy * Test function calling the old and new code mentioned in
19284990Scy * http://bugs.ntp.org/show_bug.cgi?id=2803#c22
20284990Scy */
21284990Scystatic
22284990Scyint do_test( struct timeval timetv, struct timeval tvlast )
23284990Scy{
24284990Scy	struct timeval tvdiff_old;
25284990Scy	struct timeval tvdiff_new;
26284990Scy
27284990Scy	int cond_old;
28284990Scy	int cond_new;
29284990Scy	int failed;
30284990Scy
31284990Scy	cond_old = 0;
32284990Scy	cond_new = 0;
33284990Scy
34284990Scy	// Here is the old code:
35284990Scy	tvdiff_old = abs_tval(sub_tval(timetv, tvlast));
36284990Scy	if (tvdiff_old.tv_sec > 0) {
37284990Scy		cond_old = 1;
38284990Scy	}
39284990Scy
40284990Scy	// Here is the new code:
41284990Scy	tvdiff_new = sub_tval(timetv, tvlast);
42284990Scy	if (tvdiff_new.tv_sec != 0) {
43284990Scy		cond_new = 1;
44284990Scy	}
45284990Scy
46284990Scy	failed = cond_new != cond_old;
47284990Scy
48284990Scy	if ( failed || verbose )
49284990Scy		printf( "timetv %lli|%07li, tvlast  %lli|%07li: tvdiff_old: %lli|%07li -> %i, tvdiff_new: %lli|%07li -> %i, same cond: %s\n",
50284990Scy			(long long) timetv.tv_sec, timetv.tv_usec,
51284990Scy			(long long) tvlast.tv_sec, tvlast.tv_usec,
52284990Scy			(long long) tvdiff_old.tv_sec, tvdiff_old.tv_usec, cond_old,
53284990Scy			(long long) tvdiff_new.tv_sec, tvdiff_new.tv_usec, cond_new,
54284990Scy			failed ? "NO <<" : "yes" );
55284990Scy
56284990Scy	return failed ? -1 : 0;
57284990Scy}
58284990Scy
59284990Scy
60284990Scy
61284990Scy/*
62284990Scy * Call the test function in a loop for a given set of parameters.
63284990Scy * Both timetv and tvlast iterate over the given range, in all combinations.
64284990Scy */
65284990Scystatic
66284990Scyint test_loop( long long start_sec, long start_usec,
67284990Scy	       long long stop_sec, long stop_usec,
68284990Scy	       long long step_sec, long step_usec )
69284990Scy{
70284990Scy	struct timeval timetv;
71284990Scy	struct timeval tvlast;
72284990Scy
73284990Scy	for ( timetv.tv_sec = start_sec; timetv.tv_sec <= stop_sec; timetv.tv_sec += step_sec )
74284990Scy	  for ( timetv.tv_usec = start_usec; timetv.tv_usec <= stop_usec; timetv.tv_usec += step_usec )
75284990Scy	    for ( tvlast.tv_sec = start_sec; tvlast.tv_sec <= stop_sec; tvlast.tv_sec += step_sec )
76284990Scy	      for ( tvlast.tv_usec = start_usec; tvlast.tv_usec <= stop_usec; tvlast.tv_usec += step_usec )
77284990Scy	      {
78284990Scy		int rc = do_test( timetv, tvlast );
79284990Scy		if (rc < 0 && exit_on_err )
80284990Scy			return rc;
81284990Scy	      }
82284990Scy
83284990Scy	return 0;
84284990Scy}
85284990Scy
86284990Scy
87284990Scy
88284990Scyint main2( void )
89284990Scy{
90284990Scy
91284990Scy	// loop from {0.0} to {1.1000000} stepping by tv_sec by 1 and tv_usec by 100000
92284990Scy	test_loop( 0, 0,   1,  MICROSECONDS,   1,  MICROSECONDS / 10 );
93284990Scy
94284990Scy	// test_loop( 0, 0,   5,  MICROSECONDS,   1,  MICROSECONDS / 1000 );
95284990Scy	// test_loop( 0, 0,  -5, -MICROSECONDS,  -1, -MICROSECONDS / 1000 );
96284990Scy
97284990Scy	return 0;
98284990Scy}
99284990Scy
100