Home | History | Annotate | Line # | Download | only in stdlib
t_strtod.c revision 1.12.2.1
      1 /*	$NetBSD: t_strtod.c,v 1.12.2.1 2011/06/23 14:20:40 cherry Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2011 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 /* Public domain, Otto Moerbeek <otto (at) drijf.net>, 2006. */
     33 
     34 #include <sys/cdefs.h>
     35 __RCSID("$NetBSD: t_strtod.c,v 1.12.2.1 2011/06/23 14:20:40 cherry Exp $");
     36 
     37 #include <errno.h>
     38 #include <math.h>
     39 #include <stdio.h>
     40 #include <stdlib.h>
     41 #include <string.h>
     42 
     43 #include <atf-c.h>
     44 #include <atf-c/config.h>
     45 
     46 #if defined(__i386__) || defined(__amd64__) || defined(__sparc__)
     47 #include <fenv.h>
     48 #endif
     49 
     50 #if !defined(__vax__)
     51 static const char * const inf_strings[] =
     52     { "Inf", "INF", "-Inf", "-INF", "Infinity", "+Infinity",
     53       "INFINITY", "-INFINITY", "InFiNiTy", "+InFiNiTy" };
     54 const char *nan_string = "NaN(x)y";
     55 #endif
     56 
     57 ATF_TC(strtod_basic);
     58 ATF_TC_HEAD(strtod_basic, tc)
     59 {
     60 	atf_tc_set_md_var(tc, "descr", "A basic test of strtod(3)");
     61 }
     62 
     63 ATF_TC_BODY(strtod_basic, tc)
     64 {
     65 	static const size_t n = 1024 * 1000;
     66 
     67 	for (size_t i = 1; i < n; i = i + 1024) {
     68 		char buf[512];
     69 		(void)snprintf(buf, sizeof(buf), "%zu.%zu", i, i + 1);
     70 
     71 		errno = 0;
     72 		double d = strtod(buf, NULL);
     73 
     74 		ATF_REQUIRE(d > 0.0);
     75 		ATF_REQUIRE(errno == 0);
     76 	}
     77 }
     78 
     79 ATF_TC(strtod_hex);
     80 ATF_TC_HEAD(strtod_hex, tc)
     81 {
     82 	atf_tc_set_md_var(tc, "descr", "A strtod(3) with hexadecimals");
     83 }
     84 
     85 ATF_TC_BODY(strtod_hex, tc)
     86 {
     87 	const char *str;
     88 	char *end;
     89 	double d;
     90 
     91 	str = "-0x0";
     92 	d = strtod(str, &end);	/* -0.0 */
     93 
     94 	ATF_REQUIRE(end == str + 4);
     95 	ATF_REQUIRE(signbit(d) != 0);
     96 	ATF_REQUIRE(fabs(d) < 1.0e-40);
     97 
     98 	str = "-0x";
     99 	d = strtod(str, &end);	/* -0.0 */
    100 
    101 	ATF_REQUIRE(end == str + 2);
    102 	ATF_REQUIRE(signbit(d) != 0);
    103 	ATF_REQUIRE(fabs(d) < 1.0e-40);
    104 }
    105 
    106 ATF_TC(strtod_inf);
    107 ATF_TC_HEAD(strtod_inf, tc)
    108 {
    109 	atf_tc_set_md_var(tc, "descr", "A strtod(3) with INF");
    110 }
    111 
    112 ATF_TC_BODY(strtod_inf, tc)
    113 {
    114 #ifndef __vax__
    115 	/*
    116 	 * See the closed PR lib/33262.
    117 	 */
    118 	for (size_t i = 0; i < __arraycount(inf_strings); i++) {
    119 		double d = strtod(inf_strings[i], NULL);
    120 		ATF_REQUIRE(isinf(d) != 0);
    121 	}
    122 #else
    123 	atf_tc_skip("vax not supported");
    124 #endif
    125 }
    126 
    127 ATF_TC(strtof_inf);
    128 ATF_TC_HEAD(strtof_inf, tc)
    129 {
    130 	atf_tc_set_md_var(tc, "descr", "A strtof(3) with INF");
    131 }
    132 
    133 ATF_TC_BODY(strtof_inf, tc)
    134 {
    135 #ifndef __vax__
    136 	/*
    137 	 * See the closed PR lib/33262.
    138 	 */
    139 	for (size_t i = 0; i < __arraycount(inf_strings); i++) {
    140 		float f = strtof(inf_strings[i], NULL);
    141 		ATF_REQUIRE(isinf(f) != 0);
    142 	}
    143 #else
    144 	atf_tc_skip("vax not supported");
    145 #endif
    146 }
    147 
    148 ATF_TC(strtold_inf);
    149 ATF_TC_HEAD(strtold_inf, tc)
    150 {
    151 	atf_tc_set_md_var(tc, "descr", "A strtold(3) with INF");
    152 }
    153 
    154 ATF_TC_BODY(strtold_inf, tc)
    155 {
    156 #ifndef __vax__
    157 #   ifdef __HAVE_LONG_DOUBLE
    158 	/*
    159 	 * See the closed PR lib/33262.
    160 	 *
    161 	 * This may also fail under QEMU; cf. PR misc/44767.
    162 	 */
    163 	if (system("cpuctl identify 0 | grep -q QEMU") == 0)
    164 		atf_tc_expect_fail("PR misc/44767");
    165 
    166 	for (size_t i = 0; i < __arraycount(inf_strings); i++) {
    167 		long double ld = strtold(inf_strings[i], NULL);
    168 		ATF_REQUIRE(isinf(ld) != 0);
    169 	}
    170 #   else
    171 	atf_tc_skip("Requires long double support");
    172 #   endif
    173 #else
    174 	atf_tc_skip("vax not supported");
    175 #endif
    176 }
    177 
    178 ATF_TC(strtod_nan);
    179 ATF_TC_HEAD(strtod_nan, tc)
    180 {
    181 	atf_tc_set_md_var(tc, "descr", "A strtod(3) with NaN");
    182 }
    183 
    184 ATF_TC_BODY(strtod_nan, tc)
    185 {
    186 #ifndef __vax__
    187 	char *end;
    188 
    189 	double d = strtod(nan_string, &end);
    190 	ATF_REQUIRE(isnan(d) != 0);
    191 	ATF_REQUIRE(strcmp(end, "y") == 0);
    192 #else
    193 	atf_tc_skip("vax not supported");
    194 #endif
    195 }
    196 
    197 ATF_TC(strtof_nan);
    198 ATF_TC_HEAD(strtof_nan, tc)
    199 {
    200 	atf_tc_set_md_var(tc, "descr", "A strtof(3) with NaN");
    201 }
    202 
    203 ATF_TC_BODY(strtof_nan, tc)
    204 {
    205 #ifndef __vax__
    206 	char *end;
    207 
    208 	float f = strtof(nan_string, &end);
    209 	ATF_REQUIRE(isnanf(f) != 0);
    210 	ATF_REQUIRE(strcmp(end, "y") == 0);
    211 #else
    212 	atf_tc_skip("vax not supported");
    213 #endif
    214 }
    215 
    216 ATF_TC(strtold_nan);
    217 ATF_TC_HEAD(strtold_nan, tc)
    218 {
    219 	atf_tc_set_md_var(tc, "descr", "A strtold(3) with NaN");
    220 }
    221 
    222 ATF_TC_BODY(strtold_nan, tc)
    223 {
    224 #ifndef __vax__
    225 #   ifdef __HAVE_LONG_DOUBLE
    226 	char *end;
    227 
    228 	/*
    229 	 * See PR lib/45020.
    230 	 *
    231 	 * This may also fail under QEMU; cf. PR misc/44767.
    232 	 */
    233 	if (system("cpuctl identify 0 | grep -q QEMU") == 0)
    234 		atf_tc_expect_fail("PR misc/44767");
    235 
    236 	long double ld = strtold(nan_string, &end);
    237 	ATF_REQUIRE(isnan(ld) != 0);
    238 	ATF_REQUIRE(__isnanl(ld) != 0);
    239 	ATF_REQUIRE(strcmp(end, "y") == 0);
    240 #   else
    241 	atf_tc_skip("Requires long double support");
    242 #   endif
    243 #else
    244 	atf_tc_skip("vax not supported");
    245 #endif
    246 }
    247 
    248 ATF_TC(strtod_round);
    249 ATF_TC_HEAD(strtod_round, tc)
    250 {
    251 	atf_tc_set_md_var(tc, "descr", "Test rouding in strtod(3)");
    252 }
    253 
    254 ATF_TC_BODY(strtod_round, tc)
    255 {
    256 #if defined(__i386__) || defined(__amd64__) || defined(__sparc__)
    257 	/*
    258 	 * Test that strtod(3) honors the current rounding mode.
    259 	 * The used value is somewhere near 1 + DBL_EPSILON + FLT_EPSILON.
    260 	 *
    261 	 * May fail under QEMU; cf. PR misc/44767.
    262 	 */
    263 	if (system("cpuctl identify 0 | grep -q QEMU") == 0)
    264 		atf_tc_expect_fail("PR misc/44767");
    265 
    266 	const char *val =
    267 	    "1.00000011920928977282585492503130808472633361816406";
    268 
    269 	(void)fesetround(FE_UPWARD);
    270 
    271 	double d1 = strtod(val, NULL);
    272 
    273 	(void)fesetround(FE_DOWNWARD);
    274 
    275 	double d2 = strtod(val, NULL);
    276 
    277 	ATF_REQUIRE(fabs(d1 - d2) > 0.0);
    278 #else
    279 	atf_tc_skip("Requires one of i386, amd64 or sparc");
    280 #endif
    281 }
    282 
    283 ATF_TC(strtod_underflow);
    284 ATF_TC_HEAD(strtod_underflow, tc)
    285 {
    286 	atf_tc_set_md_var(tc, "descr", "Test underflow in strtod(3)");
    287 }
    288 
    289 ATF_TC_BODY(strtod_underflow, tc)
    290 {
    291 
    292 	const char *tmp =
    293 	    "0.0000000000000000000000000000000000000000000000000000"
    294 	    "000000000000000000000000000000000000000000000000000000"
    295 	    "000000000000000000000000000000000000000000000000000000"
    296 	    "000000000000000000000000000000000000000000000000000000"
    297 	    "000000000000000000000000000000000000000000000000000000"
    298 	    "000000000000000000000000000000000000000000000000000000"
    299 	    "000000000000000000000000000000000000000000000000000000"
    300 	    "000000000000000002";
    301 
    302 	errno = 0;
    303 	double d = strtod(tmp, NULL);
    304 
    305 	if (d != 0 || errno != ERANGE)
    306 		atf_tc_fail("strtod(3) did not detect underflow");
    307 }
    308 
    309 ATF_TP_ADD_TCS(tp)
    310 {
    311 
    312 	ATF_TP_ADD_TC(tp, strtod_basic);
    313 	ATF_TP_ADD_TC(tp, strtod_hex);
    314 	ATF_TP_ADD_TC(tp, strtod_inf);
    315 	ATF_TP_ADD_TC(tp, strtof_inf);
    316 	ATF_TP_ADD_TC(tp, strtold_inf);
    317 	ATF_TP_ADD_TC(tp, strtod_nan);
    318 	ATF_TP_ADD_TC(tp, strtof_nan);
    319 	ATF_TP_ADD_TC(tp, strtold_nan);
    320 	ATF_TP_ADD_TC(tp, strtod_round);
    321 	ATF_TP_ADD_TC(tp, strtod_underflow);
    322 
    323 	return atf_no_error();
    324 }
    325