summaryrefslogtreecommitdiff
path: root/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_format_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_format_test.cc')
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_format_test.cc228
1 files changed, 188 insertions, 40 deletions
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_format_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_format_test.cc
index 87ed234fe82..c60027ad297 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_format_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_format_test.cc
@@ -1,3 +1,18 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/str_format.h"
#include <cstdarg>
#include <cstdint>
@@ -6,14 +21,16 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "absl/strings/str_format.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
using str_format_internal::FormatArgImpl;
-class FormatEntryPointTest : public ::testing::Test { };
+using FormatEntryPointTest = ::testing::Test;
TEST_F(FormatEntryPointTest, Format) {
std::string sink;
@@ -30,8 +47,8 @@ TEST_F(FormatEntryPointTest, UntypedFormat) {
"",
"a",
"%80d",
-#if !defined(_MSC_VER) && !defined(__ANDROID__)
- // MSVC and Android don't support positional syntax.
+#if !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(__native_client__)
+ // MSVC, NaCL and Android don't support positional syntax.
"complicated multipart %% %1$d format %1$0999d",
#endif // _MSC_VER
};
@@ -153,17 +170,20 @@ TEST_F(FormatEntryPointTest, Stream) {
"",
"a",
"%80d",
-#if !defined(_MSC_VER) && !defined(__ANDROID__)
- // MSVC doesn't support positional syntax.
+ "%d %u %c %s %f %g",
+#if !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(__native_client__)
+ // MSVC, NaCL and Android don't support positional syntax.
"complicated multipart %% %1$d format %1$080d",
#endif // _MSC_VER
};
std::string buf(4096, '\0');
for (const auto& fmt : formats) {
- const auto parsed = ParsedFormat<'d'>::NewAllowIgnored(fmt);
+ const auto parsed =
+ ParsedFormat<'d', 'u', 'c', 's', 'f', 'g'>::NewAllowIgnored(fmt);
std::ostringstream oss;
- oss << StreamFormat(*parsed, 123);
- int fmt_result = snprintf(&*buf.begin(), buf.size(), fmt.c_str(), 123);
+ oss << StreamFormat(*parsed, 123, 3, 49, "multistreaming!!!", 1.01, 1.01);
+ int fmt_result = snprintf(&*buf.begin(), buf.size(), fmt.c_str(), //
+ 123, 3, 49, "multistreaming!!!", 1.01, 1.01);
ASSERT_TRUE(oss) << fmt;
ASSERT_TRUE(fmt_result >= 0 && static_cast<size_t>(fmt_result) < buf.size())
<< fmt_result;
@@ -238,7 +258,7 @@ class TempFile {
std::FILE* file() const { return file_; }
- // Read the file into a std::string.
+ // Read the file into a string.
std::string ReadFile() {
std::fseek(file_, 0, SEEK_END);
int size = std::ftell(file_);
@@ -271,7 +291,7 @@ TEST_F(FormatEntryPointTest, FPrintFError) {
EXPECT_EQ(errno, EBADF);
}
-#if __GLIBC__
+#ifdef __GLIBC__
TEST_F(FormatEntryPointTest, FprintfTooLarge) {
std::FILE* f = std::fopen("/dev/null", "w");
int width = 2000000000;
@@ -341,11 +361,12 @@ TEST(StrFormat, BehavesAsDocumented) {
EXPECT_EQ(StrFormat("%c", int{'a'}), "a");
EXPECT_EQ(StrFormat("%c", long{'a'}), "a"); // NOLINT
EXPECT_EQ(StrFormat("%c", uint64_t{'a'}), "a");
- // "s" - std::string Eg: "C" -> "C", std::string("C++") -> "C++"
+ // "s" - string Eg: "C" -> "C", std::string("C++") -> "C++"
// Formats std::string, char*, string_view, and Cord.
EXPECT_EQ(StrFormat("%s", "C"), "C");
EXPECT_EQ(StrFormat("%s", std::string("C++")), "C++");
EXPECT_EQ(StrFormat("%s", string_view("view")), "view");
+ EXPECT_EQ(StrFormat("%s", absl::Cord("cord")), "cord");
// Integral Conversion
// These format integral types: char, int, long, uint64_t, etc.
EXPECT_EQ(StrFormat("%d", char{10}), "10");
@@ -446,7 +467,7 @@ struct SummarizeConsumer {
if (conv.precision.is_from_arg()) {
*out += "." + std::to_string(conv.precision.get_from_arg()) + "$*";
}
- *out += conv.conv.Char();
+ *out += str_format_internal::FormatConversionCharToChar(conv.conv);
*out += "}";
return true;
}
@@ -458,7 +479,7 @@ std::string SummarizeParsedFormat(const ParsedFormatBase& pc) {
return out;
}
-class ParsedFormatTest : public testing::Test {};
+using ParsedFormatTest = ::testing::Test;
TEST_F(ParsedFormatTest, SimpleChecked) {
EXPECT_EQ("[ABC]{d:1$d}[DEF]",
@@ -528,99 +549,226 @@ TEST_F(ParsedFormatTest, SimpleUncheckedIncorrect) {
EXPECT_FALSE((ParsedFormat<'s', 'd', 'g'>::New(format)));
}
-using str_format_internal::Conv;
+#if defined(__cpp_nontype_template_parameter_auto)
+
+template <auto T>
+std::true_type IsValidParsedFormatArgTest(ParsedFormat<T>*);
+
+template <auto T>
+std::false_type IsValidParsedFormatArgTest(...);
+
+template <auto T>
+using IsValidParsedFormatArg = decltype(IsValidParsedFormatArgTest<T>(nullptr));
+
+TEST_F(ParsedFormatTest, OnlyValidTypesAllowed) {
+ ASSERT_TRUE(IsValidParsedFormatArg<'c'>::value);
+
+ ASSERT_TRUE(IsValidParsedFormatArg<FormatConversionCharSet::d>::value);
+
+ ASSERT_TRUE(IsValidParsedFormatArg<absl::FormatConversionCharSet::d |
+ absl::FormatConversionCharSet::x>::value);
+ ASSERT_TRUE(
+ IsValidParsedFormatArg<absl::FormatConversionCharSet::kIntegral>::value);
+
+ // This is an easy mistake to make, however, this will reduce to an integer
+ // which has no meaning, so we need to ensure it doesn't compile.
+ ASSERT_FALSE(IsValidParsedFormatArg<'x' | 'd'>::value);
+
+ // For now, we disallow construction based on ConversionChar (rather than
+ // CharSet)
+ ASSERT_FALSE(IsValidParsedFormatArg<absl::FormatConversionChar::d>::value);
+}
+
+TEST_F(ParsedFormatTest, ExtendedTyping) {
+ EXPECT_FALSE(ParsedFormat<FormatConversionCharSet::d>::New(""));
+ ASSERT_TRUE(ParsedFormat<absl::FormatConversionCharSet::d>::New("%d"));
+ auto v1 = ParsedFormat<'d', absl::FormatConversionCharSet::s>::New("%d%s");
+ ASSERT_TRUE(v1);
+ auto v2 = ParsedFormat<absl::FormatConversionCharSet::d, 's'>::New("%d%s");
+ ASSERT_TRUE(v2);
+ auto v3 = ParsedFormat<absl::FormatConversionCharSet::d |
+ absl::FormatConversionCharSet::s,
+ 's'>::New("%d%s");
+ ASSERT_TRUE(v3);
+ auto v4 = ParsedFormat<absl::FormatConversionCharSet::d |
+ absl::FormatConversionCharSet::s,
+ 's'>::New("%s%s");
+ ASSERT_TRUE(v4);
+}
+#endif
TEST_F(ParsedFormatTest, UncheckedCorrect) {
- auto f = ExtendedParsedFormat<Conv::d>::New("ABC%dDEF");
+ auto f =
+ ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New("ABC%dDEF");
ASSERT_TRUE(f);
EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f));
std::string format = "%sFFF%dZZZ%f";
- auto f2 =
- ExtendedParsedFormat<Conv::string, Conv::d, Conv::floating>::New(format);
+ auto f2 = ExtendedParsedFormat<
+ absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::kFloating>::New(format);
ASSERT_TRUE(f2);
EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
- f2 = ExtendedParsedFormat<Conv::string, Conv::d, Conv::floating>::New(
- "%s %d %f");
+ f2 = ExtendedParsedFormat<
+ absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::kFloating>::New("%s %d %f");
ASSERT_TRUE(f2);
EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
- auto star = ExtendedParsedFormat<Conv::star, Conv::d>::New("%*d");
+ auto star =
+ ExtendedParsedFormat<absl::FormatConversionCharSet::kStar,
+ absl::FormatConversionCharSet::d>::New("%*d");
ASSERT_TRUE(star);
EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star));
- auto dollar = ExtendedParsedFormat<Conv::d, Conv::s>::New("%2$s %1$d");
+ auto dollar =
+ ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::New("%2$s %1$d");
ASSERT_TRUE(dollar);
EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar));
// with reuse
- dollar = ExtendedParsedFormat<Conv::d, Conv::s>::New("%2$s %1$d %1$d");
+ dollar = ExtendedParsedFormat<
+ absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::New("%2$s %1$d %1$d");
ASSERT_TRUE(dollar);
EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}",
SummarizeParsedFormat(*dollar));
}
TEST_F(ParsedFormatTest, UncheckedIgnoredArgs) {
- EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::s>::New("ABC")));
- EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::s>::New("%dABC")));
- EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::s>::New("ABC%2$s")));
- auto f = ExtendedParsedFormat<Conv::d, Conv::s>::NewAllowIgnored("ABC");
+ EXPECT_FALSE(
+ (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::New("ABC")));
+ EXPECT_FALSE(
+ (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::New("%dABC")));
+ EXPECT_FALSE(
+ (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::New("ABC%2$s")));
+ auto f = ExtendedParsedFormat<
+ absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::NewAllowIgnored("ABC");
ASSERT_TRUE(f);
EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
- f = ExtendedParsedFormat<Conv::d, Conv::s>::NewAllowIgnored("%dABC");
+ f = ExtendedParsedFormat<
+ absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::NewAllowIgnored("%dABC");
ASSERT_TRUE(f);
EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f));
- f = ExtendedParsedFormat<Conv::d, Conv::s>::NewAllowIgnored("ABC%2$s");
+ f = ExtendedParsedFormat<
+ absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::NewAllowIgnored("ABC%2$s");
ASSERT_TRUE(f);
EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f));
}
TEST_F(ParsedFormatTest, UncheckedMultipleTypes) {
- auto dx = ExtendedParsedFormat<Conv::d | Conv::x>::New("%1$d %1$x");
+ auto dx =
+ ExtendedParsedFormat<absl::FormatConversionCharSet::d |
+ absl::FormatConversionCharSet::x>::New("%1$d %1$x");
EXPECT_TRUE(dx);
EXPECT_EQ("{1$d:1$d}[ ]{1$x:1$x}", SummarizeParsedFormat(*dx));
- dx = ExtendedParsedFormat<Conv::d | Conv::x>::New("%1$d");
+ dx = ExtendedParsedFormat<absl::FormatConversionCharSet::d |
+ absl::FormatConversionCharSet::x>::New("%1$d");
EXPECT_TRUE(dx);
EXPECT_EQ("{1$d:1$d}", SummarizeParsedFormat(*dx));
}
TEST_F(ParsedFormatTest, UncheckedIncorrect) {
- EXPECT_FALSE(ExtendedParsedFormat<Conv::d>::New(""));
+ EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(""));
- EXPECT_FALSE(ExtendedParsedFormat<Conv::d>::New("ABC%dDEF%d"));
+ EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(
+ "ABC%dDEF%d"));
std::string format = "%sFFF%dZZZ%f";
- EXPECT_FALSE((ExtendedParsedFormat<Conv::s, Conv::d, Conv::g>::New(format)));
+ EXPECT_FALSE(
+ (ExtendedParsedFormat<absl::FormatConversionCharSet::s,
+ absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::g>::New(format)));
}
TEST_F(ParsedFormatTest, RegressionMixPositional) {
- EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::o>::New("%1$d %o")));
+ EXPECT_FALSE(
+ (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::o>::New("%1$d %o")));
+}
+
+using FormatWrapperTest = ::testing::Test;
+
+// Plain wrapper for StrFormat.
+template <typename... Args>
+std::string WrappedFormat(const absl::FormatSpec<Args...>& format,
+ const Args&... args) {
+ return StrFormat(format, args...);
+}
+
+TEST_F(FormatWrapperTest, ConstexprStringFormat) {
+ EXPECT_EQ(WrappedFormat("%s there", "hello"), "hello there");
+}
+
+TEST_F(FormatWrapperTest, ParsedFormat) {
+ ParsedFormat<'s'> format("%s there");
+ EXPECT_EQ(WrappedFormat(format, "hello"), "hello there");
}
} // namespace
+ABSL_NAMESPACE_END
} // namespace absl
+using FormatExtensionTest = ::testing::Test;
+
+struct Point {
+ friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |
+ absl::FormatConversionCharSet::kIntegral>
+ AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,
+ absl::FormatSink* s) {
+ if (spec.conversion_char() == absl::FormatConversionChar::s) {
+ s->Append(absl::StrCat("x=", p.x, " y=", p.y));
+ } else {
+ s->Append(absl::StrCat(p.x, ",", p.y));
+ }
+ return {true};
+ }
+
+ int x = 10;
+ int y = 20;
+};
+
+TEST_F(FormatExtensionTest, AbslFormatConvertExample) {
+ Point p;
+ EXPECT_EQ(absl::StrFormat("a %s z", p), "a x=10 y=20 z");
+ EXPECT_EQ(absl::StrFormat("a %d z", p), "a 10,20 z");
+
+ // Typed formatting will fail to compile an invalid format.
+ // StrFormat("%f", p); // Does not compile.
+ std::string actual;
+ absl::UntypedFormatSpec f1("%f");
+ // FormatUntyped will return false for bad character.
+ EXPECT_FALSE(absl::FormatUntyped(&actual, f1, {absl::FormatArg(p)}));
+}
+
// Some codegen thunks that we can use to easily dump the generated assembly for
// different StrFormat calls.
-std::string CodegenAbslStrFormatInt(int i) { // NOLINT
+std::string CodegenAbslStrFormatInt(int i) { // NOLINT
return absl::StrFormat("%d", i);
}
std::string CodegenAbslStrFormatIntStringInt64(int i, const std::string& s,
- int64_t i64) { // NOLINT
+ int64_t i64) { // NOLINT
return absl::StrFormat("%d %s %d", i, s, i64);
}
-void CodegenAbslStrAppendFormatInt(std::string* out, int i) { // NOLINT
+void CodegenAbslStrAppendFormatInt(std::string* out, int i) { // NOLINT
absl::StrAppendFormat(out, "%d", i);
}
void CodegenAbslStrAppendFormatIntStringInt64(std::string* out, int i,
- const std::string& s,
- int64_t i64) { // NOLINT
+ const std::string& s,
+ int64_t i64) { // NOLINT
absl::StrAppendFormat(out, "%d %s %d", i, s, i64);
}