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/cdefs.h> 27 #include <sys/types.h> 28 29 #include <assert.h> 30 #include <errno.h> 31 #include <float.h> 32 #include <limits.h> 33 #include <math.h> 34 #include <stdio.h> 35 #include <stdint.h> 36 #include <stdlib.h> 37 #include <strings.h> 38 #include <syslog.h> 39 #include <time.h> 40 41 #include <atf-c.h> 42 43 #define KASSERT(val, msg) assert(val) 44 45 typedef u_int32_t comp_t; 46 47 #define AHZ 1000000 48 49 #include "convert.c" 50 51 union cf { 52 comp_t c; 53 float f; 54 }; 55 56 static void 57 check_result(const char *name, float expected, union cf v) 58 { 59 double eps; 60 61 eps = fabs(expected - v.f) / expected; 62 ATF_CHECK(eps <= FLT_EPSILON); 63 if (eps > FLT_EPSILON) { 64 printf("Error in %s\n", name); 65 printf("Got 0x%08x %12g\n", v.c, v.f); 66 v.f = expected; 67 printf("Expected 0x%08x %12g (%.15lg)\n", v.c, v.f, expected); 68 printf("Epsilon=%lg, rather than %g\n", eps, FLT_EPSILON); 69 } 70 } 71 72 /* 73 * Test case for encoding {0 sec, 0 usec} within a reasonable epsilon. 74 */ 75 76 ATF_TC_WITHOUT_HEAD(encode_tv_zero); 77 ATF_TC_BODY(encode_tv_zero, tc) 78 { 79 union cf v; 80 struct timeval tv; 81 82 tv.tv_sec = 0; 83 tv.tv_usec = 0; 84 v.c = encode_timeval(tv); 85 ATF_CHECK(fabs(v.f - 0.0) < FLT_EPSILON); 86 } 87 88 /* 89 * Test case for encoding a random long number. 90 */ 91 92 ATF_TC_WITHOUT_HEAD(encode_long); 93 ATF_TC_BODY(encode_long, tc) 94 { 95 union cf v; 96 long l; 97 98 l = random(); 99 v.c = encode_long(l); 100 check_result(atf_tc_get_ident(tc), l, v); 101 } 102 103 /* 104 * Test case for encoding a small number of seconds {1 sec, 0 usec}. 105 */ 106 107 ATF_TC_WITHOUT_HEAD(encode_tv_only_sec); 108 ATF_TC_BODY(encode_tv_only_sec, tc) 109 { 110 union cf v; 111 struct timeval tv; 112 113 tv.tv_sec = 1; 114 tv.tv_usec = 0; 115 v.c = encode_timeval(tv); 116 check_result(atf_tc_get_ident(tc), 117 (float)tv.tv_sec * AHZ + tv.tv_usec, v); 118 } 119 120 /* 121 * Test case for encoding a small number of usec {0 sec, 1 usec}. 122 */ 123 124 ATF_TC_WITHOUT_HEAD(encode_tv_only_usec); 125 ATF_TC_BODY(encode_tv_only_usec, tc) 126 { 127 union cf v; 128 struct timeval tv; 129 130 tv.tv_sec = 0; 131 tv.tv_usec = 1; 132 v.c = encode_timeval(tv); 133 check_result(atf_tc_get_ident(tc), 134 (float)tv.tv_sec * AHZ + tv.tv_usec, v); 135 } 136 137 /* 138 * Test case for encoding a large number of usec {1 sec, 999.999 usec}. 139 */ 140 141 ATF_TC_WITHOUT_HEAD(encode_tv_many_usec); 142 ATF_TC_BODY(encode_tv_many_usec, tc) 143 { 144 union cf v; 145 struct timeval tv; 146 147 tv.tv_sec = 1; 148 tv.tv_usec = 999999L; 149 v.c = encode_timeval(tv); 150 check_result(atf_tc_get_ident(tc), 151 (float)tv.tv_sec * AHZ + tv.tv_usec, v); 152 } 153 154 /* 155 * Test case for encoding a huge number of usec {1 sec, 1.000.000 usec} that 156 * overflows the usec counter and should show up as an increase in timeval's 157 * seconds instead. 158 */ 159 160 ATF_TC_WITHOUT_HEAD(encode_tv_usec_overflow); 161 ATF_TC_BODY(encode_tv_usec_overflow, tc) 162 { 163 union cf v; 164 struct timeval tv; 165 166 tv.tv_sec = 1; 167 tv.tv_usec = 1000000L; 168 v.c = encode_timeval(tv); 169 check_result(atf_tc_get_ident(tc), 170 (float)tv.tv_sec * AHZ + tv.tv_usec, v); 171 } 172 173 /* 174 * Test case for encoding a very large number of seconds, one that is very 175 * near to the limit of 32-bit signed values. With a usec value of 999.999 176 * microseconds this should result in the largest value we can represent with 177 * a timeval struct. 178 */ 179 180 ATF_TC_WITHOUT_HEAD(encode_tv_upper_limit); 181 ATF_TC_BODY(encode_tv_upper_limit, tc) 182 { 183 union cf v; 184 struct timeval tv; 185 186 tv.tv_sec = 2147483647L; 187 tv.tv_usec = 999999L; 188 v.c = encode_timeval(tv); 189 check_result(atf_tc_get_ident(tc), 190 (float)tv.tv_sec * AHZ + tv.tv_usec, v); 191 } 192 193 /* 194 * Test case for encoding a million random timeval objects, and checking that 195 * the conversion does not diverge too much from the expected values. 196 */ 197 198 ATF_TC_WITHOUT_HEAD(encode_tv_random_million); 199 ATF_TC_BODY(encode_tv_random_million, tc) 200 { 201 union cf v; 202 struct timeval tv; 203 long k; 204 205 #ifdef __LP64__ 206 atf_tc_expect_fail("the testcase violates FLT_EPSILON on 64-bit " 207 "platforms, e.g. amd64"); 208 #endif 209 210 ATF_REQUIRE_MSG(unsetenv("TZ") == 0, "unsetting TZ failed; errno=%d", errno); 211 212 for (k = 1; k < 1000000L; k++) { 213 tv.tv_sec = random(); 214 tv.tv_usec = (random() % 1000000L); 215 v.c = encode_timeval(tv); 216 check_result(atf_tc_get_ident(tc), 217 (float)tv.tv_sec * AHZ + tv.tv_usec, v); 218 } 219 } 220 221 /* --------------------------------------------------------------------- 222 * Main. 223 * --------------------------------------------------------------------- */ 224 225 ATF_TP_ADD_TCS(tp) 226 { 227 228 ATF_TP_ADD_TC(tp, encode_long); 229 ATF_TP_ADD_TC(tp, encode_tv_zero); 230 ATF_TP_ADD_TC(tp, encode_tv_only_sec); 231 ATF_TP_ADD_TC(tp, encode_tv_only_usec); 232 ATF_TP_ADD_TC(tp, encode_tv_many_usec); 233 ATF_TP_ADD_TC(tp, encode_tv_usec_overflow); 234 ATF_TP_ADD_TC(tp, encode_tv_upper_limit); 235 ATF_TP_ADD_TC(tp, encode_tv_random_million); 236 237 return atf_no_error(); 238 } 239