1 /* $NetBSD: t_strtoi.c,v 1.1 2015/05/01 14:17:56 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2015 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jukka Ruohonen. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Created by Kamil Rytarowski, vesed on ID: 34 * NetBSD: t_strtol.c,v 1.5 2011/06/14 02:45:58 jruoho Exp 35 */ 36 37 #include <sys/cdefs.h> 38 __RCSID("$NetBSD: t_strtoi.c,v 1.1 2015/05/01 14:17:56 christos Exp $"); 39 40 #include <atf-c.h> 41 #include <errno.h> 42 #include <inttypes.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <limits.h> 46 47 struct test { 48 const char *str; 49 intmax_t res; 50 int base; 51 const char *end; 52 intmax_t lo; 53 intmax_t hi; 54 int rstatus; 55 }; 56 57 static void check(struct test *, intmax_t, char *, int); 58 59 static void 60 check(struct test *t, intmax_t rv, char *end, int rstatus) 61 { 62 63 if (rv != t->res) 64 atf_tc_fail_nonfatal("strtoi(%s, &end, %d, %jd, %jd, &rstatus)" 65 " failed (rv = %jd)", t->str, t->base, t->lo, t->hi, rv); 66 67 if (rstatus != t->rstatus) 68 atf_tc_fail_nonfatal("strtoi(%s, &end, %d, %jd, %jd, &rstatus)" 69 " failed (rstatus: %d ('%s'))", 70 t->str, t->base, t->lo, t->hi, rstatus, strerror(rstatus)); 71 72 if ((t->end != NULL && strcmp(t->end, end) != 0) || 73 (t->end == NULL && *end != '\0')) 74 atf_tc_fail_nonfatal("invalid end pointer ('%s') from " 75 "strtoi(%s, &end, %d, %jd, %jd, &rstatus)", 76 end, t->str, t->base, t->lo, t->hi); 77 } 78 79 ATF_TC(strtoi_base); 80 ATF_TC_HEAD(strtoi_base, tc) 81 { 82 atf_tc_set_md_var(tc, "descr", "Test strtoi(3) with different bases"); 83 } 84 85 ATF_TC_BODY(strtoi_base, tc) 86 { 87 struct test t[] = { 88 { "123456789", 123456789, 0, NULL, 89 INTMAX_MIN, INTMAX_MAX, 0 }, 90 { "111010110111100110100010101",123456789, 2, NULL, 91 INTMAX_MIN, INTMAX_MAX, 0 }, 92 { "22121022020212200", 123456789, 3, NULL, 93 INTMAX_MIN, INTMAX_MAX, 0 }, 94 { "13112330310111", 123456789, 4, NULL, 95 INTMAX_MIN, INTMAX_MAX, 0 }, 96 { "223101104124", 123456789, 5, NULL, 97 INTMAX_MIN, INTMAX_MAX, 0 }, 98 { "20130035113", 123456789, 6, NULL, 99 INTMAX_MIN, INTMAX_MAX, 0 }, 100 { "3026236221", 123456789, 7, NULL, 101 INTMAX_MIN, INTMAX_MAX, 0 }, 102 { "726746425", 123456789, 8, NULL, 103 INTMAX_MIN, INTMAX_MAX, 0 }, 104 { "277266780", 123456789, 9, NULL, 105 INTMAX_MIN, INTMAX_MAX, 0 }, 106 { "123456789", 123456789, 10, NULL, 107 INTMAX_MIN, INTMAX_MAX, 0 }, 108 { "63762A05", 123456789, 11, NULL, 109 INTMAX_MIN, INTMAX_MAX, 0 }, 110 { "35418A99", 123456789, 12, NULL, 111 INTMAX_MIN, INTMAX_MAX, 0 }, 112 { "1C767471", 123456789, 13, NULL, 113 INTMAX_MIN, INTMAX_MAX, 0 }, 114 { "12579781", 123456789, 14, NULL, 115 INTMAX_MIN, INTMAX_MAX, 0 }, 116 { "AC89BC9", 123456789, 15, NULL, 117 INTMAX_MIN, INTMAX_MAX, 0 }, 118 { "75BCD15", 123456789, 16, NULL, 119 INTMAX_MIN, INTMAX_MAX, 0 }, 120 { "1234567", 342391, 8, NULL, 121 INTMAX_MIN, INTMAX_MAX, 0 }, 122 { "01234567", 342391, 0, NULL, 123 INTMAX_MIN, INTMAX_MAX, 0 }, 124 { "0123456789", 123456789, 10, NULL, 125 INTMAX_MIN, INTMAX_MAX, 0 }, 126 { "0x75bcd15", 123456789, 0, NULL, 127 INTMAX_MIN, INTMAX_MAX, 0 }, 128 }; 129 130 intmax_t rv; 131 char *end; 132 int e; 133 size_t i; 134 135 for (i = 0; i < __arraycount(t); i++) { 136 137 errno = 0; 138 rv = strtoi(t[i].str, &end, t[i].base, t[i].lo, t[i].hi, &e); 139 140 if (errno != 0) 141 atf_tc_fail("strtoi(3) changed errno to %d ('%s')", 142 e, strerror(e)); 143 144 check(&t[i], rv, end, e); 145 } 146 } 147 148 ATF_TC(strtoi_case); 149 ATF_TC_HEAD(strtoi_case, tc) 150 { 151 atf_tc_set_md_var(tc, "descr", "Case insensitivity with strtoi(3)"); 152 } 153 154 ATF_TC_BODY(strtoi_case, tc) 155 { 156 struct test t[] = { 157 { "abcd", 0xabcd, 16, NULL, 158 INTMAX_MIN, INTMAX_MAX, 0 }, 159 { " dcba", 0xdcba, 16, NULL, 160 INTMAX_MIN, INTMAX_MAX, 0 }, 161 { "abcd dcba", 0xabcd, 16, " dcba", 162 INTMAX_MIN, INTMAX_MAX, ENOTSUP }, 163 { "abc0x123", 0xabc0, 16, "x123", 164 INTMAX_MIN, INTMAX_MAX, ENOTSUP }, 165 { "abcd\0x123", 0xabcd, 16, "\0x123", 166 INTMAX_MIN, INTMAX_MAX, 0 }, 167 { "ABCD", 0xabcd, 16, NULL, 168 INTMAX_MIN, INTMAX_MAX, 0 }, 169 { "aBcD", 0xabcd, 16, NULL, 170 INTMAX_MIN, INTMAX_MAX, 0 }, 171 { "0xABCD", 0xabcd, 16, NULL, 172 INTMAX_MIN, INTMAX_MAX, 0 }, 173 { "0xABCDX", 0xabcd, 16, "X", 174 INTMAX_MIN, INTMAX_MAX, ENOTSUP}, 175 }; 176 177 intmax_t rv; 178 char *end; 179 int e; 180 size_t i; 181 182 for (i = 0; i < __arraycount(t); i++) { 183 184 errno = 0; 185 rv = strtoi(t[i].str, &end, t[i].base, t[i].lo, t[i].hi, &e); 186 187 if (errno != 0) 188 atf_tc_fail("strtoi(3) changed errno to %d ('%s')", 189 e, strerror(e)); 190 191 check(&t[i], rv, end, e); 192 } 193 } 194 195 ATF_TC(strtoi_range); 196 ATF_TC_HEAD(strtoi_range, tc) 197 { 198 atf_tc_set_md_var(tc, "descr", "Test ERANGE from strtoi(3)"); 199 } 200 201 ATF_TC_BODY(strtoi_range, tc) 202 { 203 struct test t[] = { 204 #if INTMAX_MAX == 0x7fffffffffffffff 205 { "1000000000000000000000", INTMAX_MAX, 8, NULL, 206 INTMAX_MIN, INTMAX_MAX, ERANGE }, 207 { "9223372036854775808", INTMAX_MAX, 10, NULL, 208 INTMAX_MIN, INTMAX_MAX, ERANGE }, 209 { "8000000000000000", INTMAX_MAX, 16, NULL, 210 INTMAX_MIN, INTMAX_MAX, ERANGE }, 211 #else 212 #error extend this test to your platform! 213 #endif 214 { "10", 1, 10, NULL, 215 -1, 1, ERANGE }, 216 { "10", 11, 10, NULL, 217 11, 20, ERANGE }, 218 }; 219 220 intmax_t rv; 221 char *end; 222 int e; 223 size_t i; 224 225 for (i = 0; i < __arraycount(t); i++) { 226 227 errno = 0; 228 rv = strtoi(t[i].str, &end, t[i].base, t[i].lo, t[i].hi, &e); 229 230 if (errno != 0) 231 atf_tc_fail("strtoi(3) changed errno to %d ('%s')", 232 e, strerror(e)); 233 234 check(&t[i], rv, end, e); 235 } 236 } 237 238 ATF_TC(strtoi_signed); 239 ATF_TC_HEAD(strtoi_signed, tc) 240 { 241 atf_tc_set_md_var(tc, "descr", "A basic test of strtoi(3)"); 242 } 243 244 ATF_TC_BODY(strtoi_signed, tc) 245 { 246 struct test t[] = { 247 { "1", 1, 0, NULL, 248 INTMAX_MIN, INTMAX_MAX, 0 }, 249 { " 2", 2, 0, NULL, 250 INTMAX_MIN, INTMAX_MAX, 0 }, 251 { " 3", 3, 0, NULL, 252 INTMAX_MIN, INTMAX_MAX, 0 }, 253 { " -3", -3, 0, NULL, 254 INTMAX_MIN, INTMAX_MAX, 0 }, 255 { "--1", 0, 0, "--1", 256 INTMAX_MIN, INTMAX_MAX, ECANCELED }, 257 { "+-2", 0, 0, "+-2", 258 INTMAX_MIN, INTMAX_MAX, ECANCELED }, 259 { "++3", 0, 0, "++3", 260 INTMAX_MIN, INTMAX_MAX, ECANCELED }, 261 { "+9", 9, 0, NULL, 262 INTMAX_MIN, INTMAX_MAX, 0 }, 263 { "+123", 123, 0, NULL, 264 INTMAX_MIN, INTMAX_MAX, 0 }, 265 { "-1 3", -1, 0, " 3", 266 INTMAX_MIN, INTMAX_MAX, ENOTSUP }, 267 { "-1.3", -1, 0, ".3", 268 INTMAX_MIN, INTMAX_MAX, ENOTSUP }, 269 { "- 3", 0, 0, "- 3", 270 INTMAX_MIN, INTMAX_MAX, ECANCELED }, 271 { "+33.", 33, 0, ".", 272 INTMAX_MIN, INTMAX_MAX, ENOTSUP }, 273 { "30x0", 30, 0, "x0", 274 INTMAX_MIN, INTMAX_MAX, ENOTSUP }, 275 }; 276 277 intmax_t rv; 278 char *end; 279 int e; 280 size_t i; 281 282 for (i = 0; i < __arraycount(t); i++) { 283 284 errno = 0; 285 rv = strtoi(t[i].str, &end, t[i].base, t[i].lo, t[i].hi, &e); 286 287 if (errno != 0) 288 atf_tc_fail("strtoi(3) changed errno to %d ('%s')", 289 e, strerror(e)); 290 291 check(&t[i], rv, end, e); 292 } 293 } 294 295 ATF_TP_ADD_TCS(tp) 296 { 297 298 ATF_TP_ADD_TC(tp, strtoi_base); 299 ATF_TP_ADD_TC(tp, strtoi_case); 300 ATF_TP_ADD_TC(tp, strtoi_range); 301 ATF_TP_ADD_TC(tp, strtoi_signed); 302 303 return atf_no_error(); 304 } 305