https://gcc.gnu.org/g:01eef394913bd5d682dc5eec9c45e87dabf4d8a3

commit r17-2051-g01eef394913bd5d682dc5eec9c45e87dabf4d8a3
Author: Anlai Lu <[email protected]>
Date:   Tue Jun 30 12:49:02 2026 +0000

    libstdc++: Add stream state tests for chrono operator<<
    
    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: Jonathan Wakely <[email protected]>
    Reviewed-by: Tomasz KamiƄski <[email protected]>
    Signed-off-by: Anlai Lu <[email protected]>

Diff:
---
 libstdc++-v3/testsuite/std/time/ostream_insert.cc | 183 ++++++++++++++++++++++
 1 file changed, 183 insertions(+)

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 000000000000..7d872aa8f9fe
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/time/ostream_insert.cc
@@ -0,0 +1,183 @@
+// { dg-do run { target c++20 } }
+
+// 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.view();
+  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.view() == 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();
+}

Reply via email to