diff options
Diffstat (limited to 'third_party/abseil_cpp/absl/strings/internal/str_format/parser_test.cc')
-rw-r--r-- | third_party/abseil_cpp/absl/strings/internal/str_format/parser_test.cc | 427 |
1 files changed, 0 insertions, 427 deletions
diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/parser_test.cc b/third_party/abseil_cpp/absl/strings/internal/str_format/parser_test.cc deleted file mode 100644 index a5fa1c79aaf4..000000000000 --- a/third_party/abseil_cpp/absl/strings/internal/str_format/parser_test.cc +++ /dev/null @@ -1,427 +0,0 @@ -// 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/internal/str_format/parser.h" - -#include <string.h> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/macros.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace str_format_internal { - -namespace { - -using testing::Pair; - -TEST(LengthModTest, Names) { - struct Expectation { - int line; - LengthMod mod; - const char *name; - }; - const Expectation kExpect[] = { - {__LINE__, LengthMod::none, "" }, - {__LINE__, LengthMod::h, "h" }, - {__LINE__, LengthMod::hh, "hh"}, - {__LINE__, LengthMod::l, "l" }, - {__LINE__, LengthMod::ll, "ll"}, - {__LINE__, LengthMod::L, "L" }, - {__LINE__, LengthMod::j, "j" }, - {__LINE__, LengthMod::z, "z" }, - {__LINE__, LengthMod::t, "t" }, - {__LINE__, LengthMod::q, "q" }, - }; - EXPECT_EQ(ABSL_ARRAYSIZE(kExpect), 10); - for (auto e : kExpect) { - SCOPED_TRACE(e.line); - EXPECT_EQ(e.name, LengthModToString(e.mod)); - } -} - -TEST(ConversionCharTest, Names) { - struct Expectation { - FormatConversionChar id; - char name; - }; - // clang-format off - const Expectation kExpect[] = { -#define X(c) {FormatConversionCharInternal::c, #c[0]} - X(c), X(s), // text - X(d), X(i), X(o), X(u), X(x), X(X), // int - X(f), X(F), X(e), X(E), X(g), X(G), X(a), X(A), // float - X(n), X(p), // misc -#undef X - {FormatConversionCharInternal::kNone, '\0'}, - }; - // clang-format on - for (auto e : kExpect) { - SCOPED_TRACE(e.name); - FormatConversionChar v = e.id; - EXPECT_EQ(e.name, FormatConversionCharToChar(v)); - } -} - -class ConsumeUnboundConversionTest : public ::testing::Test { - public: - std::pair<string_view, string_view> Consume(string_view src) { - int next = 0; - o = UnboundConversion(); // refresh - const char* p = ConsumeUnboundConversion( - src.data(), src.data() + src.size(), &o, &next); - if (!p) return {{}, src}; - return {string_view(src.data(), p - src.data()), - string_view(p, src.data() + src.size() - p)}; - } - - bool Run(const char *fmt, bool force_positional = false) { - int next = force_positional ? -1 : 0; - o = UnboundConversion(); // refresh - return ConsumeUnboundConversion(fmt, fmt + strlen(fmt), &o, &next) == - fmt + strlen(fmt); - } - UnboundConversion o; -}; - -TEST_F(ConsumeUnboundConversionTest, ConsumeSpecification) { - struct Expectation { - int line; - string_view src; - string_view out; - string_view src_post; - }; - const Expectation kExpect[] = { - {__LINE__, "", "", "" }, - {__LINE__, "b", "", "b" }, // 'b' is invalid - {__LINE__, "ba", "", "ba"}, // 'b' is invalid - {__LINE__, "l", "", "l" }, // just length mod isn't okay - {__LINE__, "d", "d", "" }, // basic - {__LINE__, "d ", "d", " " }, // leave suffix - {__LINE__, "dd", "d", "d" }, // don't be greedy - {__LINE__, "d9", "d", "9" }, // leave non-space suffix - {__LINE__, "dzz", "d", "zz"}, // length mod as suffix - {__LINE__, "1$*2$d", "1$*2$d", "" }, // arg indexing and * allowed. - {__LINE__, "0-14.3hhd", "0-14.3hhd", ""}, // precision, width - {__LINE__, " 0-+#14.3hhd", " 0-+#14.3hhd", ""}, // flags - }; - for (const auto& e : kExpect) { - SCOPED_TRACE(e.line); - EXPECT_THAT(Consume(e.src), Pair(e.out, e.src_post)); - } -} - -TEST_F(ConsumeUnboundConversionTest, BasicConversion) { - EXPECT_FALSE(Run("")); - EXPECT_FALSE(Run("z")); - - EXPECT_FALSE(Run("dd")); // no excess allowed - - EXPECT_TRUE(Run("d")); - EXPECT_EQ('d', FormatConversionCharToChar(o.conv)); - EXPECT_FALSE(o.width.is_from_arg()); - EXPECT_LT(o.width.value(), 0); - EXPECT_FALSE(o.precision.is_from_arg()); - EXPECT_LT(o.precision.value(), 0); - EXPECT_EQ(1, o.arg_position); -} - -TEST_F(ConsumeUnboundConversionTest, ArgPosition) { - EXPECT_TRUE(Run("d")); - EXPECT_EQ(1, o.arg_position); - EXPECT_TRUE(Run("3$d")); - EXPECT_EQ(3, o.arg_position); - EXPECT_TRUE(Run("1$d")); - EXPECT_EQ(1, o.arg_position); - EXPECT_TRUE(Run("1$d", true)); - EXPECT_EQ(1, o.arg_position); - EXPECT_TRUE(Run("123$d")); - EXPECT_EQ(123, o.arg_position); - EXPECT_TRUE(Run("123$d", true)); - EXPECT_EQ(123, o.arg_position); - EXPECT_TRUE(Run("10$d")); - EXPECT_EQ(10, o.arg_position); - EXPECT_TRUE(Run("10$d", true)); - EXPECT_EQ(10, o.arg_position); - - // Position can't be zero. - EXPECT_FALSE(Run("0$d")); - EXPECT_FALSE(Run("0$d", true)); - EXPECT_FALSE(Run("1$*0$d")); - EXPECT_FALSE(Run("1$.*0$d")); - - // Position can't start with a zero digit at all. That is not a 'decimal'. - EXPECT_FALSE(Run("01$p")); - EXPECT_FALSE(Run("01$p", true)); - EXPECT_FALSE(Run("1$*01$p")); - EXPECT_FALSE(Run("1$.*01$p")); -} - -TEST_F(ConsumeUnboundConversionTest, WidthAndPrecision) { - EXPECT_TRUE(Run("14d")); - EXPECT_EQ('d', FormatConversionCharToChar(o.conv)); - EXPECT_FALSE(o.width.is_from_arg()); - EXPECT_EQ(14, o.width.value()); - EXPECT_FALSE(o.precision.is_from_arg()); - EXPECT_LT(o.precision.value(), 0); - - EXPECT_TRUE(Run("14.d")); - EXPECT_FALSE(o.width.is_from_arg()); - EXPECT_FALSE(o.precision.is_from_arg()); - EXPECT_EQ(14, o.width.value()); - EXPECT_EQ(0, o.precision.value()); - - EXPECT_TRUE(Run(".d")); - EXPECT_FALSE(o.width.is_from_arg()); - EXPECT_LT(o.width.value(), 0); - EXPECT_FALSE(o.precision.is_from_arg()); - EXPECT_EQ(0, o.precision.value()); - - EXPECT_TRUE(Run(".5d")); - EXPECT_FALSE(o.width.is_from_arg()); - EXPECT_LT(o.width.value(), 0); - EXPECT_FALSE(o.precision.is_from_arg()); - EXPECT_EQ(5, o.precision.value()); - - EXPECT_TRUE(Run(".0d")); - EXPECT_FALSE(o.width.is_from_arg()); - EXPECT_LT(o.width.value(), 0); - EXPECT_FALSE(o.precision.is_from_arg()); - EXPECT_EQ(0, o.precision.value()); - - EXPECT_TRUE(Run("14.5d")); - EXPECT_FALSE(o.width.is_from_arg()); - EXPECT_FALSE(o.precision.is_from_arg()); - EXPECT_EQ(14, o.width.value()); - EXPECT_EQ(5, o.precision.value()); - - EXPECT_TRUE(Run("*.*d")); - EXPECT_TRUE(o.width.is_from_arg()); - EXPECT_EQ(1, o.width.get_from_arg()); - EXPECT_TRUE(o.precision.is_from_arg()); - EXPECT_EQ(2, o.precision.get_from_arg()); - EXPECT_EQ(3, o.arg_position); - - EXPECT_TRUE(Run("*d")); - EXPECT_TRUE(o.width.is_from_arg()); - EXPECT_EQ(1, o.width.get_from_arg()); - EXPECT_FALSE(o.precision.is_from_arg()); - EXPECT_LT(o.precision.value(), 0); - EXPECT_EQ(2, o.arg_position); - - EXPECT_TRUE(Run(".*d")); - EXPECT_FALSE(o.width.is_from_arg()); - EXPECT_LT(o.width.value(), 0); - EXPECT_TRUE(o.precision.is_from_arg()); - EXPECT_EQ(1, o.precision.get_from_arg()); - EXPECT_EQ(2, o.arg_position); - - // mixed implicit and explicit: didn't specify arg position. - EXPECT_FALSE(Run("*23$.*34$d")); - - EXPECT_TRUE(Run("12$*23$.*34$d")); - EXPECT_EQ(12, o.arg_position); - EXPECT_TRUE(o.width.is_from_arg()); - EXPECT_EQ(23, o.width.get_from_arg()); - EXPECT_TRUE(o.precision.is_from_arg()); - EXPECT_EQ(34, o.precision.get_from_arg()); - - EXPECT_TRUE(Run("2$*5$.*9$d")); - EXPECT_EQ(2, o.arg_position); - EXPECT_TRUE(o.width.is_from_arg()); - EXPECT_EQ(5, o.width.get_from_arg()); - EXPECT_TRUE(o.precision.is_from_arg()); - EXPECT_EQ(9, o.precision.get_from_arg()); - - EXPECT_FALSE(Run(".*0$d")) << "no arg 0"; - - // Large values - EXPECT_TRUE(Run("999999999.999999999d")); - EXPECT_FALSE(o.width.is_from_arg()); - EXPECT_EQ(999999999, o.width.value()); - EXPECT_FALSE(o.precision.is_from_arg()); - EXPECT_EQ(999999999, o.precision.value()); - - EXPECT_FALSE(Run("1000000000.999999999d")); - EXPECT_FALSE(Run("999999999.1000000000d")); - EXPECT_FALSE(Run("9999999999d")); - EXPECT_FALSE(Run(".9999999999d")); -} - -TEST_F(ConsumeUnboundConversionTest, Flags) { - static const char kAllFlags[] = "-+ #0"; - static const int kNumFlags = ABSL_ARRAYSIZE(kAllFlags) - 1; - for (int rev = 0; rev < 2; ++rev) { - for (int i = 0; i < 1 << kNumFlags; ++i) { - std::string fmt; - for (int k = 0; k < kNumFlags; ++k) - if ((i >> k) & 1) fmt += kAllFlags[k]; - // flag order shouldn't matter - if (rev == 1) { std::reverse(fmt.begin(), fmt.end()); } - fmt += 'd'; - SCOPED_TRACE(fmt); - EXPECT_TRUE(Run(fmt.c_str())); - EXPECT_EQ(fmt.find('-') == std::string::npos, !o.flags.left); - EXPECT_EQ(fmt.find('+') == std::string::npos, !o.flags.show_pos); - EXPECT_EQ(fmt.find(' ') == std::string::npos, !o.flags.sign_col); - EXPECT_EQ(fmt.find('#') == std::string::npos, !o.flags.alt); - EXPECT_EQ(fmt.find('0') == std::string::npos, !o.flags.zero); - } - } -} - -TEST_F(ConsumeUnboundConversionTest, BasicFlag) { - // Flag is on - for (const char* fmt : {"d", "llx", "G", "1$X"}) { - SCOPED_TRACE(fmt); - EXPECT_TRUE(Run(fmt)); - EXPECT_TRUE(o.flags.basic); - } - - // Flag is off - for (const char* fmt : {"3d", ".llx", "-G", "1$#X"}) { - SCOPED_TRACE(fmt); - EXPECT_TRUE(Run(fmt)); - EXPECT_FALSE(o.flags.basic); - } -} - -TEST_F(ConsumeUnboundConversionTest, LengthMod) { - EXPECT_TRUE(Run("d")); - EXPECT_EQ(LengthMod::none, o.length_mod); - EXPECT_TRUE(Run("hd")); - EXPECT_EQ(LengthMod::h, o.length_mod); - EXPECT_TRUE(Run("hhd")); - EXPECT_EQ(LengthMod::hh, o.length_mod); - EXPECT_TRUE(Run("ld")); - EXPECT_EQ(LengthMod::l, o.length_mod); - EXPECT_TRUE(Run("lld")); - EXPECT_EQ(LengthMod::ll, o.length_mod); - EXPECT_TRUE(Run("Lf")); - EXPECT_EQ(LengthMod::L, o.length_mod); - EXPECT_TRUE(Run("qf")); - EXPECT_EQ(LengthMod::q, o.length_mod); - EXPECT_TRUE(Run("jd")); - EXPECT_EQ(LengthMod::j, o.length_mod); - EXPECT_TRUE(Run("zd")); - EXPECT_EQ(LengthMod::z, o.length_mod); - EXPECT_TRUE(Run("td")); - EXPECT_EQ(LengthMod::t, o.length_mod); -} - -struct SummarizeConsumer { - std::string* out; - explicit SummarizeConsumer(std::string* out) : out(out) {} - - bool Append(string_view s) { - *out += "[" + std::string(s) + "]"; - return true; - } - - bool ConvertOne(const UnboundConversion& conv, string_view s) { - *out += "{"; - *out += std::string(s); - *out += ":"; - *out += std::to_string(conv.arg_position) + "$"; - if (conv.width.is_from_arg()) { - *out += std::to_string(conv.width.get_from_arg()) + "$*"; - } - if (conv.precision.is_from_arg()) { - *out += "." + std::to_string(conv.precision.get_from_arg()) + "$*"; - } - *out += FormatConversionCharToChar(conv.conv); - *out += "}"; - return true; - } -}; - -std::string SummarizeParsedFormat(const ParsedFormatBase& pc) { - std::string out; - if (!pc.ProcessFormat(SummarizeConsumer(&out))) out += "!"; - return out; -} - -class ParsedFormatTest : public testing::Test {}; - -TEST_F(ParsedFormatTest, ValueSemantics) { - ParsedFormatBase p1({}, true, {}); // empty format - EXPECT_EQ("", SummarizeParsedFormat(p1)); - - ParsedFormatBase p2 = p1; // copy construct (empty) - EXPECT_EQ(SummarizeParsedFormat(p1), SummarizeParsedFormat(p2)); - - p1 = ParsedFormatBase("hello%s", true, - {FormatConversionCharSetInternal::s}); // move assign - EXPECT_EQ("[hello]{s:1$s}", SummarizeParsedFormat(p1)); - - ParsedFormatBase p3 = p1; // copy construct (nonempty) - EXPECT_EQ(SummarizeParsedFormat(p1), SummarizeParsedFormat(p3)); - - using std::swap; - swap(p1, p2); - EXPECT_EQ("", SummarizeParsedFormat(p1)); - EXPECT_EQ("[hello]{s:1$s}", SummarizeParsedFormat(p2)); - swap(p1, p2); // undo - - p2 = p1; // copy assign - EXPECT_EQ(SummarizeParsedFormat(p1), SummarizeParsedFormat(p2)); -} - -struct ExpectParse { - const char* in; - std::initializer_list<FormatConversionCharSet> conv_set; - const char* out; -}; - -TEST_F(ParsedFormatTest, Parsing) { - // Parse should be equivalent to that obtained by ConversionParseIterator. - // No need to retest the parsing edge cases here. - const ExpectParse kExpect[] = { - {"", {}, ""}, - {"ab", {}, "[ab]"}, - {"a%d", {FormatConversionCharSetInternal::d}, "[a]{d:1$d}"}, - {"a%+d", {FormatConversionCharSetInternal::d}, "[a]{+d:1$d}"}, - {"a% d", {FormatConversionCharSetInternal::d}, "[a]{ d:1$d}"}, - {"a%b %d", {}, "[a]!"}, // stop after error - }; - for (const auto& e : kExpect) { - SCOPED_TRACE(e.in); - EXPECT_EQ(e.out, - SummarizeParsedFormat(ParsedFormatBase(e.in, false, e.conv_set))); - } -} - -TEST_F(ParsedFormatTest, ParsingFlagOrder) { - const ExpectParse kExpect[] = { - {"a%+ 0d", {FormatConversionCharSetInternal::d}, "[a]{+ 0d:1$d}"}, - {"a%+0 d", {FormatConversionCharSetInternal::d}, "[a]{+0 d:1$d}"}, - {"a%0+ d", {FormatConversionCharSetInternal::d}, "[a]{0+ d:1$d}"}, - {"a% +0d", {FormatConversionCharSetInternal::d}, "[a]{ +0d:1$d}"}, - {"a%0 +d", {FormatConversionCharSetInternal::d}, "[a]{0 +d:1$d}"}, - {"a% 0+d", {FormatConversionCharSetInternal::d}, "[a]{ 0+d:1$d}"}, - {"a%+ 0+d", {FormatConversionCharSetInternal::d}, "[a]{+ 0+d:1$d}"}, - }; - for (const auto& e : kExpect) { - SCOPED_TRACE(e.in); - EXPECT_EQ(e.out, - SummarizeParsedFormat(ParsedFormatBase(e.in, false, e.conv_set))); - } -} - -} // namespace -} // namespace str_format_internal -ABSL_NAMESPACE_END -} // namespace absl |