Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
193 changes: 84 additions & 109 deletions tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,16 @@
using namespace std;
using namespace chrono;

// copied from the string_view tests
template <typename CharT>
struct choose_literal; // not defined

template <>
struct choose_literal<char> {
static constexpr const char* choose(const char* s, const wchar_t*) {
return s;
}
};

template <>
struct choose_literal<wchar_t> {
static constexpr const wchar_t* choose(const char*, const wchar_t* s) {
return s;
[[nodiscard]] constexpr const CharT* choose_literal(const char* const str, const wchar_t* const wstr) noexcept {
if constexpr (is_same_v<CharT, char>) {
return str;
} else {
return wstr;
}
};
}

#define TYPED_LITERAL(CharT, Literal) (choose_literal<CharT>::choose(Literal, L##Literal))
#define STR(Literal) TYPED_LITERAL(CharT, Literal)
#define STR(Literal) (choose_literal<CharT>(Literal, L##Literal))

template <typename CharT>
struct testing_callbacks {
Expand Down Expand Up @@ -110,13 +100,13 @@ bool test_parse_conversion_spec() {
using view_typ = basic_string_view<CharT>;
using chrono_spec = _Chrono_spec<CharT>;

view_typ s0(TYPED_LITERAL(CharT, "B"));
view_typ s1(TYPED_LITERAL(CharT, "Ec"));
view_typ s2(TYPED_LITERAL(CharT, "Od"));
view_typ s3(TYPED_LITERAL(CharT, "E"));
view_typ s4(TYPED_LITERAL(CharT, ""));
view_typ s5(TYPED_LITERAL(CharT, "}"));
view_typ s6(TYPED_LITERAL(CharT, "E}"));
view_typ s0(STR("B"));
view_typ s1(STR("Ec"));
view_typ s2(STR("Od"));
view_typ s3(STR("E"));
view_typ s4(STR(""));
view_typ s5(STR("}"));
view_typ s6(STR("E}"));

vector<chrono_spec> v0{{._Type = 'B'}};
test_parse_helper(parse_conv_spec_fn, s0, false, view_typ::npos, {.expected_chrono_specs = v0});
Expand All @@ -142,15 +132,15 @@ bool test_parse_chrono_format_specs() {
using view_typ = basic_string_view<CharT>;
using chrono_spec = _Chrono_spec<CharT>;

view_typ s0(TYPED_LITERAL(CharT, "%Oe"));
view_typ s1(TYPED_LITERAL(CharT, "lit"));
view_typ s2(TYPED_LITERAL(CharT, "%H:%M}"));
view_typ s3(TYPED_LITERAL(CharT, "6%H}"));
view_typ s4(TYPED_LITERAL(CharT, "*<6hi"));
view_typ s5(TYPED_LITERAL(CharT, "*^4.4%ymm"));
view_typ s6(TYPED_LITERAL(CharT, "%H%"));
view_typ s7(TYPED_LITERAL(CharT, "%H%}"));
view_typ s8(TYPED_LITERAL(CharT, "%nB%tC%%D"));
view_typ s0(STR("%Oe"));
view_typ s1(STR("lit"));
view_typ s2(STR("%H:%M}"));
view_typ s3(STR("6%H}"));
view_typ s4(STR("*<6hi"));
view_typ s5(STR("*^4.4%ymm"));
view_typ s6(STR("%H%"));
view_typ s7(STR("%H%}"));
view_typ s8(STR("%nB%tC%%D"));

vector<chrono_spec> v0{{._Modifier = 'O', ._Type = 'e'}};
test_parse_helper(parse_chrono_format_specs_fn, s0, false, s0.size(), {.expected_chrono_specs = v0});
Expand All @@ -172,14 +162,14 @@ bool test_parse_chrono_format_specs() {
vector<chrono_spec> v4{{._Lit_char = 'h'}, {._Lit_char = 'i'}};
test_parse_helper(parse_chrono_format_specs_fn, s4, true, s4.size(),
{.expected_alignment = _Fmt_align::_Left,
.expected_fill = view_typ(TYPED_LITERAL(CharT, "*")),
.expected_fill = view_typ(STR("*")),
.expected_width = 6,
.expected_chrono_specs = v4});

vector<chrono_spec> v5{{._Type = 'y'}, {._Lit_char = 'm'}, {._Lit_char = 'm'}};
test_parse_helper(parse_chrono_format_specs_fn, s5, false, s5.size(),
{.expected_alignment = _Fmt_align::_Center,
.expected_fill = view_typ(TYPED_LITERAL(CharT, "*")),
.expected_fill = view_typ(STR("*")),
.expected_width = 4,
.expected_precision = 4,
.expected_chrono_specs = v5});
Expand All @@ -205,22 +195,17 @@ void throw_helper(const CharT* fmt, const Args&... vals) {
throw_helper(basic_string_view<CharT>{fmt}, vals...);
}

template <class CharT, class... Args>
void stream_helper(const CharT* expect, const Args&... vals) {
basic_ostringstream<CharT> stream;
(stream << ... << vals);
assert(stream.str() == expect);
assert(stream);
}

template <class Arg, class CharT>
void empty_braces_helper(const Arg& val, const CharT* const expected) {
// N4885 [time.format]/6: "If the chrono-specs is omitted, the chrono object is formatted
// as if by streaming it to std::ostringstream os and copying os.str() through the output iterator
// of the context with additional padding and adjustments as specified by the format specifiers."
assert(format(STR("{}"), val) == expected);

stream_helper(expected, val);
basic_ostringstream<CharT> stream;
stream << val;
assert(stream.str() == expected);
assert(stream);
}

// FIXME: TEMPORARY CODE FOR WRITING TESTS, REMOVE BEFORE MERGING
Expand All @@ -235,13 +220,13 @@ constexpr void print(Str str) {

template <typename CharT>
void test_clock_formatter() {
stream_helper(STR("1970-01-01 00:00:00"), sys_seconds{});
stream_helper(STR("1970-01-01"), sys_days{});
stream_helper(STR("1970-01-01 00:00:00"), utc_seconds{});
stream_helper(STR("1958-01-01 00:00:00"), tai_seconds{});
stream_helper(STR("1980-01-06 00:00:00"), gps_seconds{});
stream_helper(STR("1601-01-01 00:00:00"), file_time<seconds>{});
stream_helper(STR("1970-01-01 00:00:00"), local_seconds{});
empty_braces_helper(sys_seconds{}, STR("1970-01-01 00:00:00"));
empty_braces_helper(sys_days{}, STR("1970-01-01"));
empty_braces_helper(utc_seconds{}, STR("1970-01-01 00:00:00"));
empty_braces_helper(tai_seconds{}, STR("1958-01-01 00:00:00"));
empty_braces_helper(gps_seconds{}, STR("1980-01-06 00:00:00"));
empty_braces_helper(file_time<seconds>{}, STR("1601-01-01 00:00:00"));
empty_braces_helper(local_seconds{}, STR("1970-01-01 00:00:00"));

assert(format(STR("{:%Z %z %Oz %Ez}"), sys_seconds{}) == STR("UTC +0000 +00:00 +00:00"));
assert(format(STR("{:%Z %z %Oz %Ez}"), sys_days{}) == STR("UTC +0000 +00:00 +00:00"));
Expand All @@ -259,25 +244,25 @@ void test_day_formatter() {
using view_typ = basic_string_view<CharT>;
using str_typ = basic_string<CharT>;

view_typ s0(TYPED_LITERAL(CharT, "{:%d}"));
view_typ s1(TYPED_LITERAL(CharT, "{:%e}"));
view_typ s2(TYPED_LITERAL(CharT, "{:%Od}"));
view_typ s3(TYPED_LITERAL(CharT, "{:%Oe}"));
view_typ s4(TYPED_LITERAL(CharT, "{}"));
view_typ s5(TYPED_LITERAL(CharT, "{:=>8}"));
view_typ s6(TYPED_LITERAL(CharT, "{:lit}"));
view_typ s7(TYPED_LITERAL(CharT, "{:%d days}"));
view_typ s8(TYPED_LITERAL(CharT, "{:*^6%dmm}"));

str_typ a0(TYPED_LITERAL(CharT, "27"));
str_typ a1(TYPED_LITERAL(CharT, "05"));
str_typ a2(TYPED_LITERAL(CharT, " 5"));
str_typ a3(TYPED_LITERAL(CharT, "50 is not a valid day"));
str_typ a4(TYPED_LITERAL(CharT, "======27"));
str_typ a5(TYPED_LITERAL(CharT, "======05"));
str_typ a6(TYPED_LITERAL(CharT, "lit27"));
str_typ a7(TYPED_LITERAL(CharT, "27 days"));
str_typ a8(TYPED_LITERAL(CharT, "*27mm*"));
view_typ s0(STR("{:%d}"));
view_typ s1(STR("{:%e}"));
view_typ s2(STR("{:%Od}"));
view_typ s3(STR("{:%Oe}"));
view_typ s4(STR("{}"));
view_typ s5(STR("{:=>8}"));
view_typ s6(STR("{:lit}"));
view_typ s7(STR("{:%d days}"));
view_typ s8(STR("{:*^6%dmm}"));

str_typ a0(STR("27"));
str_typ a1(STR("05"));
str_typ a2(STR(" 5"));
str_typ a3(STR("50 is not a valid day"));
str_typ a4(STR("======27"));
str_typ a5(STR("======05"));
str_typ a6(STR("lit27"));
str_typ a7(STR("27 days"));
str_typ a8(STR("*27mm*"));

// 2 digits
day d0{27};
Expand Down Expand Up @@ -332,20 +317,19 @@ void test_day_formatter() {
throw_helper(STR("{:%Ed}"), day{10});
throw_helper(STR("{:%Od}"), day{40});
throw_helper(STR("{:%Ed}"), day{40});
assert(format(STR("{}"), day{0}) == STR("00 is not a valid day"));

// Op <<
stream_helper(STR("00 is not a valid day"), day{0});
stream_helper(STR("27"), day{27});
stream_helper(STR("200 is not a valid day"), day{200});
empty_braces_helper(day{0}, STR("00 is not a valid day"));
empty_braces_helper(day{27}, STR("27"));
empty_braces_helper(day{200}, STR("200 is not a valid day"));
}

template <typename CharT>
void test_month_formatter() {
assert(format(STR("{}"), month{1}) == STR("Jan"));
assert(format(STR("{}"), month{12}) == STR("Dec"));
assert(format(STR("{}"), month{0}) == STR("0 is not a valid month"));
assert(format(STR("{}"), month{20}) == STR("20 is not a valid month"));
empty_braces_helper(month{1}, STR("Jan"));
empty_braces_helper(month{12}, STR("Dec"));
empty_braces_helper(month{0}, STR("0 is not a valid month"));
empty_braces_helper(month{20}, STR("20 is not a valid month"));

// Specs
assert(format(STR("{:%b %h %B}"), month{1}) == STR("Jan Jan January"));
Expand All @@ -360,35 +344,28 @@ void test_month_formatter() {
// Invalid specs
throw_helper(STR("{:%A}"), month{1});
throw_helper(STR("{:%.4}"), month{1});

// Op <<
stream_helper(STR("Jan"), month{1});
stream_helper(STR("Dec"), month{12});
stream_helper(STR("0 is not a valid month"), month{0});
stream_helper(STR("20 is not a valid month"), month{20});
}

template <typename CharT>
void test_year_formatter() {
assert(format(STR("{}"), year{0}) == STR("0000"));
assert(format(STR("{}"), year{-200}) == STR("-0200"));
assert(format(STR("{}"), year{121}) == STR("0121"));
empty_braces_helper(year{0}, STR("0000"));
empty_braces_helper(year{-200}, STR("-0200"));
empty_braces_helper(year{121}, STR("0121"));

assert(format(STR("{:%Y %y%C}"), year{1912}) == STR("1912 1219"));
assert(format(STR("{:%Y %y%C}"), year{-1912}) == STR("-1912 88-20"));
// TRANSITION, add tests for EY Oy Ey EC

stream_helper(STR("1900"), year{1900});
stream_helper(STR("2000"), year{2000});
stream_helper(STR("-32768 is not a valid year"), year{-32768});
empty_braces_helper(year{1900}, STR("1900"));
empty_braces_helper(year{2000}, STR("2000"));
empty_braces_helper(year{-32768}, STR("-32768 is not a valid year"));
}

template <typename CharT>
void test_weekday_formatter() {
weekday invalid{10};
assert(format(STR("{}"), weekday{3}) == STR("Wed"));
stream_helper(STR("Wed"), weekday{3});
stream_helper(STR("10 is not a valid weekday"), invalid);
empty_braces_helper(weekday{3}, STR("Wed"));
empty_braces_helper(invalid, STR("10 is not a valid weekday"));

assert(format(STR("{:%a %A}"), weekday{6}) == STR("Sat Saturday"));
assert(format(STR("{:%u %w}"), weekday{6}) == STR("6 6"));
Expand All @@ -400,11 +377,10 @@ void test_weekday_indexed_formatter() {
weekday_indexed invalid1{Tuesday, 10};
weekday_indexed invalid2{weekday{10}, 3};
weekday_indexed invalid3{weekday{14}, 9};
assert(format(STR("{}"), weekday_indexed{Monday, 1}) == STR("Mon[1]"));
stream_helper(STR("Mon[1]"), weekday_indexed{Monday, 1});
stream_helper(STR("Tue[10 is not a valid index]"), invalid1);
stream_helper(STR("10 is not a valid weekday[3]"), invalid2);
stream_helper(STR("14 is not a valid weekday[9 is not a valid index]"), invalid3);
empty_braces_helper(weekday_indexed{Monday, 1}, STR("Mon[1]"));
empty_braces_helper(invalid1, STR("Tue[10 is not a valid index]"));
empty_braces_helper(invalid2, STR("10 is not a valid weekday[3]"));
empty_braces_helper(invalid3, STR("14 is not a valid weekday[9 is not a valid index]"));

assert(format(STR("{:%a %A}"), weekday_indexed{Monday, 2}) == STR("Mon Monday"));
assert(format(STR("{:%u %w}"), weekday_indexed{Tuesday, 3}) == STR("2 2"));
Expand All @@ -424,16 +400,16 @@ void test_weekday_last_formatter() {

template <typename CharT>
void test_month_day_formatter() {
stream_helper(STR("Jan/16"), January / 16);
stream_helper(STR("13 is not a valid month/40 is not a valid day"), month{13} / day{40});
empty_braces_helper(January / 16, STR("Jan/16"));
empty_braces_helper(month{13} / day{40}, STR("13 is not a valid month/40 is not a valid day"));

assert(format(STR("{:%B %d}"), June / 17) == STR("June 17"));
throw_helper(STR("{:%Y}"), June / 17);
}

template <typename CharT>
void test_month_day_last_formatter() {
stream_helper(STR("Feb/last"), February / last);
empty_braces_helper(February / last, STR("Feb/last"));

assert(format(STR("{:%B}"), June / last) == STR("June"));
assert(format(STR("{:%d}"), June / last) == STR("30"));
Expand Down Expand Up @@ -484,7 +460,7 @@ void test_month_weekday_last_formatter() {

template <typename CharT>
void test_year_month_formatter() {
stream_helper(STR("1444/Oct"), 1444y / October);
empty_braces_helper(1444y / October, STR("1444/Oct"));

assert(format(STR("{:%Y %B}"), 2000y / July) == STR("2000 July"));
throw_helper(STR("{:%d}"), 2000y / July);
Expand All @@ -493,9 +469,8 @@ void test_year_month_formatter() {
template <typename CharT>
void test_year_month_day_formatter() {
year_month_day invalid{year{1234}, month{0}, day{31}};
assert(format(STR("{}"), year_month_day{year{1900}, month{2}, day{1}}) == STR("1900-02-01"));
stream_helper(STR("1900-02-01"), year_month_day{year{1900}, month{2}, day{1}});
stream_helper(STR("1234-00-31 is not a valid date"), invalid);
empty_braces_helper(year_month_day{year{1900}, month{2}, day{1}}, STR("1900-02-01"));
empty_braces_helper(invalid, STR("1234-00-31 is not a valid date"));

assert(format(STR("{:%Y %b %d}"), year_month_day{year{1234}, month{5}, day{6}}) == STR("1234 May 06"));
assert(format(STR("{:%F %D}"), invalid) == STR("1234-00-31 00/31/34"));
Expand Down Expand Up @@ -566,10 +541,10 @@ void test_year_month_weekday_last_formatter() {

template <typename CharT>
void test_hh_mm_ss_formatter() {
stream_helper(STR("-01:08:03.007"), hh_mm_ss{-4083007ms});
stream_helper(STR("01:08:03.007"), hh_mm_ss{4083007ms});
stream_helper(STR("18:15:45.123"), hh_mm_ss{65745123ms});
stream_helper(STR("18:15:45"), hh_mm_ss{65745s});
empty_braces_helper(hh_mm_ss{-4083007ms}, STR("-01:08:03.007"));
empty_braces_helper(hh_mm_ss{4083007ms}, STR("01:08:03.007"));
empty_braces_helper(hh_mm_ss{65745123ms}, STR("18:15:45.123"));
empty_braces_helper(hh_mm_ss{65745s}, STR("18:15:45"));

assert(format(STR("{:%H %I %M %S %r %R %T %p}"), hh_mm_ss{13h + 14min + 15351ms})
== STR("13 01 14 15.351 13:14:15 13:14 13:14:15.351 PM"));
Expand Down