From a4f4281ecde2cd4c353840db13df1913a8909e3d Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sun, 12 Jan 2025 18:58:26 +0100 Subject: [PATCH 1/2] Add smoke test for std::regex compatibility --- test/Jamfile.v2 | 1 + test/test_std_regex.cpp | 60 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 test/test_std_regex.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index f673b9d6..3f874432 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -43,6 +43,7 @@ run test_ios_info.cpp ; run test_ios_prop.cpp ; run test_codecvt.cpp ; run test_codepage_converter.cpp ; +run test_std_regex.cpp ; run test_stream_io.cpp ; run test_message.cpp : $(BOOST_ROOT)/libs/locale/test ; run test_generator.cpp ; diff --git a/test/test_std_regex.cpp b/test/test_std_regex.cpp new file mode 100644 index 00000000..8096d9f1 --- /dev/null +++ b/test/test_std_regex.cpp @@ -0,0 +1,60 @@ +// +// Copyright (c) 2025 Alexander Grund +// +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include "boostLocale/test/tools.hpp" +#include +#include + +/// Smoke test that std::regex works with generated locales +template +void test_by_char(const std::locale& l) +{ + using string_type = std::basic_string; + std::basic_regex pattern; + pattern.imbue(l); + pattern = ascii_to("[[:alnum:]]+"); + const string_type text = ascii_to("ab12cd"); + std::match_results pieces; + if TEST(std::regex_match(text, pieces, pattern)) { + TEST_EQ(pieces.size(), 1u); + TEST_EQ(pieces[0].str(), text); + } +} + +void test_main(int /*argc*/, char** /*argv*/) +{ + for(const std::string& backend_name : boost::locale::localization_backend_manager::global().get_all_backends()) { + TEST_CONTEXT("Backend: " << backend_name); + boost::locale::localization_backend_manager tmp_backend = boost::locale::localization_backend_manager::global(); + tmp_backend.select(backend_name); + boost::locale::localization_backend_manager::global(tmp_backend); + + boost::locale::generator gen; + const std::locale loc = gen("en_US.UTF-8"); + gen.categories(gen.categories() ^ boost::locale::category_t::collation); + const std::locale loc_no_collation = gen("en_US.UTF-8"); + gen.categories(boost::locale::category_t::collation); + const std::locale loc_collation = gen("en_US.UTF-8"); + { + TEST_CONTEXT("char"); + test_by_char(loc); + { + TEST_CONTEXT("without collation"); + test_by_char(loc_no_collation); + } + { + TEST_CONTEXT("just collation"); + test_by_char(loc_collation); + } + } + { + TEST_CONTEXT("wchar_t"); + test_by_char(loc); + } + } +} From 75aeb9e77e160f71e4c8de631d9db8f0165a1f60 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 13 Jan 2025 17:00:31 +0100 Subject: [PATCH 2/2] Use example from issue --- test/test_std_regex.cpp | 55 ++++++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/test/test_std_regex.cpp b/test/test_std_regex.cpp index 8096d9f1..adacced5 100644 --- a/test/test_std_regex.cpp +++ b/test/test_std_regex.cpp @@ -12,17 +12,50 @@ /// Smoke test that std::regex works with generated locales template -void test_by_char(const std::locale& l) +void test_by_char_impl(const std::locale& l) { using string_type = std::basic_string; - std::basic_regex pattern; - pattern.imbue(l); - pattern = ascii_to("[[:alnum:]]+"); - const string_type text = ascii_to("ab12cd"); + + // Needs at least a '\s' and '=' to reproduce issue #249 + const string_type s_pattern = ascii_to(R"([[:alnum:]]+\s*= \d+)"); + const string_type text = ascii_to("a2b2 = 42"); std::match_results pieces; + + // Sanity check using default locale + std::basic_regex pattern{s_pattern}; if TEST(std::regex_match(text, pieces, pattern)) { TEST_EQ(pieces.size(), 1u); TEST_EQ(pieces[0].str(), text); + + pattern.imbue(l); + pattern = s_pattern; + if TEST(std::regex_match(text, pieces, pattern)) { + TEST_EQ(pieces.size(), 1u); + TEST_EQ(pieces[0].str(), text); + } + + // Set via global locale + const std::locale oldLoc = std::locale::global(l); + std::basic_regex globalPattern{s_pattern}; + if TEST(std::regex_match(text, pieces, globalPattern)) { + TEST_EQ(pieces.size(), 1u); + TEST_EQ(pieces[0].str(), text); + } + std::locale::global(oldLoc); + } +} + +template +void test_by_char(const std::locale& loc, const std::locale& loc_collation, const std::locale& loc_no_collation) +{ + test_by_char_impl(loc); + { + TEST_CONTEXT("without collation"); + test_by_char_impl(loc_no_collation); + } + { + TEST_CONTEXT("just collation"); + test_by_char_impl(loc_collation); } } @@ -42,19 +75,11 @@ void test_main(int /*argc*/, char** /*argv*/) const std::locale loc_collation = gen("en_US.UTF-8"); { TEST_CONTEXT("char"); - test_by_char(loc); - { - TEST_CONTEXT("without collation"); - test_by_char(loc_no_collation); - } - { - TEST_CONTEXT("just collation"); - test_by_char(loc_collation); - } + test_by_char(loc, loc_collation, loc_no_collation); } { TEST_CONTEXT("wchar_t"); - test_by_char(loc); + test_by_char(loc, loc_collation, loc_no_collation); } } }