From 272e02b6c8840a33d8ff4b7026fb937a3c4729f5 Mon Sep 17 00:00:00 2001 From: Tim Mayberry Date: Mon, 17 Apr 2017 13:16:12 +1000 Subject: Fix string-convert tests for Windows and hopefully macOS/OS X Tests requires a locale installed on the host that uses a comma as the decimal mark/point. --- libs/pbd/test/string_convert_test.cc | 153 +++++++++++++++++++++++++++-------- libs/pbd/test/string_convert_test.h | 2 + 2 files changed, 120 insertions(+), 35 deletions(-) (limited to 'libs/pbd') diff --git a/libs/pbd/test/string_convert_test.cc b/libs/pbd/test/string_convert_test.cc index f383aed8a2..2f06ad9c52 100644 --- a/libs/pbd/test/string_convert_test.cc +++ b/libs/pbd/test/string_convert_test.cc @@ -17,10 +17,53 @@ using namespace std; CPPUNIT_TEST_SUITE_REGISTRATION (StringConvertTest); -static std::vector get_test_locales () +namespace { + +class LocaleGuard { +public: + // RAII class that sets the global C locale and then resets it to its + // previous setting when going out of scope + LocaleGuard (const std::string& locale) + { + m_previous_locale = setlocale (LC_ALL, NULL); + + CPPUNIT_ASSERT (m_previous_locale != NULL); + + const char* new_locale = setlocale (LC_ALL, locale.c_str ()); + + if (new_locale == NULL) { + std::cerr << "Failed to set locale to : " << locale << std::endl; + } + + CPPUNIT_ASSERT (new_locale != NULL); + } + + ~LocaleGuard () + { + CPPUNIT_ASSERT (setlocale (LC_ALL, m_previous_locale) != NULL); + } + +private: + const char* m_previous_locale; +}; + +static +bool +check_decimal_mark_is_comma () +{ + char buf[32]; + double const dnum = 12345.67890; + snprintf (buf, sizeof(buf), "%.12g", dnum); + bool found = (strchr (buf, ',') != NULL); + return found; +} + +static std::vector get_locale_list () { std::vector locales; + locales.push_back(""); // User preferred locale + #ifdef PLATFORM_WINDOWS locales.push_back("French_France.1252"); // must be first locales.push_back("Dutch_Netherlands.1252"); @@ -29,8 +72,12 @@ static std::vector get_test_locales () locales.push_back("Chinese_China.936"); locales.push_back("Czech_Czech Republic.1250"); #else - locales.push_back("fr_FR"); // French France // must be first + locales.push_back("fr_FR"); // French France + locales.push_back("fr_FR.UTF-8"); + locales.push_back("de_DE"); // German Germany + locales.push_back("de_DE.UTF-8"); locales.push_back("nl_NL"); // Dutch - Netherlands + locales.push_back("nl_NL.UTF-8"); locales.push_back("it_IT"); // Italian locales.push_back("fa_IR"); // Farsi Iran locales.push_back("zh_CN"); // Chinese @@ -39,37 +86,78 @@ static std::vector get_test_locales () return locales; } +static std::vector get_supported_locales () +{ + std::vector locales = get_locale_list (); + std::vector supported_locales; -namespace { + const char * m_orig_locale = setlocale (LC_ALL, NULL); -class LocaleGuard { -public: - // RAII class that sets the global C locale and then resets it to its - // previous setting when going out of scope - LocaleGuard (const std::string& locale) - { - m_previous_locale = setlocale (LC_ALL, NULL); + CPPUNIT_ASSERT (m_orig_locale != NULL); - CPPUNIT_ASSERT (m_previous_locale != NULL); + std::cerr << std::endl << "Original locale: " << m_orig_locale << std::endl; - const char* new_locale = setlocale (LC_ALL, locale.c_str ()); + for (std::vector::const_iterator it = locales.begin(); it != locales.end(); ++it) { - CPPUNIT_ASSERT (new_locale != NULL); + const char* locale = it->c_str(); + const char* new_locale = setlocale (LC_ALL, locale); + + if (new_locale == NULL) { + std::cerr << "Unable to set locale : " << locale << ", may not be installed." << std::endl; + continue; + } + + if (*it != new_locale) { + // Setting the locale may be successful but locale has a different + // (or longer) name. + if (it->empty()) { + std::cerr << "User preferred locale is : " << new_locale << std::endl; + } else { + std::cerr << "locale : " << locale << ", has name : " << new_locale << std::endl; + } + } - CPPUNIT_ASSERT (locale == new_locale); + std::cerr << "Adding locale : " << new_locale << " to test locales" << std::endl; + + supported_locales.push_back (*it); } - ~LocaleGuard () - { - CPPUNIT_ASSERT (setlocale (LC_ALL, m_previous_locale) != NULL); + if (setlocale (LC_ALL, m_orig_locale) == NULL) { + std::cerr << "ERROR: Unable to restore original locale " << m_orig_locale + << ", further tests may be invalid." << std::endl; } -private: - const char* m_previous_locale; -}; + return supported_locales; +} + +static std::vector get_test_locales () +{ + static std::vector locales = get_supported_locales (); + return locales; +} + +static bool get_locale_with_comma_decimal_mark (std::string& locale_str) { + std::vector locales = get_test_locales (); + + for (std::vector::const_iterator it = locales.begin(); it != locales.end(); ++it) { + LocaleGuard guard (*it); + if (check_decimal_mark_is_comma ()) { + locale_str = *it; + return true; + } + } + return false; +} } // anon namespace +void +StringConvertTest::test_required_locales () +{ + std::string locale_str; + CPPUNIT_ASSERT(get_locale_with_comma_decimal_mark(locale_str)); +} + static const std::string MAX_INT16_STR ("32767"); static const std::string MIN_INT16_STR ("-32768"); @@ -558,7 +646,7 @@ check_double_convert () return (num == string_to(to_string (num))); } -static const int s_iter_count = 500000; +static const int s_iter_count = 1000000; void* check_int_convert_thread(void*) @@ -589,20 +677,11 @@ check_double_convert_thread(void*) static const double s_test_double = 31459.265359; -bool -check_fr_printf () -{ - char buf[32]; - snprintf (buf, sizeof(buf), "%.12g", s_test_double); - bool found = (strchr (buf, ',') != NULL); - return found; -} - void* -check_fr_printf_thread (void*) +check_decimal_mark_is_comma_thread (void*) { for (int n = 0; n < s_iter_count; n++) { - assert (check_fr_printf ()); + assert (check_decimal_mark_is_comma ()); } return NULL; @@ -617,12 +696,16 @@ check_fr_printf_thread (void*) void StringConvertTest::test_convert_thread_safety () { - LocaleGuard guard (get_test_locales().front()); + std::string locale_str; + + CPPUNIT_ASSERT(get_locale_with_comma_decimal_mark(locale_str)); + + LocaleGuard guard (locale_str); CPPUNIT_ASSERT (check_int_convert ()); CPPUNIT_ASSERT (check_float_convert ()); CPPUNIT_ASSERT (check_double_convert ()); - CPPUNIT_ASSERT (check_fr_printf ()); + CPPUNIT_ASSERT (check_decimal_mark_is_comma ()); pthread_t convert_int_thread; pthread_t convert_float_thread; @@ -639,7 +722,7 @@ StringConvertTest::test_convert_thread_safety () pthread_create ( &convert_double_thread, NULL, check_double_convert_thread, NULL) == 0); CPPUNIT_ASSERT ( - pthread_create (&fr_printf_thread, NULL, check_fr_printf_thread, NULL) == + pthread_create (&fr_printf_thread, NULL, check_decimal_mark_is_comma_thread, NULL) == 0); void* return_value; diff --git a/libs/pbd/test/string_convert_test.h b/libs/pbd/test/string_convert_test.h index 82ccb26af3..d9a7e1f4de 100644 --- a/libs/pbd/test/string_convert_test.h +++ b/libs/pbd/test/string_convert_test.h @@ -4,6 +4,7 @@ class StringConvertTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE (StringConvertTest); + CPPUNIT_TEST (test_required_locales); CPPUNIT_TEST (test_int16_conversion); CPPUNIT_TEST (test_uint16_conversion); CPPUNIT_TEST (test_int32_conversion); @@ -17,6 +18,7 @@ class StringConvertTest : public CppUnit::TestFixture CPPUNIT_TEST_SUITE_END (); public: + void test_required_locales (); void test_int16_conversion (); void test_uint16_conversion (); void test_int32_conversion (); -- cgit v1.2.3