Jens Geyer created THRIFT-6194:
----------------------------------

             Summary: ToStringTest leaves the global locale set for the rest of 
the UnitTests binary
                 Key: THRIFT-6194
                 URL: https://issues.apache.org/jira/browse/THRIFT-6194
             Project: Thrift
          Issue Type: Bug
          Components: C++ - Library
            Reporter: Jens Geyer


h2. What happens

{{lib/cpp/test/ToStringTest.cpp}} has two cases that call 
{{std::locale::global()}} and never
restore it:

{code:cpp}
BOOST_AUTO_TEST_CASE(locale_en_US_int_to_string) {
  std::locale::global(std::locale("en_US.UTF-8"));
  BOOST_CHECK_EQUAL(to_string(1000000), "1000000");
}

BOOST_AUTO_TEST_CASE(locale_de_DE_floating_point_to_string) {
  std::locale::global(std::locale("de_DE.UTF-8"));
  ...
}
{code}

Setting the global locale is the point of these cases -- they prove 
{{to_string()}} does _not_
follow it, which is why {{TToString.h}} imbues a default locale on the streams 
it builds.
Leaving it set afterwards is not the point. Every stream constructed later in 
the same
{{UnitTests}} binary picks it up, in suites that have nothing to do with this 
one, and numbers
formatted through {{std::ostringstream}} then come out with digit grouping.

h2. Why it is worth fixing

It has already cost one debugging session. A test in {{THttpBufferBoundTest}} 
formats a chunk
size through an {{ostringstream}}:

{code:cpp}
std::ostringstream size;
size << std::hex << 4096;   // expected "1000"
{code}

which produced {{1.000}} instead. That is not a hex chunk size, so the HTTP 
transport under test
read a completely different stream and the case passed or failed depending on 
whether it was run
alone or as part of a full run -- {{ToStringTest}} is disabled by default and 
only runs when the
whole binary does.

An order-dependent test result whose cause lives in an unrelated file is 
expensive to chase, and
the next test in this binary that formats a number will hit it again.

h2. Fix

A small RAII guard in the test file that saves the previous global locale and 
restores it on
scope exit, applied to both cases. The test intent is unchanged -- the locale 
is still set for
the duration of each case.

h2. Verified

The fix was checked by removing the defensive {{imbue(std::locale::classic())}} 
that
{{THttpBufferBoundTest}} had to add for its own protection, and confirming its 
chunked case then
passes a full run anyway. Before the fix it failed there and passed in 
isolation.

Test-only; no shipped code is affected, which is why this is filed as Minor.

_Filed with AI assistance (Claude Opus 5); reviewed and filed by Jens Geyer._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to