On Wed, Jul 1, 2026 at 11:32 AM Jonathan Wakely <[email protected]> wrote:
> On Tue, 30 Jun 2026 at 15:39, Tomasz Kamiński <[email protected]> wrote: > > > > From: Anlai Lu <[email protected]> > > > > Add tests covering formatted output function semantics for the > > chrono operator<< overloads. These verify that the new stack-buffer > > implementation correctly preserves sentry construction (badbit check > > and tied stream flush), width/fill padding with all three alignment > > modes (right, left, internal), width reset after each output, and > > locale-aware output. A weekday_indexed content test and a wchar_t > > smoke test are included. > > > > libstdc++-v3/ChangeLog: > > > > * testsuite/std/time/ostream_insert.cc: New test. > > > > Reviewed-by: Tomasz Kamiński <[email protected]> > > Signed-off-by: Anlai Lu <[email protected]> > > --- > > Patch v3: > > * check prefixes in test_multiple_chrono_types (as I suggested) > > * add check_prefix funciton to simplify above > > * uses os.view() to extract the written characters > > > > Tested on x86_64-linux. OK for trunk? > Pushed to trunk with the line removed as r17-2051-g01eef394913bd5. I have verified that the test passes with the cow string ABI. > > > > .../testsuite/std/time/ostream_insert.cc | 183 ++++++++++++++++++ > > 1 file changed, 183 insertions(+) > > create mode 100644 libstdc++-v3/testsuite/std/time/ostream_insert.cc > > > > diff --git a/libstdc++-v3/testsuite/std/time/ostream_insert.cc > b/libstdc++-v3/testsuite/std/time/ostream_insert.cc > > new file mode 100644 > > index 00000000000..a78f7c1d162 > > --- /dev/null > > +++ b/libstdc++-v3/testsuite/std/time/ostream_insert.cc > > @@ -0,0 +1,183 @@ > > +// { dg-do run { target c++20 } } > > +// { dg-require-effective-target tzdb } > > This dg-require should not be here, the test doesn't require tzdb. > > OK for trunk without that line. > > > +// Test stream state semantics for chrono operator<< > > +#include <chrono> > > +#include <format> > > +#include <iomanip> > > +#include <sstream> > > +#include <testsuite_hooks.h> > > + > > +bool > > +check_prefix(std::string_view s, size_t n, char c) > > +{ > > + for (char v : s) > > + if (v != c) > > + return !n; > > + else if (!n) > > + return false; > > + else > > + --n; > > + return false; > > +} > > + > > +void > > +test_sentry_badbit() > > +{ > > + using namespace std::chrono; > > + std::ostringstream os; > > + os.setstate(std::ios::badbit); > > + VERIFY( !os.good() ); > > + os << sys_time<seconds>{1'700'000'000s}; > > + VERIFY( os.bad() ); > > + VERIFY( os.str().empty() ); > > +} > > + > > +void > > +test_sentry_tied() > > +{ > > + using namespace std::chrono; > > + struct testbuf : std::streambuf > > + { bool flushed = false; int sync() override { flushed = true; return > 0; } }; > > + testbuf tied_buf; std::ostream tied(&tied_buf); std::ostringstream os; > > + os.tie(&tied); > > + os << sys_time<seconds>{1'700'000'000s}; > > + VERIFY( tied_buf.flushed == true ); > > +} > > + > > +void > > +test_width_fill() > > +{ > > + using namespace std::chrono; > > + std::ostringstream os; > > + os << std::setw(30) << std::setfill('*') << > sys_time<seconds>{1'700'000'000s}; > > + auto s = os.view(); > > + VERIFY( s.size() == 30 ); > > + VERIFY( check_prefix(s, 11, '*') ); > > + VERIFY( s.substr(11) == "2023-11-14 22:13:20" ); > > + VERIFY( os.width() == 0 ); > > +} > > + > > +void > > +test_width_left() > > +{ > > + using namespace std::chrono; > > + std::ostringstream os; > > + os << std::setw(30) << std::left << std::setfill('.') << > sys_time<seconds>{1'700'000'000s}; > > + auto s = os.view(); > > + VERIFY( s.size() == 30 ); > > + VERIFY( s.find("2023-11-14") == 0 ); > > + VERIFY( s.back() == '.' ); > > + VERIFY( os.width() == 0 ); > > +} > > + > > +void > > +test_width_internal() > > +{ > > + using namespace std::chrono; > > + std::ostringstream os; > > + os << std::setw(30) << std::internal << std::setfill('_') << day(15); > > + auto s = os.view(); > > + VERIFY( s.size() == 30 ); > > + VERIFY( check_prefix(s, 28, '_') ); > > + VERIFY( s.substr(28) == "15" ); > > + VERIFY( os.width() == 0 ); > > +} > > + > > +void > > +test_width_reset() > > +{ > > + using namespace std::chrono; > > + std::ostringstream os; > > + os << std::setw(20) << sys_time<seconds>{1'700'000'000s}; > > + VERIFY( os.width() == 0 ); > > + os << hh_mm_ss{seconds(45296)}; > > + VERIFY( os.width() == 0 ); > > + os << std::setw(15) << day(15); > > + VERIFY( os.width() == 0 ); > > +} > > + > > +void > > +test_width_zero() > > +{ > > + using namespace std::chrono; > > + std::ostringstream os; > > + os << std::setw(0) << sys_time<seconds>{1'700'000'000s}; > > + auto s = os.view(); > > + VERIFY( s.find("2023-11-14") != std::string::npos ); > > + VERIFY( s.size() < 20 ); > > + VERIFY( os.width() == 0 ); > > +} > > + > > +void > > +test_multiple_chrono_types() > > +{ > > + using namespace std::chrono; > > + std::ostringstream os; > > + os << std::setw(25) << std::setfill('-') << > sys_time<seconds>{1'700'000'000s}; > > + VERIFY( check_prefix(os.view(), 6, '-') ); > > + VERIFY( os.width() == 0 ); > > + os << std::setw(15) << hh_mm_ss{seconds(45296)}; > > + VERIFY( check_prefix(os.view().substr(25), 7, '-') ); > > + VERIFY( os.width() == 0 ); > > + os << std::setw(10) << day(15); > > + VERIFY( check_prefix(os.view().substr(40), 8, '-') ); > > + VERIFY( os.width() == 0 ); > > + os << std::setw(10) << month(7); > > + VERIFY( check_prefix(os.view().substr(50), 7, '-') ); > > + VERIFY( os.width() == 0 ); > > + os << std::setw(10) << year(2026); > > + VERIFY( check_prefix(os.view().substr(60), 6, '-') ); > > + VERIFY( os.width() == 0 ); > > + os << std::setw(12) << Monday; > > + VERIFY( check_prefix(os.view().substr(70), 9, '-') ); > > + VERIFY( os.width() == 0 ); > > +} > > + > > +void > > +test_locale_aware() > > +{ > > + using namespace std::chrono; > > + std::ostringstream os; > > + os.imbue(std::locale::classic()); > > + os << std::setw(12) << Monday; > > + auto s = os.str(); > > + VERIFY( s.size() >= 12 ); > > + VERIFY( os.width() == 0 ); > > +} > > + > > +void > > +test_wchar_t() > > +{ > > + using namespace std::chrono; > > + std::wostringstream wos; > > + wos << std::chrono::sys_time<std::chrono::seconds>{1'700'000'000s}; > > + VERIFY( wos.str() == L"2023-11-14 22:13:20" ); > > +} > > + > > +void > > +test_weekday_indexed() > > +{ > > + using namespace std::chrono; > > + std::ostringstream os; > > + os << Monday[1]; > > + VERIFY( os.view() == "Mon[1]" ); > > + os.str(""); > > + os << Monday[6]; // invalid index > > + VERIFY( os.view().find("Mon[") != std::string::npos ); > > +} > > + > > +int > > +main() > > +{ > > + test_sentry_badbit(); > > + test_sentry_tied(); > > + test_width_fill(); > > + test_width_left(); > > + test_width_internal(); > > + test_width_reset(); > > + test_width_zero(); > > + test_multiple_chrono_types(); > > + test_locale_aware(); > > + test_wchar_t(); > > + test_weekday_indexed(); > > +} > > -- > > 2.54.0 > > > >
