From 39411504a55a51790b728c5da3923726b9aead19 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sat, 18 Nov 2017 07:42:54 -0800 Subject: [PATCH] More tests --- include/fmt/format.h | 51 ++++++++++++----------------- test/format-test.cc | 76 ++++++++++++++++++++++++++++---------------- test/ostream-test.cc | 12 +++---- 3 files changed, 74 insertions(+), 65 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index 0b74fb66..74b78cda 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -2192,32 +2192,32 @@ class specs_checker : public Handler { constexpr void on_align(alignment align) { if (align == ALIGN_NUMERIC) - require_numeric_argument('='); + require_numeric_argument(); Handler::on_align(align); } constexpr void on_plus() { - check_sign('+'); + check_sign(); Handler::on_plus(); } constexpr void on_minus() { - check_sign('-'); + check_sign(); Handler::on_minus(); } constexpr void on_space() { - check_sign(' '); + check_sign(); Handler::on_space(); } constexpr void on_hash() { - require_numeric_argument('#'); + require_numeric_argument(); Handler::on_hash(); } constexpr void on_zero() { - require_numeric_argument('0'); + require_numeric_argument(); Handler::on_zero(); } @@ -2227,26 +2227,16 @@ class specs_checker : public Handler { } private: - template - void report_error(string_view format_str, const Args &... args) { - this->on_error(format(format_str, args...).c_str()); + constexpr void require_numeric_argument() { + if (!is_numeric(arg_type_)) + this->on_error("format specifier requires numeric argument"); } - template - constexpr void require_numeric_argument(Char spec) { - if (!is_numeric(arg_type_)) { - report_error("format specifier '{}' requires numeric argument", - static_cast(spec)); - } - } - - template - constexpr void check_sign(Char sign) { - require_numeric_argument(sign); + constexpr void check_sign() { + require_numeric_argument(); if (is_integral(arg_type_) && arg_type_ != INT && arg_type_ != LONG_LONG && arg_type_ != CHAR) { - report_error("format specifier '{}' requires signed argument", - static_cast(sign)); + this->on_error("format specifier requires signed argument"); } } @@ -2636,7 +2626,7 @@ class format_string_checker : public ErrorHandler { constexpr const Char *on_format_specs(const Char *s) { parse_context_type ctx(basic_string_view(s, end_ - s), *this); - return parse_funcs_[arg_index_](ctx); + return arg_index_ < NUM_ARGS ? parse_funcs_[arg_index_](ctx) : s; } private: @@ -3200,9 +3190,9 @@ void basic_writer::write_int(T value, const Spec& spec) { unsigned_type abs_value; char prefix[4] = ""; - spec_handler(basic_writer &w, T value, const Spec& s) - : writer(w), spec(s), abs_value(static_cast(value)) { - if (internal::is_negative(value)) { + spec_handler(basic_writer &w, T val, const Spec& s) + : writer(w), spec(s), abs_value(static_cast(val)) { + if (internal::is_negative(val)) { prefix[0] = '-'; ++prefix_size; abs_value = 0 - abs_value; @@ -3769,10 +3759,9 @@ struct formatter< handler(handler_type(specs_, ctx), internal::get_type()); it = parse_format_specs(it, handler); if (std::is_integral::value) { - using type_checker = - internal::int_type_checker; + auto eh = ctx.error_handler(); handle_integral_type_spec( - specs_.type(), type_checker(ctx.error_handler())); + specs_.type(), internal::int_type_checker(eh)); } return pointer_from(it); } @@ -3887,9 +3876,9 @@ void vformat_to(basic_buffer &buffer, basic_string_view format_str, using iterator = internal::null_terminating_iterator; struct handler : internal::error_handler { - handler(basic_buffer &b, basic_string_view format_str, + handler(basic_buffer &b, basic_string_view str, basic_args args) - : buffer(b), context(format_str, args) {} + : buffer(b), context(str, args) {} void on_text(iterator begin, iterator end) { buffer.append(pointer_from(begin), pointer_from(end)); diff --git a/test/format-test.cc b/test/format-test.cc index 55dd8832..13c39692 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -563,9 +563,9 @@ TEST(FormatterTest, NumericAlign) { EXPECT_THROW_MSG(format("{0:=5}", 'c'), format_error, "invalid format specifier for char"); EXPECT_THROW_MSG(format("{0:=5}", "abc"), - format_error, "format specifier '=' requires numeric argument"); + format_error, "format specifier requires numeric argument"); EXPECT_THROW_MSG(format("{0:=8}", reinterpret_cast(0xface)), - format_error, "format specifier '=' requires numeric argument"); + format_error, "format specifier requires numeric argument"); } TEST(FormatterTest, CenterAlign) { @@ -609,13 +609,13 @@ TEST(FormatterTest, PlusSign) { EXPECT_EQ("-42", format("{0:+}", -42)); EXPECT_EQ("+42", format("{0:+}", 42)); EXPECT_THROW_MSG(format("{0:+}", 42u), - format_error, "format specifier '+' requires signed argument"); + format_error, "format specifier requires signed argument"); EXPECT_EQ("+42", format("{0:+}", 42l)); EXPECT_THROW_MSG(format("{0:+}", 42ul), - format_error, "format specifier '+' requires signed argument"); + format_error, "format specifier requires signed argument"); EXPECT_EQ("+42", format("{0:+}", 42ll)); EXPECT_THROW_MSG(format("{0:+}", 42ull), - format_error, "format specifier '+' requires signed argument"); + format_error, "format specifier requires signed argument"); EXPECT_EQ("+42", format("{0:+}", 42.0)); EXPECT_EQ("+42", format("{0:+}", 42.0l)); EXPECT_THROW_MSG(format("{0:+", 'c'), @@ -623,9 +623,9 @@ TEST(FormatterTest, PlusSign) { EXPECT_THROW_MSG(format("{0:+}", 'c'), format_error, "invalid format specifier for char"); EXPECT_THROW_MSG(format("{0:+}", "abc"), - format_error, "format specifier '+' requires numeric argument"); + format_error, "format specifier requires numeric argument"); EXPECT_THROW_MSG(format("{0:+}", reinterpret_cast(0x42)), - format_error, "format specifier '+' requires numeric argument"); + format_error, "format specifier requires numeric argument"); } TEST(FormatterTest, MinusSign) { @@ -633,13 +633,13 @@ TEST(FormatterTest, MinusSign) { EXPECT_EQ("-42", format("{0:-}", -42)); EXPECT_EQ("42", format("{0:-}", 42)); EXPECT_THROW_MSG(format("{0:-}", 42u), - format_error, "format specifier '-' requires signed argument"); + format_error, "format specifier requires signed argument"); EXPECT_EQ("42", format("{0:-}", 42l)); EXPECT_THROW_MSG(format("{0:-}", 42ul), - format_error, "format specifier '-' requires signed argument"); + format_error, "format specifier requires signed argument"); EXPECT_EQ("42", format("{0:-}", 42ll)); EXPECT_THROW_MSG(format("{0:-}", 42ull), - format_error, "format specifier '-' requires signed argument"); + format_error, "format specifier requires signed argument"); EXPECT_EQ("42", format("{0:-}", 42.0)); EXPECT_EQ("42", format("{0:-}", 42.0l)); EXPECT_THROW_MSG(format("{0:-", 'c'), @@ -647,9 +647,9 @@ TEST(FormatterTest, MinusSign) { EXPECT_THROW_MSG(format("{0:-}", 'c'), format_error, "invalid format specifier for char"); EXPECT_THROW_MSG(format("{0:-}", "abc"), - format_error, "format specifier '-' requires numeric argument"); + format_error, "format specifier requires numeric argument"); EXPECT_THROW_MSG(format("{0:-}", reinterpret_cast(0x42)), - format_error, "format specifier '-' requires numeric argument"); + format_error, "format specifier requires numeric argument"); } TEST(FormatterTest, SpaceSign) { @@ -657,13 +657,13 @@ TEST(FormatterTest, SpaceSign) { EXPECT_EQ("-42", format("{0: }", -42)); EXPECT_EQ(" 42", format("{0: }", 42)); EXPECT_THROW_MSG(format("{0: }", 42u), - format_error, "format specifier ' ' requires signed argument"); + format_error, "format specifier requires signed argument"); EXPECT_EQ(" 42", format("{0: }", 42l)); EXPECT_THROW_MSG(format("{0: }", 42ul), - format_error, "format specifier ' ' requires signed argument"); + format_error, "format specifier requires signed argument"); EXPECT_EQ(" 42", format("{0: }", 42ll)); EXPECT_THROW_MSG(format("{0: }", 42ull), - format_error, "format specifier ' ' requires signed argument"); + format_error, "format specifier requires signed argument"); EXPECT_EQ(" 42", format("{0: }", 42.0)); EXPECT_EQ(" 42", format("{0: }", 42.0l)); EXPECT_THROW_MSG(format("{0: ", 'c'), @@ -671,9 +671,9 @@ TEST(FormatterTest, SpaceSign) { EXPECT_THROW_MSG(format("{0: }", 'c'), format_error, "invalid format specifier for char"); EXPECT_THROW_MSG(format("{0: }", "abc"), - format_error, "format specifier ' ' requires numeric argument"); + format_error, "format specifier requires numeric argument"); EXPECT_THROW_MSG(format("{0: }", reinterpret_cast(0x42)), - format_error, "format specifier ' ' requires numeric argument"); + format_error, "format specifier requires numeric argument"); } TEST(FormatterTest, HashFlag) { @@ -716,9 +716,9 @@ TEST(FormatterTest, HashFlag) { EXPECT_THROW_MSG(format("{0:#}", 'c'), format_error, "invalid format specifier for char"); EXPECT_THROW_MSG(format("{0:#}", "abc"), - format_error, "format specifier '#' requires numeric argument"); + format_error, "format specifier requires numeric argument"); EXPECT_THROW_MSG(format("{0:#}", reinterpret_cast(0x42)), - format_error, "format specifier '#' requires numeric argument"); + format_error, "format specifier requires numeric argument"); } TEST(FormatterTest, ZeroFlag) { @@ -736,9 +736,9 @@ TEST(FormatterTest, ZeroFlag) { EXPECT_THROW_MSG(format("{0:05}", 'c'), format_error, "invalid format specifier for char"); EXPECT_THROW_MSG(format("{0:05}", "abc"), - format_error, "format specifier '0' requires numeric argument"); + format_error, "format specifier requires numeric argument"); EXPECT_THROW_MSG(format("{0:05}", reinterpret_cast(0x42)), - format_error, "format specifier '0' requires numeric argument"); + format_error, "format specifier requires numeric argument"); } TEST(FormatterTest, Width) { @@ -1566,17 +1566,17 @@ TEST(FormatTest, DynamicFormatter) { EXPECT_THROW_MSG(format("{:{0}}", num), format_error, "cannot switch from automatic to manual argument indexing"); EXPECT_THROW_MSG(format("{:=}", str), - format_error, "format specifier '=' requires numeric argument"); + format_error, "format specifier requires numeric argument"); EXPECT_THROW_MSG(format("{:+}", str), - format_error, "format specifier '+' requires numeric argument"); + format_error, "format specifier requires numeric argument"); EXPECT_THROW_MSG(format("{:-}", str), - format_error, "format specifier '-' requires numeric argument"); + format_error, "format specifier requires numeric argument"); EXPECT_THROW_MSG(format("{: }", str), - format_error, "format specifier ' ' requires numeric argument"); + format_error, "format specifier requires numeric argument"); EXPECT_THROW_MSG(format("{:#}", str), - format_error, "format specifier '#' requires numeric argument"); + format_error, "format specifier requires numeric argument"); EXPECT_THROW_MSG(format("{:0}", str), - format_error, "format specifier '=' requires numeric argument"); + format_error, "format specifier requires numeric argument"); EXPECT_THROW_MSG(format("{:.2}", num), format_error, "precision not allowed for this argument type"); } @@ -1705,6 +1705,8 @@ struct test_context { constexpr unsigned next_arg_index(const char *&) { return 33; } void on_error(const char *) {} + + constexpr test_context error_handler() { return *this; } }; constexpr fmt::format_specs parse_specs(const char *s) { @@ -1872,15 +1874,33 @@ TEST(FormatTest, FormatStringErrors) { EXPECT_ERROR("{:{<}", "invalid fill character '{'", int); EXPECT_ERROR("{:10000000000}", "number is too big", int); EXPECT_ERROR("{:.10000000000}", "number is too big", int); + EXPECT_ERROR("{:x}", "argument index out of range"); + EXPECT_ERROR("{:=}", "format specifier requires numeric argument", + const char *); #endif EXPECT_ERROR("{foo", "missing '}' in format string", int); EXPECT_ERROR("{10000000000}", "number is too big"); EXPECT_ERROR("{0x}", "invalid format string"); EXPECT_ERROR("{-}", "invalid format string"); - EXPECT_ERROR("{1}", "argument index out of range", int); EXPECT_ERROR("{:{0x}}", "invalid format string", int); EXPECT_ERROR("{:{-}}", "invalid format string", int); EXPECT_ERROR("{:.{0x}}", "invalid format string", int); EXPECT_ERROR("{:.{-}}", "invalid format string", int); EXPECT_ERROR("{:.x}", "missing precision specifier", int); + EXPECT_ERROR("{}", "argument index out of range"); + EXPECT_ERROR("{1}", "argument index out of range", int); + EXPECT_ERROR("{:+}", "format specifier requires numeric argument", + const char *); + EXPECT_ERROR("{:-}", "format specifier requires numeric argument", + const char *); + EXPECT_ERROR("{:#}", "format specifier requires numeric argument", + const char *); + EXPECT_ERROR("{: }", "format specifier requires numeric argument", + const char *); + EXPECT_ERROR("{:0}", "format specifier requires numeric argument", + const char *); + EXPECT_ERROR("{:+}", "format specifier requires signed argument", unsigned); + EXPECT_ERROR("{:-}", "format specifier requires signed argument", unsigned); + EXPECT_ERROR("{: }", "format specifier requires signed argument", unsigned); + EXPECT_ERROR("{:.2}", "precision not allowed for this argument type", int); } diff --git a/test/ostream-test.cc b/test/ostream-test.cc index cff83272..cb18388b 100644 --- a/test/ostream-test.cc +++ b/test/ostream-test.cc @@ -85,19 +85,19 @@ TEST(OStreamTest, FormatSpecs) { EXPECT_EQ("def ", format("{0:<5}", TestString("def"))); EXPECT_EQ(" def", format("{0:>5}", TestString("def"))); EXPECT_THROW_MSG(format("{0:=5}", TestString("def")), - format_error, "format specifier '=' requires numeric argument"); + format_error, "format specifier requires numeric argument"); EXPECT_EQ(" def ", format("{0:^5}", TestString("def"))); EXPECT_EQ("def**", format("{0:*<5}", TestString("def"))); EXPECT_THROW_MSG(format("{0:+}", TestString()), - format_error, "format specifier '+' requires numeric argument"); + format_error, "format specifier requires numeric argument"); EXPECT_THROW_MSG(format("{0:-}", TestString()), - format_error, "format specifier '-' requires numeric argument"); + format_error, "format specifier requires numeric argument"); EXPECT_THROW_MSG(format("{0: }", TestString()), - format_error, "format specifier ' ' requires numeric argument"); + format_error, "format specifier requires numeric argument"); EXPECT_THROW_MSG(format("{0:#}", TestString()), - format_error, "format specifier '#' requires numeric argument"); + format_error, "format specifier requires numeric argument"); EXPECT_THROW_MSG(format("{0:05}", TestString()), - format_error, "format specifier '0' requires numeric argument"); + format_error, "format specifier requires numeric argument"); EXPECT_EQ("test ", format("{0:13}", TestString("test"))); EXPECT_EQ("test ", format("{0:{1}}", TestString("test"), 13)); EXPECT_EQ("te", format("{0:.2}", TestString("test")));