blob: a2d71a9881dbc243b305d395fd3c08bef89317bb [file] [log] [blame]
//===----------------------------------------------------------------------===//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef TEST_STD_UTILITIES_FORMAT_FORMAT_FUNCTIONS_FORMAT_TESTS_H
#define TEST_STD_UTILITIES_FORMAT_FORMAT_FUNCTIONS_FORMAT_TESTS_H
#include "make_string.h"
// In this file the following template types are used:
// TestFunction must be callable as check(expected-result, string-to-format, args-to-format...)
// ExceptionTest must be callable as check_exception(expected-exception, string-to-format, args-to-format...)
#define STR(S) MAKE_STRING(CharT, S)
#define CSTR(S) MAKE_CSTRING(CharT, S)
template <class CharT>
std::vector<std::basic_string<CharT>> invalid_types(std::string valid) {
std::vector<std::basic_string<CharT>> result;
#define CASE(T) \
case #T[0]: \
result.push_back(STR("Invalid formatter type {:" #T "}")); \
break;
for (auto type : "aAbBcdeEfFgGopsxX") {
if (valid.find(type) != std::string::npos)
continue;
switch (type) {
CASE(a)
CASE(A)
CASE(b)
CASE(B)
CASE(c)
CASE(d)
CASE(e)
CASE(E)
CASE(f)
CASE(F)
CASE(g)
CASE(G)
CASE(o)
CASE(p)
CASE(s)
CASE(x)
CASE(X)
case 0:
break;
default:
assert(false && "Add the type to the list of cases.");
}
}
#undef CASE
return result;
}
template <class CharT, class T, class TestFunction, class ExceptionTest>
void format_test_string(T world, T universe, TestFunction check,
ExceptionTest check_exception) {
// *** Valid input tests ***
// Unsed argument is ignored. TODO FMT what does the Standard mandate?
check(STR("hello world"), STR("hello {}"), world, universe);
check(STR("hello world and universe"), STR("hello {} and {}"), world,
universe);
check(STR("hello world"), STR("hello {0}"), world, universe);
check(STR("hello universe"), STR("hello {1}"), world, universe);
check(STR("hello universe and world"), STR("hello {1} and {0}"), world,
universe);
check(STR("hello world"), STR("hello {:_>}"), world);
check(STR("hello world"), STR("hello {:>8}"), world);
check(STR("hello ___world"), STR("hello {:_>8}"), world);
check(STR("hello _world__"), STR("hello {:_^8}"), world);
check(STR("hello world___"), STR("hello {:_<8}"), world);
check(STR("hello >>>world"), STR("hello {:>>8}"), world);
check(STR("hello <<<world"), STR("hello {:<>8}"), world);
check(STR("hello ^^^world"), STR("hello {:^>8}"), world);
check(STR("hello $world"), STR("hello {:$>{}}"), world, 6);
check(STR("hello $world"), STR("hello {0:$>{1}}"), world, 6);
check(STR("hello $world"), STR("hello {1:$>{0}}"), 6, world);
check(STR("hello world"), STR("hello {:.5}"), world);
check(STR("hello unive"), STR("hello {:.5}"), universe);
check(STR("hello univer"), STR("hello {:.{}}"), universe, 6);
check(STR("hello univer"), STR("hello {0:.{1}}"), universe, 6);
check(STR("hello univer"), STR("hello {1:.{0}}"), 6, universe);
check(STR("hello %world%"), STR("hello {:%^7.7}"), world);
check(STR("hello univers"), STR("hello {:%^7.7}"), universe);
check(STR("hello %world%"), STR("hello {:%^{}.{}}"), world, 7, 7);
check(STR("hello %world%"), STR("hello {0:%^{1}.{2}}"), world, 7, 7);
check(STR("hello %world%"), STR("hello {0:%^{2}.{1}}"), world, 7, 7);
check(STR("hello %world%"), STR("hello {1:%^{0}.{2}}"), 7, world, 7);
check(STR("hello world"), STR("hello {:_>s}"), world);
check(STR("hello $world"), STR("hello {:$>{}s}"), world, 6);
check(STR("hello world"), STR("hello {:.5s}"), world);
check(STR("hello univer"), STR("hello {:.{}s}"), universe, 6);
check(STR("hello %world%"), STR("hello {:%^7.7s}"), world);
check(STR("hello #####uni"), STR("hello {:#>8.3s}"), universe);
check(STR("hello ##uni###"), STR("hello {:#^8.3s}"), universe);
check(STR("hello uni#####"), STR("hello {:#<8.3s}"), universe);
// *** sign ***
check_exception("The format-spec should consume the input or end with a '}'",
STR("hello {:-}"), world);
// *** alternate form ***
check_exception("The format-spec should consume the input or end with a '}'",
STR("hello {:#}"), world);
// *** zero-padding ***
check_exception("A format-spec width field shouldn't have a leading zero",
STR("hello {:0}"), world);
// *** width ***
#if _LIBCPP_VERSION
// This limit isn't specified in the Standard.
static_assert(std::__format::__number_max == 2'147'483'647,
"Update the assert and the test.");
check_exception("The numeric value of the format-spec is too large",
STR("{:2147483648}"), world);
check_exception("The numeric value of the format-spec is too large",
STR("{:5000000000}"), world);
check_exception("The numeric value of the format-spec is too large",
STR("{:10000000000}"), world);
#endif
check_exception(
"A format-spec width field replacement should have a positive value",
STR("hello {:{}}"), world, 0);
check_exception(
"A format-spec arg-id replacement shouldn't have a negative value",
STR("hello {:{}}"), world, -1);
check_exception(
"A format-spec arg-id replacement exceeds the maximum supported value",
STR("hello {:{}}"), world, -1u);
check_exception("Argument index out of bounds", STR("hello {:{}}"), world);
check_exception(
"A format-spec arg-id replacement argument isn't an integral type",
STR("hello {:{}}"), world, universe);
check_exception(
"Using manual argument numbering in automatic argument numbering mode",
STR("hello {:{0}}"), world, 1);
check_exception(
"Using automatic argument numbering in manual argument numbering mode",
STR("hello {0:{}}"), world, 1);
// *** precision ***
check_exception("A format-spec precision field shouldn't have a leading zero",
STR("hello {:.01}"), world);
#if _LIBCPP_VERSION
// This limit isn't specified in the Standard.
static_assert(std::__format::__number_max == 2'147'483'647,
"Update the assert and the test.");
check_exception("The numeric value of the format-spec is too large",
STR("{:.2147483648}"), world);
check_exception("The numeric value of the format-spec is too large",
STR("{:.5000000000}"), world);
check_exception("The numeric value of the format-spec is too large",
STR("{:.10000000000}"), world);
#endif
// Precision 0 allowed, but not useful for string arguments.
check(STR("hello "), STR("hello {:.{}}"), world, 0);
check_exception(
"A format-spec arg-id replacement shouldn't have a negative value",
STR("hello {:.{}}"), world, -1);
check_exception(
"A format-spec arg-id replacement exceeds the maximum supported value",
STR("hello {:.{}}"), world, -1u);
check_exception("Argument index out of bounds", STR("hello {:.{}}"), world);
check_exception(
"A format-spec arg-id replacement argument isn't an integral type",
STR("hello {:.{}}"), world, universe);
check_exception(
"Using manual argument numbering in automatic argument numbering mode",
STR("hello {:.{0}}"), world, 1);
check_exception(
"Using automatic argument numbering in manual argument numbering mode",
STR("hello {0:.{}}"), world, 1);
// *** locale-specific form ***
check_exception("The format-spec should consume the input or end with a '}'",
STR("hello {:L}"), world);
// *** type ***
for (const auto& fmt : invalid_types<CharT>("s"))
check_exception(
"The format-spec type has a type not supported for a string argument",
fmt, world);
}
template <class CharT, class TestFunction>
void format_test_string_unicode(TestFunction check) {
#ifndef _LIBCPP_HAS_NO_UNICODE
// ß requires one column
check(STR("aßc"), STR("{}"), STR("aßc"));
check(STR("aßc"), STR("{:.3}"), STR("aßc"));
check(STR("aß"), STR("{:.2}"), STR("aßc"));
check(STR("a"), STR("{:.1}"), STR("aßc"));
check(STR("aßc"), STR("{:3.3}"), STR("aßc"));
check(STR("aß"), STR("{:2.2}"), STR("aßc"));
check(STR("a"), STR("{:1.1}"), STR("aßc"));
check(STR("aßc---"), STR("{:-<6}"), STR("aßc"));
check(STR("-aßc--"), STR("{:-^6}"), STR("aßc"));
check(STR("---aßc"), STR("{:->6}"), STR("aßc"));
// \u1000 requires two columns
check(STR("a\u1110c"), STR("{}"), STR("a\u1110c"));
check(STR("a\u1100c"), STR("{:.4}"), STR("a\u1100c"));
check(STR("a\u1100"), STR("{:.3}"), STR("a\u1100c"));
check(STR("a"), STR("{:.2}"), STR("a\u1100c"));
check(STR("a"), STR("{:.1}"), STR("a\u1100c"));
check(STR("a\u1100c"), STR("{:-<4.4}"), STR("a\u1100c"));
check(STR("a\u1100"), STR("{:-<3.3}"), STR("a\u1100c"));
check(STR("a-"), STR("{:-<2.2}"), STR("a\u1100c"));
check(STR("a"), STR("{:-<1.1}"), STR("a\u1100c"));
check(STR("a\u1110c---"), STR("{:-<7}"), STR("a\u1110c"));
check(STR("-a\u1110c--"), STR("{:-^7}"), STR("a\u1110c"));
check(STR("---a\u1110c"), STR("{:->7}"), STR("a\u1110c"));
#else
(void)check;
#endif
}
template <class CharT, class TestFunction, class ExceptionTest>
void format_string_tests(TestFunction check, ExceptionTest check_exception) {
std::basic_string<CharT> world = STR("world");
std::basic_string<CharT> universe = STR("universe");
// Testing the char const[] is a bit tricky due to array to pointer decay.
// Since there are separate tests in format.formatter.spec the array is not
// tested here.
format_test_string<CharT>(world.c_str(), universe.c_str(), check,
check_exception);
format_test_string<CharT>(const_cast<CharT*>(world.c_str()),
const_cast<CharT*>(universe.c_str()), check,
check_exception);
format_test_string<CharT>(std::basic_string_view<CharT>(world),
std::basic_string_view<CharT>(universe), check,
check_exception);
format_test_string<CharT>(world, universe, check, check_exception);
format_test_string_unicode<CharT>(check);
}
template <class CharT, class TestFunction, class ExceptionTest>
void format_test_bool(TestFunction check, ExceptionTest check_exception) {
// *** align-fill & width ***
check(STR("answer is 'true '"), STR("answer is '{:7}'"), true);
check(STR("answer is ' true'"), STR("answer is '{:>7}'"), true);
check(STR("answer is 'true '"), STR("answer is '{:<7}'"), true);
check(STR("answer is ' true '"), STR("answer is '{:^7}'"), true);
check(STR("answer is 'false '"), STR("answer is '{:8s}'"), false);
check(STR("answer is ' false'"), STR("answer is '{:>8s}'"), false);
check(STR("answer is 'false '"), STR("answer is '{:<8s}'"), false);
check(STR("answer is ' false '"), STR("answer is '{:^8s}'"), false);
check(STR("answer is '---true'"), STR("answer is '{:->7}'"), true);
check(STR("answer is 'true---'"), STR("answer is '{:-<7}'"), true);
check(STR("answer is '-true--'"), STR("answer is '{:-^7}'"), true);
check(STR("answer is '---false'"), STR("answer is '{:->8s}'"), false);
check(STR("answer is 'false---'"), STR("answer is '{:-<8s}'"), false);
check(STR("answer is '-false--'"), STR("answer is '{:-^8s}'"), false);
// *** Sign ***
check_exception("A sign field isn't allowed in this format-spec", STR("{:-}"),
true);
check_exception("A sign field isn't allowed in this format-spec", STR("{:+}"),
true);
check_exception("A sign field isn't allowed in this format-spec", STR("{: }"),
true);
check_exception("A sign field isn't allowed in this format-spec",
STR("{:-s}"), true);
check_exception("A sign field isn't allowed in this format-spec",
STR("{:+s}"), true);
check_exception("A sign field isn't allowed in this format-spec",
STR("{: s}"), true);
// *** alternate form ***
check_exception("An alternate form field isn't allowed in this format-spec",
STR("{:#}"), true);
check_exception("An alternate form field isn't allowed in this format-spec",
STR("{:#s}"), true);
// *** zero-padding ***
check_exception("A zero-padding field isn't allowed in this format-spec",
STR("{:0}"), true);
check_exception("A zero-padding field isn't allowed in this format-spec",
STR("{:0s}"), true);
// *** precision ***
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.}"), true);
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.0}"), true);
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.42}"), true);
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.s}"), true);
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.0s}"), true);
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.42s}"), true);
// *** locale-specific form ***
// See locale-specific_form.pass.cpp
// *** type ***
for (const auto& fmt : invalid_types<CharT>("bBcdosxX"))
check_exception(
"The format-spec type has a type not supported for a bool argument",
fmt, true);
}
template <class CharT, class TestFunction, class ExceptionTest>
void format_test_bool_as_char(TestFunction check,
ExceptionTest check_exception) {
// *** align-fill & width ***
check(STR("answer is '\1 '"), STR("answer is '{:6c}'"), true);
check(STR("answer is ' \1'"), STR("answer is '{:>6c}'"), true);
check(STR("answer is '\1 '"), STR("answer is '{:<6c}'"), true);
check(STR("answer is ' \1 '"), STR("answer is '{:^6c}'"), true);
check(STR("answer is '-----\1'"), STR("answer is '{:->6c}'"), true);
check(STR("answer is '\1-----'"), STR("answer is '{:-<6c}'"), true);
check(STR("answer is '--\1---'"), STR("answer is '{:-^6c}'"), true);
check(std::basic_string<CharT>(CSTR("answer is '\0 '"), 18),
STR("answer is '{:6c}'"), false);
check(std::basic_string<CharT>(CSTR("answer is '\0 '"), 18),
STR("answer is '{:6c}'"), false);
check(std::basic_string<CharT>(CSTR("answer is ' \0'"), 18),
STR("answer is '{:>6c}'"), false);
check(std::basic_string<CharT>(CSTR("answer is '\0 '"), 18),
STR("answer is '{:<6c}'"), false);
check(std::basic_string<CharT>(CSTR("answer is ' \0 '"), 18),
STR("answer is '{:^6c}'"), false);
check(std::basic_string<CharT>(CSTR("answer is '-----\0'"), 18),
STR("answer is '{:->6c}'"), false);
check(std::basic_string<CharT>(CSTR("answer is '\0-----'"), 18),
STR("answer is '{:-<6c}'"), false);
check(std::basic_string<CharT>(CSTR("answer is '--\0---'"), 18),
STR("answer is '{:-^6c}'"), false);
// *** Sign ***
check_exception("A sign field isn't allowed in this format-spec",
STR("{:-c}"), true);
check_exception("A sign field isn't allowed in this format-spec",
STR("{:+c}"), true);
check_exception("A sign field isn't allowed in this format-spec",
STR("{: c}"), true);
// *** alternate form ***
check_exception("An alternate form field isn't allowed in this format-spec",
STR("{:#c}"), true);
// *** zero-padding ***
check_exception("A zero-padding field isn't allowed in this format-spec",
STR("{:0c}"), true);
// *** precision ***
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.c}"), true);
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.0c}"), true);
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.42c}"), true);
// *** locale-specific form ***
// Note it has no effect but it's allowed.
check(STR("answer is '*'"), STR("answer is '{:Lc}'"), '*');
// *** type ***
for (const auto& fmt : invalid_types<CharT>("bBcdosxX"))
check_exception(
"The format-spec type has a type not supported for a bool argument",
fmt, true);
}
template <class CharT, class TestFunction, class ExceptionTest>
void format_test_bool_as_integer(TestFunction check,
ExceptionTest check_exception) {
// *** align-fill & width ***
check(STR("answer is '1'"), STR("answer is '{:<1d}'"), true);
check(STR("answer is '1 '"), STR("answer is '{:<2d}'"), true);
check(STR("answer is '0 '"), STR("answer is '{:<2d}'"), false);
check(STR("answer is ' 1'"), STR("answer is '{:6d}'"), true);
check(STR("answer is ' 1'"), STR("answer is '{:>6d}'"), true);
check(STR("answer is '1 '"), STR("answer is '{:<6d}'"), true);
check(STR("answer is ' 1 '"), STR("answer is '{:^6d}'"), true);
check(STR("answer is '*****0'"), STR("answer is '{:*>6d}'"), false);
check(STR("answer is '0*****'"), STR("answer is '{:*<6d}'"), false);
check(STR("answer is '**0***'"), STR("answer is '{:*^6d}'"), false);
// Test whether zero padding is ignored
check(STR("answer is ' 1'"), STR("answer is '{:>06d}'"), true);
check(STR("answer is '1 '"), STR("answer is '{:<06d}'"), true);
check(STR("answer is ' 1 '"), STR("answer is '{:^06d}'"), true);
// *** Sign ***
check(STR("answer is 1"), STR("answer is {:d}"), true);
check(STR("answer is 0"), STR("answer is {:-d}"), false);
check(STR("answer is +1"), STR("answer is {:+d}"), true);
check(STR("answer is 0"), STR("answer is {: d}"), false);
// *** alternate form ***
check(STR("answer is +1"), STR("answer is {:+#d}"), true);
check(STR("answer is +1"), STR("answer is {:+b}"), true);
check(STR("answer is +0b1"), STR("answer is {:+#b}"), true);
check(STR("answer is +0B1"), STR("answer is {:+#B}"), true);
check(STR("answer is +1"), STR("answer is {:+o}"), true);
check(STR("answer is +01"), STR("answer is {:+#o}"), true);
check(STR("answer is +1"), STR("answer is {:+x}"), true);
check(STR("answer is +0x1"), STR("answer is {:+#x}"), true);
check(STR("answer is +1"), STR("answer is {:+X}"), true);
check(STR("answer is +0X1"), STR("answer is {:+#X}"), true);
check(STR("answer is 0"), STR("answer is {:#d}"), false);
check(STR("answer is 0"), STR("answer is {:b}"), false);
check(STR("answer is 0b0"), STR("answer is {:#b}"), false);
check(STR("answer is 0B0"), STR("answer is {:#B}"), false);
check(STR("answer is 0"), STR("answer is {:o}"), false);
check(STR("answer is 0"), STR("answer is {:#o}"), false);
check(STR("answer is 0"), STR("answer is {:x}"), false);
check(STR("answer is 0x0"), STR("answer is {:#x}"), false);
check(STR("answer is 0"), STR("answer is {:X}"), false);
check(STR("answer is 0X0"), STR("answer is {:#X}"), false);
// *** zero-padding & width ***
check(STR("answer is +00000000001"), STR("answer is {:+#012d}"), true);
check(STR("answer is +00000000001"), STR("answer is {:+012b}"), true);
check(STR("answer is +0b000000001"), STR("answer is {:+#012b}"), true);
check(STR("answer is +0B000000001"), STR("answer is {:+#012B}"), true);
check(STR("answer is +00000000001"), STR("answer is {:+012o}"), true);
check(STR("answer is +00000000001"), STR("answer is {:+#012o}"), true);
check(STR("answer is +00000000001"), STR("answer is {:+012x}"), true);
check(STR("answer is +0x000000001"), STR("answer is {:+#012x}"), true);
check(STR("answer is +00000000001"), STR("answer is {:+012X}"), true);
check(STR("answer is +0X000000001"), STR("answer is {:+#012X}"), true);
check(STR("answer is 000000000000"), STR("answer is {:#012d}"), false);
check(STR("answer is 000000000000"), STR("answer is {:012b}"), false);
check(STR("answer is 0b0000000000"), STR("answer is {:#012b}"), false);
check(STR("answer is 0B0000000000"), STR("answer is {:#012B}"), false);
check(STR("answer is 000000000000"), STR("answer is {:012o}"), false);
check(STR("answer is 000000000000"), STR("answer is {:#012o}"), false);
check(STR("answer is 000000000000"), STR("answer is {:012x}"), false);
check(STR("answer is 0x0000000000"), STR("answer is {:#012x}"), false);
check(STR("answer is 000000000000"), STR("answer is {:012X}"), false);
check(STR("answer is 0X0000000000"), STR("answer is {:#012X}"), false);
// *** precision ***
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.}"), true);
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.0}"), true);
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.42}"), true);
// *** locale-specific form ***
// See locale-specific_form.pass.cpp
// *** type ***
for (const auto& fmt : invalid_types<CharT>("bBcdosxX"))
check_exception(
"The format-spec type has a type not supported for a bool argument",
fmt, true);
}
template <class I, class CharT, class TestFunction, class ExceptionTest>
void format_test_integer_as_integer(TestFunction check,
ExceptionTest check_exception) {
// *** align-fill & width ***
check(STR("answer is '42'"), STR("answer is '{:<1}'"), I(42));
check(STR("answer is '42'"), STR("answer is '{:<2}'"), I(42));
check(STR("answer is '42 '"), STR("answer is '{:<3}'"), I(42));
check(STR("answer is ' 42'"), STR("answer is '{:7}'"), I(42));
check(STR("answer is ' 42'"), STR("answer is '{:>7}'"), I(42));
check(STR("answer is '42 '"), STR("answer is '{:<7}'"), I(42));
check(STR("answer is ' 42 '"), STR("answer is '{:^7}'"), I(42));
check(STR("answer is '*****42'"), STR("answer is '{:*>7}'"), I(42));
check(STR("answer is '42*****'"), STR("answer is '{:*<7}'"), I(42));
check(STR("answer is '**42***'"), STR("answer is '{:*^7}'"), I(42));
// Test whether zero padding is ignored
check(STR("answer is ' 42'"), STR("answer is '{:>07}'"), I(42));
check(STR("answer is '42 '"), STR("answer is '{:<07}'"), I(42));
check(STR("answer is ' 42 '"), STR("answer is '{:^07}'"), I(42));
// *** Sign ***
if constexpr (std::signed_integral<I>)
check(STR("answer is -42"), STR("answer is {}"), I(-42));
check(STR("answer is 0"), STR("answer is {}"), I(0));
check(STR("answer is 42"), STR("answer is {}"), I(42));
if constexpr (std::signed_integral<I>)
check(STR("answer is -42"), STR("answer is {:-}"), I(-42));
check(STR("answer is 0"), STR("answer is {:-}"), I(0));
check(STR("answer is 42"), STR("answer is {:-}"), I(42));
if constexpr (std::signed_integral<I>)
check(STR("answer is -42"), STR("answer is {:+}"), I(-42));
check(STR("answer is +0"), STR("answer is {:+}"), I(0));
check(STR("answer is +42"), STR("answer is {:+}"), I(42));
if constexpr (std::signed_integral<I>)
check(STR("answer is -42"), STR("answer is {: }"), I(-42));
check(STR("answer is 0"), STR("answer is {: }"), I(0));
check(STR("answer is 42"), STR("answer is {: }"), I(42));
// *** alternate form ***
if constexpr (std::signed_integral<I>) {
check(STR("answer is -42"), STR("answer is {:#}"), I(-42));
check(STR("answer is -42"), STR("answer is {:#d}"), I(-42));
check(STR("answer is -101010"), STR("answer is {:b}"), I(-42));
check(STR("answer is -0b101010"), STR("answer is {:#b}"), I(-42));
check(STR("answer is -0B101010"), STR("answer is {:#B}"), I(-42));
check(STR("answer is -52"), STR("answer is {:o}"), I(-42));
check(STR("answer is -052"), STR("answer is {:#o}"), I(-42));
check(STR("answer is -2a"), STR("answer is {:x}"), I(-42));
check(STR("answer is -0x2a"), STR("answer is {:#x}"), I(-42));
check(STR("answer is -2A"), STR("answer is {:X}"), I(-42));
check(STR("answer is -0X2A"), STR("answer is {:#X}"), I(-42));
}
check(STR("answer is 0"), STR("answer is {:#}"), I(0));
check(STR("answer is 0"), STR("answer is {:#d}"), I(0));
check(STR("answer is 0"), STR("answer is {:b}"), I(0));
check(STR("answer is 0b0"), STR("answer is {:#b}"), I(0));
check(STR("answer is 0B0"), STR("answer is {:#B}"), I(0));
check(STR("answer is 0"), STR("answer is {:o}"), I(0));
check(STR("answer is 0"), STR("answer is {:#o}"), I(0));
check(STR("answer is 0"), STR("answer is {:x}"), I(0));
check(STR("answer is 0x0"), STR("answer is {:#x}"), I(0));
check(STR("answer is 0"), STR("answer is {:X}"), I(0));
check(STR("answer is 0X0"), STR("answer is {:#X}"), I(0));
check(STR("answer is +42"), STR("answer is {:+#}"), I(42));
check(STR("answer is +42"), STR("answer is {:+#d}"), I(42));
check(STR("answer is +101010"), STR("answer is {:+b}"), I(42));
check(STR("answer is +0b101010"), STR("answer is {:+#b}"), I(42));
check(STR("answer is +0B101010"), STR("answer is {:+#B}"), I(42));
check(STR("answer is +52"), STR("answer is {:+o}"), I(42));
check(STR("answer is +052"), STR("answer is {:+#o}"), I(42));
check(STR("answer is +2a"), STR("answer is {:+x}"), I(42));
check(STR("answer is +0x2a"), STR("answer is {:+#x}"), I(42));
check(STR("answer is +2A"), STR("answer is {:+X}"), I(42));
check(STR("answer is +0X2A"), STR("answer is {:+#X}"), I(42));
// *** zero-padding & width ***
if constexpr (std::signed_integral<I>) {
check(STR("answer is -00000000042"), STR("answer is {:#012}"), I(-42));
check(STR("answer is -00000000042"), STR("answer is {:#012d}"), I(-42));
check(STR("answer is -00000101010"), STR("answer is {:012b}"), I(-42));
check(STR("answer is -0b000101010"), STR("answer is {:#012b}"), I(-42));
check(STR("answer is -0B000101010"), STR("answer is {:#012B}"), I(-42));
check(STR("answer is -00000000052"), STR("answer is {:012o}"), I(-42));
check(STR("answer is -00000000052"), STR("answer is {:#012o}"), I(-42));
check(STR("answer is -0000000002a"), STR("answer is {:012x}"), I(-42));
check(STR("answer is -0x00000002a"), STR("answer is {:#012x}"), I(-42));
check(STR("answer is -0000000002A"), STR("answer is {:012X}"), I(-42));
check(STR("answer is -0X00000002A"), STR("answer is {:#012X}"), I(-42));
}
check(STR("answer is 000000000000"), STR("answer is {:#012}"), I(0));
check(STR("answer is 000000000000"), STR("answer is {:#012d}"), I(0));
check(STR("answer is 000000000000"), STR("answer is {:012b}"), I(0));
check(STR("answer is 0b0000000000"), STR("answer is {:#012b}"), I(0));
check(STR("answer is 0B0000000000"), STR("answer is {:#012B}"), I(0));
check(STR("answer is 000000000000"), STR("answer is {:012o}"), I(0));
check(STR("answer is 000000000000"), STR("answer is {:#012o}"), I(0));
check(STR("answer is 000000000000"), STR("answer is {:012x}"), I(0));
check(STR("answer is 0x0000000000"), STR("answer is {:#012x}"), I(0));
check(STR("answer is 000000000000"), STR("answer is {:012X}"), I(0));
check(STR("answer is 0X0000000000"), STR("answer is {:#012X}"), I(0));
check(STR("answer is +00000000042"), STR("answer is {:+#012}"), I(42));
check(STR("answer is +00000000042"), STR("answer is {:+#012d}"), I(42));
check(STR("answer is +00000101010"), STR("answer is {:+012b}"), I(42));
check(STR("answer is +0b000101010"), STR("answer is {:+#012b}"), I(42));
check(STR("answer is +0B000101010"), STR("answer is {:+#012B}"), I(42));
check(STR("answer is +00000000052"), STR("answer is {:+012o}"), I(42));
check(STR("answer is +00000000052"), STR("answer is {:+#012o}"), I(42));
check(STR("answer is +0000000002a"), STR("answer is {:+012x}"), I(42));
check(STR("answer is +0x00000002a"), STR("answer is {:+#012x}"), I(42));
check(STR("answer is +0000000002A"), STR("answer is {:+012X}"), I(42));
check(STR("answer is +0X00000002A"), STR("answer is {:+#012X}"), I(42));
// *** precision ***
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.}"), I(0));
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.0}"), I(0));
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.42}"), I(0));
// *** locale-specific form ***
// See locale-specific_form.pass.cpp
// *** type ***
for (const auto& fmt : invalid_types<CharT>("bBcdoxX"))
check_exception(
"The format-spec type has a type not supported for an integer argument",
fmt, 42);
}
template <class I, class CharT, class TestFunction, class ExceptionTest>
void format_test_integer_as_char(TestFunction check,
ExceptionTest check_exception) {
// *** align-fill & width ***
check(STR("answer is '* '"), STR("answer is '{:6c}'"), I(42));
check(STR("answer is ' *'"), STR("answer is '{:>6c}'"), I(42));
check(STR("answer is '* '"), STR("answer is '{:<6c}'"), I(42));
check(STR("answer is ' * '"), STR("answer is '{:^6c}'"), I(42));
check(STR("answer is '-----*'"), STR("answer is '{:->6c}'"), I(42));
check(STR("answer is '*-----'"), STR("answer is '{:-<6c}'"), I(42));
check(STR("answer is '--*---'"), STR("answer is '{:-^6c}'"), I(42));
// *** Sign ***
check(STR("answer is *"), STR("answer is {:c}"), I(42));
check_exception("A sign field isn't allowed in this format-spec",
STR("answer is {:-c}"), I(42));
check_exception("A sign field isn't allowed in this format-spec",
STR("answer is {:+c}"), I(42));
check_exception("A sign field isn't allowed in this format-spec",
STR("answer is {: c}"), I(42));
// *** alternate form ***
check_exception("An alternate form field isn't allowed in this format-spec",
STR("answer is {:#c}"), I(42));
// *** zero-padding & width ***
check_exception("A zero-padding field isn't allowed in this format-spec",
STR("answer is {:01c}"), I(42));
// *** precision ***
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.c}"), I(0));
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.0c}"), I(0));
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.42c}"), I(0));
// *** locale-specific form ***
// Note it has no effect but it's allowed.
check(STR("answer is '*'"), STR("answer is '{:Lc}'"), I(42));
// *** type ***
for (const auto& fmt : invalid_types<CharT>("bBcdoxX"))
check_exception(
"The format-spec type has a type not supported for an integer argument",
fmt, I(42));
// *** Validate range ***
// TODO FMT Update test after adding 128-bit support.
if constexpr (sizeof(I) <= sizeof(long long)) {
// The code has some duplications to keep the if statement readable.
if constexpr (std::signed_integral<CharT>) {
if constexpr (std::signed_integral<I> && sizeof(I) > sizeof(CharT)) {
check_exception("Integral value outside the range of the char type",
STR("{:c}"), std::numeric_limits<I>::min());
check_exception("Integral value outside the range of the char type",
STR("{:c}"), std::numeric_limits<I>::max());
} else if constexpr (std::unsigned_integral<I> &&
sizeof(I) >= sizeof(CharT)) {
check_exception("Integral value outside the range of the char type",
STR("{:c}"), std::numeric_limits<I>::max());
}
} else if constexpr (sizeof(I) > sizeof(CharT)) {
check_exception("Integral value outside the range of the char type",
STR("{:c}"), std::numeric_limits<I>::max());
}
}
}
template <class I, class CharT, class TestFunction, class ExceptionTest>
void format_test_integer(TestFunction check, ExceptionTest check_exception) {
format_test_integer_as_integer<I, CharT>(check, check_exception);
format_test_integer_as_char<I, CharT>(check, check_exception);
}
template <class CharT, class TestFunction, class ExceptionTest>
void format_test_signed_integer(TestFunction check,
ExceptionTest check_exception) {
format_test_integer<signed char, CharT>(check, check_exception);
format_test_integer<short, CharT>(check, check_exception);
format_test_integer<int, CharT>(check, check_exception);
format_test_integer<long, CharT>(check, check_exception);
format_test_integer<long long, CharT>(check, check_exception);
#ifndef _LIBCPP_HAS_NO_INT128
format_test_integer<__int128_t, CharT>(check, check_exception);
#endif
// *** check the minma and maxima ***
check(STR("-0b10000000"), STR("{:#b}"), std::numeric_limits<int8_t>::min());
check(STR("-0200"), STR("{:#o}"), std::numeric_limits<int8_t>::min());
check(STR("-128"), STR("{:#}"), std::numeric_limits<int8_t>::min());
check(STR("-0x80"), STR("{:#x}"), std::numeric_limits<int8_t>::min());
check(STR("-0b1000000000000000"), STR("{:#b}"),
std::numeric_limits<int16_t>::min());
check(STR("-0100000"), STR("{:#o}"), std::numeric_limits<int16_t>::min());
check(STR("-32768"), STR("{:#}"), std::numeric_limits<int16_t>::min());
check(STR("-0x8000"), STR("{:#x}"), std::numeric_limits<int16_t>::min());
check(STR("-0b10000000000000000000000000000000"), STR("{:#b}"),
std::numeric_limits<int32_t>::min());
check(STR("-020000000000"), STR("{:#o}"),
std::numeric_limits<int32_t>::min());
check(STR("-2147483648"), STR("{:#}"), std::numeric_limits<int32_t>::min());
check(STR("-0x80000000"), STR("{:#x}"), std::numeric_limits<int32_t>::min());
check(STR("-0b100000000000000000000000000000000000000000000000000000000000000"
"0"),
STR("{:#b}"), std::numeric_limits<int64_t>::min());
check(STR("-01000000000000000000000"), STR("{:#o}"),
std::numeric_limits<int64_t>::min());
check(STR("-9223372036854775808"), STR("{:#}"),
std::numeric_limits<int64_t>::min());
check(STR("-0x8000000000000000"), STR("{:#x}"),
std::numeric_limits<int64_t>::min());
check(STR("0b1111111"), STR("{:#b}"), std::numeric_limits<int8_t>::max());
check(STR("0177"), STR("{:#o}"), std::numeric_limits<int8_t>::max());
check(STR("127"), STR("{:#}"), std::numeric_limits<int8_t>::max());
check(STR("0x7f"), STR("{:#x}"), std::numeric_limits<int8_t>::max());
check(STR("0b111111111111111"), STR("{:#b}"),
std::numeric_limits<int16_t>::max());
check(STR("077777"), STR("{:#o}"), std::numeric_limits<int16_t>::max());
check(STR("32767"), STR("{:#}"), std::numeric_limits<int16_t>::max());
check(STR("0x7fff"), STR("{:#x}"), std::numeric_limits<int16_t>::max());
check(STR("0b1111111111111111111111111111111"), STR("{:#b}"),
std::numeric_limits<int32_t>::max());
check(STR("017777777777"), STR("{:#o}"), std::numeric_limits<int32_t>::max());
check(STR("2147483647"), STR("{:#}"), std::numeric_limits<int32_t>::max());
check(STR("0x7fffffff"), STR("{:#x}"), std::numeric_limits<int32_t>::max());
check(
STR("0b111111111111111111111111111111111111111111111111111111111111111"),
STR("{:#b}"), std::numeric_limits<int64_t>::max());
check(STR("0777777777777777777777"), STR("{:#o}"),
std::numeric_limits<int64_t>::max());
check(STR("9223372036854775807"), STR("{:#}"),
std::numeric_limits<int64_t>::max());
check(STR("0x7fffffffffffffff"), STR("{:#x}"),
std::numeric_limits<int64_t>::max());
// TODO FMT Add __int128_t test after implementing full range.
}
template <class CharT, class TestFunction, class ExceptionTest>
void format_test_unsigned_integer(TestFunction check,
ExceptionTest check_exception) {
format_test_integer<unsigned char, CharT>(check, check_exception);
format_test_integer<unsigned short, CharT>(check, check_exception);
format_test_integer<unsigned, CharT>(check, check_exception);
format_test_integer<unsigned long, CharT>(check, check_exception);
format_test_integer<unsigned long long, CharT>(check, check_exception);
#ifndef _LIBCPP_HAS_NO_INT128
format_test_integer<__uint128_t, CharT>(check, check_exception);
#endif
// *** test the maxima ***
check(STR("0b11111111"), STR("{:#b}"), std::numeric_limits<uint8_t>::max());
check(STR("0377"), STR("{:#o}"), std::numeric_limits<uint8_t>::max());
check(STR("255"), STR("{:#}"), std::numeric_limits<uint8_t>::max());
check(STR("0xff"), STR("{:#x}"), std::numeric_limits<uint8_t>::max());
check(STR("0b1111111111111111"), STR("{:#b}"),
std::numeric_limits<uint16_t>::max());
check(STR("0177777"), STR("{:#o}"), std::numeric_limits<uint16_t>::max());
check(STR("65535"), STR("{:#}"), std::numeric_limits<uint16_t>::max());
check(STR("0xffff"), STR("{:#x}"), std::numeric_limits<uint16_t>::max());
check(STR("0b11111111111111111111111111111111"), STR("{:#b}"),
std::numeric_limits<uint32_t>::max());
check(STR("037777777777"), STR("{:#o}"),
std::numeric_limits<uint32_t>::max());
check(STR("4294967295"), STR("{:#}"), std::numeric_limits<uint32_t>::max());
check(STR("0xffffffff"), STR("{:#x}"), std::numeric_limits<uint32_t>::max());
check(
STR("0b1111111111111111111111111111111111111111111111111111111111111111"),
STR("{:#b}"), std::numeric_limits<uint64_t>::max());
check(STR("01777777777777777777777"), STR("{:#o}"),
std::numeric_limits<uint64_t>::max());
check(STR("18446744073709551615"), STR("{:#}"),
std::numeric_limits<uint64_t>::max());
check(STR("0xffffffffffffffff"), STR("{:#x}"),
std::numeric_limits<uint64_t>::max());
// TODO FMT Add __uint128_t test after implementing full range.
}
template <class CharT, class TestFunction, class ExceptionTest>
void format_test_char(TestFunction check, ExceptionTest check_exception) {
// ***** Char type *****
// *** align-fill & width ***
check(STR("answer is '* '"), STR("answer is '{:6}'"), CharT('*'));
check(STR("answer is ' *'"), STR("answer is '{:>6}'"), CharT('*'));
check(STR("answer is '* '"), STR("answer is '{:<6}'"), CharT('*'));
check(STR("answer is ' * '"), STR("answer is '{:^6}'"), CharT('*'));
check(STR("answer is '* '"), STR("answer is '{:6c}'"), CharT('*'));
check(STR("answer is ' *'"), STR("answer is '{:>6c}'"), CharT('*'));
check(STR("answer is '* '"), STR("answer is '{:<6c}'"), CharT('*'));
check(STR("answer is ' * '"), STR("answer is '{:^6c}'"), CharT('*'));
check(STR("answer is '-----*'"), STR("answer is '{:->6}'"), CharT('*'));
check(STR("answer is '*-----'"), STR("answer is '{:-<6}'"), CharT('*'));
check(STR("answer is '--*---'"), STR("answer is '{:-^6}'"), CharT('*'));
check(STR("answer is '-----*'"), STR("answer is '{:->6c}'"), CharT('*'));
check(STR("answer is '*-----'"), STR("answer is '{:-<6c}'"), CharT('*'));
check(STR("answer is '--*---'"), STR("answer is '{:-^6c}'"), CharT('*'));
// *** Sign ***
check_exception("A sign field isn't allowed in this format-spec", STR("{:-}"),
CharT('*'));
check_exception("A sign field isn't allowed in this format-spec", STR("{:+}"),
CharT('*'));
check_exception("A sign field isn't allowed in this format-spec", STR("{: }"),
CharT('*'));
check_exception("A sign field isn't allowed in this format-spec",
STR("{:-c}"), CharT('*'));
check_exception("A sign field isn't allowed in this format-spec",
STR("{:+c}"), CharT('*'));
check_exception("A sign field isn't allowed in this format-spec",
STR("{: c}"), CharT('*'));
// *** alternate form ***
check_exception("An alternate form field isn't allowed in this format-spec",
STR("{:#}"), CharT('*'));
check_exception("An alternate form field isn't allowed in this format-spec",
STR("{:#c}"), CharT('*'));
// *** zero-padding ***
check_exception("A zero-padding field isn't allowed in this format-spec",
STR("{:0}"), CharT('*'));
check_exception("A zero-padding field isn't allowed in this format-spec",
STR("{:0c}"), CharT('*'));
// *** precision ***
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.}"), CharT('*'));
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.0}"), CharT('*'));
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.42}"), CharT('*'));
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.c}"), CharT('*'));
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.0c}"), CharT('*'));
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.42c}"), CharT('*'));
// *** locale-specific form ***
// Note it has no effect but it's allowed.
check(STR("answer is '*'"), STR("answer is '{:L}'"), '*');
check(STR("answer is '*'"), STR("answer is '{:Lc}'"), '*');
// *** type ***
for (const auto& fmt : invalid_types<CharT>("bBcdoxX"))
check_exception(
"The format-spec type has a type not supported for a char argument",
fmt, CharT('*'));
}
template <class CharT, class TestFunction, class ExceptionTest>
void format_test_char_as_integer(TestFunction check,
ExceptionTest check_exception) {
// *** align-fill & width ***
check(STR("answer is '42'"), STR("answer is '{:<1d}'"), CharT('*'));
check(STR("answer is '42'"), STR("answer is '{:<2d}'"), CharT('*'));
check(STR("answer is '42 '"), STR("answer is '{:<3d}'"), CharT('*'));
check(STR("answer is ' 42'"), STR("answer is '{:7d}'"), CharT('*'));
check(STR("answer is ' 42'"), STR("answer is '{:>7d}'"), CharT('*'));
check(STR("answer is '42 '"), STR("answer is '{:<7d}'"), CharT('*'));
check(STR("answer is ' 42 '"), STR("answer is '{:^7d}'"), CharT('*'));
check(STR("answer is '*****42'"), STR("answer is '{:*>7d}'"), CharT('*'));
check(STR("answer is '42*****'"), STR("answer is '{:*<7d}'"), CharT('*'));
check(STR("answer is '**42***'"), STR("answer is '{:*^7d}'"), CharT('*'));
// Test whether zero padding is ignored
check(STR("answer is ' 42'"), STR("answer is '{:>07d}'"), CharT('*'));
check(STR("answer is '42 '"), STR("answer is '{:<07d}'"), CharT('*'));
check(STR("answer is ' 42 '"), STR("answer is '{:^07d}'"), CharT('*'));
// *** Sign ***
check(STR("answer is 42"), STR("answer is {:d}"), CharT('*'));
check(STR("answer is 42"), STR("answer is {:-d}"), CharT('*'));
check(STR("answer is +42"), STR("answer is {:+d}"), CharT('*'));
check(STR("answer is 42"), STR("answer is {: d}"), CharT('*'));
// *** alternate form ***
check(STR("answer is +42"), STR("answer is {:+#d}"), CharT('*'));
check(STR("answer is +101010"), STR("answer is {:+b}"), CharT('*'));
check(STR("answer is +0b101010"), STR("answer is {:+#b}"), CharT('*'));
check(STR("answer is +0B101010"), STR("answer is {:+#B}"), CharT('*'));
check(STR("answer is +52"), STR("answer is {:+o}"), CharT('*'));
check(STR("answer is +052"), STR("answer is {:+#o}"), CharT('*'));
check(STR("answer is +2a"), STR("answer is {:+x}"), CharT('*'));
check(STR("answer is +0x2a"), STR("answer is {:+#x}"), CharT('*'));
check(STR("answer is +2A"), STR("answer is {:+X}"), CharT('*'));
check(STR("answer is +0X2A"), STR("answer is {:+#X}"), CharT('*'));
// *** zero-padding & width ***
check(STR("answer is +00000000042"), STR("answer is {:+#012d}"), CharT('*'));
check(STR("answer is +00000101010"), STR("answer is {:+012b}"), CharT('*'));
check(STR("answer is +0b000101010"), STR("answer is {:+#012b}"), CharT('*'));
check(STR("answer is +0B000101010"), STR("answer is {:+#012B}"), CharT('*'));
check(STR("answer is +00000000052"), STR("answer is {:+012o}"), CharT('*'));
check(STR("answer is +00000000052"), STR("answer is {:+#012o}"), CharT('*'));
check(STR("answer is +0000000002a"), STR("answer is {:+012x}"), CharT('*'));
check(STR("answer is +0x00000002a"), STR("answer is {:+#012x}"), CharT('*'));
check(STR("answer is +0000000002A"), STR("answer is {:+012X}"), CharT('*'));
check(STR("answer is +0X00000002A"), STR("answer is {:+#012X}"), CharT('*'));
// *** precision ***
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.d}"), CharT('*'));
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.0d}"), CharT('*'));
check_exception("The format-spec should consume the input or end with a '}'",
STR("{:.42d}"), CharT('*'));
// *** locale-specific form ***
// See locale-specific_form.pass.cpp
// *** type ***
for (const auto& fmt : invalid_types<CharT>("bBcdoxX"))
check_exception(
"The format-spec type has a type not supported for a char argument",
fmt, '*');
}
template <class CharT, class TestFunction, class ExceptionTest>
void format_tests(TestFunction check, ExceptionTest check_exception) {
// *** Test escaping ***
check(STR("{"), STR("{{"));
check(STR("}"), STR("}}"));
// *** Test argument ID ***
check(STR("hello false true"), STR("hello {0:} {1:}"), false, true);
check(STR("hello true false"), STR("hello {1:} {0:}"), false, true);
// ** Test invalid format strings ***
check_exception("The format string terminates at a '{'", STR("{"));
check_exception("The replacement field misses a terminating '}'", STR("{:"),
42);
check_exception("The format string contains an invalid escape sequence",
STR("}"));
check_exception("The format string contains an invalid escape sequence",
STR("{:}-}"), 42);
check_exception("The format string contains an invalid escape sequence",
STR("} "));
check_exception(
"The arg-id of the format-spec starts with an invalid character",
STR("{-"), 42);
check_exception("Argument index out of bounds", STR("hello {}"));
check_exception("Argument index out of bounds", STR("hello {0}"));
check_exception("Argument index out of bounds", STR("hello {1}"), 42);
// *** Test char format argument ***
// The `char` to `wchar_t` formatting is tested separately.
check(STR("hello 09azAZ!"), STR("hello {}{}{}{}{}{}{}"), CharT('0'),
CharT('9'), CharT('a'), CharT('z'), CharT('A'), CharT('Z'), CharT('!'));
format_test_char<CharT>(check, check_exception);
format_test_char_as_integer<CharT>(check, check_exception);
// *** Test string format argument ***
{
CharT buffer[] = {CharT('0'), CharT('9'), CharT('a'), CharT('z'),
CharT('A'), CharT('Z'), CharT('!'), 0};
CharT* data = buffer;
check(STR("hello 09azAZ!"), STR("hello {}"), data);
}
{
CharT buffer[] = {CharT('0'), CharT('9'), CharT('a'), CharT('z'),
CharT('A'), CharT('Z'), CharT('!'), 0};
const CharT* data = buffer;
check(STR("hello 09azAZ!"), STR("hello {}"), data);
}
{
std::basic_string<CharT> data = STR("world");
check(STR("hello world"), STR("hello {}"), data);
}
{
std::basic_string<CharT> buffer = STR("world");
std::basic_string_view<CharT> data = buffer;
check(STR("hello world"), STR("hello {}"), data);
}
format_string_tests<CharT>(check, check_exception);
// *** Test Boolean format argument ***
check(STR("hello false true"), STR("hello {} {}"), false, true);
format_test_bool<CharT>(check, check_exception);
format_test_bool_as_char<CharT>(check, check_exception);
format_test_bool_as_integer<CharT>(check, check_exception);
// *** Test signed integral format argument ***
check(STR("hello 42"), STR("hello {}"), static_cast<signed char>(42));
check(STR("hello 42"), STR("hello {}"), static_cast<short>(42));
check(STR("hello 42"), STR("hello {}"), static_cast<int>(42));
check(STR("hello 42"), STR("hello {}"), static_cast<long>(42));
check(STR("hello 42"), STR("hello {}"), static_cast<long long>(42));
#ifndef _LIBCPP_HAS_NO_INT128
check(STR("hello 42"), STR("hello {}"), static_cast<__int128_t>(42));
{
// Note 128-bit support is only partly implemented test the range
// conditions here.
std::basic_string<CharT> min =
std::format(STR("{}"), std::numeric_limits<long long>::min());
check(min, STR("{}"),
static_cast<__int128_t>(std::numeric_limits<long long>::min()));
std::basic_string<CharT> max =
std::format(STR("{}"), std::numeric_limits<long long>::max());
check(max, STR("{}"),
static_cast<__int128_t>(std::numeric_limits<long long>::max()));
check_exception(
"128-bit value is outside of implemented range", STR("{}"),
static_cast<__int128_t>(std::numeric_limits<long long>::min()) - 1);
check_exception(
"128-bit value is outside of implemented range", STR("{}"),
static_cast<__int128_t>(std::numeric_limits<long long>::max()) + 1);
}
#endif
format_test_signed_integer<CharT>(check, check_exception);
// ** Test unsigned integral format argument ***
check(STR("hello 42"), STR("hello {}"), static_cast<unsigned char>(42));
check(STR("hello 42"), STR("hello {}"), static_cast<unsigned short>(42));
check(STR("hello 42"), STR("hello {}"), static_cast<unsigned>(42));
check(STR("hello 42"), STR("hello {}"), static_cast<unsigned long>(42));
check(STR("hello 42"), STR("hello {}"), static_cast<unsigned long long>(42));
#ifndef _LIBCPP_HAS_NO_INT128
check(STR("hello 42"), STR("hello {}"), static_cast<__uint128_t>(42));
{
// Note 128-bit support is only partly implemented test the range
// conditions here.
std::basic_string<CharT> max =
std::format(STR("{}"), std::numeric_limits<unsigned long long>::max());
check(max, STR("{}"),
static_cast<__uint128_t>(
std::numeric_limits<unsigned long long>::max()));
check_exception("128-bit value is outside of implemented range", STR("{}"),
static_cast<__uint128_t>(
std::numeric_limits<unsigned long long>::max()) +
1);
}
#endif
format_test_unsigned_integer<CharT>(check, check_exception);
// *** Test floating point format argument ***
// TODO FMT Enable after floating-point support has been enabled
#if 0
check(STR("hello 42.000000"), STR("hello {}"), static_cast<float>(42));
check(STR("hello 42.000000"), STR("hello {}"), static_cast<double>(42));
check(STR("hello 42.000000"), STR("hello {}"), static_cast<long double>(42));
#endif
}
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
template <class TestFunction>
void format_tests_char_to_wchar_t(TestFunction check) {
using CharT = wchar_t;
check(STR("hello 09azA"), STR("hello {}{}{}{}{}"), '0', '9', 'a', 'z', 'A');
}
#endif
#endif