1 /*- 2 * Copyright (c) 2011 Giorgos Keramidas. All rights reserved. 3 * Copyright (c) 2007 Diomidis Spinellis. All rights reserved. 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #include <sys/types.h> 27 28 #include <assert.h> 29 #include <errno.h> 30 #include <float.h> 31 #include <limits.h> 32 #include <math.h> 33 #include <stdio.h> 34 #include <stdint.h> 35 #include <stdlib.h> 36 #include <strings.h> 37 #include <syslog.h> 38 #include <time.h> 39 40 #include <atf-c.h> 41 42 #define KASSERT(val, msg) assert(val) 43 44 typedef u_int32_t comp_t; 45 46 #define AHZ 1000000 47 48 #include "convert.c" 49 50 union cf { 51 comp_t c; 52 float f; 53 }; 54 55 static void 56 check_result(const char *name, float expected, union cf v) 57 { 58 double eps; 59 60 eps = fabs(expected - v.f) / expected; 61 ATF_CHECK(eps <= FLT_EPSILON); 62 if (eps > FLT_EPSILON) { 63 printf("Error in %s\n", name); 64 printf("Got 0x%08x %12g\n", v.c, v.f); 65 v.f = expected; 66 printf("Expected 0x%08x %12g (%.15lg)\n", v.c, v.f, expected); 67 printf("Epsilon=%lg, rather than %g\n", eps, FLT_EPSILON); 68 } 69 } 70 71 /* 72 * Test case for encoding {0 sec, 0 usec} within a reasonable epsilon. 73 */ 74 75 ATF_TC_WITHOUT_HEAD(encode_tv_zero); 76 ATF_TC_BODY(encode_tv_zero, tc) 77 { 78 union cf v; 79 struct timeval tv; 80 81 tv.tv_sec = 0; 82 tv.tv_usec = 0; 83 v.c = encode_timeval(tv); 84 ATF_CHECK(fabs(v.f - 0.0) < FLT_EPSILON); 85 } 86 87 /* 88 * Test case for encoding a random long number. 89 */ 90 91 ATF_TC_WITHOUT_HEAD(encode_long); 92 ATF_TC_BODY(encode_long, tc) 93 { 94 union cf v; 95 long l; 96 97 l = random(); 98 v.c = encode_long(l); 99 check_result(atf_tc_get_ident(tc), l, v); 100 } 101 102 /* 103 * Test case for encoding a small number of seconds {1 sec, 0 usec}. 104 */ 105 106 ATF_TC_WITHOUT_HEAD(encode_tv_only_sec); 107 ATF_TC_BODY(encode_tv_only_sec, tc) 108 { 109 union cf v; 110 struct timeval tv; 111 112 tv.tv_sec = 1; 113 tv.tv_usec = 0; 114 v.c = encode_timeval(tv); 115 check_result(atf_tc_get_ident(tc), 116 (float)tv.tv_sec * AHZ + tv.tv_usec, v); 117 } 118 119 /* 120 * Test case for encoding a small number of usec {0 sec, 1 usec}. 121 */ 122 123 ATF_TC_WITHOUT_HEAD(encode_tv_only_usec); 124 ATF_TC_BODY(encode_tv_only_usec, tc) 125 { 126 union cf v; 127 struct timeval tv; 128 129 tv.tv_sec = 0; 130 tv.tv_usec = 1; 131 v.c = encode_timeval(tv); 132 check_result(atf_tc_get_ident(tc), 133 (float)tv.tv_sec * AHZ + tv.tv_usec, v); 134 } 135 136 /* 137 * Test case for encoding a large number of usec {1 sec, 999.999 usec}. 138 */ 139 140 ATF_TC_WITHOUT_HEAD(encode_tv_many_usec); 141 ATF_TC_BODY(encode_tv_many_usec, tc) 142 { 143 union cf v; 144 struct timeval tv; 145 146 tv.tv_sec = 1; 147 tv.tv_usec = 999999L; 148 v.c = encode_timeval(tv); 149 check_result(atf_tc_get_ident(tc), 150 (float)tv.tv_sec * AHZ + tv.tv_usec, v); 151 } 152 153 /* 154 * Test case for encoding a huge number of usec {1 sec, 1.000.000 usec} that 155 * overflows the usec counter and should show up as an increase in timeval's 156 * seconds instead. 157 */ 158 159 ATF_TC_WITHOUT_HEAD(encode_tv_usec_overflow); 160 ATF_TC_BODY(encode_tv_usec_overflow, tc) 161 { 162 union cf v; 163 struct timeval tv; 164 165 tv.tv_sec = 1; 166 tv.tv_usec = 1000000L; 167 v.c = encode_timeval(tv); 168 check_result(atf_tc_get_ident(tc), 169 (float)tv.tv_sec * AHZ + tv.tv_usec, v); 170 } 171 172 /* 173 * Test case for encoding a very large number of seconds, one that is very 174 * near to the limit of 32-bit signed values. With a usec value of 999.999 175 * microseconds this should result in the largest value we can represent with 176 * a timeval struct. 177 */ 178 179 ATF_TC_WITHOUT_HEAD(encode_tv_upper_limit); 180 ATF_TC_BODY(encode_tv_upper_limit, tc) 181 { 182 union cf v; 183 struct timeval tv; 184 185 tv.tv_sec = 2147483647L; 186 tv.tv_usec = 999999L; 187 v.c = encode_timeval(tv); 188 check_result(atf_tc_get_ident(tc), 189 (float)tv.tv_sec * AHZ + tv.tv_usec, v); 190 } 191 192 /* 193 * Test case for encoding a million random timeval objects, and checking that 194 * the conversion does not diverge too much from the expected values. 195 */ 196 197 ATF_TC_WITHOUT_HEAD(encode_tv_random_million); 198 ATF_TC_BODY(encode_tv_random_million, tc) 199 { 200 union cf v; 201 struct timeval tv; 202 long k; 203 204 #ifdef __LP64__ 205 atf_tc_expect_fail("the testcase violates FLT_EPSILON on 64-bit " 206 "platforms, e.g. amd64"); 207 #endif 208 209 ATF_REQUIRE_MSG(unsetenv("TZ") == 0, "unsetting TZ failed; errno=%d", errno); 210 211 for (k = 1; k < 1000000L; k++) { 212 tv.tv_sec = random(); 213 tv.tv_usec = (random() % 1000000L); 214 v.c = encode_timeval(tv); 215 check_result(atf_tc_get_ident(tc), 216 (float)tv.tv_sec * AHZ + tv.tv_usec, v); 217 } 218 } 219 220 /* --------------------------------------------------------------------- 221 * Main. 222 * --------------------------------------------------------------------- */ 223 224 ATF_TP_ADD_TCS(tp) 225 { 226 227 ATF_TP_ADD_TC(tp, encode_long); 228 ATF_TP_ADD_TC(tp, encode_tv_zero); 229 ATF_TP_ADD_TC(tp, encode_tv_only_sec); 230 ATF_TP_ADD_TC(tp, encode_tv_only_usec); 231 ATF_TP_ADD_TC(tp, encode_tv_many_usec); 232 ATF_TP_ADD_TC(tp, encode_tv_usec_overflow); 233 ATF_TP_ADD_TC(tp, encode_tv_upper_limit); 234 ATF_TP_ADD_TC(tp, encode_tv_random_million); 235 236 return atf_no_error(); 237 } 238