Home | History | Annotate | Line # | Download | only in libntp
timespecops.c revision 1.1.1.3
      1 /*	$NetBSD: timespecops.c,v 1.1.1.3 2015/10/23 17:47:45 christos Exp $	*/
      2 
      3 #include "config.h"
      4 
      5 #include "ntp_types.h"
      6 #include "ntp_fp.h"
      7 #include "timespecops.h"
      8 
      9 #include "unity.h"
     10 
     11 #include <math.h>
     12 #include <string.h>
     13 
     14 
     15 #define TEST_ASSERT_EQUAL_timespec(a, b) { \
     16     TEST_ASSERT_EQUAL_MESSAGE(a.tv_sec, b.tv_sec, "Field tv_sec"); \
     17     TEST_ASSERT_EQUAL_MESSAGE(a.tv_nsec, b.tv_nsec, "Field tv_nsec");	\
     18 }
     19 
     20 
     21 #define TEST_ASSERT_EQUAL_l_fp(a, b) { \
     22     TEST_ASSERT_EQUAL_MESSAGE(a.l_i, b.l_i, "Field l_i"); \
     23     TEST_ASSERT_EQUAL_UINT_MESSAGE(a.l_uf, b.l_uf, "Field l_uf");	\
     24 }
     25 
     26 
     27 static u_int32 my_tick_to_tsf(u_int32 ticks);
     28 static u_int32 my_tsf_to_tick(u_int32 tsf);
     29 
     30 
     31 // that's it...
     32 struct lfpfracdata {
     33 	long	nsec;
     34 	u_int32 frac;
     35 };
     36 
     37 
     38 void test_Helpers1(void);
     39 void test_Normalise(void);
     40 void test_SignNoFrac(void);
     41 void test_SignWithFrac(void);
     42 void test_CmpFracEQ(void);
     43 void test_CmpFracGT(void);
     44 void test_CmpFracLT(void);
     45 void test_AddFullNorm(void);
     46 void test_AddFullOflow1(void);
     47 void test_AddNsecNorm(void);
     48 void test_AddNsecOflow1(void);
     49 void test_SubFullNorm(void);
     50 void test_SubFullOflow(void);
     51 void test_SubNsecNorm(void);
     52 void test_SubNsecOflow(void);
     53 void test_Neg(void);
     54 void test_AbsNoFrac(void);
     55 void test_AbsWithFrac(void);
     56 void test_Helpers2(void);
     57 void test_ToLFPbittest(void);
     58 void test_ToLFPrelPos(void);
     59 void test_ToLFPrelNeg(void);
     60 void test_ToLFPabs(void);
     61 void test_FromLFPbittest(void);
     62 void test_FromLFPrelPos(void);
     63 void test_FromLFPrelNeg(void);
     64 void test_LFProundtrip(void);
     65 void test_ToString(void);
     66 
     67 typedef int bool;
     68 
     69 const bool timespec_isValid(struct timespec V);
     70 struct timespec timespec_init(time_t hi, long lo);
     71 l_fp l_fp_init(int32 i, u_int32 f);
     72 bool AssertFpClose(const l_fp m, const l_fp n, const l_fp limit);
     73 bool AssertTimespecClose(const struct timespec m, const struct timespec n, const struct timespec limit);
     74 
     75 
     76 //******************************************MY CUSTOM FUNCTIONS*******************************
     77 
     78 
     79 
     80 const bool
     81 timespec_isValid(struct timespec V) {
     82 	return V.tv_nsec >= 0 && V.tv_nsec < 1000000000;
     83 }
     84 
     85 
     86 struct timespec
     87 timespec_init(time_t hi, long lo) {
     88 	struct timespec V;
     89 	V.tv_sec = hi;
     90 	V.tv_nsec = lo;
     91 	return V;
     92 }
     93 
     94 
     95 l_fp
     96 l_fp_init(int32 i, u_int32 f) {
     97 	l_fp temp;
     98 	temp.l_i  = i;
     99 	temp.l_uf = f;
    100 
    101 	return temp;
    102 }
    103 
    104 
    105 bool
    106 AssertFpClose(const l_fp m, const l_fp n, const l_fp limit) {
    107 	l_fp diff;
    108 
    109 	if (L_ISGEQ(&m, &n)) {
    110 		diff = m;
    111 		L_SUB(&diff, &n);
    112 	} else {
    113 		diff = n;
    114 		L_SUB(&diff, &m);
    115 	}
    116 	if (L_ISGEQ(&limit, &diff)){
    117 		return TRUE;
    118 	}
    119 	else {
    120 		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));
    121 		return FALSE;
    122 	}
    123 }
    124 
    125 
    126 bool
    127 AssertTimespecClose(const struct timespec m, const struct timespec n, const struct timespec limit) {
    128 	struct timespec diff;
    129 
    130 	diff = abs_tspec(sub_tspec(m, n));
    131 	if (cmp_tspec(limit, diff) >= 0)
    132 		return TRUE;
    133 	else
    134 	{
    135 		printf("m_expr which is %ld.%lu \nand\nn_expr which is %ld.%lu\nare not close; diff=%ld.%lunsec\n", m.tv_sec, m.tv_nsec, n.tv_sec, n.tv_nsec, diff.tv_sec, diff.tv_nsec);
    136 		return FALSE;
    137 	}
    138 }
    139 
    140 //-----------------------------------------------
    141 
    142 static const struct lfpfracdata fdata[] = {
    143 	{	  0, 0x00000000 }, {   2218896, 0x00916ae6 },
    144 	{  16408100, 0x0433523d }, { 125000000, 0x20000000 },
    145 	{ 250000000, 0x40000000 }, { 287455871, 0x4996b53d },
    146 	{ 375000000, 0x60000000 }, { 500000000, 0x80000000 },
    147 	{ 518978897, 0x84dbcd0e }, { 563730222, 0x90509fb3 },
    148 	{ 563788007, 0x9054692c }, { 583289882, 0x95527c57 },
    149 	{ 607074509, 0x9b693c2a }, { 625000000, 0xa0000000 },
    150 	{ 645184059, 0xa52ac851 }, { 676497788, 0xad2ef583 },
    151 	{ 678910895, 0xadcd1abb }, { 679569625, 0xadf84663 },
    152 	{ 690926741, 0xb0e0932d }, { 705656483, 0xb4a5e73d },
    153 	{ 723553854, 0xb93ad34c }, { 750000000, 0xc0000000 },
    154 	{ 763550253, 0xc3780785 }, { 775284917, 0xc6791284 },
    155 	{ 826190764, 0xd3813ce8 }, { 875000000, 0xe0000000 },
    156 	{ 956805507, 0xf4f134a9 }, { 982570733, 0xfb89c16c }
    157 	};
    158 
    159 
    160 u_int32
    161 my_tick_to_tsf(u_int32 ticks) {
    162 	// convert nanoseconds to l_fp fractional units, using double
    163 	// precision float calculations or, if available, 64bit integer
    164 	// arithmetic. This should give the precise fraction, rounded to
    165 	// the nearest representation.
    166 #ifdef HAVE_U_INT64
    167 	return (u_int32)((( ((u_int64)(ticks)) << 32) + 500000000) / 1000000000);
    168 #else
    169 	return (u_int32)((double(ticks)) * 4.294967296 + 0.5);
    170 #endif
    171 	// And before you ask: if ticks >= 1000000000, the result is
    172 	// truncated nonsense, so don't use it out-of-bounds.
    173 }
    174 
    175 
    176 u_int32
    177 my_tsf_to_tick(u_int32 tsf) {
    178 	// Inverse operation: converts fraction to microseconds.
    179 #ifdef HAVE_U_INT64
    180 	return (u_int32)(( ((u_int64)(tsf)) * 1000000000 + 0x80000000) >> 32);
    181 #else
    182 	return (u_int32)(double(tsf) / 4.294967296 + 0.5);
    183 #endif
    184 	// Beware: The result might be 10^9 due to rounding!
    185 }
    186 
    187 
    188 
    189 // ---------------------------------------------------------------------
    190 // test support stuff -- part 1
    191 // ---------------------------------------------------------------------
    192 
    193 void
    194 test_Helpers1(void) {
    195 	struct timespec x;
    196 
    197 	for (x.tv_sec = -2; x.tv_sec < 3; x.tv_sec++) {
    198 		x.tv_nsec = -1;
    199 		TEST_ASSERT_FALSE(timespec_isValid(x));
    200 		x.tv_nsec = 0;
    201 		TEST_ASSERT_TRUE(timespec_isValid(x));
    202 		x.tv_nsec = 999999999;
    203 		TEST_ASSERT_TRUE(timespec_isValid(x));
    204 		x.tv_nsec = 1000000000;
    205 		TEST_ASSERT_FALSE(timespec_isValid(x));
    206 	}
    207 }
    208 
    209 
    210 //----------------------------------------------------------------------
    211 // test normalisation
    212 //----------------------------------------------------------------------
    213 
    214 void
    215 test_Normalise(void) {
    216 	long ns;
    217 	for ( ns = -2000000000; ns <= 2000000000; ns += 10000000) {
    218 		struct timespec x = timespec_init(0, ns);
    219 
    220 		x = normalize_tspec(x);
    221 		TEST_ASSERT_TRUE(timespec_isValid(x));
    222 	}
    223 }
    224 
    225 //----------------------------------------------------------------------
    226 // test classification
    227 //----------------------------------------------------------------------
    228 
    229 void
    230 test_SignNoFrac(void) {
    231 	// sign test, no fraction
    232 	int i;
    233 	for (i = -4; i <= 4; ++i) {
    234 		struct timespec a = timespec_init(i, 0);
    235 		int E = (i > 0) - (i < 0);
    236 		int r = test_tspec(a);
    237 
    238 		TEST_ASSERT_EQUAL(E, r);
    239 	}
    240 }
    241 
    242 
    243 void
    244 test_SignWithFrac(void) {
    245 	// sign test, with fraction
    246 	int i;
    247 	for (i = -4; i <= 4; ++i) {
    248 		struct timespec a = timespec_init(i, 10);
    249 		int E = (i >= 0) - (i < 0);
    250 		int r = test_tspec(a);
    251 		TEST_ASSERT_EQUAL(E, r);
    252 	}
    253 }
    254 
    255 //----------------------------------------------------------------------
    256 // test compare
    257 //----------------------------------------------------------------------
    258 void
    259 test_CmpFracEQ(void) {
    260 	// fractions are equal
    261 	int i, j;
    262 	for (i = -4; i <= 4; ++i)
    263 		for (j = -4; j <= 4; ++j) {
    264 			struct timespec a = timespec_init( i , 200);
    265 			struct timespec b = timespec_init( j , 200);
    266 			int   E = (i > j) - (i < j);
    267 			int   r = cmp_tspec_denorm(a, b);
    268 			TEST_ASSERT_EQUAL(E, r);
    269 		}
    270 }
    271 
    272 
    273 void
    274 test_CmpFracGT(void) {
    275 	// fraction a bigger fraction b
    276 	int i, j;
    277 	for (i = -4; i <= 4; ++i)
    278 		for (j = -4; j <= 4; ++j) {
    279 			struct timespec a = timespec_init(i, 999999800);
    280 			struct timespec b = timespec_init(j, 200);
    281 			int   E = (i >= j) - (i < j);
    282 			int   r = cmp_tspec_denorm(a, b);
    283 			TEST_ASSERT_EQUAL(E, r);
    284 		}
    285 }
    286 
    287 
    288 void
    289 test_CmpFracLT(void) {
    290 	// fraction a less fraction b
    291 	int i, j;
    292 	for (i = -4; i <= 4; ++i)
    293 		for (j = -4; j <= 4; ++j) {
    294 			struct timespec a = timespec_init(i, 200);
    295 			struct timespec b = timespec_init(j, 999999800);
    296 			int   E = (i > j) - (i <= j);
    297 			int   r = cmp_tspec_denorm(a, b);
    298 			TEST_ASSERT_EQUAL(E, r);
    299 		}
    300 }
    301 
    302 //----------------------------------------------------------------------
    303 // Test addition (sum)
    304 //----------------------------------------------------------------------
    305 
    306 void
    307 test_AddFullNorm(void) {
    308 	int i, j;
    309 	for (i = -4; i <= 4; ++i)
    310 		for (j = -4; j <= 4; ++j) {
    311 			struct timespec a = timespec_init(i, 200);
    312 			struct timespec b = timespec_init(j, 400);
    313 			struct timespec E = timespec_init(i + j, 200 + 400);
    314 			struct timespec c;
    315 
    316 			c = add_tspec(a, b);
    317 			TEST_ASSERT_EQUAL_timespec(E, c);
    318 		}
    319 }
    320 
    321 
    322 void
    323 test_AddFullOflow1(void) {
    324 	int i, j;
    325 	for (i = -4; i <= 4; ++i)
    326 		for (j = -4; j <= 4; ++j) {
    327 			struct timespec a = timespec_init(i, 200);
    328 			struct timespec b = timespec_init(j, 999999900);
    329 			struct timespec E = timespec_init(i + j + 1, 100);
    330 			struct timespec c;
    331 
    332 			c = add_tspec(a, b);
    333 			TEST_ASSERT_EQUAL_timespec(E, c);
    334 		}
    335 }
    336 
    337 
    338 void
    339 test_AddNsecNorm(void) {
    340 	int i;
    341 	for (i = -4; i <= 4; ++i) {
    342 		struct timespec a = timespec_init(i, 200);
    343 		struct timespec E = timespec_init(i, 600);
    344 		struct timespec c;
    345 
    346 		c = add_tspec_ns(a, 600 - 200);
    347 		TEST_ASSERT_EQUAL_timespec(E, c);
    348 	}
    349 }
    350 
    351 
    352 void
    353 test_AddNsecOflow1(void) {
    354 	int i;
    355 	for (i = -4; i <= 4; ++i) {
    356 		struct timespec a = timespec_init(i, 200);
    357 		struct timespec E = timespec_init(i + 1, 100);
    358 		struct timespec c;
    359 
    360 		c = add_tspec_ns(a, NANOSECONDS - 100);
    361 		TEST_ASSERT_EQUAL_timespec(E, c);
    362 	}
    363 }
    364 
    365 //----------------------------------------------------------------------
    366 // test subtraction (difference)
    367 //----------------------------------------------------------------------
    368 
    369 void
    370 test_SubFullNorm(void) {
    371 	int i, j;
    372 	for (i = -4; i <= 4; ++i)
    373 		for (j = -4; j <= 4; ++j) {
    374 			struct timespec a = timespec_init( i , 600);
    375 			struct timespec b = timespec_init( j , 400);
    376 			struct timespec E = timespec_init(i-j, 200);
    377 			struct timespec c;
    378 
    379 			c = sub_tspec(a, b);
    380 			TEST_ASSERT_EQUAL_timespec(E, c);
    381 		}
    382 }
    383 
    384 
    385 void
    386 test_SubFullOflow(void) {
    387 	int i, j;
    388 	for (i = -4; i <= 4; ++i)
    389 		for (j = -4; j <= 4; ++j) {
    390 			struct timespec a = timespec_init(i, 100);
    391 			struct timespec b = timespec_init(j, 999999900);
    392 			struct timespec E = timespec_init(i - j - 1, 200);
    393 			struct timespec c;
    394 
    395 			c = sub_tspec(a, b);
    396 			TEST_ASSERT_EQUAL_timespec(E, c);
    397 		}
    398 }
    399 
    400 
    401 void
    402 test_SubNsecNorm(void) {
    403 	int i;
    404 	for (i = -4; i <= 4; ++i) {
    405 		struct timespec a = timespec_init(i, 600);
    406 		struct timespec E = timespec_init(i, 200);
    407 		struct timespec c;
    408 
    409 		c = sub_tspec_ns(a, 600 - 200);
    410 		TEST_ASSERT_EQUAL_timespec(E, c);
    411 	}
    412 }
    413 
    414 
    415 void
    416 test_SubNsecOflow(void) {
    417 	int i;
    418 	for (i = -4; i <= 4; ++i) {
    419 		struct timespec a = timespec_init( i , 100);
    420 		struct timespec E = timespec_init(i-1, 200);
    421 		struct timespec c;
    422 
    423 		c = sub_tspec_ns(a, NANOSECONDS - 100);
    424 		TEST_ASSERT_EQUAL_timespec(E, c);
    425 	}
    426 }
    427 
    428 //----------------------------------------------------------------------
    429 // test negation
    430 //----------------------------------------------------------------------
    431 
    432 
    433 void
    434 test_Neg(void) {
    435 	int i;
    436 	for (i = -4; i <= 4; ++i) {
    437 		struct timespec a = timespec_init(i, 100);
    438 		struct timespec b;
    439 		struct timespec c;
    440 
    441 		b = neg_tspec(a);
    442 		c = add_tspec(a, b);
    443 		TEST_ASSERT_EQUAL(0, test_tspec(c));
    444 	}
    445 }
    446 
    447 //----------------------------------------------------------------------
    448 // test abs value
    449 //----------------------------------------------------------------------
    450 
    451 void
    452 test_AbsNoFrac(void) {
    453 	int i;
    454 	for (i = -4; i <= 4; ++i) {
    455 		struct timespec a = timespec_init(i , 0);
    456 		struct timespec b;
    457 
    458 		b = abs_tspec(a);
    459 		TEST_ASSERT_EQUAL((i != 0), test_tspec(b));
    460 	}
    461 }
    462 
    463 
    464 void
    465 test_AbsWithFrac(void) {
    466 	int i;
    467 	for (i = -4; i <= 4; ++i) {
    468 		struct timespec a = timespec_init(i, 100);
    469 		struct timespec b;
    470 
    471 		b = abs_tspec(a);
    472 		TEST_ASSERT_EQUAL(1, test_tspec(b));
    473 	}
    474 }
    475 
    476 // ---------------------------------------------------------------------
    477 // test support stuff -- part 2
    478 // ---------------------------------------------------------------------
    479 
    480 void
    481 test_Helpers2(void) {
    482 	struct timespec limit = timespec_init(0, 2);
    483 
    484 	struct timespec x, y;
    485 	long i;
    486 
    487 	for (x.tv_sec = -2; x.tv_sec < 3; x.tv_sec++)
    488 		for (x.tv_nsec = 1;
    489 		     x.tv_nsec < 1000000000;
    490 		     x.tv_nsec += 499999999) {
    491 			for (i = -4; i < 5; ++i) {
    492 				y = x;
    493 				y.tv_nsec += i;
    494 				if (i >= -2 && i <= 2){
    495 					TEST_ASSERT_TRUE(AssertTimespecClose(x, y, limit));
    496 				}
    497 				else
    498 				{
    499 					TEST_ASSERT_FALSE(AssertTimespecClose(x, y, limit));
    500 				}
    501 			}
    502 		}
    503 }
    504 
    505 //----------------------------------------------------------------------
    506 // conversion to l_fp
    507 //----------------------------------------------------------------------
    508 
    509 void
    510 test_ToLFPbittest(void) {
    511 	l_fp lfpClose =  l_fp_init(0, 1);
    512 	u_int32 i;
    513 	for (i = 0; i < 1000000000; i+=1000) {
    514 		struct timespec a = timespec_init(1, i);
    515 		l_fp E= l_fp_init(1, my_tick_to_tsf(i));
    516 		l_fp r;
    517 
    518 		r = tspec_intv_to_lfp(a);
    519 		TEST_ASSERT_TRUE(AssertFpClose(E, r, lfpClose));
    520 	}
    521 }
    522 
    523 
    524 void
    525 test_ToLFPrelPos(void) {
    526 	int i;
    527 	for (i = 0; i < COUNTOF(fdata); ++i) {
    528 		struct timespec a = timespec_init(1, fdata[i].nsec);
    529 		l_fp E = l_fp_init(1, fdata[i].frac);
    530 		l_fp r;
    531 
    532 		r = tspec_intv_to_lfp(a);
    533 		TEST_ASSERT_EQUAL_l_fp(E, r);
    534 	}
    535 }
    536 
    537 
    538 void
    539 test_ToLFPrelNeg(void) {
    540 	int i;
    541 	for (i = 0; i < COUNTOF(fdata); ++i) {
    542 		struct timespec a = timespec_init(-1, fdata[i].nsec);
    543 		l_fp E = l_fp_init(~0, fdata[i].frac);
    544 		l_fp r;
    545 
    546 		r = tspec_intv_to_lfp(a);
    547 		TEST_ASSERT_EQUAL_l_fp(E, r);
    548 	}
    549 }
    550 
    551 
    552 void
    553 test_ToLFPabs(void) {
    554 	int i;
    555 	for (i = 0; i < COUNTOF(fdata); ++i) {
    556 		struct timespec a = timespec_init(1, fdata[i].nsec);
    557 		l_fp E = l_fp_init(1 + JAN_1970, fdata[i].frac);
    558 		l_fp r;
    559 
    560 		r = tspec_stamp_to_lfp(a);
    561 		TEST_ASSERT_EQUAL_l_fp(E, r);
    562 	}
    563 }
    564 
    565 //----------------------------------------------------------------------
    566 // conversion from l_fp
    567 //----------------------------------------------------------------------
    568 
    569 void
    570 test_FromLFPbittest(void) {
    571 	struct timespec limit = timespec_init(0, 2);
    572 
    573 	// Not *exactly* a bittest, because 2**32 tests would take a
    574 	// really long time even on very fast machines! So we do test
    575 	// every 1000 fractional units.
    576 	u_int32 tsf;
    577 	for (tsf = 0; tsf < ~((u_int32)(1000)); tsf += 1000) {
    578 		struct timespec E = timespec_init(1, my_tsf_to_tick(tsf));
    579 		l_fp a = l_fp_init(1, tsf);
    580 		struct timespec r;
    581 
    582 		r = lfp_intv_to_tspec(a);
    583 		// The conversion might be off by one nanosecond when
    584 		// comparing to calculated value.
    585 		TEST_ASSERT_TRUE(AssertTimespecClose(E, r, limit));
    586 	}
    587 }
    588 
    589 
    590 void
    591 test_FromLFPrelPos(void) {
    592 	struct timespec limit = timespec_init(0, 2);
    593 	int i;
    594 	for (i = 0; i < COUNTOF(fdata); ++i) {
    595 		l_fp a = l_fp_init(1, fdata[i].frac);
    596 		struct timespec E = timespec_init(1, fdata[i].nsec);
    597 		struct timespec r;
    598 
    599 		r = lfp_intv_to_tspec(a);
    600 		TEST_ASSERT_TRUE(AssertTimespecClose(E, r, limit));
    601 	}
    602 }
    603 
    604 
    605 void
    606 test_FromLFPrelNeg(void) {
    607 	struct timespec limit = timespec_init(0, 2);
    608 	int i;
    609 	for (i = 0; i < COUNTOF(fdata); ++i) {
    610 		l_fp a = l_fp_init(~0, fdata[i].frac);
    611 		struct timespec E = timespec_init(-1, fdata[i].nsec);
    612 		struct timespec r;
    613 
    614 		r = lfp_intv_to_tspec(a);
    615 		TEST_ASSERT_TRUE(AssertTimespecClose(E, r, limit));
    616 	}
    617 }
    618 
    619 
    620 // nsec -> frac -> nsec roundtrip, using a prime start and increment
    621 void
    622 test_LFProundtrip(void) {
    623 	int32_t t;
    624 	u_int32 i;
    625 	for (t = -1; t < 2; ++t)
    626 		for (i = 4999; i < 1000000000; i += 10007) {
    627 			struct timespec E = timespec_init(t, i);
    628 			l_fp a;
    629 			struct timespec r;
    630 
    631 			a = tspec_intv_to_lfp(E);
    632 			r = lfp_intv_to_tspec(a);
    633 			TEST_ASSERT_EQUAL_timespec(E, r);
    634 		}
    635 }
    636 
    637 //----------------------------------------------------------------------
    638 // string formatting
    639 //----------------------------------------------------------------------
    640 
    641 void
    642 test_ToString(void) {
    643 	static const struct {
    644 		time_t		sec;
    645 		long		nsec;
    646 		const char *	repr;
    647 	} data [] = {
    648 		{ 0, 0,	 "0.000000000" },
    649 		{ 2, 0,	 "2.000000000" },
    650 		{-2, 0, "-2.000000000" },
    651 		{ 0, 1,	 "0.000000001" },
    652 		{ 0,-1,	"-0.000000001" },
    653 		{ 1,-1,	 "0.999999999" },
    654 		{-1, 1, "-0.999999999" },
    655 		{-1,-1, "-1.000000001" },
    656 	};
    657 	int i;
    658 	for (i = 0; i < COUNTOF(data); ++i) {
    659 		struct timespec a = timespec_init(data[i].sec, data[i].nsec);
    660 		const char * E = data[i].repr;
    661 		const char * r = tspectoa(a);
    662 		TEST_ASSERT_EQUAL_STRING(E, r);
    663 	}
    664 }
    665 
    666 // -*- EOF -*-
    667