Drop range limit and cleanup tests

This commit is contained in:
Victor Zverovich 2021-05-04 20:53:56 -07:00
parent c738c3431f
commit 38bcc04a11
2 changed files with 88 additions and 118 deletions

View File

@ -17,11 +17,6 @@
#include "format.h"
// output only up to N items from the range.
#ifndef FMT_RANGE_OUTPUT_LENGTH_LIMIT
# define FMT_RANGE_OUTPUT_LENGTH_LIMIT 256
#endif
FMT_BEGIN_NAMESPACE
template <typename Char> struct formatting_base {
@ -33,9 +28,6 @@ template <typename Char> struct formatting_base {
template <typename Char, typename Enable = void>
struct formatting_range : formatting_base<Char> {
static FMT_CONSTEXPR_DECL const size_t range_length_limit =
FMT_RANGE_OUTPUT_LENGTH_LIMIT; // output only up to N items from the
// range.
Char prefix = '{';
Char postfix = '}';
};
@ -360,10 +352,7 @@ struct formatter<
for (; it != end; ++it) {
if (i > 0) out = detail::write_delimiter(out);
out = detail::write_range_entry<Char>(out, *it);
if (++i > formatting.range_length_limit) {
out = format_to(out, FMT_STRING("{}"), " ... <other elements>");
break;
}
++i;
}
return detail::copy(formatting.postfix, out);
}

View File

@ -44,69 +44,65 @@ TEST(ranges_test, format_array_of_literals) {
#endif // FMT_RANGES_TEST_ENABLE_C_STYLE_ARRAY
TEST(ranges_test, format_vector) {
std::vector<int32_t> iv{1, 2, 3, 5, 7, 11};
auto ivf = fmt::format("{}", iv);
EXPECT_EQ("{1, 2, 3, 5, 7, 11}", ivf);
auto v = std::vector<int>{1, 2, 3, 5, 7, 11};
EXPECT_EQ(fmt::format("{}", v), "{1, 2, 3, 5, 7, 11}");
}
TEST(ranges_test, format_vector2) {
std::vector<std::vector<int32_t>> ivv{{1, 2}, {3, 5}, {7, 11}};
auto ivf = fmt::format("{}", ivv);
EXPECT_EQ("{{1, 2}, {3, 5}, {7, 11}}", ivf);
auto v = std::vector<std::vector<int>>{{1, 2}, {3, 5}, {7, 11}};
EXPECT_EQ(fmt::format("{}", v), "{{1, 2}, {3, 5}, {7, 11}}");
}
TEST(ranges_test, FormatMap) {
std::map<std::string, int32_t> simap{{"one", 1}, {"two", 2}};
EXPECT_EQ("{(\"one\", 1), (\"two\", 2)}", fmt::format("{}", simap));
TEST(ranges_test, format_map) {
auto m = std::map<std::string, int>{{"one", 1}, {"two", 2}};
EXPECT_EQ(fmt::format("{}", m), "{(\"one\", 1), (\"two\", 2)}");
}
TEST(ranges_test, FormatPair) {
std::pair<int64_t, float> pa1{42, 1.5f};
EXPECT_EQ("(42, 1.5)", fmt::format("{}", pa1));
TEST(ranges_test, format_pair) {
auto p = std::pair<int, float>(42, 1.5f);
EXPECT_EQ(fmt::format("{}", p), "(42, 1.5)");
}
TEST(ranges_test, FormatTuple) {
std::tuple<int64_t, float, std::string, char> t{42, 1.5f, "this is tuple",
'i'};
EXPECT_EQ("(42, 1.5, \"this is tuple\", 'i')", fmt::format("{}", t));
EXPECT_EQ("()", fmt::format("{}", std::tuple<>()));
TEST(ranges_test, format_tuple) {
auto t =
std::tuple<int, float, std::string, char>(42, 1.5f, "this is tuple", 'i');
EXPECT_EQ(fmt::format("{}", t), "(42, 1.5, \"this is tuple\", 'i')");
EXPECT_EQ(fmt::format("{}", std::tuple<>()), "()");
}
#ifdef FMT_RANGES_TEST_ENABLE_FORMAT_STRUCT
struct my_struct {
int32_t i;
std::string str; // can throw
template <size_t N> fmt::enable_if_t<N == 0, int32_t> get() const noexcept {
struct tuple_like {
int i;
std::string str;
template <size_t N> fmt::enable_if_t<N == 0, int> get() const noexcept {
return i;
}
template <size_t N>
fmt::enable_if_t<N == 1, fmt::string_view> get() const noexcept {
return {str};
return str;
}
};
template <size_t N>
auto get(const my_struct& s) noexcept -> decltype(s.get<N>()) {
return s.get<N>();
auto get(const tuple_like& t) noexcept -> decltype(t.get<N>()) {
return t.get<N>();
}
namespace std {
template <>
struct std::tuple_size<tuple_like> : std::integral_constant<size_t, 2> {};
template <> struct tuple_size<my_struct> : std::integral_constant<size_t, 2> {};
template <size_t N> struct tuple_element<N, my_struct> {
using type = decltype(std::declval<my_struct>().get<N>());
template <size_t N> struct std::tuple_element<N, tuple_like> {
using type = decltype(std::declval<tuple_like>().get<N>());
};
} // namespace std
TEST(ranges_test, FormatStruct) {
my_struct mst{13, "my struct"};
EXPECT_EQ("(13, \"my struct\")", fmt::format("{}", mst));
TEST(ranges_test, format_struct) {
auto t = tuple_like{42, "foo"};
EXPECT_EQ(fmt::format("{}", t), "(42, \"foo\")");
}
#endif // FMT_RANGES_TEST_ENABLE_FORMAT_STRUCT
TEST(ranges_test, FormatTo) {
TEST(ranges_test, format_to) {
char buf[10];
auto end = fmt::format_to(buf, "{}", std::vector<int>{1, 2, 3});
*end = '\0';
@ -120,7 +116,7 @@ struct path_like {
operator std::string() const;
};
TEST(ranges_test, PathLike) {
TEST(ranges_test, path_like) {
EXPECT_FALSE((fmt::is_range<path_like, char>::value));
}
@ -132,15 +128,15 @@ struct string_like {
explicit operator std::string_view() const { return "foo"; }
};
TEST(ranges_test, FormatStringLike) {
EXPECT_EQ("foo", fmt::format("{}", string_like()));
TEST(ranges_test, format_string_like) {
EXPECT_EQ(fmt::format("{}", string_like()), "foo");
}
#endif // FMT_USE_STRING_VIEW
// A range that provides non-const only begin()/end() to test fmt::join handles
// that
// that.
//
// Some ranges (eg those produced by range-v3's views::filter()) can cache
// Some ranges (e.g. those produced by range-v3's views::filter()) can cache
// information during iteration so they only provide non-const begin()/end().
template <typename T> class non_const_only_range {
private:
@ -151,7 +147,7 @@ template <typename T> class non_const_only_range {
template <typename... Args>
explicit non_const_only_range(Args&&... args)
: vec(::std::forward<Args>(args)...) {}
: vec(std::forward<Args>(args)...) {}
const_iterator begin() { return vec.begin(); }
const_iterator end() { return vec.end(); }
@ -166,7 +162,7 @@ template <typename T> class noncopyable_range {
template <typename... Args>
explicit noncopyable_range(Args&&... args)
: vec(::std::forward<Args>(args)...) {}
: vec(std::forward<Args>(args)...) {}
noncopyable_range(noncopyable_range const&) = delete;
noncopyable_range(noncopyable_range&) = delete;
@ -175,75 +171,61 @@ template <typename T> class noncopyable_range {
const_iterator end() const { return vec.end(); }
};
TEST(ranges_test, Range) {
TEST(ranges_test, range) {
noncopyable_range<int> w(3u, 0);
EXPECT_EQ("{0, 0, 0}", fmt::format("{}", w));
EXPECT_EQ("{0, 0, 0}", fmt::format("{}", noncopyable_range<int>(3u, 0)));
EXPECT_EQ(fmt::format("{}", w), "{0, 0, 0}");
EXPECT_EQ(fmt::format("{}", noncopyable_range<int>(3u, 0)), "{0, 0, 0}");
non_const_only_range<int> x(3u, 0);
EXPECT_EQ("{0, 0, 0}", fmt::format("{}", x));
EXPECT_EQ("{0, 0, 0}", fmt::format("{}", non_const_only_range<int>(3u, 0)));
EXPECT_EQ(fmt::format("{}", x), "{0, 0, 0}");
EXPECT_EQ(fmt::format("{}", non_const_only_range<int>(3u, 0)), "{0, 0, 0}");
std::vector<int> y(3u, 0);
EXPECT_EQ("{0, 0, 0}", fmt::format("{}", y));
EXPECT_EQ("{0, 0, 0}", fmt::format("{}", std::vector<int>(3u, 0)));
auto y = std::vector<int>(3u, 0);
EXPECT_EQ(fmt::format("{}", y), "{0, 0, 0}");
EXPECT_EQ(fmt::format("{}", std::vector<int>(3u, 0)), "{0, 0, 0}");
const std::vector<int> z(3u, 0);
EXPECT_EQ("{0, 0, 0}", fmt::format("{}", z));
const auto z = std::vector<int>(3u, 0);
EXPECT_EQ(fmt::format("{}", z), "{0, 0, 0}");
}
#if !FMT_MSC_VER || FMT_MSC_VER >= 1927
struct unformattable {};
TEST(ranges_test, UnformattableRange) {
TEST(ranges_test, unformattable_range) {
EXPECT_FALSE((fmt::has_formatter<std::vector<unformattable>,
fmt::format_context>::value));
}
#endif
#ifdef FMT_RANGES_TEST_ENABLE_JOIN
TEST(ranges_test, JoinTuple) {
// Value tuple args
std::tuple<char, int, float> t1 = std::make_tuple('a', 1, 2.0f);
EXPECT_EQ("(a, 1, 2)", fmt::format("({})", fmt::join(t1, ", ")));
TEST(ranges_test, join_tuple) {
// Value tuple args.
auto t1 = std::tuple<char, int, float>('a', 1, 2.0f);
EXPECT_EQ(fmt::format("({})", fmt::join(t1, ", ")), "(a, 1, 2)");
// Testing lvalue tuple args
// Testing lvalue tuple args.
int x = 4;
std::tuple<char, int&> t2{'b', x};
EXPECT_EQ("b + 4", fmt::format("{}", fmt::join(t2, " + ")));
auto t2 = std::tuple<char, int&>('b', x);
EXPECT_EQ(fmt::format("{}", fmt::join(t2, " + ")), "b + 4");
// Empty tuple
std::tuple<> t3;
EXPECT_EQ("", fmt::format("{}", fmt::join(t3, "|")));
// Empty tuple.
auto t3 = std::tuple<>();
EXPECT_EQ(fmt::format("{}", fmt::join(t3, "|")), "");
// Single element tuple
std::tuple<float> t4{4.0f};
EXPECT_EQ("4", fmt::format("{}", fmt::join(t4, "/")));
// Single element tuple.
auto t4 = std::tuple<float>(4.0f);
EXPECT_EQ(fmt::format("{}", fmt::join(t4, "/")), "4");
}
TEST(ranges_test, WideStringJoinTuple) {
// Value tuple args
std::tuple<wchar_t, int, float> t1 = std::make_tuple('a', 1, 2.0f);
EXPECT_EQ(L"(a, 1, 2)", fmt::format(L"({})", fmt::join(t1, L", ")));
// Testing lvalue tuple args
int x = 4;
std::tuple<wchar_t, int&> t2{'b', x};
EXPECT_EQ(L"b + 4", fmt::format(L"{}", fmt::join(t2, L" + ")));
// Empty tuple
std::tuple<> t3;
EXPECT_EQ(L"", fmt::format(L"{}", fmt::join(t3, L"|")));
// Single element tuple
std::tuple<float> t4{4.0f};
EXPECT_EQ(L"4", fmt::format(L"{}", fmt::join(t4, L"/")));
TEST(ranges_test, wide_string_join_tuple) {
auto t = std::tuple<wchar_t, int, float>('a', 1, 2.0f);
EXPECT_EQ(fmt::format(L"({})", fmt::join(t, L", ")), L"(a, 1, 2)");
}
TEST(ranges_test, JoinInitializerList) {
EXPECT_EQ("1, 2, 3", fmt::format("{}", fmt::join({1, 2, 3}, ", ")));
EXPECT_EQ("fmt rocks !",
fmt::format("{}", fmt::join({"fmt", "rocks", "!"}, " ")));
TEST(ranges_test, join_initializer_list) {
EXPECT_EQ(fmt::format("{}", fmt::join({1, 2, 3}, ", ")), "1, 2, 3");
EXPECT_EQ(fmt::format("{}", fmt::join({"fmt", "rocks", "!"}, " ")),
"fmt rocks !");
}
struct zstring_sentinel {};
@ -257,30 +239,29 @@ struct zstring {
zstring_sentinel end() const { return {}; }
};
TEST(ranges_test, JoinSentinel) {
zstring hello{"hello"};
EXPECT_EQ("{'h', 'e', 'l', 'l', 'o'}", fmt::format("{}", hello));
EXPECT_EQ("h_e_l_l_o", fmt::format("{}", fmt::join(hello, "_")));
TEST(ranges_test, join_sentinel) {
auto hello = zstring{"hello"};
EXPECT_EQ(fmt::format("{}", hello), "{'h', 'e', 'l', 'l', 'o'}");
EXPECT_EQ(fmt::format("{}", fmt::join(hello, "_")), "h_e_l_l_o");
}
TEST(ranges_test, JoinRange) {
TEST(ranges_test, join_range) {
noncopyable_range<int> w(3u, 0);
EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(w, ",")));
EXPECT_EQ("0,0,0",
fmt::format("{}", fmt::join(noncopyable_range<int>(3u, 0), ",")));
EXPECT_EQ(fmt::format("{}", fmt::join(w, ",")), "0,0,0");
EXPECT_EQ(fmt::format("{}", fmt::join(noncopyable_range<int>(3u, 0), ",")),
"0,0,0");
non_const_only_range<int> x(3u, 0);
EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(x, ",")));
EXPECT_EQ(
"0,0,0",
fmt::format("{}", fmt::join(non_const_only_range<int>(3u, 0), ",")));
EXPECT_EQ(fmt::format("{}", fmt::join(x, ",")), "0,0,0");
EXPECT_EQ(fmt::format("{}", fmt::join(non_const_only_range<int>(3u, 0), ",")),
"0,0,0");
std::vector<int> y(3u, 0);
EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(y, ",")));
EXPECT_EQ("0,0,0",
fmt::format("{}", fmt::join(std::vector<int>(3u, 0), ",")));
auto y = std::vector<int>(3u, 0);
EXPECT_EQ(fmt::format("{}", fmt::join(y, ",")), "0,0,0");
EXPECT_EQ(fmt::format("{}", fmt::join(std::vector<int>(3u, 0), ",")),
"0,0,0");
const std::vector<int> z(3u, 0);
EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(z, ",")));
const auto z = std::vector<int>(3u, 0);
EXPECT_EQ(fmt::format("{}", fmt::join(z, ",")), "0,0,0");
}
#endif // FMT_RANGES_TEST_ENABLE_JOIN