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: c++03, c++11, c++14, c++17 10 // UNSUPPORTED: no-localization 11 // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME 12 13 // TODO FMT This test should not require std::to_chars(floating-point) 14 // XFAIL: availability-fp_to_chars-missing 15 16 // REQUIRES: locale.fr_FR.UTF-8 17 // REQUIRES: locale.ja_JP.UTF-8 18 19 // <chrono> 20 21 // template<class Rep, class Period = ratio<1>> class duration; 22 23 // template<class charT, class traits, class Rep, class Period> 24 // basic_ostream<charT, traits>& 25 // operator<<(basic_ostream<charT, traits>& os, 26 // const duration<Rep, Period>& d); 27 28 #include <chrono> 29 30 #include <cassert> 31 #include <concepts> 32 #include <ratio> 33 #include <sstream> 34 35 #include "make_string.h" 36 #include "platform_support.h" // locale name macros 37 #include "test_macros.h" 38 39 #define SV(S) MAKE_STRING_VIEW(CharT, S) 40 41 template <class CharT, class Rep, class Period> 42 static std::basic_string<CharT> stream_c_locale(std::chrono::duration<Rep, Period> duration) { 43 std::basic_stringstream<CharT> sstr; 44 sstr.precision(4); 45 sstr << std::fixed << duration; 46 return sstr.str(); 47 } 48 49 template <class CharT, class Rep, class Period> 50 static std::basic_string<CharT> stream_fr_FR_locale(std::chrono::duration<Rep, Period> duration) { 51 std::basic_stringstream<CharT> sstr; 52 const std::locale locale(LOCALE_fr_FR_UTF_8); 53 sstr.imbue(locale); 54 sstr.precision(4); 55 sstr << std::fixed << duration; 56 return sstr.str(); 57 } 58 59 template <class CharT, class Rep, class Period> 60 static std::basic_string<CharT> stream_ja_JP_locale(std::chrono::duration<Rep, Period> duration) { 61 std::basic_stringstream<CharT> sstr; 62 const std::locale locale(LOCALE_ja_JP_UTF_8); 63 sstr.imbue(locale); 64 sstr.precision(4); 65 sstr << std::fixed << duration; 66 return sstr.str(); 67 } 68 69 template <class CharT> 70 static void test_values() { 71 using namespace std::literals::chrono_literals; 72 73 assert(stream_c_locale<CharT>(-1'000'000s) == SV("-1000000s")); 74 assert(stream_c_locale<CharT>(1'000'000s) == SV("1000000s")); 75 assert(stream_c_locale<CharT>(-1'000.123456s) == SV("-1000.1235s")); 76 assert(stream_c_locale<CharT>(1'000.123456s) == SV("1000.1235s")); 77 78 if constexpr (std::same_as<CharT, char>) { 79 #if defined(__APPLE__) 80 assert(stream_fr_FR_locale<CharT>(-1'000'000s) == SV("-1000000s")); 81 assert(stream_fr_FR_locale<CharT>(1'000'000s) == SV("1000000s")); 82 assert(stream_fr_FR_locale<CharT>(-1'000.123456s) == SV("-1000,1235s")); 83 assert(stream_fr_FR_locale<CharT>(1'000.123456s) == SV("1000,1235s")); 84 #else 85 assert(stream_fr_FR_locale<CharT>(-1'000'000s) == SV("-1 000 000s")); 86 assert(stream_fr_FR_locale<CharT>(1'000'000s) == SV("1 000 000s")); 87 assert(stream_fr_FR_locale<CharT>(-1'000.123456s) == SV("-1 000,1235s")); 88 assert(stream_fr_FR_locale<CharT>(1'000.123456s) == SV("1 000,1235s")); 89 #endif 90 } else { 91 #ifdef _WIN32 92 assert(stream_fr_FR_locale<CharT>(-1'000'000s) == SV("-1\u00A0000\u00A0000s")); 93 assert(stream_fr_FR_locale<CharT>(1'000'000s) == SV("1\u00A0000\u00A0000s")); 94 assert(stream_fr_FR_locale<CharT>(-1'000.123456s) == SV("-1\u00A0000,1235s")); 95 assert(stream_fr_FR_locale<CharT>(1'000.123456s) == SV("1\u00A0000,1235s")); 96 #elif defined(__APPLE__) 97 assert(stream_fr_FR_locale<CharT>(-1'000'000s) == SV("-1000000s")); 98 assert(stream_fr_FR_locale<CharT>(1'000'000s) == SV("1000000s")); 99 assert(stream_fr_FR_locale<CharT>(-1'000.123456s) == SV("-1000,1235s")); 100 assert(stream_fr_FR_locale<CharT>(1'000.123456s) == SV("1000,1235s")); 101 #else 102 assert(stream_fr_FR_locale<CharT>(-1'000'000s) == SV("-1\u202f000\u202f000s")); 103 assert(stream_fr_FR_locale<CharT>(1'000'000s) == SV("1\u202f000\u202f000s")); 104 assert(stream_fr_FR_locale<CharT>(-1'000.123456s) == SV("-1\u202f000,1235s")); 105 assert(stream_fr_FR_locale<CharT>(1'000.123456s) == SV("1\u202f000,1235s")); 106 #endif 107 } 108 109 assert(stream_ja_JP_locale<CharT>(-1'000'000s) == SV("-1,000,000s")); 110 assert(stream_ja_JP_locale<CharT>(1'000'000s) == SV("1,000,000s")); 111 assert(stream_ja_JP_locale<CharT>(-1'000.123456s) == SV("-1,000.1235s")); 112 assert(stream_ja_JP_locale<CharT>(1'000.123456s) == SV("1,000.1235s")); 113 } 114 115 template <class CharT> 116 static void test_units() { 117 using namespace std::literals::chrono_literals; 118 119 // C locale 120 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::atto>(0)) == SV("0as")); 121 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::femto>(0)) == SV("0fs")); 122 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::pico>(0)) == SV("0ps")); 123 assert(stream_c_locale<CharT>(0ns) == SV("0ns")); 124 #ifndef TEST_HAS_NO_UNICODE 125 assert(stream_c_locale<CharT>(0us) == SV("0\u00b5s")); 126 #else 127 assert(stream_c_locale<CharT>(0us) == SV("0us")); 128 #endif 129 assert(stream_c_locale<CharT>(0ms) == SV("0ms")); 130 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::centi>(0)) == SV("0cs")); 131 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::deci>(0)) == SV("0ds")); 132 133 assert(stream_c_locale<CharT>(0s) == SV("0s")); 134 135 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::deca>(0)) == SV("0das")); 136 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::hecto>(0)) == SV("0hs")); 137 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::kilo>(0)) == SV("0ks")); 138 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::mega>(0)) == SV("0Ms")); 139 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::giga>(0)) == SV("0Gs")); 140 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::tera>(0)) == SV("0Ts")); 141 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::peta>(0)) == SV("0Ps")); 142 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::exa>(0)) == SV("0Es")); 143 144 assert(stream_c_locale<CharT>(0min) == SV("0min")); 145 assert(stream_c_locale<CharT>(0h) == SV("0h")); 146 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::ratio<86400>>(0)) == SV("0d")); 147 148 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::ratio<42>>(0)) == SV("0[42]s")); 149 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::ratio<33, 3>>(0)) == SV("0[11]s")); 150 assert(stream_c_locale<CharT>(std::chrono::duration<int, std::ratio<11, 9>>(0)) == SV("0[11/9]s")); 151 152 // fr_FR locale 153 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::atto>(0)) == SV("0as")); 154 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::femto>(0)) == SV("0fs")); 155 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::pico>(0)) == SV("0ps")); 156 assert(stream_fr_FR_locale<CharT>(0ns) == SV("0ns")); 157 #ifndef TEST_HAS_NO_UNICODE 158 assert(stream_fr_FR_locale<CharT>(0us) == SV("0\u00b5s")); 159 #else 160 assert(stream_fr_FR_locale<CharT>(0us) == SV("0us")); 161 #endif 162 assert(stream_fr_FR_locale<CharT>(0ms) == SV("0ms")); 163 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::centi>(0)) == SV("0cs")); 164 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::deci>(0)) == SV("0ds")); 165 166 assert(stream_fr_FR_locale<CharT>(0s) == SV("0s")); 167 168 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::deca>(0)) == SV("0das")); 169 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::hecto>(0)) == SV("0hs")); 170 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::kilo>(0)) == SV("0ks")); 171 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::mega>(0)) == SV("0Ms")); 172 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::giga>(0)) == SV("0Gs")); 173 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::tera>(0)) == SV("0Ts")); 174 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::peta>(0)) == SV("0Ps")); 175 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::exa>(0)) == SV("0Es")); 176 177 assert(stream_fr_FR_locale<CharT>(0min) == SV("0min")); 178 assert(stream_fr_FR_locale<CharT>(0h) == SV("0h")); 179 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::ratio<86400>>(0)) == SV("0d")); 180 181 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::ratio<42>>(0)) == SV("0[42]s")); 182 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::ratio<33, 3>>(0)) == SV("0[11]s")); 183 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<int, std::ratio<11, 9>>(0)) == SV("0[11/9]s")); 184 185 // ja_JP locale 186 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::atto>(0)) == SV("0as")); 187 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::femto>(0)) == SV("0fs")); 188 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::pico>(0)) == SV("0ps")); 189 assert(stream_ja_JP_locale<CharT>(0ns) == SV("0ns")); 190 #ifndef TEST_HAS_NO_UNICODE 191 assert(stream_ja_JP_locale<CharT>(0us) == SV("0\u00b5s")); 192 #else 193 assert(stream_ja_JP_locale<CharT>(0us) == SV("0us")); 194 #endif 195 assert(stream_ja_JP_locale<CharT>(0ms) == SV("0ms")); 196 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::centi>(0)) == SV("0cs")); 197 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::deci>(0)) == SV("0ds")); 198 199 assert(stream_ja_JP_locale<CharT>(0s) == SV("0s")); 200 201 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::deca>(0)) == SV("0das")); 202 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::hecto>(0)) == SV("0hs")); 203 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::kilo>(0)) == SV("0ks")); 204 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::mega>(0)) == SV("0Ms")); 205 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::giga>(0)) == SV("0Gs")); 206 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::tera>(0)) == SV("0Ts")); 207 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::peta>(0)) == SV("0Ps")); 208 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::exa>(0)) == SV("0Es")); 209 210 assert(stream_ja_JP_locale<CharT>(0min) == SV("0min")); 211 assert(stream_ja_JP_locale<CharT>(0h) == SV("0h")); 212 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::ratio<86400>>(0)) == SV("0d")); 213 214 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::ratio<42>>(0)) == SV("0[42]s")); 215 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::ratio<33, 3>>(0)) == SV("0[11]s")); 216 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<int, std::ratio<11, 9>>(0)) == SV("0[11/9]s")); 217 } 218 219 template <class CharT> 220 static void test_unsigned_types() { 221 // Reported in https://github.com/llvm/llvm-project/issues/96820 222 using namespace std::literals::chrono_literals; 223 224 // C locale 225 assert(stream_c_locale<CharT>(std::chrono::duration<unsigned short, std::atto>(0)) == SV("0as")); 226 assert(stream_c_locale<CharT>(std::chrono::duration<unsigned, std::femto>(0)) == SV("0fs")); 227 assert(stream_c_locale<CharT>(std::chrono::duration<unsigned long, std::pico>(0)) == SV("0ps")); 228 assert(stream_c_locale<CharT>(std::chrono::duration<unsigned long long, std::nano>(0)) == SV("0ns")); 229 230 // fr_FR locale 231 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<unsigned short, std::atto>(0)) == SV("0as")); 232 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<unsigned, std::femto>(0)) == SV("0fs")); 233 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<unsigned long, std::pico>(0)) == SV("0ps")); 234 assert(stream_fr_FR_locale<CharT>(std::chrono::duration<unsigned long long, std::nano>(0)) == SV("0ns")); 235 236 // ja_JP locale 237 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<unsigned short, std::atto>(0)) == SV("0as")); 238 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<unsigned, std::femto>(0)) == SV("0fs")); 239 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<unsigned long, std::pico>(0)) == SV("0ps")); 240 assert(stream_ja_JP_locale<CharT>(std::chrono::duration<unsigned long long, std::nano>(0)) == SV("0ns")); 241 } 242 243 template <class CharT> 244 static void test() { 245 test_values<CharT>(); 246 test_units<CharT>(); 247 test_unsigned_types<CharT>(); 248 } 249 250 int main(int, char**) { 251 test<char>(); 252 253 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 254 test<wchar_t>(); 255 #endif 256 257 return 0; 258 } 259