From 6805c2db39bad207e4434f9d8109a31efbc61229 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Wed, 9 Aug 2017 14:55:27 -0700 Subject: [PATCH 1/2] Expand wcsto* tests. Test: bionic unit tests Bug: None Change-Id: Ib6bdd09ea2b30274f5312d2edd63ba9e727e9b9c --- tests/wchar_test.cpp | 238 ++++++++++++++++++++++++++++++++----------- 1 file changed, 180 insertions(+), 58 deletions(-) diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp index a795d2cc7..a7e49e8c6 100644 --- a/tests/wchar_test.cpp +++ b/tests/wchar_test.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -406,20 +407,98 @@ TEST(wchar, mbsrtowcs) { ASSERT_EQ('\x20', *invalid); } -TEST(wchar, wcstol) { - ASSERT_EQ(123L, wcstol(L"123", NULL, 0)); +template +using WcsToIntFn = T (*)(const wchar_t*, wchar_t**, int); + +template +void TestSingleWcsToInt(WcsToIntFn fn, const wchar_t* str, int base, + T expected_value, ptrdiff_t expected_len) { + wchar_t* p; + ASSERT_EQ(expected_value, fn(str, &p, base)); + ASSERT_EQ(expected_len, p - str) << str; } -TEST(wchar, wcstoll) { - ASSERT_EQ(123LL, wcstol(L"123", NULL, 0)); +template +void TestWcsToInt(WcsToIntFn fn) { + TestSingleWcsToInt(fn, L"123", 10, static_cast(123), 3); + TestSingleWcsToInt(fn, L"123", 0, static_cast(123), 3); + TestSingleWcsToInt(fn, L"123#", 10, static_cast(123), 3); + TestSingleWcsToInt(fn, L"01000", 8, static_cast(512), 5); + TestSingleWcsToInt(fn, L"01000", 0, static_cast(512), 5); + TestSingleWcsToInt(fn, L" 123 45", 0, static_cast(123), 6); + TestSingleWcsToInt(fn, L" -123", 0, static_cast(-123), 6); + TestSingleWcsToInt(fn, L"0x10000", 0, static_cast(65536), 7); +} + +template +void TestWcsToIntLimits(WcsToIntFn fn, const wchar_t* min_str, + const wchar_t* max_str) { + if (std::is_signed::value) { + ASSERT_EQ(std::numeric_limits::min(), fn(min_str, nullptr, 0)) << min_str; + } else { + // If the subject sequence begins with a , the value resulting + // from the conversion shall be negated. + // http://pubs.opengroup.org/onlinepubs/9699919799/functions/strtoul.html + ASSERT_EQ(std::numeric_limits::max(), fn(min_str, nullptr, 0)) << min_str; + } + ASSERT_EQ(std::numeric_limits::max(), fn(max_str, nullptr, 0)) << max_str; +} + +TEST(wchar, wcstol) { + TestWcsToInt(wcstol); +} + +TEST(wchar, wcstol_limits) { + if (sizeof(long) == 8) { + TestWcsToIntLimits(wcstol, L"-9223372036854775809", L"9223372036854775808"); + } else { + TestWcsToIntLimits(wcstol, L"-2147483649", L"2147483648"); + } } TEST(wchar, wcstoul) { - ASSERT_EQ(123UL, wcstoul(L"123", NULL, 0)); + TestWcsToInt(wcstoul); +} + +TEST(wchar, wcstoul_limits) { + if (sizeof(long) == 8) { + TestWcsToIntLimits(wcstoul, L"-1", L"18446744073709551616"); + } else { + TestWcsToIntLimits(wcstoul, L"-1", L"4294967296"); + } +} + +TEST(wchar, wcstoll) { + TestWcsToInt(wcstoll); +} + +TEST(wchar, wcstoll_limits) { + TestWcsToIntLimits(wcstoll, L"-9223372036854775809", L"9223372036854775808"); } TEST(wchar, wcstoull) { - ASSERT_EQ(123ULL, wcstoul(L"123", NULL, 0)); + TestWcsToInt(wcstoull); +} + +TEST(wchar, wcstoull_limits) { + TestWcsToIntLimits(wcstoull, L"-1", L"18446744073709551616"); +} + +TEST(wchar, wcstoimax) { + TestWcsToInt(wcstoimax); +} + +TEST(wchar, wcstoimax_limits) { + TestWcsToIntLimits(wcstoimax, L"-9223372036854775809", + L"9223372036854775808"); +} + +TEST(wchar, wcstoumax) { + TestWcsToInt(wcstoumax); +} + +TEST(wchar, wcstoumax_limits) { + TestWcsToIntLimits(wcstoumax, L"-1", L"18446744073709551616"); } TEST(wchar, mbsnrtowcs) { @@ -691,68 +770,111 @@ TEST(wchar, wmempcpy) { } template -static void CheckWcsToFloat(T fn(const wchar_t* s, wchar_t** end)) { - FpUlpEq<0, T> pred; +using WcsToFloatFn = T (*)(const wchar_t*, wchar_t**); - EXPECT_PRED_FORMAT2(pred, 9.0, fn(L"9.0", nullptr)); - EXPECT_PRED_FORMAT2(pred, 9.0, fn(L"0.9e1", nullptr)); - EXPECT_PRED_FORMAT2(pred, 9.0, fn(L"0x1.2p3", nullptr)); - - const wchar_t* s = L" \t\v\f\r\n9.0"; +template +void TestSingleWcsToFloat(WcsToFloatFn fn, const wchar_t* str, + T expected_value, ptrdiff_t expected_len) { wchar_t* p; - EXPECT_PRED_FORMAT2(pred, 9.0, fn(s, &p)); - EXPECT_EQ(s + wcslen(s), p); - - EXPECT_TRUE(isnan(fn(L"+nan", nullptr))); - EXPECT_TRUE(isnan(fn(L"nan", nullptr))); - EXPECT_TRUE(isnan(fn(L"-nan", nullptr))); - - EXPECT_TRUE(isnan(fn(L"+nan(0xff)", nullptr))); - EXPECT_TRUE(isnan(fn(L"nan(0xff)", nullptr))); - EXPECT_TRUE(isnan(fn(L"-nan(0xff)", nullptr))); - - EXPECT_TRUE(isnan(fn(L"+nanny", &p))); - EXPECT_STREQ(L"ny", p); - EXPECT_TRUE(isnan(fn(L"nanny", &p))); - EXPECT_STREQ(L"ny", p); - EXPECT_TRUE(isnan(fn(L"-nanny", &p))); - EXPECT_STREQ(L"ny", p); - - EXPECT_EQ(0, fn(L"muppet", &p)); - EXPECT_STREQ(L"muppet", p); - EXPECT_EQ(0, fn(L" muppet", &p)); - EXPECT_STREQ(L" muppet", p); - - EXPECT_EQ(std::numeric_limits::infinity(), fn(L"+inf", nullptr)); - EXPECT_EQ(std::numeric_limits::infinity(), fn(L"inf", nullptr)); - EXPECT_EQ(-std::numeric_limits::infinity(), fn(L"-inf", nullptr)); - - EXPECT_EQ(std::numeric_limits::infinity(), fn(L"+infinity", nullptr)); - EXPECT_EQ(std::numeric_limits::infinity(), fn(L"infinity", nullptr)); - EXPECT_EQ(-std::numeric_limits::infinity(), fn(L"-infinity", nullptr)); - - EXPECT_EQ(std::numeric_limits::infinity(), fn(L"+infinitude", &p)); - EXPECT_STREQ(L"initude", p); - EXPECT_EQ(std::numeric_limits::infinity(), fn(L"infinitude", &p)); - EXPECT_STREQ(L"initude", p); - EXPECT_EQ(-std::numeric_limits::infinity(), fn(L"-infinitude", &p)); - EXPECT_STREQ(L"initude", p); - - // Check case-insensitivity. - EXPECT_EQ(std::numeric_limits::infinity(), fn(L"InFiNiTy", nullptr)); - EXPECT_TRUE(isnan(fn(L"NaN", nullptr))); + ASSERT_EQ(expected_value, fn(str, &p)); + ASSERT_EQ(expected_len, p - str); } -TEST(wchar, wcstod) { - CheckWcsToFloat(wcstod); +template +void TestWcsToFloat(WcsToFloatFn fn) { + TestSingleWcsToFloat(fn, L"123", static_cast(123.0), 3); + TestSingleWcsToFloat(fn, L"123#", static_cast(123.0), 3); + TestSingleWcsToFloat(fn, L" 123 45", static_cast(123.0), 6); + TestSingleWcsToFloat(fn, L"9.0", static_cast(9.0), 3); + TestSingleWcsToFloat(fn, L"-9.0", static_cast(-9.0), 4); + TestSingleWcsToFloat(fn, L" \t\v\f\r\n9.0", static_cast(9.0), 9); +} + +template +void TestWcsToFloatHexFloats(WcsToFloatFn fn) { + TestSingleWcsToFloat(fn, L"0.9e1", static_cast(9.0), 5); + TestSingleWcsToFloat(fn, L"0x1.2p3", static_cast(9.0), 7); + TestSingleWcsToFloat(fn, L"+1e+100", static_cast(1e100), 7); + TestSingleWcsToFloat(fn, L"0x10000.80", static_cast(65536.50), 10); +} + +template +void TestWcsToFloatInfNan(WcsToFloatFn fn) { + ASSERT_TRUE(isnan(fn(L"+nan", nullptr))); + ASSERT_TRUE(isnan(fn(L"nan", nullptr))); + ASSERT_TRUE(isnan(fn(L"-nan", nullptr))); + + ASSERT_TRUE(isnan(fn(L"+nan(0xff)", nullptr))); + ASSERT_TRUE(isnan(fn(L"nan(0xff)", nullptr))); + ASSERT_TRUE(isnan(fn(L"-nan(0xff)", nullptr))); + + wchar_t* p; + ASSERT_TRUE(isnan(fn(L"+nanny", &p))); + ASSERT_STREQ(L"ny", p); + ASSERT_TRUE(isnan(fn(L"nanny", &p))); + ASSERT_STREQ(L"ny", p); + ASSERT_TRUE(isnan(fn(L"-nanny", &p))); + ASSERT_STREQ(L"ny", p); + + ASSERT_EQ(0, fn(L"muppet", &p)); + ASSERT_STREQ(L"muppet", p); + ASSERT_EQ(0, fn(L" muppet", &p)); + ASSERT_STREQ(L" muppet", p); + + ASSERT_EQ(std::numeric_limits::infinity(), fn(L"+inf", nullptr)); + ASSERT_EQ(std::numeric_limits::infinity(), fn(L"inf", nullptr)); + ASSERT_EQ(-std::numeric_limits::infinity(), fn(L"-inf", nullptr)); + + ASSERT_EQ(std::numeric_limits::infinity(), fn(L"+infinity", nullptr)); + ASSERT_EQ(std::numeric_limits::infinity(), fn(L"infinity", nullptr)); + ASSERT_EQ(-std::numeric_limits::infinity(), fn(L"-infinity", nullptr)); + + ASSERT_EQ(std::numeric_limits::infinity(), fn(L"+infinitude", &p)); + ASSERT_STREQ(L"initude", p); + ASSERT_EQ(std::numeric_limits::infinity(), fn(L"infinitude", &p)); + ASSERT_STREQ(L"initude", p); + ASSERT_EQ(-std::numeric_limits::infinity(), fn(L"-infinitude", &p)); + ASSERT_STREQ(L"initude", p); + + // Check case-insensitivity. + ASSERT_EQ(std::numeric_limits::infinity(), fn(L"InFiNiTy", nullptr)); + ASSERT_TRUE(isnan(fn(L"NaN", nullptr))); } TEST(wchar, wcstof) { - CheckWcsToFloat(wcstof); + TestWcsToFloat(wcstof); +} + +TEST(wchar, wcstof_hex_floats) { + TestWcsToFloatHexFloats(wcstof); +} + +TEST(wchar, wcstof_hex_inf_nan) { + TestWcsToFloatInfNan(wcstof); +} + +TEST(wchar, wcstod) { + TestWcsToFloat(wcstod); +} + +TEST(wchar, wcstod_hex_floats) { + TestWcsToFloatHexFloats(wcstod); +} + +TEST(wchar, wcstod_hex_inf_nan) { + TestWcsToFloatInfNan(wcstod); } TEST(wchar, wcstold) { - CheckWcsToFloat(wcstold); + TestWcsToFloat(wcstold); +} + +TEST(wchar, wcstold_hex_floats) { + TestWcsToFloatHexFloats(wcstold); +} + +TEST(wchar, wcstold_hex_inf_nan) { + TestWcsToFloatInfNan(wcstold); } static void AssertWcwidthRange(wchar_t begin, wchar_t end, int expected) { From 9601f162f406a7b8f103195a75afc98f2fe4c2fe Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Wed, 9 Aug 2017 14:59:06 -0700 Subject: [PATCH 2/2] Expand swprintf tests. Test: bionic unit tests Bug: None Change-Id: I36924c4bdd2fa2c25e50ef7fef5500a365721a05 --- tests/stdio_test.cpp | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp index 1bb97a361..7b7737d6d 100644 --- a/tests/stdio_test.cpp +++ b/tests/stdio_test.cpp @@ -556,6 +556,45 @@ TEST(STDIO_TEST, swprintf_swscanf_inf_nan) { L"[-NAN]", L"[NAN]", L"[+NAN]"); } +TEST(STDIO_TEST, swprintf) { + constexpr size_t nchars = 32; + wchar_t buf[nchars]; + + ASSERT_EQ(2, swprintf(buf, nchars, L"ab")) << strerror(errno); + ASSERT_EQ(std::wstring(L"ab"), buf); + ASSERT_EQ(5, swprintf(buf, nchars, L"%s", "abcde")); + ASSERT_EQ(std::wstring(L"abcde"), buf); + + // Unlike swprintf(), swprintf() returns -1 in case of truncation + // and doesn't necessarily zero-terminate the output! + ASSERT_EQ(-1, swprintf(buf, 4, L"%s", "abcde")); + + const char kString[] = "Hello, World"; + ASSERT_EQ(12, swprintf(buf, nchars, L"%s", kString)); + ASSERT_EQ(std::wstring(L"Hello, World"), buf); + ASSERT_EQ(12, swprintf(buf, 13, L"%s", kString)); + ASSERT_EQ(std::wstring(L"Hello, World"), buf); +} + +TEST(STDIO_TEST, swprintf_a) { + constexpr size_t nchars = 32; + wchar_t buf[nchars]; + + ASSERT_EQ(20, swprintf(buf, nchars, L"%a", 3.1415926535)); + ASSERT_EQ(std::wstring(L"0x1.921fb54411744p+1"), buf); +} + +TEST(STDIO_TEST, swprintf_ls) { + constexpr size_t nchars = 32; + wchar_t buf[nchars]; + + static const wchar_t kWideString[] = L"Hello\uff41 World"; + ASSERT_EQ(12, swprintf(buf, nchars, L"%ls", kWideString)); + ASSERT_EQ(std::wstring(kWideString), buf); + ASSERT_EQ(12, swprintf(buf, 13, L"%ls", kWideString)); + ASSERT_EQ(std::wstring(kWideString), buf); +} + TEST(STDIO_TEST, snprintf_d_INT_MAX) { char buf[BUFSIZ]; snprintf(buf, sizeof(buf), "%d", INT_MAX);