// Unit test for boost::lexical_cast. // // See http://www.boost.org for most recent version, including documentation. // // Copyright Terje Sletteb and Kevlin Henney, 2005. // Copyright Alexander Nasonov, 2006. // Copyright Antony Polukhin, 2011-2012. // // Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). // // Note: The unit test no longer compile on MSVC 6, but lexical_cast itself works for it. // // We need this #define before any #includes: otherwise msvc will emit warnings // deep within std::string, resulting from our (perfectly legal) use of basic_string // with a custom traits class: // #define _SCL_SECURE_NO_WARNINGS #include #if defined(__INTEL_COMPILER) #pragma warning(disable: 193 383 488 981 1418 1419) #elif defined(BOOST_MSVC) #pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800) #endif #include #include #include #include #include #include #include #include #if (defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64)) \ && !(defined(BOOST_MSVC) && BOOST_MSVC < 1300) #define LCAST_TEST_LONGLONG #endif #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) #define BOOST_LCAST_NO_WCHAR_T #endif template struct my_traits : std::char_traits { }; template struct my_allocator : std::allocator { }; using namespace boost; void test_conversion_to_char(); void test_conversion_to_int(); void test_conversion_to_double(); void test_conversion_to_bool(); void test_conversion_with_nonconst_char(); void test_conversion_to_string(); void test_conversion_from_to_wchar_t_alias(); void test_conversion_to_pointer(); void test_conversion_from_wchar_t(); void test_conversion_to_wchar_t(); void test_conversion_from_wstring(); void test_conversion_to_wstring(); void test_bad_lexical_cast(); void test_no_whitespace_stripping(); #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION void test_traits(); void test_wtraits(); void test_allocator(); void test_wallocator(); #endif void test_char_types_conversions(); void operators_overload_test(); #if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) void test_char16_conversions(); #endif #if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) void test_char32_conversions(); #endif unit_test::test_suite *init_unit_test_suite(int, char *[]) { unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast unit test"); suite->add(BOOST_TEST_CASE(test_conversion_to_char)); suite->add(BOOST_TEST_CASE(test_conversion_to_int)); suite->add(BOOST_TEST_CASE(test_conversion_to_double)); suite->add(BOOST_TEST_CASE(test_conversion_to_bool)); suite->add(BOOST_TEST_CASE(test_conversion_from_to_wchar_t_alias)); suite->add(BOOST_TEST_CASE(test_conversion_to_pointer)); suite->add(BOOST_TEST_CASE(test_conversion_to_string)); suite->add(BOOST_TEST_CASE(test_conversion_with_nonconst_char)); #ifndef BOOST_LCAST_NO_WCHAR_T suite->add(BOOST_TEST_CASE(test_conversion_from_wchar_t)); suite->add(BOOST_TEST_CASE(test_conversion_to_wchar_t)); suite->add(BOOST_TEST_CASE(test_conversion_from_wstring)); suite->add(BOOST_TEST_CASE(test_conversion_to_wstring)); #endif suite->add(BOOST_TEST_CASE(test_bad_lexical_cast)); suite->add(BOOST_TEST_CASE(test_no_whitespace_stripping)); #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION suite->add(BOOST_TEST_CASE(&test_traits)); suite->add(BOOST_TEST_CASE(&test_wtraits)); suite->add(BOOST_TEST_CASE(&test_allocator)); suite->add(BOOST_TEST_CASE(&test_wallocator)); #endif suite->add(BOOST_TEST_CASE(&test_char_types_conversions)); suite->add(BOOST_TEST_CASE(&operators_overload_test)); #if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) suite->add(BOOST_TEST_CASE(&test_char16_conversions)); #endif #if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) suite->add(BOOST_TEST_CASE(&test_char32_conversions)); #endif return suite; } void test_conversion_to_char() { BOOST_CHECK_EQUAL('A', lexical_cast('A')); BOOST_CHECK_EQUAL(' ', lexical_cast(' ')); BOOST_CHECK_EQUAL('1', lexical_cast(1)); BOOST_CHECK_EQUAL('0', lexical_cast(0)); BOOST_CHECK_THROW(lexical_cast(123), bad_lexical_cast); BOOST_CHECK_EQUAL('1', lexical_cast(1.0)); BOOST_CHECK_EQUAL('1', lexical_cast(true)); BOOST_CHECK_EQUAL('0', lexical_cast(false)); BOOST_CHECK_EQUAL('A', lexical_cast("A")); BOOST_CHECK_EQUAL(' ', lexical_cast(" ")); BOOST_CHECK_THROW(lexical_cast(""), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast("Test"), bad_lexical_cast); BOOST_CHECK_EQUAL('A', lexical_cast(std::string("A"))); BOOST_CHECK_EQUAL(' ', lexical_cast(std::string(" "))); BOOST_CHECK_THROW( lexical_cast(std::string("")), bad_lexical_cast); BOOST_CHECK_THROW( lexical_cast(std::string("Test")), bad_lexical_cast); } void test_conversion_to_int() { BOOST_CHECK_EQUAL(1, lexical_cast('1')); BOOST_CHECK_EQUAL(0, lexical_cast('0')); BOOST_CHECK_THROW(lexical_cast('A'), bad_lexical_cast); BOOST_CHECK_EQUAL(1, lexical_cast(1)); BOOST_CHECK_EQUAL(1, lexical_cast(1.0)); BOOST_CHECK_EQUAL( (std::numeric_limits::max)(), lexical_cast((std::numeric_limits::max)())); BOOST_CHECK_EQUAL( (std::numeric_limits::min)(), lexical_cast((std::numeric_limits::min)())); BOOST_CHECK_THROW(lexical_cast(1.23), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(1e20), bad_lexical_cast); BOOST_CHECK_EQUAL(1, lexical_cast(true)); BOOST_CHECK_EQUAL(0, lexical_cast(false)); BOOST_CHECK_EQUAL(123, lexical_cast("123")); BOOST_CHECK_THROW( lexical_cast(" 123"), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(""), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast("Test"), bad_lexical_cast); BOOST_CHECK_EQUAL(123, lexical_cast("123")); BOOST_CHECK_EQUAL(123, lexical_cast(std::string("123"))); BOOST_CHECK_THROW( lexical_cast(std::string(" 123")), bad_lexical_cast); BOOST_CHECK_THROW( lexical_cast(std::string("")), bad_lexical_cast); BOOST_CHECK_THROW( lexical_cast(std::string("Test")), bad_lexical_cast); } void test_conversion_with_nonconst_char() { std::vector buffer; buffer.push_back('1'); buffer.push_back('\0'); BOOST_CHECK_EQUAL(boost::lexical_cast(&buffer[0]), 1); std::vector buffer2; buffer2.push_back('1'); buffer2.push_back('\0'); BOOST_CHECK_EQUAL(boost::lexical_cast(&buffer2[0]), 1); std::vector buffer3; buffer3.push_back('1'); buffer3.push_back('\0'); BOOST_CHECK_EQUAL(boost::lexical_cast(&buffer3[0]), 1); #ifndef BOOST_LCAST_NO_WCHAR_T std::vector buffer4; buffer4.push_back(L'1'); buffer4.push_back(L'\0'); BOOST_CHECK_EQUAL(boost::lexical_cast(&buffer4[0]), 1); #endif } void test_conversion_to_double() { BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast('1'), (std::numeric_limits::epsilon())); BOOST_CHECK_THROW(lexical_cast('A'), bad_lexical_cast); BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast(1), (std::numeric_limits::epsilon())); BOOST_CHECK_CLOSE_FRACTION(1.23, lexical_cast(1.23), (std::numeric_limits::epsilon())); BOOST_CHECK_CLOSE_FRACTION(1.234567890, lexical_cast(1.234567890), std::numeric_limits::epsilon()); BOOST_CHECK_CLOSE_FRACTION(1.234567890, lexical_cast("1.234567890"), std::numeric_limits::epsilon()); BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast(true), (std::numeric_limits::epsilon())); BOOST_CHECK_CLOSE_FRACTION(0.0, lexical_cast(false), (std::numeric_limits::epsilon())); BOOST_CHECK_CLOSE_FRACTION(1.23, lexical_cast("1.23"), (std::numeric_limits::epsilon())); BOOST_CHECK_THROW(lexical_cast(""), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast("Test"), bad_lexical_cast); BOOST_CHECK_CLOSE_FRACTION(1.23, lexical_cast(std::string("1.23")), (std::numeric_limits::epsilon())); BOOST_CHECK_THROW( lexical_cast(std::string("")), bad_lexical_cast); BOOST_CHECK_THROW( lexical_cast(std::string("Test")), bad_lexical_cast); } void test_conversion_to_bool() { BOOST_CHECK_EQUAL(true, lexical_cast('1')); BOOST_CHECK_EQUAL(false, lexical_cast('0')); BOOST_CHECK_THROW(lexical_cast('A'), bad_lexical_cast); BOOST_CHECK_EQUAL(true, lexical_cast(1)); BOOST_CHECK_EQUAL(false, lexical_cast(0)); BOOST_CHECK_THROW(lexical_cast(123), bad_lexical_cast); BOOST_CHECK_EQUAL(true, lexical_cast(1.0)); BOOST_CHECK_EQUAL(false, lexical_cast(0.0)); BOOST_CHECK_EQUAL(true, lexical_cast(true)); BOOST_CHECK_EQUAL(false, lexical_cast(false)); BOOST_CHECK_EQUAL(true, lexical_cast("1")); BOOST_CHECK_EQUAL(false, lexical_cast("0")); BOOST_CHECK_THROW(lexical_cast(""), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast("Test"), bad_lexical_cast); BOOST_CHECK_EQUAL(true, lexical_cast("1")); BOOST_CHECK_EQUAL(false, lexical_cast("0")); BOOST_CHECK_EQUAL(true, lexical_cast(std::string("1"))); BOOST_CHECK_EQUAL(false, lexical_cast(std::string("0"))); BOOST_CHECK_THROW(lexical_cast(1.0001L), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(2), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(2u), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(-1), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(-2), bad_lexical_cast); BOOST_CHECK_THROW( lexical_cast(std::string("")), bad_lexical_cast); BOOST_CHECK_THROW( lexical_cast(std::string("Test")), bad_lexical_cast); BOOST_CHECK(lexical_cast("+1") == true ); BOOST_CHECK(lexical_cast("+0") == false ); BOOST_CHECK(lexical_cast("-0") == false ); BOOST_CHECK_THROW(lexical_cast("--0"), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast("-+-0"), bad_lexical_cast); } void test_conversion_to_string() { char buf[] = "hello"; char* str = buf; BOOST_CHECK_EQUAL(str, lexical_cast(str)); BOOST_CHECK_EQUAL("A", lexical_cast('A')); BOOST_CHECK_EQUAL(" ", lexical_cast(' ')); BOOST_CHECK_EQUAL("123", lexical_cast(123)); BOOST_CHECK_EQUAL("1.23", lexical_cast(1.23)); BOOST_CHECK_EQUAL("1.111111111", lexical_cast(1.111111111)); BOOST_CHECK_EQUAL("1", lexical_cast(true)); BOOST_CHECK_EQUAL("0", lexical_cast(false)); BOOST_CHECK_EQUAL("Test", lexical_cast("Test")); BOOST_CHECK_EQUAL(" ", lexical_cast(" ")); BOOST_CHECK_EQUAL("", lexical_cast("")); BOOST_CHECK_EQUAL("Test", lexical_cast(std::string("Test"))); BOOST_CHECK_EQUAL(" ", lexical_cast(std::string(" "))); BOOST_CHECK_EQUAL("", lexical_cast(std::string(""))); } void test_conversion_from_to_wchar_t_alias() { BOOST_CHECK_EQUAL(123u, lexical_cast("123")); BOOST_CHECK_EQUAL(123u, lexical_cast("123")); BOOST_CHECK_EQUAL(123u, lexical_cast("123")); BOOST_CHECK_EQUAL(std::string("123"), lexical_cast(static_cast(123))); BOOST_CHECK_EQUAL(std::string("123"), lexical_cast(123u)); BOOST_CHECK_EQUAL(std::string("123"), lexical_cast(123ul)); } void test_conversion_to_pointer() { BOOST_CHECK_THROW(lexical_cast("Test"), bad_lexical_cast); #ifndef BOOST_LCAST_NO_WCHAR_T BOOST_CHECK_THROW(lexical_cast("Test"), bad_lexical_cast); #endif } void test_conversion_from_wchar_t() { #ifndef BOOST_LCAST_NO_WCHAR_T #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) BOOST_CHECK_EQUAL(1, lexical_cast(L'1')); BOOST_CHECK_THROW(lexical_cast(L'A'), bad_lexical_cast); #endif BOOST_CHECK_EQUAL(123, lexical_cast(L"123")); BOOST_CHECK_THROW(lexical_cast(L""), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(L"Test"), bad_lexical_cast); #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) BOOST_CHECK_EQUAL(1.0, lexical_cast(L'1')); BOOST_CHECK_THROW(lexical_cast(L'A'), bad_lexical_cast); #endif BOOST_CHECK_EQUAL(1.23, lexical_cast(L"1.23")); BOOST_CHECK_THROW(lexical_cast(L""), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(L"Test"), bad_lexical_cast); #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) BOOST_CHECK_EQUAL(true, lexical_cast(L'1')); BOOST_CHECK_EQUAL(false, lexical_cast(L'0')); BOOST_CHECK_THROW(lexical_cast(L'A'), bad_lexical_cast); #endif BOOST_CHECK_EQUAL(true, lexical_cast(L"1")); BOOST_CHECK_EQUAL(false, lexical_cast(L"0")); BOOST_CHECK_THROW(lexical_cast(L""), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(L"Test"), bad_lexical_cast); #endif } void test_conversion_to_wchar_t() { #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) BOOST_CHECK_EQUAL(L'1', lexical_cast(1)); BOOST_CHECK_EQUAL(L'0', lexical_cast(0)); BOOST_CHECK_EQUAL(L'1', lexical_cast('1')); BOOST_CHECK_EQUAL(L'0', lexical_cast('0')); BOOST_CHECK_THROW(lexical_cast(123), bad_lexical_cast); BOOST_CHECK_EQUAL(L'1', lexical_cast(1.0)); BOOST_CHECK_EQUAL(L'0', lexical_cast(0.0)); BOOST_CHECK_EQUAL(L'1', lexical_cast(true)); BOOST_CHECK_EQUAL(L'0', lexical_cast(false)); BOOST_CHECK_EQUAL(L'A', lexical_cast(L'A')); BOOST_CHECK_EQUAL(L' ', lexical_cast(L' ')); BOOST_CHECK_EQUAL(L'A', lexical_cast(L"A")); BOOST_CHECK_EQUAL(L' ', lexical_cast(L" ")); BOOST_CHECK_THROW(lexical_cast(L""), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(L"Test"), bad_lexical_cast); BOOST_CHECK_EQUAL(L'A', lexical_cast(std::wstring(L"A"))); BOOST_CHECK_EQUAL(L' ', lexical_cast(std::wstring(L" "))); BOOST_CHECK_THROW( lexical_cast(std::wstring(L"")), bad_lexical_cast); BOOST_CHECK_THROW( lexical_cast(std::wstring(L"Test")), bad_lexical_cast); #endif BOOST_CHECK(true); } void test_conversion_from_wstring() { #ifndef BOOST_LCAST_NO_WCHAR_T BOOST_CHECK_EQUAL(123, lexical_cast(std::wstring(L"123"))); BOOST_CHECK_THROW( lexical_cast(std::wstring(L"")), bad_lexical_cast); BOOST_CHECK_THROW( lexical_cast(std::wstring(L"Test")), bad_lexical_cast); BOOST_CHECK_EQUAL(true, lexical_cast(std::wstring(L"1"))); BOOST_CHECK_EQUAL(false, lexical_cast(std::wstring(L"0"))); BOOST_CHECK_THROW( lexical_cast(std::wstring(L"")), bad_lexical_cast); BOOST_CHECK_THROW( lexical_cast(std::wstring(L"Test")), bad_lexical_cast); #endif BOOST_CHECK(true); } void test_conversion_to_wstring() { #ifndef BOOST_LCAST_NO_WCHAR_T wchar_t buf[] = L"hello"; wchar_t* str = buf; BOOST_CHECK(str == lexical_cast(str)); BOOST_CHECK(L"123" == lexical_cast(123)); BOOST_CHECK(L"1.23" == lexical_cast(1.23)); BOOST_CHECK(L"1" == lexical_cast(true)); BOOST_CHECK(L"0" == lexical_cast(false)); #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) BOOST_CHECK(L"A" == lexical_cast(L'A')); BOOST_CHECK(L" " == lexical_cast(L' ')); BOOST_CHECK(L"A" == lexical_cast('A')); #endif BOOST_CHECK(L"Test" == lexical_cast(L"Test")); BOOST_CHECK(L" " == lexical_cast(L" ")); BOOST_CHECK(L"" == lexical_cast(L"")); BOOST_CHECK(L"Test" == lexical_cast(std::wstring(L"Test"))); BOOST_CHECK(L" " == lexical_cast(std::wstring(L" "))); BOOST_CHECK(L"" == lexical_cast(std::wstring(L""))); #endif BOOST_CHECK(true); } void test_bad_lexical_cast() { try { lexical_cast(std::string("Test")); BOOST_CHECK(false); // Exception expected } catch(const bad_lexical_cast &e) { BOOST_CHECK(e.source_type() == typeid(std::string)); BOOST_CHECK(e.target_type() == typeid(int)); } } void test_no_whitespace_stripping() { BOOST_CHECK_THROW(lexical_cast(" 123"), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast("123 "), bad_lexical_cast); } #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION void test_traits() { typedef std::basic_string > my_string; my_string const s("s"); BOOST_CHECK(boost::lexical_cast(s) == s[0]); BOOST_CHECK(boost::lexical_cast(s) == s); BOOST_CHECK(boost::lexical_cast(-1) == "-1"); } void test_wtraits() { typedef std::basic_string > my_string; my_string const s(L"s"); BOOST_CHECK(boost::lexical_cast(s) == s[0]); BOOST_CHECK(boost::lexical_cast(s) == s); //BOOST_CHECK(boost::lexical_cast(-1) == L"-1"); // Commented out because gcc 3.3 doesn't support this: // basic_ostream > o; o << -1; } void test_allocator() { typedef std::basic_string< char , std::char_traits , my_allocator > my_string; my_string s("s"); BOOST_CHECK(boost::lexical_cast(s) == s[0]); BOOST_CHECK(boost::lexical_cast(s) == "s"); BOOST_CHECK(boost::lexical_cast(s) == s); BOOST_CHECK(boost::lexical_cast(1) == "1"); BOOST_CHECK(boost::lexical_cast("s") == s); BOOST_CHECK(boost::lexical_cast(std::string("s")) == s); } void test_wallocator() { typedef std::basic_string< wchar_t , std::char_traits , my_allocator > my_string; my_string s(L"s"); BOOST_CHECK(boost::lexical_cast(s) == s[0]); BOOST_CHECK(boost::lexical_cast(s) == L"s"); BOOST_CHECK(boost::lexical_cast(s) == s); BOOST_CHECK(boost::lexical_cast(1) == L"1"); BOOST_CHECK(boost::lexical_cast(L"s") == s); BOOST_CHECK(boost::lexical_cast(std::wstring(L"s")) == s); } #endif void test_char_types_conversions() { const char c_arr[] = "Test array of chars"; const unsigned char uc_arr[] = "Test array of chars"; const signed char sc_arr[] = "Test array of chars"; BOOST_CHECK(boost::lexical_cast(c_arr) == std::string(c_arr)); BOOST_CHECK(boost::lexical_cast(uc_arr) == std::string(c_arr)); BOOST_CHECK(boost::lexical_cast(sc_arr) == std::string(c_arr)); BOOST_CHECK(boost::lexical_cast(c_arr[0]) == c_arr[0]); BOOST_CHECK(boost::lexical_cast(uc_arr[0]) == c_arr[0]); BOOST_CHECK(boost::lexical_cast(sc_arr[0]) == c_arr[0]); BOOST_CHECK(boost::lexical_cast(c_arr[0]) == uc_arr[0]); BOOST_CHECK(boost::lexical_cast(uc_arr[0]) == uc_arr[0]); BOOST_CHECK(boost::lexical_cast(sc_arr[0]) == uc_arr[0]); BOOST_CHECK(boost::lexical_cast(c_arr[0]) == sc_arr[0]); BOOST_CHECK(boost::lexical_cast(uc_arr[0]) == sc_arr[0]); BOOST_CHECK(boost::lexical_cast(sc_arr[0]) == sc_arr[0]); #ifndef BOOST_LCAST_NO_WCHAR_T const wchar_t wc_arr[]=L"Test array of chars"; BOOST_CHECK(boost::lexical_cast(wc_arr) == std::wstring(wc_arr)); BOOST_CHECK(boost::lexical_cast(wc_arr[0]) == wc_arr[0]); #endif } struct foo_operators_test { foo_operators_test() : f(2) {} int f; }; template OStream& operator<<(OStream& ostr, const foo_operators_test& foo) { ostr << foo.f; return ostr; } template IStream& operator>>(IStream& istr, foo_operators_test& foo) { istr >> foo.f; return istr; } void operators_overload_test() { foo_operators_test foo; BOOST_CHECK_EQUAL(boost::lexical_cast(foo), "2"); BOOST_CHECK_EQUAL((boost::lexical_cast("2")).f, 2); // Must compile (void)boost::lexical_cast(foo); } #if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) void test_char16_conversions() { BOOST_CHECK(u"100" == lexical_cast(u"100")); BOOST_CHECK(u"1" == lexical_cast(u'1')); } #endif #if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) void test_char32_conversions() { BOOST_CHECK(U"100" == lexical_cast(U"100")); BOOST_CHECK(U"1" == lexical_cast(U'1')); } #endif