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
> >
>
>

Reply via email to