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