From a6408a3b09021a8170b6abf0f526f27487fe7af7 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Thu, 18 Mar 2021 09:04:17 -0700 Subject: [PATCH] Add args-test --- test/CMakeLists.txt | 1 + test/args-test.cc | 149 ++++++++++++++++++++++++++++++++++++++++++++ test/core-test.cc | 141 +---------------------------------------- 3 files changed, 151 insertions(+), 140 deletions(-) create mode 100644 test/args-test.cc diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b4ba9794..fb920746 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -87,6 +87,7 @@ function(add_fmt_test name) add_test(NAME ${name} COMMAND ${name}) endfunction() +add_fmt_test(args-test) add_fmt_test(assert-test) add_fmt_test(chrono-test) add_fmt_test(color-test) diff --git a/test/args-test.cc b/test/args-test.cc new file mode 100644 index 00000000..27a874d5 --- /dev/null +++ b/test/args-test.cc @@ -0,0 +1,149 @@ +// Formatting library for C++ - dynamic argument store tests +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#include "fmt/args.h" + +#include "gmock.h" + +TEST(ArgsTest, Basic) { + fmt::dynamic_format_arg_store store; + store.push_back(42); + store.push_back("abc1"); + store.push_back(1.5f); + EXPECT_EQ("42 and abc1 and 1.5", fmt::vformat("{} and {} and {}", store)); +} + +TEST(ArgsTest, StringsAndRefs) { + // Unfortunately the tests are compiled with old ABI so strings use COW. + fmt::dynamic_format_arg_store store; + char str[] = "1234567890"; + store.push_back(str); + store.push_back(std::cref(str)); + store.push_back(fmt::string_view{str}); + str[0] = 'X'; + + std::string result = fmt::vformat("{} and {} and {}", store); + EXPECT_EQ("1234567890 and X234567890 and X234567890", result); +} + +struct custom_type { + int i = 0; +}; + +FMT_BEGIN_NAMESPACE +template <> struct formatter { + auto parse(format_parse_context& ctx) const -> decltype(ctx.begin()) { + return ctx.begin(); + } + + template + auto format(const custom_type& p, FormatContext& ctx) -> decltype(ctx.out()) { + return format_to(ctx.out(), "cust={}", p.i); + } +}; +FMT_END_NAMESPACE + +TEST(ArgsTest, CustomFormat) { + fmt::dynamic_format_arg_store store; + custom_type c{}; + store.push_back(c); + ++c.i; + store.push_back(c); + ++c.i; + store.push_back(std::cref(c)); + ++c.i; + std::string result = fmt::vformat("{} and {} and {}", store); + EXPECT_EQ("cust=0 and cust=1 and cust=3", result); +} + +TEST(ArgsTest, NamedInt) { + fmt::dynamic_format_arg_store store; + store.push_back(fmt::arg("a1", 42)); + EXPECT_EQ("42", fmt::vformat("{a1}", store)); +} + +TEST(ArgsTest, NamedStrings) { + fmt::dynamic_format_arg_store store; + char str[]{"1234567890"}; + store.push_back(fmt::arg("a1", str)); + store.push_back(fmt::arg("a2", std::cref(str))); + str[0] = 'X'; + EXPECT_EQ("1234567890 and X234567890", fmt::vformat("{a1} and {a2}", store)); +} + +TEST(ArgsTest, NamedArgByRef) { + fmt::dynamic_format_arg_store store; + char band[] = "Rolling Stones"; + store.push_back(fmt::arg("band", std::cref(band))); + band[9] = 'c'; // Changing band affects the output. + EXPECT_EQ(fmt::vformat("{band}", store), "Rolling Scones"); +} + +TEST(ArgsTest, NamedCustomFormat) { + fmt::dynamic_format_arg_store store; + custom_type c{}; + store.push_back(fmt::arg("c1", c)); + ++c.i; + store.push_back(fmt::arg("c2", c)); + ++c.i; + store.push_back(fmt::arg("c_ref", std::cref(c))); + ++c.i; + std::string result = fmt::vformat("{c1} and {c2} and {c_ref}", store); + EXPECT_EQ("cust=0 and cust=1 and cust=3", result); +} + +TEST(ArgsTest, Clear) { + fmt::dynamic_format_arg_store store; + store.push_back(42); + + std::string result = fmt::vformat("{}", store); + EXPECT_EQ("42", result); + + store.push_back(43); + result = fmt::vformat("{} and {}", store); + EXPECT_EQ("42 and 43", result); + + store.clear(); + store.push_back(44); + result = fmt::vformat("{}", store); + EXPECT_EQ("44", result); +} + +TEST(ArgsTest, Reserve) { + fmt::dynamic_format_arg_store store; + store.reserve(2, 1); + store.push_back(1.5f); + store.push_back(fmt::arg("a1", 42)); + std::string result = fmt::vformat("{a1} and {}", store); + EXPECT_EQ("42 and 1.5", result); +} + +struct copy_throwable { + copy_throwable() {} + copy_throwable(const copy_throwable&) { throw "deal with it"; } +}; + +FMT_BEGIN_NAMESPACE +template <> struct formatter { + auto parse(format_parse_context& ctx) const -> decltype(ctx.begin()) { + return ctx.begin(); + } + auto format(copy_throwable, format_context& ctx) -> decltype(ctx.out()) { + return ctx.out(); + } +}; +FMT_END_NAMESPACE + +TEST(ArgsTest, ThrowOnCopy) { + fmt::dynamic_format_arg_store store; + store.push_back(std::string("foo")); + try { + store.push_back(copy_throwable()); + } catch (...) { + } + EXPECT_EQ(fmt::vformat("{}", store), "foo"); +} diff --git a/test/core-test.cc b/test/core-test.cc index 5114f226..a20c0620 100644 --- a/test/core-test.cc +++ b/test/core-test.cc @@ -23,7 +23,7 @@ # include #endif -#include "fmt/args.h" +#include "fmt/core.h" #if defined(FMT_COMPILE_TIME_CHECKS) && FMT_COMPILE_TIME_CHECKS # include "fmt/format.h" #endif @@ -401,145 +401,6 @@ TEST(ArgTest, VisitInvalidArg) { fmt::visit_format_arg(visitor, arg); } -TEST(FormatDynArgsTest, Basic) { - fmt::dynamic_format_arg_store store; - store.push_back(42); - store.push_back("abc1"); - store.push_back(1.5f); - EXPECT_EQ("42 and abc1 and 1.5", fmt::vformat("{} and {} and {}", store)); -} - -TEST(FormatDynArgsTest, StringsAndRefs) { - // Unfortunately the tests are compiled with old ABI so strings use COW. - fmt::dynamic_format_arg_store store; - char str[] = "1234567890"; - store.push_back(str); - store.push_back(std::cref(str)); - store.push_back(fmt::string_view{str}); - str[0] = 'X'; - - std::string result = fmt::vformat("{} and {} and {}", store); - EXPECT_EQ("1234567890 and X234567890 and X234567890", result); -} - -struct custom_type { - int i = 0; -}; - -FMT_BEGIN_NAMESPACE -template <> struct formatter { - auto parse(format_parse_context& ctx) const -> decltype(ctx.begin()) { - return ctx.begin(); - } - - template - auto format(const custom_type& p, FormatContext& ctx) -> decltype(ctx.out()) { - return format_to(ctx.out(), "cust={}", p.i); - } -}; -FMT_END_NAMESPACE - -TEST(FormatDynArgsTest, CustomFormat) { - fmt::dynamic_format_arg_store store; - custom_type c{}; - store.push_back(c); - ++c.i; - store.push_back(c); - ++c.i; - store.push_back(std::cref(c)); - ++c.i; - std::string result = fmt::vformat("{} and {} and {}", store); - EXPECT_EQ("cust=0 and cust=1 and cust=3", result); -} - -TEST(FormatDynArgsTest, NamedInt) { - fmt::dynamic_format_arg_store store; - store.push_back(fmt::arg("a1", 42)); - EXPECT_EQ("42", fmt::vformat("{a1}", store)); -} - -TEST(FormatDynArgsTest, NamedStrings) { - fmt::dynamic_format_arg_store store; - char str[]{"1234567890"}; - store.push_back(fmt::arg("a1", str)); - store.push_back(fmt::arg("a2", std::cref(str))); - str[0] = 'X'; - EXPECT_EQ("1234567890 and X234567890", fmt::vformat("{a1} and {a2}", store)); -} - -TEST(FormatDynArgsTest, NamedArgByRef) { - fmt::dynamic_format_arg_store store; - char band[] = "Rolling Stones"; - store.push_back(fmt::arg("band", std::cref(band))); - band[9] = 'c'; // Changing band affects the output. - EXPECT_EQ(fmt::vformat("{band}", store), "Rolling Scones"); -} - -TEST(FormatDynArgsTest, NamedCustomFormat) { - fmt::dynamic_format_arg_store store; - custom_type c{}; - store.push_back(fmt::arg("c1", c)); - ++c.i; - store.push_back(fmt::arg("c2", c)); - ++c.i; - store.push_back(fmt::arg("c_ref", std::cref(c))); - ++c.i; - std::string result = fmt::vformat("{c1} and {c2} and {c_ref}", store); - EXPECT_EQ("cust=0 and cust=1 and cust=3", result); -} - -TEST(FormatDynArgsTest, Clear) { - fmt::dynamic_format_arg_store store; - store.push_back(42); - - std::string result = fmt::vformat("{}", store); - EXPECT_EQ("42", result); - - store.push_back(43); - result = fmt::vformat("{} and {}", store); - EXPECT_EQ("42 and 43", result); - - store.clear(); - store.push_back(44); - result = fmt::vformat("{}", store); - EXPECT_EQ("44", result); -} - -TEST(FormatDynArgsTest, Reserve) { - fmt::dynamic_format_arg_store store; - store.reserve(2, 1); - store.push_back(1.5f); - store.push_back(fmt::arg("a1", 42)); - std::string result = fmt::vformat("{a1} and {}", store); - EXPECT_EQ("42 and 1.5", result); -} - -struct copy_throwable { - copy_throwable() {} - copy_throwable(const copy_throwable&) { throw "deal with it"; } -}; - -FMT_BEGIN_NAMESPACE -template <> struct formatter { - auto parse(format_parse_context& ctx) const -> decltype(ctx.begin()) { - return ctx.begin(); - } - auto format(copy_throwable, format_context& ctx) -> decltype(ctx.out()) { - return ctx.out(); - } -}; -FMT_END_NAMESPACE - -TEST(FormatDynArgsTest, ThrowOnCopy) { - fmt::dynamic_format_arg_store store; - store.push_back(std::string("foo")); - try { - store.push_back(copy_throwable()); - } catch (...) { - } - EXPECT_EQ(fmt::vformat("{}", store), "foo"); -} - TEST(StringViewTest, ValueType) { static_assert(std::is_same::value, ""); }