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