1 /* $NetBSD: timevalops.c,v 1.1.1.2 2015/07/10 13:11:14 christos Exp $ */ 2 3 #include "config.h" 4 5 //some unused features are still in the wrapper, unconverted 6 7 #include "ntp_types.h" 8 #include "ntp_fp.h" 9 10 #include <math.h> 11 #include "timevalops.h" 12 13 #include "unity.h" 14 15 16 //in unity_helper.h : 17 #define TEST_ASSERT_EQUAL_timeval(a, b) { \ 18 TEST_ASSERT_EQUAL_MESSAGE(a.tv_sec, b.tv_sec, "Field tv_sec"); \ 19 TEST_ASSERT_EQUAL_MESSAGE(a.tv_usec, b.tv_usec, "Field tv_usec"); \ 20 } 21 22 //timeval has time_t, long, and time_t is basically uint 23 24 static u_int32 my_tick_to_tsf(u_int32 ticks); 25 static u_int32 my_tsf_to_tick(u_int32 tsf); 26 27 // that's it... 28 typedef struct { 29 long usec; 30 u_int32 frac; 31 } lfpfracdata ; 32 33 34 //******************************************MY CUSTOM FUNCTIONS******************************* 35 36 typedef int bool; //TRUE and FALSE are already defined somewhere, so I can't do typedef enum { FALSE, TRUE } boolean; 37 38 struct timeval timeval_init( time_t hi, long lo){ 39 struct timeval V; 40 V.tv_sec = hi; 41 V.tv_usec = lo; 42 return V; 43 } 44 45 const bool timeval_isValid(struct timeval V) 46 { return V.tv_usec >= 0 && V.tv_usec < 1000000; } 47 48 //taken from lfpfunc.c -> maybe remove this from timevalops.c and lfpfunc. and put in c_timstructs.h ????!!!!! 49 l_fp l_fp_init(int32 i, u_int32 f) 50 { 51 l_fp temp; 52 temp.l_i = i; 53 temp.l_uf = f; 54 55 return temp; 56 } 57 58 bool AssertTimevalClose(const struct timeval m, const struct timeval n, const struct timeval limit) 59 { 60 struct timeval diff; 61 62 diff = abs_tval(sub_tval(m, n)); 63 if (cmp_tval(limit, diff) >= 0) 64 return TRUE; 65 66 else 67 { 68 //printf(""); 69 //<< m_expr << " which is " << timeval_wrap(m) 70 //<< "\nand\n" 71 //<< n_expr << " which is " << timeval_wrap(n) 72 //<< "\nare not close; diff=" << timeval_wrap(diff); 73 return FALSE; 74 } 75 } 76 77 bool AssertFpClose(const l_fp m,const l_fp n, const l_fp limit) 78 { 79 l_fp diff; 80 81 if (L_ISGEQ(&m, &n)) { 82 diff = m; 83 L_SUB(&diff, &n); 84 } else { 85 diff = n; 86 L_SUB(&diff, &m); 87 } 88 if (L_ISGEQ(&limit, &diff)){ 89 return TRUE; 90 } 91 else { 92 //<< m_expr << " which is " << l_fp_wrap(m) 93 //<< "\nand\n" 94 //<< n_expr << " which is " << l_fp_wrap(n) 95 //<< "\nare not close; diff=" << l_fp_wrap(diff); 96 return FALSE; 97 } 98 } 99 100 101 //--------------------------------------------------- 102 103 static const lfpfracdata fdata[] = { 104 { 0, 0x00000000 }, { 7478, 0x01ea1405 }, 105 { 22077, 0x05a6d699 }, { 125000, 0x20000000 }, 106 { 180326, 0x2e29d841 }, { 207979, 0x353e1c9b }, 107 { 250000, 0x40000000 }, { 269509, 0x44fe8ab5 }, 108 { 330441, 0x5497c808 }, { 333038, 0x5541fa76 }, 109 { 375000, 0x60000000 }, { 394734, 0x650d4995 }, 110 { 446327, 0x72427c7c }, { 500000, 0x80000000 }, 111 { 517139, 0x846338b4 }, { 571953, 0x926b8306 }, 112 { 587353, 0x965cc426 }, { 625000, 0xa0000000 }, 113 { 692136, 0xb12fd32c }, { 750000, 0xc0000000 }, 114 { 834068, 0xd5857aff }, { 848454, 0xd9344806 }, 115 { 854222, 0xdaae4b02 }, { 861465, 0xdc88f862 }, 116 { 875000, 0xe0000000 }, { 910661, 0xe921144d }, 117 { 922162, 0xec12cf10 }, { 942190, 0xf1335d25 } 118 }; 119 120 121 u_int32 my_tick_to_tsf(u_int32 ticks) 122 { 123 // convert microseconds to l_fp fractional units, using double 124 // precision float calculations or, if available, 64bit integer 125 // arithmetic. This should give the precise fraction, rounded to 126 // the nearest representation. 127 #ifdef HAVE_U_INT64 128 return (u_int32)((( ((u_int64)(ticks)) << 32) + 500000) / 1000000); //I put too much () when casting just to be safe 129 #else 130 return (u_int32)( ((double)(ticks)) * 4294.967296 + 0.5); 131 #endif 132 // And before you ask: if ticks >= 1000000, the result is 133 // truncated nonsense, so don't use it out-of-bounds. 134 } 135 136 u_int32 my_tsf_to_tick(u_int32 tsf) 137 { 138 // Inverse operation: converts fraction to microseconds. 139 #ifdef HAVE_U_INT64 140 return (u_int32)( ((u_int64)(tsf) * 1000000 + 0x80000000) >> 32); //CHECK ME!!! 141 #else 142 return (u_int32)(double(tsf) / 4294.967296 + 0.5); 143 #endif 144 // Beware: The result might be 10^6 due to rounding! 145 } 146 147 148 //***************************************END OF CUSTOM FUNCTIONS***************************** 149 150 151 // --------------------------------------------------------------------- 152 // test support stuff - part1 153 // --------------------------------------------------------------------- 154 155 void test_Helpers1() { 156 struct timeval x; 157 158 for (x.tv_sec = -2; x.tv_sec < 3; x.tv_sec++) { 159 x.tv_usec = -1; 160 TEST_ASSERT_FALSE(timeval_isValid(x)); 161 x.tv_usec = 0; 162 TEST_ASSERT_TRUE(timeval_isValid(x)); 163 x.tv_usec = 999999; 164 TEST_ASSERT_TRUE(timeval_isValid(x)); 165 x.tv_usec = 1000000; 166 TEST_ASSERT_FALSE(timeval_isValid(x)); 167 } 168 } 169 170 171 //---------------------------------------------------------------------- 172 // test normalisation 173 //---------------------------------------------------------------------- 174 175 void test_Normalise() { 176 long ns; 177 for (ns = -2000000000; ns <= 2000000000; ns += 10000000) { 178 struct timeval x = timeval_init(0, ns); 179 180 x = normalize_tval(x); 181 TEST_ASSERT_TRUE(timeval_isValid(x)); 182 } 183 } 184 185 //---------------------------------------------------------------------- 186 // test classification 187 //---------------------------------------------------------------------- 188 189 void test_SignNoFrac() { 190 int i; 191 // sign test, no fraction 192 for (i = -4; i <= 4; ++i) { 193 struct timeval a = timeval_init(i, 0); 194 int E = (i > 0) - (i < 0); 195 int r = test_tval(a); 196 197 TEST_ASSERT_EQUAL(E, r); 198 } 199 } 200 201 void test_SignWithFrac() { 202 // sign test, with fraction 203 int i; 204 for (i = -4; i <= 4; ++i) { 205 struct timeval a = timeval_init(i, 10); 206 int E = (i >= 0) - (i < 0); 207 int r = test_tval(a); 208 209 TEST_ASSERT_EQUAL(E, r); 210 } 211 } 212 213 //---------------------------------------------------------------------- 214 // test compare 215 //---------------------------------------------------------------------- 216 void test_CmpFracEQ() { 217 int i,j; 218 // fractions are equal 219 for (i = -4; i <= 4; ++i) 220 for (j = -4; j <= 4; ++j) { 221 struct timeval a = timeval_init(i, 200); 222 struct timeval b = timeval_init(j, 200); 223 int E = (i > j) - (i < j); 224 int r = cmp_tval_denorm(a, b); 225 226 TEST_ASSERT_EQUAL(E, r); 227 } 228 } 229 230 void test_CmpFracGT() { 231 // fraction a bigger fraction b 232 int i,j; 233 for (i = -4; i <= 4; ++i) 234 for (j = -4; j <= 4; ++j) { 235 struct timeval a = timeval_init( i , 999800); 236 struct timeval b = timeval_init( j , 200); 237 int E = (i >= j) - (i < j); 238 int r = cmp_tval_denorm(a, b); 239 240 TEST_ASSERT_EQUAL(E, r); 241 } 242 } 243 244 void test_CmpFracLT() { 245 // fraction a less fraction b 246 int i,j; 247 for (i = -4; i <= 4; ++i) 248 for (j = -4; j <= 4; ++j) { 249 struct timeval a = timeval_init(i, 200); 250 struct timeval b = timeval_init(j, 999800); 251 int E = (i > j) - (i <= j); 252 int r = cmp_tval_denorm(a, b); 253 254 TEST_ASSERT_EQUAL(E, r); 255 } 256 } 257 258 //---------------------------------------------------------------------- 259 // Test addition (sum) 260 //---------------------------------------------------------------------- 261 262 void test_AddFullNorm() { 263 int i,j; 264 for (i = -4; i <= 4; ++i) 265 for (j = -4; j <= 4; ++j) { 266 struct timeval a = timeval_init(i, 200); 267 struct timeval b = timeval_init(j, 400); 268 struct timeval E = timeval_init(i + j, 200 + 400); 269 struct timeval c; 270 271 c = add_tval(a, b); 272 TEST_ASSERT_EQUAL_timeval(E, c); 273 } 274 } 275 276 void test_AddFullOflow1() { 277 int i,j; 278 for (i = -4; i <= 4; ++i) 279 for (j = -4; j <= 4; ++j) { 280 struct timeval a = timeval_init(i, 200); 281 struct timeval b = timeval_init(j, 999900); 282 struct timeval E = timeval_init(i + j + 1, 100); 283 struct timeval c; 284 285 c = add_tval(a, b); 286 TEST_ASSERT_EQUAL_timeval(E, c); 287 } 288 } 289 290 void test_AddUsecNorm() { 291 int i; 292 for (i = -4; i <= 4; ++i) { 293 struct timeval a = timeval_init(i, 200); 294 struct timeval E = timeval_init(i, 600); 295 struct timeval c; 296 297 c = add_tval_us(a, 600 - 200); 298 TEST_ASSERT_EQUAL_timeval(E, c); 299 } 300 } 301 302 void test_AddUsecOflow1() { 303 int i; 304 for (i = -4; i <= 4; ++i) { 305 struct timeval a = timeval_init(i, 200); 306 struct timeval E = timeval_init(i + 1, 100); 307 struct timeval c; 308 309 c = add_tval_us(a, MICROSECONDS - 100); 310 TEST_ASSERT_EQUAL_timeval(E, c); 311 } 312 } 313 314 //---------------------------------------------------------------------- 315 // test subtraction (difference) 316 //---------------------------------------------------------------------- 317 318 void test_SubFullNorm() { 319 int i,j; 320 for (i = -4; i <= 4; ++i) 321 for (j = -4; j <= 4; ++j) { 322 struct timeval a = timeval_init(i, 600); 323 struct timeval b = timeval_init(j, 400); 324 struct timeval E = timeval_init(i - j, 600 - 400); 325 struct timeval c; 326 327 c = sub_tval(a, b); 328 TEST_ASSERT_EQUAL_timeval(E, c); 329 } 330 } 331 332 void test_SubFullOflow() { 333 int i,j; 334 for (i = -4; i <= 4; ++i) 335 for (j = -4; j <= 4; ++j) { 336 struct timeval a = timeval_init(i, 100); 337 struct timeval b = timeval_init(j, 999900); 338 struct timeval E = timeval_init(i - j - 1, 200); 339 struct timeval c; 340 341 c = sub_tval(a, b); 342 TEST_ASSERT_EQUAL_timeval(E, c); 343 } 344 } 345 346 void test_SubUsecNorm() { 347 int i = -4; 348 for (i = -4; i <= 4; ++i) { 349 struct timeval a = timeval_init(i, 600); 350 struct timeval E = timeval_init(i, 200); 351 struct timeval c; 352 353 c = sub_tval_us(a, 600 - 200); 354 TEST_ASSERT_EQUAL_timeval(E, c); 355 } 356 } 357 358 void test_SubUsecOflow() { 359 int i = -4; 360 for (i = -4; i <= 4; ++i) { 361 struct timeval a = timeval_init(i, 100); 362 struct timeval E = timeval_init(i - 1, 200); 363 struct timeval c; 364 365 c = sub_tval_us(a, MICROSECONDS - 100); 366 TEST_ASSERT_EQUAL_timeval(E, c); 367 } 368 } 369 370 //---------------------------------------------------------------------- 371 // test negation 372 //---------------------------------------------------------------------- 373 374 void test_Neg() { 375 int i = -4; 376 for (i = -4; i <= 4; ++i) { 377 struct timeval a = timeval_init(i, 100); 378 struct timeval b; 379 struct timeval c; 380 381 b = neg_tval(a); 382 c = add_tval(a, b); 383 TEST_ASSERT_EQUAL(0, test_tval(c)); 384 } 385 } 386 387 //---------------------------------------------------------------------- 388 // test abs value 389 //---------------------------------------------------------------------- 390 391 void test_AbsNoFrac() { 392 int i = -4; 393 for (i = -4; i <= 4; ++i) { 394 struct timeval a = timeval_init(i, 0); 395 struct timeval b; 396 397 b = abs_tval(a); 398 TEST_ASSERT_EQUAL((i != 0), test_tval(b)); 399 } 400 } 401 402 void test_AbsWithFrac() { 403 int i = -4; 404 for (i = -4; i <= 4; ++i) { 405 struct timeval a = timeval_init(i, 100); 406 struct timeval b; 407 408 b = abs_tval(a); 409 TEST_ASSERT_EQUAL(1, test_tval(b)); 410 } 411 } 412 413 // --------------------------------------------------------------------- 414 // test support stuff -- part 2 415 // --------------------------------------------------------------------- 416 417 418 void test_Helpers2() { 419 //struct AssertTimevalClose isClose = AssertTimevalClose_init(0, 2); 420 struct timeval limit = timeval_init(0, 2); 421 struct timeval x, y; 422 long i; 423 424 for (x.tv_sec = -2; x.tv_sec < 3; x.tv_sec++){ 425 for (x.tv_usec = 1; 426 x.tv_usec < 1000000; 427 x.tv_usec += 499999) { 428 for (i = -4; i < 5; i++) { 429 y = x; 430 y.tv_usec += i; 431 if (i >= -2 && i <= 2){ 432 TEST_ASSERT_TRUE(AssertTimevalClose(x,y,limit));//ASSERT_PRED_FORMAT2(isClose, x, y); 433 } 434 else { 435 TEST_ASSERT_FALSE(AssertTimevalClose(x,y,limit));//ASSERT_PRED_FORMAT2(!isClose, x, y); 436 } 437 } 438 } 439 } 440 } 441 442 // and the global predicate instances we're using here 443 444 //static l_fp lfpClose = l_fp_init(0,1); //static AssertFpClose FpClose(0, 1); 445 //static struct timeval timevalClose = timeval_init(0,1); //static AssertTimevalClose TimevalClose(0, 1); 446 447 //---------------------------------------------------------------------- 448 // conversion to l_fp 449 //---------------------------------------------------------------------- 450 451 void test_ToLFPbittest() { 452 l_fp lfpClose = l_fp_init(0,1); 453 454 u_int32 i = 0; 455 for (i = 0; i < 1000000; i++) { 456 struct timeval a = timeval_init(1, i); 457 l_fp E = l_fp_init(1,my_tick_to_tsf(i)); 458 l_fp r; 459 460 r = tval_intv_to_lfp(a); 461 TEST_ASSERT_TRUE(AssertFpClose(E,r,lfpClose)); //ASSERT_PRED_FORMAT2(FpClose, E, r); 462 } 463 } 464 465 466 void test_ToLFPrelPos() { 467 l_fp lfpClose = l_fp_init(0,1); 468 469 int i = 0; 470 for (i = 0; i < COUNTOF(fdata); i++) { 471 struct timeval a = timeval_init(1, fdata[i].usec); 472 l_fp E = l_fp_init(1, fdata[i].frac); 473 l_fp r; 474 475 r = tval_intv_to_lfp(a); 476 TEST_ASSERT_TRUE(AssertFpClose(E,r,lfpClose)); //ASSERT_PRED_FORMAT2(FpClose, E, r); 477 } 478 } 479 480 void test_ToLFPrelNeg() { 481 l_fp lfpClose = l_fp_init(0,1); 482 int i = 0; 483 for (i = 0; i < COUNTOF(fdata); i++) { 484 struct timeval a = timeval_init(-1, fdata[i].usec); 485 l_fp E = l_fp_init(~0, fdata[i].frac); 486 l_fp r; 487 488 r = tval_intv_to_lfp(a); 489 TEST_ASSERT_TRUE(AssertFpClose(E,r,lfpClose)); //ASSERT_PRED_FORMAT2(FpClose,E, r); 490 } 491 } 492 493 void test_ToLFPabs() { 494 l_fp lfpClose = l_fp_init(0,1); 495 496 int i = 0; 497 for (i = 0; i < COUNTOF(fdata); i++) { 498 struct timeval a = timeval_init(1, fdata[i].usec); 499 l_fp E = l_fp_init(1 + JAN_1970, fdata[i].frac); 500 l_fp r; 501 502 r = tval_stamp_to_lfp(a); 503 TEST_ASSERT_TRUE(AssertFpClose(E,r,lfpClose)); //ASSERT_PRED_FORMAT2(FpClose, E, r); 504 } 505 } 506 507 //---------------------------------------------------------------------- 508 // conversion from l_fp 509 //---------------------------------------------------------------------- 510 511 void test_FromLFPbittest() { 512 struct timeval timevalClose = timeval_init(0,1); 513 // Not *exactly* a bittest, because 2**32 tests would take a 514 // really long time even on very fast machines! So we do test 515 // every 1000 fractional units. 516 u_int32 tsf = 0; 517 for (tsf = 0; tsf < ~((u_int32)(1000)); tsf += 1000) { 518 struct timeval E = timeval_init(1, my_tsf_to_tick(tsf)); 519 l_fp a = l_fp_init(1, tsf); 520 struct timeval r; 521 522 r = lfp_intv_to_tval(a); 523 // The conversion might be off by one microsecond when 524 // comparing to calculated value. 525 TEST_ASSERT_TRUE(AssertTimevalClose(E,r,timevalClose)); //ASSERT_PRED_FORMAT2(TimevalClose, E, r); 526 } 527 } 528 529 void test_FromLFPrelPos() { 530 struct timeval timevalClose = timeval_init(0,1); 531 int i = 0; 532 for (i = 0; i < COUNTOF(fdata); i++) { 533 l_fp a = l_fp_init(1, fdata[i].frac); 534 struct timeval E = timeval_init(1, fdata[i].usec); 535 struct timeval r; 536 537 r = lfp_intv_to_tval(a); 538 TEST_ASSERT_TRUE(AssertTimevalClose(E,r,timevalClose)); //ASSERT_PRED_FORMAT2(TimevalClose, E, r); 539 } 540 } 541 542 void test_FromLFPrelNeg() { 543 struct timeval timevalClose = timeval_init(0,1); 544 int i = 0; 545 for (i = 0; i < COUNTOF(fdata); i++) { 546 l_fp a = l_fp_init(~0, fdata[i].frac); 547 struct timeval E = timeval_init(-1, fdata[i].usec); 548 struct timeval r; 549 550 r = lfp_intv_to_tval(a); 551 TEST_ASSERT_TRUE(AssertTimevalClose(E,r,timevalClose)); //ASSERT_PRED_FORMAT2(TimevalClose, E, r); 552 } 553 } 554 555 // usec -> frac -> usec roundtrip, using a prime start and increment 556 void test_LFProundtrip() { 557 int32_t t = -1; 558 u_int32 i = 5; 559 for (t = -1; t < 2; ++t) 560 for (i = 5; i < 1000000; i+=11) { 561 struct timeval E = timeval_init(t, i); 562 l_fp a; 563 struct timeval r; 564 565 a = tval_intv_to_lfp(E); 566 r = lfp_intv_to_tval(a); 567 TEST_ASSERT_EQUAL_timeval(E, r); 568 } 569 } 570 571 //---------------------------------------------------------------------- 572 // string formatting 573 //---------------------------------------------------------------------- 574 575 void test_ToString() { 576 static const struct { 577 time_t sec; 578 long usec; 579 const char * repr; 580 } data [] = { 581 { 0, 0, "0.000000" }, 582 { 2, 0, "2.000000" }, 583 {-2, 0, "-2.000000" }, 584 { 0, 1, "0.000001" }, 585 { 0,-1, "-0.000001" }, 586 { 1,-1, "0.999999" }, 587 {-1, 1, "-0.999999" }, 588 {-1,-1, "-1.000001" }, 589 }; 590 int i; 591 for (i = 0; i < COUNTOF(data); ++i) { 592 struct timeval a = timeval_init(data[i].sec, data[i].usec); 593 const char * E = data[i].repr; //?? 594 const char * r = tvaltoa(a); 595 596 TEST_ASSERT_EQUAL_STRING(E, r); 597 } 598 } 599 600 // -*- EOF -*- 601