format_ut.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. #include <library/cpp/testing/gtest/gtest.h>
  2. #include <library/cpp/yt/string/format.h>
  3. #include <library/cpp/yt/small_containers/compact_vector.h>
  4. #include <util/generic/hash_set.h>
  5. #include <limits>
  6. namespace NYT {
  7. namespace {
  8. ////////////////////////////////////////////////////////////////////////////////
  9. // Some compile-time sanity checks.
  10. static_assert(CFormattable<int>);
  11. static_assert(CFormattable<double>);
  12. static_assert(CFormattable<void*>);
  13. static_assert(CFormattable<const char*>);
  14. static_assert(CFormattable<TStringBuf>);
  15. static_assert(CFormattable<TString>);
  16. static_assert(CFormattable<std::span<int>>);
  17. static_assert(CFormattable<std::vector<int>>);
  18. // N.B. TCompactVector<int, 1> is not buildable on Windows
  19. static_assert(CFormattable<TCompactVector<int, 2>>);
  20. static_assert(CFormattable<std::set<int>>);
  21. static_assert(CFormattable<std::map<int, int>>);
  22. static_assert(CFormattable<std::multimap<int, int>>);
  23. static_assert(CFormattable<THashSet<int>>);
  24. static_assert(CFormattable<THashMap<int, int>>);
  25. static_assert(CFormattable<THashMultiSet<int>>);
  26. static_assert(CFormattable<std::pair<int, int>>);
  27. static_assert(CFormattable<std::optional<int>>);
  28. static_assert(CFormattable<TDuration>);
  29. static_assert(CFormattable<TInstant>);
  30. struct TUnformattable
  31. { };
  32. static_assert(!CFormattable<TUnformattable>);
  33. ////////////////////////////////////////////////////////////////////////////////
  34. TEST(TFormatTest, Nothing)
  35. {
  36. EXPECT_EQ("abc", Format("a%nb%nc", 1, 2));
  37. }
  38. TEST(TFormatTest, Verbatim)
  39. {
  40. EXPECT_EQ("", Format(""));
  41. EXPECT_EQ("test", Format("test"));
  42. EXPECT_EQ("%", Format("%%"));
  43. EXPECT_EQ("%hello%world%", Format("%%hello%%world%%"));
  44. }
  45. TEST(TFormatTest, MultipleArgs)
  46. {
  47. EXPECT_EQ("2+2=4", Format("%v+%v=%v", 2, 2, 4));
  48. }
  49. TEST(TFormatTest, Strings)
  50. {
  51. EXPECT_EQ("test", Format("%s", "test"));
  52. EXPECT_EQ("test", Format("%s", TStringBuf("test")));
  53. EXPECT_EQ("test", Format("%s", TString("test")));
  54. EXPECT_EQ(" abc", Format("%6s", TString("abc")));
  55. EXPECT_EQ("abc ", Format("%-6s", TString("abc")));
  56. EXPECT_EQ(" abc", Format("%10v", TString("abc")));
  57. EXPECT_EQ("abc ", Format("%-10v", TString("abc")));
  58. EXPECT_EQ("abc", Format("%2s", TString("abc")));
  59. EXPECT_EQ("abc", Format("%-2s", TString("abc")));
  60. EXPECT_EQ("abc", Format("%0s", TString("abc")));
  61. EXPECT_EQ("abc", Format("%-0s", TString("abc")));
  62. EXPECT_EQ(100, std::ssize(Format("%100v", "abc")));
  63. }
  64. TEST(TFormatTest, DecIntegers)
  65. {
  66. EXPECT_EQ("123", Format("%d", 123));
  67. EXPECT_EQ("123", Format("%v", 123));
  68. EXPECT_EQ("042", Format("%03d", 42));
  69. EXPECT_EQ("42", Format("%01d", 42));
  70. EXPECT_EQ("2147483647", Format("%d", std::numeric_limits<i32>::max()));
  71. EXPECT_EQ("-2147483648", Format("%d", std::numeric_limits<i32>::min()));
  72. EXPECT_EQ("0", Format("%u", 0U));
  73. EXPECT_EQ("0", Format("%v", 0U));
  74. EXPECT_EQ("4294967295", Format("%u", std::numeric_limits<ui32>::max()));
  75. EXPECT_EQ("4294967295", Format("%v", std::numeric_limits<ui32>::max()));
  76. EXPECT_EQ("9223372036854775807", Format("%" PRId64, std::numeric_limits<i64>::max()));
  77. EXPECT_EQ("9223372036854775807", Format("%v", std::numeric_limits<i64>::max()));
  78. EXPECT_EQ("-9223372036854775808", Format("%" PRId64, std::numeric_limits<i64>::min()));
  79. EXPECT_EQ("-9223372036854775808", Format("%v", std::numeric_limits<i64>::min()));
  80. EXPECT_EQ("0", Format("%" PRIu64, 0ULL));
  81. EXPECT_EQ("0", Format("%v", 0ULL));
  82. EXPECT_EQ("18446744073709551615", Format("%" PRIu64, std::numeric_limits<ui64>::max()));
  83. EXPECT_EQ("18446744073709551615", Format("%v", std::numeric_limits<ui64>::max()));
  84. }
  85. TEST(TFormatTest, HexIntegers)
  86. {
  87. EXPECT_EQ("7b", Format("%x", 123));
  88. EXPECT_EQ("7B", Format("%X", 123));
  89. EXPECT_EQ("02a", Format("%03x", 42));
  90. EXPECT_EQ("2a", Format("%01x", 42));
  91. EXPECT_EQ("7fffffff", Format("%x", std::numeric_limits<i32>::max()));
  92. EXPECT_EQ("-80000000", Format("%x", std::numeric_limits<i32>::min()));
  93. EXPECT_EQ("0", Format("%x", 0U));
  94. EXPECT_EQ("0", Format("%X", 0U));
  95. EXPECT_EQ("ffffffff", Format("%x", std::numeric_limits<ui32>::max()));
  96. EXPECT_EQ("7fffffffffffffff", Format("%x", std::numeric_limits<i64>::max()));
  97. EXPECT_EQ("-8000000000000000", Format("%x", std::numeric_limits<i64>::min()));
  98. EXPECT_EQ("0", Format("%x", 0ULL));
  99. EXPECT_EQ("ffffffffffffffff", Format("%x", std::numeric_limits<ui64>::max()));
  100. }
  101. TEST(TFormatTest, Floats)
  102. {
  103. EXPECT_EQ("3.14", Format("%.2f", 3.1415F));
  104. EXPECT_EQ("3.14", Format("%.2v", 3.1415F));
  105. EXPECT_EQ("3.14", Format("%.2lf", 3.1415));
  106. EXPECT_EQ("3.14", Format("%.2v", 3.1415));
  107. EXPECT_EQ(TString(std::to_string(std::numeric_limits<double>::max())),
  108. Format("%lF", std::numeric_limits<double>::max()));
  109. }
  110. TEST(TFormatTest, Bool)
  111. {
  112. EXPECT_EQ("True", Format("%v", true));
  113. EXPECT_EQ("False", Format("%v", false));
  114. EXPECT_EQ("true", Format("%lv", true));
  115. EXPECT_EQ("false", Format("%lv", false));
  116. }
  117. TEST(TFormatTest, Quotes)
  118. {
  119. EXPECT_EQ("\"True\"", Format("%Qv", true));
  120. EXPECT_EQ("'False'", Format("%qv", false));
  121. EXPECT_EQ("'\\\'\"'", Format("%qv", "\'\""));
  122. EXPECT_EQ("\"\\x01\"", Format("%Qv", "\x1"));
  123. EXPECT_EQ("'\\x1b'", Format("%qv", '\x1b'));
  124. EXPECT_EQ("'\\\\'", Format("%qv", '\\'));
  125. EXPECT_EQ("'\\n'", Format("%qv", '\n'));
  126. EXPECT_EQ("'\\t'", Format("%qv", '\t'));
  127. EXPECT_EQ("'\\\''", Format("%qv", '\''));
  128. EXPECT_EQ("\"'\"", Format("%Qv", '\''));
  129. EXPECT_EQ("'\"'", Format("%qv", '\"'));
  130. EXPECT_EQ("\"\\\"\"", Format("%Qv", '\"'));
  131. }
  132. TEST(TFormatTest, Escape)
  133. {
  134. EXPECT_EQ("\'\"", Format("%hv", "\'\""));
  135. EXPECT_EQ("\\x01", Format("%hv", "\x1"));
  136. EXPECT_EQ("\\x1b", Format("%hv", '\x1b'));
  137. EXPECT_EQ("\\\\", Format("%hv", '\\'));
  138. EXPECT_EQ("\\n", Format("%hv", '\n'));
  139. EXPECT_EQ("\\t", Format("%hv", '\t'));
  140. EXPECT_EQ("\'", Format("%hv", '\''));
  141. }
  142. TEST(TFormatTest, Nullable)
  143. {
  144. EXPECT_EQ("1", Format("%v", std::make_optional<int>(1)));
  145. EXPECT_EQ("<null>", Format("%v", std::nullopt));
  146. EXPECT_EQ("<null>", Format("%v", std::optional<int>()));
  147. EXPECT_EQ("3.14", Format("%.2f", std::optional<double>(3.1415)));
  148. }
  149. TEST(TFormatTest, Pointers)
  150. {
  151. {
  152. auto ptr = reinterpret_cast<void*>(0x12345678);
  153. EXPECT_EQ("0x12345678", Format("%p", ptr));
  154. EXPECT_EQ("0x12345678", Format("%v", ptr));
  155. EXPECT_EQ("12345678", Format("%x", ptr));
  156. EXPECT_EQ("12345678", Format("%X", ptr));
  157. }
  158. {
  159. auto ptr = reinterpret_cast<void*>(0x12345678abcdefab);
  160. EXPECT_EQ("0x12345678abcdefab", Format("%p", ptr));
  161. EXPECT_EQ("0x12345678abcdefab", Format("%v", ptr));
  162. EXPECT_EQ("12345678abcdefab", Format("%x", ptr));
  163. EXPECT_EQ("12345678ABCDEFAB", Format("%X", ptr));
  164. }
  165. }
  166. TEST(TFormatTest, LazyMultiValueFormatter)
  167. {
  168. int i = 1;
  169. TString s = "hello";
  170. std::vector<int> range{1, 2, 3};
  171. auto lazyFormatter = MakeLazyMultiValueFormatter(
  172. "int: %v, string: %v, range: %v",
  173. i,
  174. s,
  175. MakeFormattableView(range, TDefaultFormatter{}));
  176. EXPECT_EQ("int: 1, string: hello, range: [1, 2, 3]", Format("%v", lazyFormatter));
  177. }
  178. TEST(TFormatTest, VectorArg)
  179. {
  180. std::vector<TString> params = {"a", "b", "c"};
  181. EXPECT_EQ(FormatVector("a is %v, b is %v, c is %v", params), "a is a, b is b, c is c");
  182. }
  183. TEST(TFormatTest, RuntimeFormat)
  184. {
  185. TString format = "Hello %v";
  186. EXPECT_EQ(Format(TRuntimeFormat(format), "World"), "Hello World");
  187. }
  188. ////////////////////////////////////////////////////////////////////////////////
  189. } // namespace
  190. } // namespace NYT