00001 #include <errno.h>
00002 #include <stdarg.h>
00003 #include <stdio.h>
00004 #include <cctype>
00005 #include <cmath>
00006 #include <string>
00007
00008 #include "gtest/gtest.h"
00009 #include "absl/strings/internal/str_format/bind.h"
00010
00011 namespace absl {
00012 namespace str_format_internal {
00013 namespace {
00014
00015 template <typename T, size_t N>
00016 size_t ArraySize(T (&)[N]) {
00017 return N;
00018 }
00019
00020 std::string LengthModFor(float) { return ""; }
00021 std::string LengthModFor(double) { return ""; }
00022 std::string LengthModFor(long double) { return "L"; }
00023 std::string LengthModFor(char) { return "hh"; }
00024 std::string LengthModFor(signed char) { return "hh"; }
00025 std::string LengthModFor(unsigned char) { return "hh"; }
00026 std::string LengthModFor(short) { return "h"; }
00027 std::string LengthModFor(unsigned short) { return "h"; }
00028 std::string LengthModFor(int) { return ""; }
00029 std::string LengthModFor(unsigned) { return ""; }
00030 std::string LengthModFor(long) { return "l"; }
00031 std::string LengthModFor(unsigned long) { return "l"; }
00032 std::string LengthModFor(long long) { return "ll"; }
00033 std::string LengthModFor(unsigned long long) { return "ll"; }
00034
00035 std::string EscCharImpl(int v) {
00036 if (std::isprint(static_cast<unsigned char>(v))) {
00037 return std::string(1, static_cast<char>(v));
00038 }
00039 char buf[64];
00040 int n = snprintf(buf, sizeof(buf), "\\%#.2x",
00041 static_cast<unsigned>(v & 0xff));
00042 assert(n > 0 && n < sizeof(buf));
00043 return std::string(buf, n);
00044 }
00045
00046 std::string Esc(char v) { return EscCharImpl(v); }
00047 std::string Esc(signed char v) { return EscCharImpl(v); }
00048 std::string Esc(unsigned char v) { return EscCharImpl(v); }
00049
00050 template <typename T>
00051 std::string Esc(const T &v) {
00052 std::ostringstream oss;
00053 oss << v;
00054 return oss.str();
00055 }
00056
00057 void StrAppend(std::string *dst, const char *format, va_list ap) {
00058
00059 static const int kSpaceLength = 1024;
00060 char space[kSpaceLength];
00061
00062
00063
00064
00065 va_list backup_ap;
00066 va_copy(backup_ap, ap);
00067 int result = vsnprintf(space, kSpaceLength, format, backup_ap);
00068 va_end(backup_ap);
00069 if (result < kSpaceLength) {
00070 if (result >= 0) {
00071
00072 dst->append(space, result);
00073 return;
00074 }
00075 if (result < 0) {
00076
00077 return;
00078 }
00079 }
00080
00081
00082
00083 int length = result + 1;
00084 char *buf = new char[length];
00085
00086
00087 va_copy(backup_ap, ap);
00088 result = vsnprintf(buf, length, format, backup_ap);
00089 va_end(backup_ap);
00090
00091 if (result >= 0 && result < length) {
00092
00093 dst->append(buf, result);
00094 }
00095 delete[] buf;
00096 }
00097
00098 std::string StrPrint(const char *format, ...) {
00099 va_list ap;
00100 va_start(ap, format);
00101 std::string result;
00102 StrAppend(&result, format, ap);
00103 va_end(ap);
00104 return result;
00105 }
00106
00107 class FormatConvertTest : public ::testing::Test { };
00108
00109 template <typename T>
00110 void TestStringConvert(const T& str) {
00111 const FormatArgImpl args[] = {FormatArgImpl(str)};
00112 struct Expectation {
00113 const char *out;
00114 const char *fmt;
00115 };
00116 const Expectation kExpect[] = {
00117 {"hello", "%1$s" },
00118 {"", "%1$.s" },
00119 {"", "%1$.0s" },
00120 {"h", "%1$.1s" },
00121 {"he", "%1$.2s" },
00122 {"hello", "%1$.10s" },
00123 {" hello", "%1$6s" },
00124 {" he", "%1$5.2s" },
00125 {"he ", "%1$-5.2s" },
00126 {"hello ", "%1$-6.10s" },
00127 };
00128 for (const Expectation &e : kExpect) {
00129 UntypedFormatSpecImpl format(e.fmt);
00130 EXPECT_EQ(e.out, FormatPack(format, absl::MakeSpan(args)));
00131 }
00132 }
00133
00134 TEST_F(FormatConvertTest, BasicString) {
00135 TestStringConvert("hello");
00136 TestStringConvert(static_cast<const char*>("hello"));
00137 TestStringConvert(std::string("hello"));
00138 TestStringConvert(string_view("hello"));
00139 }
00140
00141 TEST_F(FormatConvertTest, NullString) {
00142 const char* p = nullptr;
00143 UntypedFormatSpecImpl format("%s");
00144 EXPECT_EQ("", FormatPack(format, {FormatArgImpl(p)}));
00145 }
00146
00147 TEST_F(FormatConvertTest, StringPrecision) {
00148
00149 char c = 'a';
00150 const char* p = &c;
00151 UntypedFormatSpecImpl format("%.1s");
00152 EXPECT_EQ("a", FormatPack(format, {FormatArgImpl(p)}));
00153
00154
00155 p = "ABC";
00156 UntypedFormatSpecImpl format2("%.10s");
00157 EXPECT_EQ("ABC", FormatPack(format2, {FormatArgImpl(p)}));
00158 }
00159
00160 TEST_F(FormatConvertTest, Pointer) {
00161 #ifdef _MSC_VER
00162
00163
00164 return;
00165 #endif
00166 static int x = 0;
00167 const int *xp = &x;
00168 char c = 'h';
00169 char *mcp = &c;
00170 const char *cp = "hi";
00171 const char *cnil = nullptr;
00172 const int *inil = nullptr;
00173 using VoidF = void (*)();
00174 VoidF fp = [] {}, fnil = nullptr;
00175 volatile char vc;
00176 volatile char* vcp = &vc;
00177 volatile char* vcnil = nullptr;
00178 const FormatArgImpl args[] = {
00179 FormatArgImpl(xp), FormatArgImpl(cp), FormatArgImpl(inil),
00180 FormatArgImpl(cnil), FormatArgImpl(mcp), FormatArgImpl(fp),
00181 FormatArgImpl(fnil), FormatArgImpl(vcp), FormatArgImpl(vcnil),
00182 };
00183 struct Expectation {
00184 std::string out;
00185 const char *fmt;
00186 };
00187 const Expectation kExpect[] = {
00188 {StrPrint("%p", &x), "%p"},
00189 {StrPrint("%20p", &x), "%20p"},
00190 {StrPrint("%.1p", &x), "%.1p"},
00191 {StrPrint("%.20p", &x), "%.20p"},
00192 {StrPrint("%30.20p", &x), "%30.20p"},
00193
00194 {StrPrint("%-p", &x), "%-p"},
00195 {StrPrint("%-20p", &x), "%-20p"},
00196 {StrPrint("%-.1p", &x), "%-.1p"},
00197 {StrPrint("%.20p", &x), "%.20p"},
00198 {StrPrint("%-30.20p", &x), "%-30.20p"},
00199
00200 {StrPrint("%p", cp), "%2$p"},
00201 {"(nil)", "%3$p"},
00202 {"(nil)", "%4$p"},
00203 {StrPrint("%p", mcp), "%5$p"},
00204
00205 {StrPrint("%p", fp), "%6$p"},
00206 {StrPrint("%p", vcp), "%8$p"},
00207
00208 #ifndef __APPLE__
00209
00210 {StrPrint("%p", fnil), "%7$p"},
00211 {StrPrint("%p", vcnil), "%9$p"},
00212 #endif
00213 };
00214 for (const Expectation &e : kExpect) {
00215 UntypedFormatSpecImpl format(e.fmt);
00216 EXPECT_EQ(e.out, FormatPack(format, absl::MakeSpan(args))) << e.fmt;
00217 }
00218 }
00219
00220 struct Cardinal {
00221 enum Pos { k1 = 1, k2 = 2, k3 = 3 };
00222 enum Neg { kM1 = -1, kM2 = -2, kM3 = -3 };
00223 };
00224
00225 TEST_F(FormatConvertTest, Enum) {
00226 const Cardinal::Pos k3 = Cardinal::k3;
00227 const Cardinal::Neg km3 = Cardinal::kM3;
00228 const FormatArgImpl args[] = {FormatArgImpl(k3), FormatArgImpl(km3)};
00229 UntypedFormatSpecImpl format("%1$d");
00230 UntypedFormatSpecImpl format2("%2$d");
00231 EXPECT_EQ("3", FormatPack(format, absl::MakeSpan(args)));
00232 EXPECT_EQ("-3", FormatPack(format2, absl::MakeSpan(args)));
00233 }
00234
00235 template <typename T>
00236 class TypedFormatConvertTest : public FormatConvertTest { };
00237
00238 TYPED_TEST_SUITE_P(TypedFormatConvertTest);
00239
00240 std::vector<std::string> AllFlagCombinations() {
00241 const char kFlags[] = {'-', '#', '0', '+', ' '};
00242 std::vector<std::string> result;
00243 for (size_t fsi = 0; fsi < (1ull << ArraySize(kFlags)); ++fsi) {
00244 std::string flag_set;
00245 for (size_t fi = 0; fi < ArraySize(kFlags); ++fi)
00246 if (fsi & (1ull << fi))
00247 flag_set += kFlags[fi];
00248 result.push_back(flag_set);
00249 }
00250 return result;
00251 }
00252
00253 TYPED_TEST_P(TypedFormatConvertTest, AllIntsWithFlags) {
00254 typedef TypeParam T;
00255 typedef typename std::make_unsigned<T>::type UnsignedT;
00256 using remove_volatile_t = typename std::remove_volatile<T>::type;
00257 const T kMin = std::numeric_limits<remove_volatile_t>::min();
00258 const T kMax = std::numeric_limits<remove_volatile_t>::max();
00259 const T kVals[] = {
00260 remove_volatile_t(1),
00261 remove_volatile_t(2),
00262 remove_volatile_t(3),
00263 remove_volatile_t(123),
00264 remove_volatile_t(-1),
00265 remove_volatile_t(-2),
00266 remove_volatile_t(-3),
00267 remove_volatile_t(-123),
00268 remove_volatile_t(0),
00269 kMax - remove_volatile_t(1),
00270 kMax,
00271 kMin + remove_volatile_t(1),
00272 kMin,
00273 };
00274 const char kConvChars[] = {'d', 'i', 'u', 'o', 'x', 'X'};
00275 const std::string kWid[] = {"", "4", "10"};
00276 const std::string kPrec[] = {"", ".", ".0", ".4", ".10"};
00277
00278 const std::vector<std::string> flag_sets = AllFlagCombinations();
00279
00280 for (size_t vi = 0; vi < ArraySize(kVals); ++vi) {
00281 const T val = kVals[vi];
00282 SCOPED_TRACE(Esc(val));
00283 const FormatArgImpl args[] = {FormatArgImpl(val)};
00284 for (size_t ci = 0; ci < ArraySize(kConvChars); ++ci) {
00285 const char conv_char = kConvChars[ci];
00286 for (size_t fsi = 0; fsi < flag_sets.size(); ++fsi) {
00287 const std::string &flag_set = flag_sets[fsi];
00288 for (size_t wi = 0; wi < ArraySize(kWid); ++wi) {
00289 const std::string &wid = kWid[wi];
00290 for (size_t pi = 0; pi < ArraySize(kPrec); ++pi) {
00291 const std::string &prec = kPrec[pi];
00292
00293 const bool is_signed_conv = (conv_char == 'd' || conv_char == 'i');
00294 const bool is_unsigned_to_signed =
00295 !std::is_signed<T>::value && is_signed_conv;
00296
00297
00298 if (is_unsigned_to_signed &&
00299 flag_set.find_first_of("+ ") != std::string::npos) {
00300 continue;
00301 }
00302
00303 std::string new_fmt("%");
00304 new_fmt += flag_set;
00305 new_fmt += wid;
00306 new_fmt += prec;
00307
00308 std::string old_fmt = new_fmt;
00309 new_fmt += conv_char;
00310 std::string old_result;
00311 if (is_unsigned_to_signed) {
00312
00313
00314
00315
00316 UnsignedT uval = val;
00317 old_fmt += LengthModFor(uval);
00318 old_fmt += "u";
00319 old_result = StrPrint(old_fmt.c_str(), uval);
00320 } else {
00321 old_fmt += LengthModFor(val);
00322 old_fmt += conv_char;
00323 old_result = StrPrint(old_fmt.c_str(), val);
00324 }
00325
00326 SCOPED_TRACE(std::string() + " old_fmt: \"" + old_fmt +
00327 "\"'"
00328 " new_fmt: \"" +
00329 new_fmt + "\"");
00330 UntypedFormatSpecImpl format(new_fmt);
00331 EXPECT_EQ(old_result, FormatPack(format, absl::MakeSpan(args)));
00332 }
00333 }
00334 }
00335 }
00336 }
00337 }
00338
00339 TYPED_TEST_P(TypedFormatConvertTest, Char) {
00340 typedef TypeParam T;
00341 using remove_volatile_t = typename std::remove_volatile<T>::type;
00342 static const T kMin = std::numeric_limits<remove_volatile_t>::min();
00343 static const T kMax = std::numeric_limits<remove_volatile_t>::max();
00344 T kVals[] = {
00345 remove_volatile_t(1), remove_volatile_t(2), remove_volatile_t(10),
00346 remove_volatile_t(-1), remove_volatile_t(-2), remove_volatile_t(-10),
00347 remove_volatile_t(0),
00348 kMin + remove_volatile_t(1), kMin,
00349 kMax - remove_volatile_t(1), kMax
00350 };
00351 for (const T &c : kVals) {
00352 const FormatArgImpl args[] = {FormatArgImpl(c)};
00353 UntypedFormatSpecImpl format("%c");
00354 EXPECT_EQ(StrPrint("%c", c), FormatPack(format, absl::MakeSpan(args)));
00355 }
00356 }
00357
00358 REGISTER_TYPED_TEST_CASE_P(TypedFormatConvertTest, AllIntsWithFlags, Char);
00359
00360 typedef ::testing::Types<
00361 int, unsigned, volatile int,
00362 short, unsigned short,
00363 long, unsigned long,
00364 long long, unsigned long long,
00365 signed char, unsigned char, char>
00366 AllIntTypes;
00367 INSTANTIATE_TYPED_TEST_CASE_P(TypedFormatConvertTestWithAllIntTypes,
00368 TypedFormatConvertTest, AllIntTypes);
00369
00370 TEST_F(FormatConvertTest, VectorBool) {
00371
00372 std::vector<bool> v = {true, false};
00373 const std::vector<bool> cv = {true, false};
00374 EXPECT_EQ("1,0,1,0",
00375 FormatPack(UntypedFormatSpecImpl("%d,%d,%d,%d"),
00376 absl::Span<const FormatArgImpl>(
00377 {FormatArgImpl(v[0]), FormatArgImpl(v[1]),
00378 FormatArgImpl(cv[0]), FormatArgImpl(cv[1])})));
00379 }
00380
00381 TEST_F(FormatConvertTest, Uint128) {
00382 absl::uint128 v = static_cast<absl::uint128>(0x1234567890abcdef) * 1979;
00383 absl::uint128 max = absl::Uint128Max();
00384 const FormatArgImpl args[] = {FormatArgImpl(v), FormatArgImpl(max)};
00385
00386 struct Case {
00387 const char* format;
00388 const char* expected;
00389 } cases[] = {
00390 {"%1$d", "2595989796776606496405"},
00391 {"%1$30d", " 2595989796776606496405"},
00392 {"%1$-30d", "2595989796776606496405 "},
00393 {"%1$u", "2595989796776606496405"},
00394 {"%1$x", "8cba9876066020f695"},
00395 {"%2$d", "340282366920938463463374607431768211455"},
00396 {"%2$u", "340282366920938463463374607431768211455"},
00397 {"%2$x", "ffffffffffffffffffffffffffffffff"},
00398 };
00399
00400 for (auto c : cases) {
00401 UntypedFormatSpecImpl format(c.format);
00402 EXPECT_EQ(c.expected, FormatPack(format, absl::MakeSpan(args)));
00403 }
00404 }
00405
00406 TEST_F(FormatConvertTest, Float) {
00407 #ifdef _MSC_VER
00408
00409
00410 return;
00411 #endif // _MSC_VER
00412
00413 const char *const kFormats[] = {
00414 "%", "%.3", "%8.5", "%9", "%.60", "%.30", "%03", "%+",
00415 "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"};
00416
00417 std::vector<double> doubles = {0.0,
00418 -0.0,
00419 .99999999999999,
00420 99999999999999.,
00421 std::numeric_limits<double>::max(),
00422 -std::numeric_limits<double>::max(),
00423 std::numeric_limits<double>::min(),
00424 -std::numeric_limits<double>::min(),
00425 std::numeric_limits<double>::lowest(),
00426 -std::numeric_limits<double>::lowest(),
00427 std::numeric_limits<double>::epsilon(),
00428 std::numeric_limits<double>::epsilon() + 1,
00429 std::numeric_limits<double>::infinity(),
00430 -std::numeric_limits<double>::infinity()};
00431
00432 #ifndef __APPLE__
00433
00434 doubles.push_back(std::nan(""));
00435 #endif
00436
00437
00438 doubles.push_back(0.99999999999999989);
00439
00440 if (std::numeric_limits<double>::has_denorm != std::denorm_absent) {
00441 doubles.push_back(std::numeric_limits<double>::denorm_min());
00442 doubles.push_back(-std::numeric_limits<double>::denorm_min());
00443 }
00444
00445 for (double base :
00446 {1., 12., 123., 1234., 12345., 123456., 1234567., 12345678., 123456789.,
00447 1234567890., 12345678901., 123456789012., 1234567890123.}) {
00448 for (int exp = -123; exp <= 123; ++exp) {
00449 for (int sign : {1, -1}) {
00450 doubles.push_back(sign * std::ldexp(base, exp));
00451 }
00452 }
00453 }
00454
00455 for (const char *fmt : kFormats) {
00456 for (char f : {'f', 'F',
00457 'g', 'G',
00458 'a', 'A',
00459 'e', 'E'}) {
00460 std::string fmt_str = std::string(fmt) + f;
00461 for (double d : doubles) {
00462 int i = -10;
00463 FormatArgImpl args[2] = {FormatArgImpl(d), FormatArgImpl(i)};
00464 UntypedFormatSpecImpl format(fmt_str);
00465
00466
00467
00468 ASSERT_EQ(StrPrint(fmt_str.c_str(), d, i),
00469 FormatPack(format, absl::MakeSpan(args)))
00470 << fmt_str << " " << StrPrint("%.18g", d) << " "
00471 << StrPrint("%.999f", d);
00472 }
00473 }
00474 }
00475 }
00476
00477 TEST_F(FormatConvertTest, LongDouble) {
00478 const char *const kFormats[] = {"%", "%.3", "%8.5", "%9",
00479 "%.60", "%+", "% ", "%-10"};
00480
00481
00482
00483
00484
00485 long double very_precise = 10000000000000000.25L;
00486
00487 std::vector<long double> doubles = {
00488 0.0,
00489 -0.0,
00490 very_precise,
00491 1 / very_precise,
00492 std::numeric_limits<long double>::max(),
00493 -std::numeric_limits<long double>::max(),
00494 std::numeric_limits<long double>::min(),
00495 -std::numeric_limits<long double>::min(),
00496 std::numeric_limits<long double>::infinity(),
00497 -std::numeric_limits<long double>::infinity()};
00498
00499 for (const char *fmt : kFormats) {
00500 for (char f : {'f', 'F',
00501 'g', 'G',
00502 'a', 'A',
00503 'e', 'E'}) {
00504 std::string fmt_str = std::string(fmt) + 'L' + f;
00505 for (auto d : doubles) {
00506 FormatArgImpl arg(d);
00507 UntypedFormatSpecImpl format(fmt_str);
00508
00509
00510
00511 ASSERT_EQ(StrPrint(fmt_str.c_str(), d),
00512 FormatPack(format, {&arg, 1}))
00513 << fmt_str << " " << StrPrint("%.18Lg", d) << " "
00514 << StrPrint("%.999Lf", d);
00515 }
00516 }
00517 }
00518 }
00519
00520 TEST_F(FormatConvertTest, IntAsFloat) {
00521 const int kMin = std::numeric_limits<int>::min();
00522 const int kMax = std::numeric_limits<int>::max();
00523 const int ia[] = {
00524 1, 2, 3, 123,
00525 -1, -2, -3, -123,
00526 0, kMax - 1, kMax, kMin + 1, kMin };
00527 for (const int fx : ia) {
00528 SCOPED_TRACE(fx);
00529 const FormatArgImpl args[] = {FormatArgImpl(fx)};
00530 struct Expectation {
00531 int line;
00532 std::string out;
00533 const char *fmt;
00534 };
00535 const double dx = static_cast<double>(fx);
00536 const Expectation kExpect[] = {
00537 { __LINE__, StrPrint("%f", dx), "%f" },
00538 { __LINE__, StrPrint("%12f", dx), "%12f" },
00539 { __LINE__, StrPrint("%.12f", dx), "%.12f" },
00540 { __LINE__, StrPrint("%12a", dx), "%12a" },
00541 { __LINE__, StrPrint("%.12a", dx), "%.12a" },
00542 };
00543 for (const Expectation &e : kExpect) {
00544 SCOPED_TRACE(e.line);
00545 SCOPED_TRACE(e.fmt);
00546 UntypedFormatSpecImpl format(e.fmt);
00547 EXPECT_EQ(e.out, FormatPack(format, absl::MakeSpan(args)));
00548 }
00549 }
00550 }
00551
00552 template <typename T>
00553 bool FormatFails(const char* test_format, T value) {
00554 std::string format_string = std::string("<<") + test_format + ">>";
00555 UntypedFormatSpecImpl format(format_string);
00556
00557 int one = 1;
00558 const FormatArgImpl args[] = {FormatArgImpl(value), FormatArgImpl(one)};
00559 EXPECT_EQ(FormatPack(format, absl::MakeSpan(args)), "")
00560 << "format=" << test_format << " value=" << value;
00561 return FormatPack(format, absl::MakeSpan(args)).empty();
00562 }
00563
00564 TEST_F(FormatConvertTest, ExpectedFailures) {
00565
00566 EXPECT_TRUE(FormatFails("%p", 1));
00567 EXPECT_TRUE(FormatFails("%s", 1));
00568 EXPECT_TRUE(FormatFails("%n", 1));
00569
00570
00571 EXPECT_TRUE(FormatFails("%p", 1.));
00572 EXPECT_TRUE(FormatFails("%s", 1.));
00573 EXPECT_TRUE(FormatFails("%n", 1.));
00574 EXPECT_TRUE(FormatFails("%c", 1.));
00575 EXPECT_TRUE(FormatFails("%d", 1.));
00576 EXPECT_TRUE(FormatFails("%x", 1.));
00577 EXPECT_TRUE(FormatFails("%*d", 1.));
00578
00579
00580 EXPECT_TRUE(FormatFails("%n", ""));
00581 EXPECT_TRUE(FormatFails("%c", ""));
00582 EXPECT_TRUE(FormatFails("%d", ""));
00583 EXPECT_TRUE(FormatFails("%x", ""));
00584 EXPECT_TRUE(FormatFails("%f", ""));
00585 EXPECT_TRUE(FormatFails("%*d", ""));
00586 }
00587
00588 }
00589 }
00590 }