summaryrefslogtreecommitdiff
path: root/absl/strings/str_format_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'absl/strings/str_format_test.cc')
-rw-r--r--absl/strings/str_format_test.cc237
1 files changed, 183 insertions, 54 deletions
diff --git a/absl/strings/str_format_test.cc b/absl/strings/str_format_test.cc
index 4ac6aa27..9ef69837 100644
--- a/absl/strings/str_format_test.cc
+++ b/absl/strings/str_format_test.cc
@@ -42,6 +42,18 @@ TEST_F(FormatEntryPointTest, Format) {
EXPECT_TRUE(Format(&sink, pc, 123));
EXPECT_EQ("A format 123", sink);
}
+
+TEST_F(FormatEntryPointTest, FormatWithV) {
+ std::string sink;
+ EXPECT_TRUE(Format(&sink, "A format %v", 123));
+ EXPECT_EQ("A format 123", sink);
+ sink.clear();
+
+ ParsedFormat<'v'> pc("A format %v");
+ EXPECT_TRUE(Format(&sink, pc, 123));
+ EXPECT_EQ("A format 123", sink);
+}
+
TEST_F(FormatEntryPointTest, UntypedFormat) {
constexpr const char* formats[] = {
"",
@@ -87,6 +99,9 @@ TEST_F(FormatEntryPointTest, StringFormat) {
TEST_F(FormatEntryPointTest, StringFormatV) {
std::string hello = "hello";
EXPECT_EQ("hello", StrFormat("%v", hello));
+ EXPECT_EQ("123", StrFormat("%v", 123));
+ constexpr absl::string_view view("=%v=", 4);
+ EXPECT_EQ("=123=", StrFormat(view, 123));
}
TEST_F(FormatEntryPointTest, AppendFormat) {
@@ -96,6 +111,13 @@ TEST_F(FormatEntryPointTest, AppendFormat) {
EXPECT_EQ("123", r);
}
+TEST_F(FormatEntryPointTest, AppendFormatWithV) {
+ std::string s;
+ std::string& r = StrAppendFormat(&s, "%v", 123);
+ EXPECT_EQ(&s, &r); // should be same object
+ EXPECT_EQ("123", r);
+}
+
TEST_F(FormatEntryPointTest, AppendFormatFail) {
std::string s = "orig";
@@ -108,6 +130,17 @@ TEST_F(FormatEntryPointTest, AppendFormatFail) {
{&arg, 1}));
}
+TEST_F(FormatEntryPointTest, AppendFormatFailWithV) {
+ std::string s = "orig";
+
+ UntypedFormatSpec format(" more %v");
+ FormatArgImpl arg("not an int");
+
+ EXPECT_EQ("orig",
+ str_format_internal::AppendPack(
+ &s, str_format_internal::UntypedFormatSpecImpl::Extract(format),
+ {&arg, 1}));
+}
TEST_F(FormatEntryPointTest, ManyArgs) {
EXPECT_EQ("24", StrFormat("%24$d", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
@@ -128,6 +161,15 @@ TEST_F(FormatEntryPointTest, Preparsed) {
EXPECT_EQ("=123=", StrFormat(ParsedFormat<'d'>(view), 123));
}
+TEST_F(FormatEntryPointTest, PreparsedWithV) {
+ ParsedFormat<'v'> pc("%v");
+ EXPECT_EQ("123", StrFormat(pc, 123));
+ // rvalue ok?
+ EXPECT_EQ("123", StrFormat(ParsedFormat<'v'>("%v"), 123));
+ constexpr absl::string_view view("=%v=", 4);
+ EXPECT_EQ("=123=", StrFormat(ParsedFormat<'v'>(view), 123));
+}
+
TEST_F(FormatEntryPointTest, FormatCountCapture) {
int n = 0;
EXPECT_EQ("", StrFormat("%n", FormatCountCapture(&n)));
@@ -136,6 +178,14 @@ TEST_F(FormatEntryPointTest, FormatCountCapture) {
EXPECT_EQ(3, n);
}
+TEST_F(FormatEntryPointTest, FormatCountCaptureWithV) {
+ int n = 0;
+ EXPECT_EQ("", StrFormat("%n", FormatCountCapture(&n)));
+ EXPECT_EQ(0, n);
+ EXPECT_EQ("123", StrFormat("%v%n", 123, FormatCountCapture(&n)));
+ EXPECT_EQ(3, n);
+}
+
TEST_F(FormatEntryPointTest, FormatCountCaptureWrongType) {
// Should reject int*.
int n = 0;
@@ -148,6 +198,18 @@ TEST_F(FormatEntryPointTest, FormatCountCaptureWrongType) {
absl::MakeSpan(args)));
}
+TEST_F(FormatEntryPointTest, FormatCountCaptureWrongTypeWithV) {
+ // Should reject int*.
+ int n = 0;
+ UntypedFormatSpec format("%v%n");
+ int i = 123, *ip = &n;
+ FormatArgImpl args[2] = {FormatArgImpl(i), FormatArgImpl(ip)};
+
+ EXPECT_EQ("", str_format_internal::FormatPack(
+ str_format_internal::UntypedFormatSpecImpl::Extract(format),
+ absl::MakeSpan(args)));
+}
+
TEST_F(FormatEntryPointTest, FormatCountCaptureMultiple) {
int n1 = 0;
int n2 = 0;
@@ -212,23 +274,33 @@ TEST_F(FormatEntryPointTest, Stream) {
}
TEST_F(FormatEntryPointTest, StreamWithV) {
- const std::string format = "%d %u %c %v %f %g";
+ const std::string formats[] = {
+ "",
+ "a",
+ "%v %u %c %v %f %v",
+ };
- const std::string format_for_buf = "%d %u %c %s %f %g";
+ const std::string formats_for_buf[] = {
+ "",
+ "a",
+ "%d %u %c %s %f %g",
+ };
std::string buf(4096, '\0');
- const auto parsed =
- ParsedFormat<'d', 'u', 'c', 'v', 'f', 'g'>::NewAllowIgnored(format);
- std::ostringstream oss;
- oss << StreamFormat(*parsed, 123, 3, 49,
- absl::string_view("multistreaming!!!"), 1.01, 1.01);
- int fmt_result =
- snprintf(&*buf.begin(), buf.size(), format_for_buf.c_str(), //
- 123, 3, 49, "multistreaming!!!", 1.01, 1.01);
- ASSERT_TRUE(oss) << format;
- ASSERT_TRUE(fmt_result >= 0 && static_cast<size_t>(fmt_result) < buf.size())
- << fmt_result;
- EXPECT_EQ(buf.c_str(), oss.str());
+ for (auto i = 0; i < ABSL_ARRAYSIZE(formats); ++i) {
+ const auto parsed =
+ ParsedFormat<'v', 'u', 'c', 'v', 'f', 'v'>::NewAllowIgnored(formats[i]);
+ std::ostringstream oss;
+ oss << StreamFormat(*parsed, 123, 3, 49,
+ absl::string_view("multistreaming!!!"), 1.01, 1.01);
+ int fmt_result =
+ snprintf(&*buf.begin(), buf.size(), formats_for_buf[i].c_str(), //
+ 123, 3, 49, "multistreaming!!!", 1.01, 1.01);
+ ASSERT_TRUE(oss) << formats[i];
+ ASSERT_TRUE(fmt_result >= 0 && static_cast<size_t>(fmt_result) < buf.size())
+ << fmt_result;
+ EXPECT_EQ(buf.c_str(), oss.str());
+ }
}
TEST_F(FormatEntryPointTest, StreamOk) {
@@ -238,6 +310,13 @@ TEST_F(FormatEntryPointTest, StreamOk) {
EXPECT_TRUE(oss.good());
}
+TEST_F(FormatEntryPointTest, StreamOkWithV) {
+ std::ostringstream oss;
+ oss << StreamFormat("hello %v", 123);
+ EXPECT_EQ("hello 123", oss.str());
+ EXPECT_TRUE(oss.good());
+}
+
TEST_F(FormatEntryPointTest, StreamFail) {
std::ostringstream oss;
UntypedFormatSpec format("hello %d");
@@ -248,6 +327,16 @@ TEST_F(FormatEntryPointTest, StreamFail) {
EXPECT_TRUE(oss.fail());
}
+TEST_F(FormatEntryPointTest, StreamFailWithV) {
+ std::ostringstream oss;
+ UntypedFormatSpec format("hello %v");
+ FormatArgImpl arg("non-numeric");
+ oss << str_format_internal::Streamable(
+ str_format_internal::UntypedFormatSpecImpl::Extract(format), {&arg, 1});
+ EXPECT_EQ("hello ", oss.str()); // partial write
+ EXPECT_TRUE(oss.fail());
+}
+
std::string WithSnprintf(const char* fmt, ...) {
std::string buf;
buf.resize(128);
@@ -425,19 +514,19 @@ TEST_F(FormatEntryPointTest, SNPrintFWithV) {
EXPECT_EQ(result, 11);
EXPECT_EQ(std::string(buffer), "STRING: ABC");
- result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 123456);
+ result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %v", 123456);
EXPECT_EQ(result, 14);
EXPECT_EQ(std::string(buffer), "NUMBER: 123456");
- result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 1234567);
+ result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %v", 1234567);
EXPECT_EQ(result, 15);
EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
- result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 12345678);
+ result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %v", 12345678);
EXPECT_EQ(result, 16);
EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
- result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 123456789);
+ result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %v", 123456789);
EXPECT_EQ(result, 17);
EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
@@ -451,7 +540,7 @@ TEST(StrFormat, BehavesAsDocumented) {
std::string s = absl::StrFormat("%s, %d!", "Hello", 123);
EXPECT_EQ("Hello, 123!", s);
std::string hello = "Hello";
- std::string s2 = absl::StrFormat("%v, %d!", hello, 123);
+ std::string s2 = absl::StrFormat("%v, %v!", hello, 123);
EXPECT_EQ("Hello, 123!", s2);
// The format of a replacement is
// '%'[position][flags][width['.'precision]][length_modifier][format]
@@ -480,13 +569,18 @@ TEST(StrFormat, BehavesAsDocumented) {
EXPECT_EQ(StrFormat("%d", int{10}), "10");
EXPECT_EQ(StrFormat("%d", long{10}), "10"); // NOLINT
EXPECT_EQ(StrFormat("%d", uint64_t{10}), "10");
+ EXPECT_EQ(StrFormat("%v", int{10}), "10");
+ EXPECT_EQ(StrFormat("%v", long{10}), "10"); // NOLINT
+ EXPECT_EQ(StrFormat("%v", uint64_t{10}), "10");
// d,i - signed decimal Eg: -10 -> "-10"
EXPECT_EQ(StrFormat("%d", -10), "-10");
EXPECT_EQ(StrFormat("%i", -10), "-10");
+ EXPECT_EQ(StrFormat("%v", -10), "-10");
// o - octal Eg: 10 -> "12"
EXPECT_EQ(StrFormat("%o", 10), "12");
// u - unsigned decimal Eg: 10 -> "10"
EXPECT_EQ(StrFormat("%u", 10), "10");
+ EXPECT_EQ(StrFormat("%v", 10), "10");
// x/X - lower,upper case hex Eg: 10 -> "a"/"A"
EXPECT_EQ(StrFormat("%x", 10), "a");
EXPECT_EQ(StrFormat("%X", 10), "A");
@@ -511,6 +605,8 @@ TEST(StrFormat, BehavesAsDocumented) {
EXPECT_EQ(StrFormat("%g", .01), "0.01");
EXPECT_EQ(StrFormat("%g", 1e10), "1e+10");
EXPECT_EQ(StrFormat("%G", 1e10), "1E+10");
+ EXPECT_EQ(StrFormat("%v", .01), "0.01");
+ EXPECT_EQ(StrFormat("%v", 1e10), "1e+10");
// a/A - lower,upper case hex Eg: -3.0 -> "-0x1.8p+1"/"-0X1.8P+1"
// On Android platform <=21, there is a regression in hexfloat formatting.
@@ -598,10 +694,10 @@ TEST_F(ParsedFormatTest, SimpleChecked) {
}
TEST_F(ParsedFormatTest, SimpleCheckedWithV) {
- EXPECT_EQ("[ABC]{d:1$d}[DEF]",
- SummarizeParsedFormat(ParsedFormat<'d'>("ABC%dDEF")));
- EXPECT_EQ("{v:1$v}[FFF]{d:2$d}[ZZZ]{f:3$f}",
- SummarizeParsedFormat(ParsedFormat<'v', 'd', 'f'>("%vFFF%dZZZ%f")));
+ EXPECT_EQ("[ABC]{v:1$v}[DEF]",
+ SummarizeParsedFormat(ParsedFormat<'v'>("ABC%vDEF")));
+ EXPECT_EQ("{v:1$v}[FFF]{v:2$v}[ZZZ]{f:3$f}",
+ SummarizeParsedFormat(ParsedFormat<'v', 'v', 'f'>("%vFFF%vZZZ%f")));
EXPECT_EQ("{v:1$v}[ ]{.*d:3$.2$*d}",
SummarizeParsedFormat(ParsedFormat<'v', '*', 'd'>("%v %.*d")));
}
@@ -637,20 +733,20 @@ TEST_F(ParsedFormatTest, SimpleUncheckedCorrect) {
}
TEST_F(ParsedFormatTest, SimpleUncheckedCorrectWithV) {
- auto f = ParsedFormat<'d'>::New("ABC%dDEF");
+ auto f = ParsedFormat<'v'>::New("ABC%vDEF");
ASSERT_TRUE(f);
- EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f));
+ EXPECT_EQ("[ABC]{v:1$v}[DEF]", SummarizeParsedFormat(*f));
- std::string format = "%vFFF%dZZZ%f";
- auto f2 = ParsedFormat<'v', 'd', 'f'>::New(format);
+ std::string format = "%vFFF%vZZZ%f";
+ auto f2 = ParsedFormat<'v', 'v', 'f'>::New(format);
ASSERT_TRUE(f2);
- EXPECT_EQ("{v:1$v}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
+ EXPECT_EQ("{v:1$v}[FFF]{v:2$v}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
- f2 = ParsedFormat<'v', 'd', 'f'>::New("%v %d %f");
+ f2 = ParsedFormat<'v', 'v', 'f'>::New("%v %v %f");
ASSERT_TRUE(f2);
- EXPECT_EQ("{v:1$v}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
+ EXPECT_EQ("{v:1$v}[ ]{v:2$v}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
}
TEST_F(ParsedFormatTest, SimpleUncheckedIgnoredArgs) {
@@ -668,6 +764,18 @@ TEST_F(ParsedFormatTest, SimpleUncheckedIgnoredArgs) {
EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f));
}
+TEST_F(ParsedFormatTest, SimpleUncheckedIgnoredArgsWithV) {
+ EXPECT_FALSE((ParsedFormat<'v', 'v'>::New("ABC")));
+ EXPECT_FALSE((ParsedFormat<'v', 'v'>::New("%vABC")));
+ EXPECT_FALSE((ParsedFormat<'v', 's'>::New("ABC%2$s")));
+ auto f = ParsedFormat<'v', 'v'>::NewAllowIgnored("ABC");
+ ASSERT_TRUE(f);
+ EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
+ f = ParsedFormat<'v', 'v'>::NewAllowIgnored("%vABC");
+ ASSERT_TRUE(f);
+ EXPECT_EQ("{v:1$v}[ABC]", SummarizeParsedFormat(*f));
+}
+
TEST_F(ParsedFormatTest, SimpleUncheckedUnsupported) {
EXPECT_FALSE(ParsedFormat<'d'>::New("%1$d %1$x"));
EXPECT_FALSE(ParsedFormat<'x'>::New("%1$d %1$x"));
@@ -683,12 +791,12 @@ TEST_F(ParsedFormatTest, SimpleUncheckedIncorrect) {
}
TEST_F(ParsedFormatTest, SimpleUncheckedIncorrectWithV) {
- EXPECT_FALSE(ParsedFormat<'d'>::New(""));
+ EXPECT_FALSE(ParsedFormat<'v'>::New(""));
- EXPECT_FALSE(ParsedFormat<'d'>::New("ABC%dDEF%d"));
+ EXPECT_FALSE(ParsedFormat<'v'>::New("ABC%vDEF%v"));
- std::string format = "%vFFF%dZZZ%f";
- EXPECT_FALSE((ParsedFormat<'v', 'd', 'g'>::New(format)));
+ std::string format = "%vFFF%vZZZ%f";
+ EXPECT_FALSE((ParsedFormat<'v', 'v', 'g'>::New(format)));
}
#if defined(__cpp_nontype_template_parameter_auto)
@@ -739,17 +847,17 @@ TEST_F(ParsedFormatTest, ExtendedTyping) {
}
TEST_F(ParsedFormatTest, ExtendedTypingWithV) {
- EXPECT_FALSE(ParsedFormat<FormatConversionCharSet::d>::New(""));
- ASSERT_TRUE(ParsedFormat<absl::FormatConversionCharSet::d>::New("%d"));
- auto v1 = ParsedFormat<'d', absl::FormatConversionCharSet::v>::New("%d%v");
+ EXPECT_FALSE(ParsedFormat<FormatConversionCharSet::v>::New(""));
+ ASSERT_TRUE(ParsedFormat<absl::FormatConversionCharSet::v>::New("%v"));
+ auto v1 = ParsedFormat<'v', absl::FormatConversionCharSet::v>::New("%v%v");
ASSERT_TRUE(v1);
- auto v2 = ParsedFormat<absl::FormatConversionCharSet::d, 'v'>::New("%d%v");
+ auto v2 = ParsedFormat<absl::FormatConversionCharSet::v, 'v'>::New("%v%v");
ASSERT_TRUE(v2);
- auto v3 = ParsedFormat<absl::FormatConversionCharSet::d |
+ auto v3 = ParsedFormat<absl::FormatConversionCharSet::v |
absl::FormatConversionCharSet::v,
- 'v'>::New("%d%v");
+ 'v'>::New("%v%v");
ASSERT_TRUE(v3);
- auto v4 = ParsedFormat<absl::FormatConversionCharSet::d |
+ auto v4 = ParsedFormat<absl::FormatConversionCharSet::v |
absl::FormatConversionCharSet::v,
'v'>::New("%v%v");
ASSERT_TRUE(v4);
@@ -799,24 +907,24 @@ TEST_F(ParsedFormatTest, UncheckedCorrect) {
TEST_F(ParsedFormatTest, UncheckedCorrectWithV) {
auto f =
- ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New("ABC%dDEF");
+ ExtendedParsedFormat<absl::FormatConversionCharSet::v>::New("ABC%vDEF");
ASSERT_TRUE(f);
- EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f));
+ EXPECT_EQ("[ABC]{v:1$v}[DEF]", SummarizeParsedFormat(*f));
- std::string format = "%vFFF%dZZZ%f";
+ std::string format = "%vFFF%vZZZ%f";
auto f2 = ExtendedParsedFormat<
- absl::FormatConversionCharSet::v, absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::v, absl::FormatConversionCharSet::v,
absl::FormatConversionCharSet::kFloating>::New(format);
ASSERT_TRUE(f2);
- EXPECT_EQ("{v:1$v}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
+ EXPECT_EQ("{v:1$v}[FFF]{v:2$v}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
f2 = ExtendedParsedFormat<
- absl::FormatConversionCharSet::v, absl::FormatConversionCharSet::d,
- absl::FormatConversionCharSet::kFloating>::New("%v %d %f");
+ absl::FormatConversionCharSet::v, absl::FormatConversionCharSet::v,
+ absl::FormatConversionCharSet::kFloating>::New("%v %v %f");
ASSERT_TRUE(f2);
- EXPECT_EQ("{v:1$v}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
+ EXPECT_EQ("{v:1$v}[ ]{v:2$v}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
}
TEST_F(ParsedFormatTest, UncheckedIgnoredArgs) {
@@ -846,6 +954,28 @@ TEST_F(ParsedFormatTest, UncheckedIgnoredArgs) {
EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f));
}
+TEST_F(ParsedFormatTest, UncheckedIgnoredArgsWithV) {
+ EXPECT_FALSE(
+ (ExtendedParsedFormat<absl::FormatConversionCharSet::v,
+ absl::FormatConversionCharSet::v>::New("ABC")));
+ EXPECT_FALSE(
+ (ExtendedParsedFormat<absl::FormatConversionCharSet::v,
+ absl::FormatConversionCharSet::v>::New("%vABC")));
+ EXPECT_FALSE((ExtendedParsedFormat<absl::FormatConversionCharSet::v,
+ absl::FormatConversionCharSet::s>::
+ New("ABC%2$s")));
+ auto f = ExtendedParsedFormat<
+ absl::FormatConversionCharSet::v,
+ absl::FormatConversionCharSet::v>::NewAllowIgnored("ABC");
+ ASSERT_TRUE(f);
+ EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
+ f = ExtendedParsedFormat<
+ absl::FormatConversionCharSet::v,
+ absl::FormatConversionCharSet::v>::NewAllowIgnored("%vABC");
+ ASSERT_TRUE(f);
+ EXPECT_EQ("{v:1$v}[ABC]", SummarizeParsedFormat(*f));
+}
+
TEST_F(ParsedFormatTest, UncheckedMultipleTypes) {
auto dx =
ExtendedParsedFormat<absl::FormatConversionCharSet::d |
@@ -873,15 +1003,14 @@ TEST_F(ParsedFormatTest, UncheckedIncorrect) {
}
TEST_F(ParsedFormatTest, UncheckedIncorrectWithV) {
- EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(""));
+ EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::v>::New(""));
- EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(
- "ABC%dDEF%d"));
+ EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::v>::New(
+ "ABC%vDEF%v"));
- std::string format = "%vFFF%dZZZ%f";
+ std::string format = "%vFFF%vZZZ%f";
EXPECT_FALSE(
(ExtendedParsedFormat<absl::FormatConversionCharSet::v,
- absl::FormatConversionCharSet::d,
absl::FormatConversionCharSet::g>::New(format)));
}