1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: no-threads
10 // UNSUPPORTED: no-localization
11 // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
12 
13 // REQUIRES: locale.fr_FR.UTF-8
14 
15 // TODO FMT This test should not require std::to_chars(floating-point)
16 // XFAIL: availability-fp_to_chars-missing
17 
18 // <thread>
19 
20 // class thread::id
21 
22 // template<class charT, class traits>
23 // basic_ostream<charT, traits>&
24 // operator<<(basic_ostream<charT, traits>& out, thread::id id);
25 
26 #include <cassert>
27 #include <format>
28 #include <locale>
29 #include <sstream>
30 #include <thread>
31 
32 #include "make_string.h"
33 #include "platform_support.h" // locale name macros
34 #include "test_macros.h"
35 
36 template <class CharT>
basic()37 static void basic() {
38   std::thread::id id0 = std::this_thread::get_id();
39   std::basic_ostringstream<CharT> os;
40   os << id0;
41 
42 #if TEST_STD_VER > 20
43   // C++23 added a formatter specialization for thread::id.
44   // This changed the requirement of ostream to have a
45   // [thread.thread.id]/2
46   //   The text representation for the character type charT of an object of
47   //   type thread::id is an unspecified sequence of charT ...
48   // This definition is used for both streaming and formatting.
49   //
50   // Test whether the output is identical.
51   std::basic_string<CharT> s = std::format(MAKE_STRING_VIEW(CharT, "{}"), id0);
52   assert(s == os.str());
53 #endif
54 }
55 
56 template <class CharT>
format(std::ios_base::fmtflags flags)57 static std::basic_string<CharT> format(std::ios_base::fmtflags flags) {
58   std::basic_stringstream<CharT> sstr;
59   sstr.flags(flags);
60   sstr << std::this_thread::get_id();
61   return sstr.str();
62 }
63 
64 template <class CharT>
stream_state()65 static void stream_state() {
66   std::basic_stringstream<CharT> sstr;
67   sstr << std::this_thread::get_id();
68   std::basic_string<CharT> expected = sstr.str();
69 
70   // Unaffected by fill, width, and align.
71 
72   assert(expected == format<CharT>(std::ios_base::dec | std::ios_base::skipws)); // default flags
73 
74   assert(expected == format<CharT>(std::ios_base::oct));
75   assert(expected == format<CharT>(std::ios_base::hex));
76 
77   assert(expected == format<CharT>(std::ios_base::scientific));
78   assert(expected == format<CharT>(std::ios_base::fixed));
79 
80   assert(expected == format<CharT>(std::ios_base::boolalpha));
81   assert(expected == format<CharT>(std::ios_base::showbase));
82   assert(expected == format<CharT>(std::ios_base::showpoint));
83   assert(expected == format<CharT>(std::ios_base::showpos));
84   assert(expected == format<CharT>(std::ios_base::skipws));  // added for completeness
85   assert(expected == format<CharT>(std::ios_base::unitbuf)); // added for completeness
86   assert(expected == format<CharT>(std::ios_base::uppercase));
87 
88   // Test fill, width, and align.
89 
90   sstr.str(std::basic_string<CharT>());
91   sstr.fill(CharT('#'));
92   sstr.width(expected.size() + 10); // Make sure fill and align affect the output.
93   sstr.flags(std::ios_base::dec | std::ios_base::skipws | std::ios_base::right);
94   sstr << std::this_thread::get_id();
95   expected = sstr.str();
96 
97   sstr.str(std::basic_string<CharT>());
98   sstr.fill(CharT('*'));
99   sstr.width(expected.size());
100   sstr.flags(std::ios_base::dec | std::ios_base::skipws | std::ios_base::right);
101   sstr << std::this_thread::get_id();
102   assert(expected != sstr.str());
103 
104   sstr.str(std::basic_string<CharT>());
105   sstr.fill(CharT('#'));
106   sstr.width(expected.size() - 1);
107   sstr.flags(std::ios_base::dec | std::ios_base::skipws | std::ios_base::right);
108   sstr << std::this_thread::get_id();
109   assert(expected != sstr.str());
110 
111   sstr.str(std::basic_string<CharT>());
112   sstr.fill(CharT('#'));
113   sstr.width(expected.size());
114   sstr.flags(std::ios_base::dec | std::ios_base::skipws | std::ios_base::left);
115   sstr << std::this_thread::get_id();
116   assert(expected != sstr.str());
117 
118   sstr.str(std::basic_string<CharT>());
119   sstr.fill(CharT('#'));
120   sstr.width(expected.size());
121   sstr.flags(std::ios_base::dec | std::ios_base::skipws | std::ios_base::internal);
122   sstr << std::this_thread::get_id();
123   assert(expected == sstr.str()); // internal does *not* affect strings
124 
125   // Test the locale's numpunct.
126 
127   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
128   sstr.str(std::basic_string<CharT>());
129   sstr.fill(CharT('#'));
130   sstr.width(expected.size());
131   sstr << std::this_thread::get_id();
132   assert(expected == sstr.str());
133 }
134 
135 template <class CharT>
test()136 static void test() {
137   basic<CharT>();
138   stream_state<CharT>();
139 }
140 
main(int,char **)141 int main(int, char**) {
142   test<char>();
143 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
144   test<wchar_t>();
145 #endif
146 
147   return 0;
148 }
149