1 // Formatting library for C++ - std::ostream support tests
3 // Copyright (c) 2012 - present, Victor Zverovich
4 // All rights reserved.
6 // For the license information refer to format.h.
8 #define FMT_STRING_ALIAS 1
9 #include "fmt/ostream.h"
13 #include "gtest-extra.h"
17 using fmt::format_error
;
19 static std::ostream
&operator<<(std::ostream
&os
, const Date
&d
) {
20 os
<< d
.year() << '-' << d
.month() << '-' << d
.day();
24 static std::wostream
&operator<<(std::wostream
&os
, const Date
&d
) {
25 os
<< d
.year() << L
'-' << d
.month() << L
'-' << d
.day();
30 static std::ostream
&operator<<(std::ostream
&os
, TestEnum
) {
31 return os
<< "TestEnum";
34 static std::wostream
&operator<<(std::wostream
&os
, TestEnum
) {
35 return os
<< L
"TestEnum";
40 TEST(OStreamTest
, Enum
) {
41 EXPECT_FALSE((fmt::convert_to_int
<TestEnum
, char>::value
));
42 EXPECT_EQ("TestEnum", fmt::format("{}", TestEnum()));
43 EXPECT_EQ("0", fmt::format("{}", A
));
44 EXPECT_FALSE((fmt::convert_to_int
<TestEnum
, wchar_t>::value
));
45 EXPECT_EQ(L
"TestEnum", fmt::format(L
"{}", TestEnum()));
46 EXPECT_EQ(L
"0", fmt::format(L
"{}", A
));
49 typedef fmt::back_insert_range
<fmt::internal::buffer
> range
;
51 struct test_arg_formatter
: fmt::arg_formatter
<range
> {
52 test_arg_formatter(fmt::format_context
&ctx
, fmt::format_specs
&s
)
53 : fmt::arg_formatter
<range
>(ctx
, &s
) {}
56 TEST(OStreamTest
, CustomArg
) {
57 fmt::memory_buffer buffer
;
58 fmt::internal::buffer
&base
= buffer
;
59 fmt::format_context
ctx(std::back_inserter(base
), "", fmt::format_args());
60 fmt::format_specs spec
;
61 test_arg_formatter
af(ctx
, spec
);
62 visit(af
, fmt::internal::make_arg
<fmt::format_context
>(TestEnum()));
63 EXPECT_EQ("TestEnum", std::string(buffer
.data(), buffer
.size()));
66 TEST(OStreamTest
, Format
) {
67 EXPECT_EQ("a string", format("{0}", TestString("a string")));
68 std::string s
= format("The date is {0}", Date(2012, 12, 9));
69 EXPECT_EQ("The date is 2012-12-9", s
);
70 Date
date(2012, 12, 9);
71 EXPECT_EQ(L
"The date is 2012-12-9",
72 format(L
"The date is {0}", Date(2012, 12, 9)));
75 TEST(OStreamTest
, FormatSpecs
) {
76 EXPECT_EQ("def ", format("{0:<5}", TestString("def")));
77 EXPECT_EQ(" def", format("{0:>5}", TestString("def")));
78 EXPECT_THROW_MSG(format("{0:=5}", TestString("def")),
79 format_error
, "format specifier requires numeric argument");
80 EXPECT_EQ(" def ", format("{0:^5}", TestString("def")));
81 EXPECT_EQ("def**", format("{0:*<5}", TestString("def")));
82 EXPECT_THROW_MSG(format("{0:+}", TestString()),
83 format_error
, "format specifier requires numeric argument");
84 EXPECT_THROW_MSG(format("{0:-}", TestString()),
85 format_error
, "format specifier requires numeric argument");
86 EXPECT_THROW_MSG(format("{0: }", TestString()),
87 format_error
, "format specifier requires numeric argument");
88 EXPECT_THROW_MSG(format("{0:#}", TestString()),
89 format_error
, "format specifier requires numeric argument");
90 EXPECT_THROW_MSG(format("{0:05}", TestString()),
91 format_error
, "format specifier requires numeric argument");
92 EXPECT_EQ("test ", format("{0:13}", TestString("test")));
93 EXPECT_EQ("test ", format("{0:{1}}", TestString("test"), 13));
94 EXPECT_EQ("te", format("{0:.2}", TestString("test")));
95 EXPECT_EQ("te", format("{0:.{1}}", TestString("test"), 2));
99 static std::ostream
&operator<<(std::ostream
&os
, EmptyTest
) {
103 TEST(OStreamTest
, EmptyCustomOutput
) {
104 EXPECT_EQ("", fmt::format("{}", EmptyTest()));
107 TEST(OStreamTest
, Print
) {
108 std::ostringstream os
;
109 fmt::print(os
, "Don't {}!", "panic");
110 EXPECT_EQ("Don't panic!", os
.str());
111 std::wostringstream wos
;
112 fmt::print(wos
, L
"Don't {}!", L
"panic");
113 EXPECT_EQ(L
"Don't panic!", wos
.str());
116 TEST(OStreamTest
, WriteToOStream
) {
117 std::ostringstream os
;
118 fmt::memory_buffer buffer
;
119 const char *foo
= "foo";
120 buffer
.append(foo
, foo
+ std::strlen(foo
));
121 fmt::internal::write(os
, buffer
);
122 EXPECT_EQ("foo", os
.str());
125 TEST(OStreamTest
, WriteToOStreamMaxSize
) {
126 std::size_t max_size
= std::numeric_limits
<std::size_t>::max();
127 std::streamsize max_streamsize
= std::numeric_limits
<std::streamsize
>::max();
128 if (max_size
<= fmt::internal::to_unsigned(max_streamsize
))
131 struct test_buffer
: fmt::internal::buffer
{
132 explicit test_buffer(std::size_t size
) { resize(size
); }
133 void grow(std::size_t) {}
136 struct mock_streambuf
: std::streambuf
{
137 MOCK_METHOD2(xsputn
, std::streamsize (const void *s
, std::streamsize n
));
138 std::streamsize
xsputn(const char *s
, std::streamsize n
) {
144 struct test_ostream
: std::ostream
{
145 explicit test_ostream(mock_streambuf
&buffer
) : std::ostream(&buffer
) {}
148 testing::InSequence sequence
;
149 const char *data
= FMT_NULL
;
150 typedef std::make_unsigned
<std::streamsize
>::type ustreamsize
;
151 ustreamsize size
= max_size
;
153 auto n
= std::min(size
, fmt::internal::to_unsigned(max_streamsize
));
154 EXPECT_CALL(streambuf
, xsputn(data
, static_cast<std::streamsize
>(n
)))
155 .WillOnce(testing::Return(max_streamsize
));
159 fmt::internal::write(os
, buffer
);
162 TEST(OStreamTest
, Join
) {
163 int v
[3] = {1, 2, 3};
164 EXPECT_EQ("1, 2, 3", fmt::format("{}", fmt::join(v
, v
+ 3, ", ")));
167 #if FMT_USE_CONSTEXPR
168 TEST(OStreamTest
, ConstexprString
) {
169 EXPECT_EQ("42", format(fmt("{}"), std::string("42")));
176 template <typename Output
> Output
&operator<<(Output
&out
, ABC
) {
180 } // namespace fmt_test
182 TEST(FormatTest
, FormatToN
) {
185 auto result
= fmt::format_to_n(buffer
, 3, "{}", fmt_test::ABC());
186 EXPECT_EQ(3u, result
.size
);
187 EXPECT_EQ(buffer
+ 3, result
.out
);
188 EXPECT_EQ("ABCx", fmt::string_view(buffer
, 4));
189 result
= fmt::format_to_n(buffer
, 3, "x{}y", fmt_test::ABC());
190 EXPECT_EQ(5u, result
.size
);
191 EXPECT_EQ(buffer
+ 3, result
.out
);
192 EXPECT_EQ("xABx", fmt::string_view(buffer
, 4));
195 #if FMT_USE_USER_DEFINED_LITERALS
196 TEST(FormatTest
, UDL
) {
197 using namespace fmt::literals
;
198 EXPECT_EQ("{}"_format("test"), "test");