cast_ut.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. #include "cast.h"
  2. #include <library/cpp/testing/unittest/registar.h>
  3. #include <util/charset/wide.h>
  4. #include <util/system/defaults.h>
  5. #include <limits>
  6. // positive test (return true or no exception)
  7. #define test1(t, v) \
  8. F<t>().CheckTryOK(v); \
  9. F<t>().CheckOK(v)
  10. // negative test (return false or exception)
  11. #define test2(t, v) \
  12. F<t>().CheckTryFail(v); \
  13. F<t>().CheckExc(v)
  14. #define EPS 10E-7
  15. #define HEX_MACROS_MAP(mac, type, val) mac(type, val, 2) mac(type, val, 8) mac(type, val, 10) mac(type, val, 16)
  16. #define OK_HEX_CHECK(type, val, base) UNIT_ASSERT_EQUAL((IntFromStringForCheck<base>(IntToString<base>(val))), val);
  17. #define EXC_HEX_CHECK(type, val, base) UNIT_ASSERT_EXCEPTION((IntFromString<type, base>(IntToString<base>(val))), yexception);
  18. #define TRY_HEX_MACROS_MAP(mac, type, val, result, def) \
  19. mac(type, val, result, def, 2) \
  20. mac(type, val, result, def, 8) \
  21. mac(type, val, result, def, 10) \
  22. mac(type, val, result, def, 16)
  23. #define TRY_OK_HEX_CHECK(type, val, result, def, base) \
  24. result = def; \
  25. UNIT_ASSERT_EQUAL(TryIntFromStringForCheck<base>(IntToString<base>(val), result), true); \
  26. UNIT_ASSERT_EQUAL(result, val);
  27. #define TRY_FAIL_HEX_CHECK(type, val, result, def, base) \
  28. result = def; \
  29. UNIT_ASSERT_VALUES_EQUAL(TryIntFromStringForCheck<base>(IntToString<base>(val), result), false); \
  30. UNIT_ASSERT_VALUES_EQUAL(result, def);
  31. template <class A>
  32. struct TRet {
  33. template <int base>
  34. inline A IntFromStringForCheck(const TString& str) {
  35. return IntFromString<A, base>(str);
  36. }
  37. template <int base>
  38. inline bool TryIntFromStringForCheck(const TString& str, A& result) {
  39. return TryIntFromString<base>(str, result);
  40. }
  41. template <class B>
  42. inline void CheckOK(B v) {
  43. UNIT_ASSERT_VALUES_EQUAL(FromString<A>(ToString(v)), v); // char
  44. UNIT_ASSERT_VALUES_EQUAL(FromString<A>(ToWtring(v)), v); // wide char
  45. HEX_MACROS_MAP(OK_HEX_CHECK, A, v);
  46. }
  47. template <class B>
  48. inline void CheckExc(B v) {
  49. UNIT_ASSERT_EXCEPTION(FromString<A>(ToString(v)), yexception); // char
  50. UNIT_ASSERT_EXCEPTION(FromString<A>(ToWtring(v)), yexception); // wide char
  51. HEX_MACROS_MAP(EXC_HEX_CHECK, A, v);
  52. }
  53. template <class B>
  54. inline void CheckTryOK(B v) {
  55. static const A defaultV = 42;
  56. A convV;
  57. UNIT_ASSERT_VALUES_EQUAL(TryFromString<A>(ToString(v), convV), true); // char
  58. UNIT_ASSERT_VALUES_EQUAL(v, convV);
  59. UNIT_ASSERT_VALUES_EQUAL(TryFromString<A>(ToWtring(v), convV), true); // wide char
  60. UNIT_ASSERT_VALUES_EQUAL(v, convV);
  61. TRY_HEX_MACROS_MAP(TRY_OK_HEX_CHECK, A, v, convV, defaultV);
  62. }
  63. template <class B>
  64. inline void CheckTryFail(B v) {
  65. static const A defaultV = 42;
  66. A convV = defaultV; // to check that original value is not trashed on bad cast
  67. UNIT_ASSERT_VALUES_EQUAL(TryFromString<A>(ToString(v), convV), false); // char
  68. UNIT_ASSERT_VALUES_EQUAL(defaultV, convV);
  69. UNIT_ASSERT_VALUES_EQUAL(TryFromString<A>(ToWtring(v), convV), false); // wide char
  70. UNIT_ASSERT_VALUES_EQUAL(defaultV, convV);
  71. TRY_HEX_MACROS_MAP(TRY_FAIL_HEX_CHECK, A, v, convV, defaultV);
  72. }
  73. };
  74. template <>
  75. struct TRet<bool> {
  76. template <class B>
  77. inline void CheckOK(B v) {
  78. UNIT_ASSERT_VALUES_EQUAL(FromString<bool>(ToString(v)), v);
  79. }
  80. template <class B>
  81. inline void CheckTryOK(B v) {
  82. B convV;
  83. UNIT_ASSERT_VALUES_EQUAL(TryFromString<bool>(ToString(v), convV), true);
  84. UNIT_ASSERT_VALUES_EQUAL(v, convV);
  85. }
  86. template <class B>
  87. inline void CheckExc(B v) {
  88. UNIT_ASSERT_EXCEPTION(FromString<bool>(ToString(v)), yexception);
  89. }
  90. template <class B>
  91. inline void CheckTryFail(B v) {
  92. static const bool defaultV = false;
  93. bool convV = defaultV;
  94. UNIT_ASSERT_VALUES_EQUAL(TryFromString<bool>(ToString(v), convV), false);
  95. UNIT_ASSERT_VALUES_EQUAL(defaultV, convV);
  96. }
  97. };
  98. template <class A>
  99. inline TRet<A> F() {
  100. return TRet<A>();
  101. }
  102. #if 0
  103. template <class T>
  104. inline void CheckConvertToBuffer(const T& value, const size_t size, const TString& canonValue) {
  105. const size_t maxSize = 256;
  106. char buffer[maxSize];
  107. const char magic = 0x7F;
  108. memset(buffer, magic, maxSize);
  109. size_t length = 0;
  110. if (canonValue.size() > size) { // overflow will occur
  111. UNIT_ASSERT_EXCEPTION(length = ToString(value, buffer, size), yexception);
  112. // check that no bytes after size was trashed
  113. for (size_t i = size; i < maxSize; ++i)
  114. UNIT_ASSERT_VALUES_EQUAL(buffer[i], magic);
  115. } else {
  116. length = ToString(value, buffer, size);
  117. UNIT_ASSERT(length < maxSize);
  118. // check that no bytes after length was trashed
  119. for (size_t i = length; i < maxSize; ++i)
  120. UNIT_ASSERT_VALUES_EQUAL(buffer[i], magic);
  121. TStringBuf result(buffer, length);
  122. UNIT_ASSERT_VALUES_EQUAL(result, TStringBuf(canonValue));
  123. }
  124. }
  125. #endif
  126. Y_UNIT_TEST_SUITE(TCastTest) {
  127. template <class A>
  128. inline TRet<A> F() {
  129. return TRet<A>();
  130. }
  131. template <class TFloat>
  132. void GoodFloatTester(const char* str, const TFloat canonValue, const double eps) {
  133. TFloat f = canonValue + 42.0; // shift value to make it far from proper
  134. UNIT_ASSERT_VALUES_EQUAL(TryFromString<TFloat>(str, f), true);
  135. UNIT_ASSERT_DOUBLES_EQUAL(f, canonValue, eps);
  136. f = FromString<TFloat>(str);
  137. UNIT_ASSERT_DOUBLES_EQUAL(f, canonValue, eps);
  138. }
  139. template <class TFloat>
  140. void BadFloatTester(const char* str) {
  141. const double eps = 10E-5;
  142. TFloat f = 42.0; // make it far from proper
  143. auto res = TryFromString<TFloat>(str, f);
  144. UNIT_ASSERT_VALUES_EQUAL(res, false);
  145. UNIT_ASSERT_DOUBLES_EQUAL(f, 42.0, eps); // check value was not trashed
  146. UNIT_ASSERT_EXCEPTION(f = FromString<TFloat>(str), TFromStringException);
  147. Y_UNUSED(f); // shut up compiler about 'assigned value that is not used'
  148. }
  149. Y_UNIT_TEST(TestToFrom) {
  150. test1(bool, true);
  151. test1(bool, false);
  152. test2(bool, "");
  153. test2(bool, "a");
  154. test2(ui8, -1);
  155. test1(i8, -1);
  156. test1(i8, SCHAR_MAX);
  157. test1(i8, SCHAR_MIN);
  158. test1(i8, SCHAR_MAX - 1);
  159. test1(i8, SCHAR_MIN + 1);
  160. test2(i8, (int)SCHAR_MAX + 1);
  161. test2(i8, (int)SCHAR_MIN - 1);
  162. test1(ui8, UCHAR_MAX);
  163. test1(ui8, UCHAR_MAX - 1);
  164. test2(ui8, (int)UCHAR_MAX + 1);
  165. test2(ui8, -1);
  166. test1(int, -1);
  167. test2(unsigned int, -1);
  168. test1(short int, -1);
  169. test2(unsigned short int, -1);
  170. test1(long int, -1);
  171. test2(unsigned long int, -1);
  172. test1(int, INT_MAX);
  173. test1(int, INT_MIN);
  174. test1(int, INT_MAX - 1);
  175. test1(int, INT_MIN + 1);
  176. test2(int, (long long int)INT_MAX + 1);
  177. test2(int, (long long int)INT_MIN - 1);
  178. test1(unsigned int, UINT_MAX);
  179. test1(unsigned int, UINT_MAX - 1);
  180. test2(unsigned int, (long long int)UINT_MAX + 1);
  181. test1(short int, SHRT_MAX);
  182. test1(short int, SHRT_MIN);
  183. test1(short int, SHRT_MAX - 1);
  184. test1(short int, SHRT_MIN + 1);
  185. test2(short int, (long long int)SHRT_MAX + 1);
  186. test2(short int, (long long int)SHRT_MIN - 1);
  187. test1(unsigned short int, USHRT_MAX);
  188. test1(unsigned short int, USHRT_MAX - 1);
  189. test2(unsigned short int, (long long int)USHRT_MAX + 1);
  190. test1(long int, LONG_MAX);
  191. test1(long int, LONG_MIN);
  192. test1(long int, LONG_MAX - 1);
  193. test1(long int, LONG_MIN + 1);
  194. test1(long long int, LLONG_MAX);
  195. test1(long long int, LLONG_MIN);
  196. test1(long long int, LLONG_MAX - 1);
  197. test1(long long int, LLONG_MIN + 1);
  198. }
  199. Y_UNIT_TEST(TestVolatile) {
  200. volatile int x = 1;
  201. UNIT_ASSERT_VALUES_EQUAL(ToString(x), "1");
  202. }
  203. Y_UNIT_TEST(TestStrToD) {
  204. UNIT_ASSERT_DOUBLES_EQUAL(StrToD("1.1", nullptr), 1.1, EPS);
  205. UNIT_ASSERT_DOUBLES_EQUAL(StrToD("1.12345678", nullptr), 1.12345678, EPS);
  206. UNIT_ASSERT_DOUBLES_EQUAL(StrToD("10E-5", nullptr), 10E-5, EPS);
  207. UNIT_ASSERT_DOUBLES_EQUAL(StrToD("1.1E+5", nullptr), 1.1E+5, EPS);
  208. char* ret = nullptr;
  209. UNIT_ASSERT_DOUBLES_EQUAL(StrToD("1.1y", &ret), 1.1, EPS);
  210. UNIT_ASSERT_VALUES_EQUAL(*ret, 'y');
  211. UNIT_ASSERT_DOUBLES_EQUAL(StrToD("1.12345678z", &ret), 1.12345678, EPS);
  212. UNIT_ASSERT_VALUES_EQUAL(*ret, 'z');
  213. UNIT_ASSERT_DOUBLES_EQUAL(StrToD("10E-5y", &ret), 10E-5, EPS);
  214. UNIT_ASSERT_VALUES_EQUAL(*ret, 'y');
  215. UNIT_ASSERT_DOUBLES_EQUAL(StrToD("1.1E+5z", &ret), 1.1E+5, EPS);
  216. UNIT_ASSERT_VALUES_EQUAL(*ret, 'z');
  217. }
  218. Y_UNIT_TEST(TestFloats) {
  219. // "%g" mode
  220. UNIT_ASSERT_VALUES_EQUAL(FloatToString(0.1f, PREC_NDIGITS, 6), "0.1"); // drop trailing zeroes
  221. UNIT_ASSERT_VALUES_EQUAL(FloatToString(0.12345678f, PREC_NDIGITS, 6), "0.123457");
  222. UNIT_ASSERT_VALUES_EQUAL(FloatToString(1e-20f, PREC_NDIGITS, 6), "1e-20");
  223. // "%f" mode
  224. UNIT_ASSERT_VALUES_EQUAL(FloatToString(0.1f, PREC_POINT_DIGITS, 6), "0.100000");
  225. UNIT_ASSERT_VALUES_EQUAL(FloatToString(0.12345678f, PREC_POINT_DIGITS, 6), "0.123457");
  226. UNIT_ASSERT_VALUES_EQUAL(FloatToString(1e-20f, PREC_POINT_DIGITS, 6), "0.000000");
  227. UNIT_ASSERT_VALUES_EQUAL(FloatToString(12.34f, PREC_POINT_DIGITS, 0), "12"); // rounding to integers drops '.'
  228. // strip trailing zeroes
  229. UNIT_ASSERT_VALUES_EQUAL(FloatToString(0.1f, PREC_POINT_DIGITS_STRIP_ZEROES, 6), "0.1");
  230. UNIT_ASSERT_VALUES_EQUAL(FloatToString(0.12345678f, PREC_POINT_DIGITS_STRIP_ZEROES, 6), "0.123457");
  231. UNIT_ASSERT_VALUES_EQUAL(FloatToString(1e-20f, PREC_POINT_DIGITS_STRIP_ZEROES, 6), "0");
  232. UNIT_ASSERT_VALUES_EQUAL(FloatToString(12.34f, PREC_POINT_DIGITS_STRIP_ZEROES, 0), "12"); // rounding to integers drops '.'
  233. UNIT_ASSERT_VALUES_EQUAL(FloatToString(10000.0f, PREC_POINT_DIGITS_STRIP_ZEROES, 0), "10000");
  234. // automatic selection of ndigits
  235. UNIT_ASSERT_VALUES_EQUAL(FloatToString(0.1f), "0.1"); // drop trailing zeroes
  236. UNIT_ASSERT_VALUES_EQUAL(FloatToString(0.12345678f), "0.12345678"); // 8 valid digits
  237. UNIT_ASSERT_VALUES_EQUAL(FloatToString(1000.00006f), "1000.00006"); // 9 valid digits
  238. UNIT_ASSERT_VALUES_EQUAL(FloatToString(1e-45f), "1e-45"); // denormalized: 1 valid digit
  239. UNIT_ASSERT_VALUES_EQUAL(FloatToString(-0.0f), "-0"); // sign must be preserved
  240. // version for double
  241. UNIT_ASSERT_VALUES_EQUAL(FloatToString(1.0 / 10000), "0.0001"); // trailing zeroes
  242. UNIT_ASSERT_VALUES_EQUAL(FloatToString(1.2345678901234567), "1.2345678901234567"); // no truncation
  243. UNIT_ASSERT_VALUES_EQUAL(FloatToString(5e-324), "5e-324"); // denormalized
  244. UNIT_ASSERT_VALUES_EQUAL(FloatToString(-0.0), "-0"); // sign must be preserved
  245. UNIT_ASSERT_STRINGS_EQUAL(FloatToString(std::numeric_limits<double>::quiet_NaN()), "nan");
  246. UNIT_ASSERT_STRINGS_EQUAL(FloatToString(std::numeric_limits<double>::infinity()), "inf");
  247. UNIT_ASSERT_STRINGS_EQUAL(FloatToString(-std::numeric_limits<double>::infinity()), "-inf");
  248. UNIT_ASSERT_STRINGS_EQUAL(FloatToString(std::numeric_limits<float>::quiet_NaN()), "nan");
  249. UNIT_ASSERT_STRINGS_EQUAL(FloatToString(std::numeric_limits<float>::infinity()), "inf");
  250. UNIT_ASSERT_STRINGS_EQUAL(FloatToString(-std::numeric_limits<float>::infinity()), "-inf");
  251. }
  252. Y_UNIT_TEST(TestReadFloats) {
  253. GoodFloatTester<float>("0.0001", 0.0001f, EPS);
  254. GoodFloatTester<double>("0.0001", 0.0001, EPS);
  255. GoodFloatTester<long double>("0.0001", 0.0001, EPS);
  256. GoodFloatTester<float>("10E-5", 10E-5f, EPS);
  257. GoodFloatTester<double>("1.0001E5", 1.0001E5, EPS);
  258. GoodFloatTester<long double>("1.0001e5", 1.0001e5, EPS);
  259. GoodFloatTester<long double>(".0001e5", .0001e5, EPS);
  260. BadFloatTester<float>("a10E-5");
  261. BadFloatTester<float>("10 ");
  262. BadFloatTester<float>("10\t");
  263. // BadFloatTester<float>("10E");
  264. // BadFloatTester<float>("10.E");
  265. BadFloatTester<float>("..0");
  266. BadFloatTester<float>(""); // IGNIETFERRO-300
  267. BadFloatTester<double>("1.00.01");
  268. BadFloatTester<double>("1.0001E5b");
  269. BadFloatTester<double>("1.0001s");
  270. BadFloatTester<double>("1..01");
  271. BadFloatTester<double>(""); // IGNIETFERRO-300
  272. BadFloatTester<long double>(".1.00");
  273. BadFloatTester<long double>("1.00.");
  274. BadFloatTester<long double>("1.0001e5-");
  275. BadFloatTester<long double>("10e 2");
  276. BadFloatTester<long double>(""); // IGNIETFERRO-300
  277. }
  278. Y_UNIT_TEST(TestLiteral) {
  279. UNIT_ASSERT_VALUES_EQUAL(ToString("abc"), TString("abc"));
  280. }
  281. Y_UNIT_TEST(TestFromStringStringBuf) {
  282. TString a = "xyz";
  283. TStringBuf b = FromString<TStringBuf>(a);
  284. UNIT_ASSERT_VALUES_EQUAL(a, b);
  285. UNIT_ASSERT_VALUES_EQUAL((void*)a.data(), (void*)b.data());
  286. }
  287. #if 0
  288. Y_UNIT_TEST(TestBufferOverflow) {
  289. CheckConvertToBuffer<float>(1.f, 5, "1");
  290. CheckConvertToBuffer<float>(1.005f, 3, "1.005");
  291. CheckConvertToBuffer<float>(1.00000000f, 3, "1");
  292. CheckConvertToBuffer<double>(1.f, 5, "1");
  293. CheckConvertToBuffer<double>(1.005f, 3, "1.005");
  294. CheckConvertToBuffer<double>(1.00000000f, 3, "1");
  295. CheckConvertToBuffer<int>(2, 5, "2");
  296. CheckConvertToBuffer<int>(1005, 3, "1005");
  297. CheckConvertToBuffer<size_t>(2, 5, "2");
  298. CheckConvertToBuffer<ui64>(1005000000000000ull, 32, "1005000000000000");
  299. CheckConvertToBuffer<ui64>(1005000000000000ull, 3, "1005000000000000");
  300. // TString longNumber = TString("1.") + TString(1 << 20, '1');
  301. // UNIT_ASSERT_EXCEPTION(FromString<double>(longNumber), yexception);
  302. }
  303. #endif
  304. Y_UNIT_TEST(TestWide) {
  305. TUtf16String iw = u"-100500";
  306. int iv = 0;
  307. UNIT_ASSERT_VALUES_EQUAL(TryFromString(iw, iv), true);
  308. UNIT_ASSERT_VALUES_EQUAL(iv, -100500);
  309. ui64 uv = 0;
  310. TUtf16String uw = u"21474836470";
  311. UNIT_ASSERT_VALUES_EQUAL(TryFromString(uw, uv), true);
  312. UNIT_ASSERT_VALUES_EQUAL(uv, 21474836470ull);
  313. TWtringBuf bw(uw.data(), uw.size());
  314. uv = 0;
  315. UNIT_ASSERT_VALUES_EQUAL(TryFromString(uw, uv), true);
  316. UNIT_ASSERT_VALUES_EQUAL(uv, 21474836470ull);
  317. const wchar16* beg = uw.data();
  318. uv = 0;
  319. UNIT_ASSERT_VALUES_EQUAL(TryFromString(beg, uw.size(), uv), true);
  320. UNIT_ASSERT_VALUES_EQUAL(uv, 21474836470ull);
  321. }
  322. Y_UNIT_TEST(TestDefault) {
  323. size_t res = 0;
  324. const size_t def1 = 42;
  325. TString s1("100500");
  326. UNIT_ASSERT_VALUES_EQUAL(TryFromStringWithDefault(s1, res, def1), true);
  327. UNIT_ASSERT_VALUES_EQUAL(res, 100500);
  328. UNIT_ASSERT_VALUES_EQUAL(TryFromStringWithDefault(s1, res), true);
  329. UNIT_ASSERT_VALUES_EQUAL(res, 100500);
  330. UNIT_ASSERT_VALUES_EQUAL(TryFromStringWithDefault("100500", res, def1), true);
  331. UNIT_ASSERT_VALUES_EQUAL(res, 100500);
  332. UNIT_CHECK_GENERATED_NO_EXCEPTION(FromStringWithDefault(s1, def1), yexception);
  333. UNIT_ASSERT_VALUES_EQUAL(FromStringWithDefault(s1, def1), 100500);
  334. UNIT_ASSERT_VALUES_EQUAL(FromStringWithDefault<size_t>(s1), 100500);
  335. UNIT_ASSERT_VALUES_EQUAL(FromStringWithDefault("100500", def1), 100500);
  336. TString s2("100q500");
  337. UNIT_ASSERT_VALUES_EQUAL(TryFromStringWithDefault(s2, res), false);
  338. UNIT_ASSERT_VALUES_EQUAL(res, size_t());
  339. UNIT_ASSERT_VALUES_EQUAL(TryFromStringWithDefault(s2, res, def1), false);
  340. UNIT_ASSERT_VALUES_EQUAL(res, def1);
  341. UNIT_ASSERT_VALUES_EQUAL(TryFromStringWithDefault("100q500", res), false);
  342. UNIT_ASSERT_VALUES_EQUAL(res, size_t());
  343. UNIT_ASSERT_VALUES_EQUAL(TryFromStringWithDefault("100 500", res), false);
  344. UNIT_ASSERT_VALUES_EQUAL(res, size_t());
  345. UNIT_CHECK_GENERATED_NO_EXCEPTION(FromStringWithDefault(s2, def1), yexception);
  346. UNIT_CHECK_GENERATED_NO_EXCEPTION(FromStringWithDefault("100q500", def1), yexception);
  347. UNIT_ASSERT_VALUES_EQUAL(FromStringWithDefault(s2, def1), def1);
  348. UNIT_ASSERT_VALUES_EQUAL(FromStringWithDefault<size_t>(s2), size_t());
  349. UNIT_ASSERT_VALUES_EQUAL(FromStringWithDefault<size_t>("100q500"), size_t());
  350. UNIT_CHECK_GENERATED_EXCEPTION(FromString<size_t>(s2), TFromStringException);
  351. int res2 = 0;
  352. const int def2 = -6;
  353. TUtf16String s3 = u"-100500";
  354. UNIT_ASSERT_VALUES_EQUAL(TryFromStringWithDefault(s3, res2, def2), true);
  355. UNIT_ASSERT_VALUES_EQUAL(res2, -100500);
  356. UNIT_ASSERT_VALUES_EQUAL(TryFromStringWithDefault(s3, res2), true);
  357. UNIT_ASSERT_VALUES_EQUAL(res2, -100500);
  358. UNIT_CHECK_GENERATED_NO_EXCEPTION(FromStringWithDefault(s3, def1), yexception);
  359. UNIT_ASSERT_VALUES_EQUAL(FromStringWithDefault(s3, def2), -100500);
  360. UNIT_ASSERT_VALUES_EQUAL(FromStringWithDefault<size_t>(s3), size_t());
  361. TUtf16String s4 = u"-f100500";
  362. UNIT_ASSERT_VALUES_EQUAL(TryFromStringWithDefault(s4, res2, def2), false);
  363. UNIT_ASSERT_VALUES_EQUAL(res2, def2);
  364. UNIT_ASSERT_VALUES_EQUAL(TryFromStringWithDefault(s4, res2), false);
  365. UNIT_ASSERT_VALUES_EQUAL(res2, size_t());
  366. UNIT_CHECK_GENERATED_NO_EXCEPTION(FromStringWithDefault(s4, def2), yexception);
  367. UNIT_ASSERT_VALUES_EQUAL(FromStringWithDefault(s4, def2), def2);
  368. UNIT_CHECK_GENERATED_EXCEPTION(FromString<size_t>(s4), yexception);
  369. UNIT_ASSERT_VALUES_EQUAL(FromStringWithDefault<size_t>(s4), size_t());
  370. }
  371. Y_UNIT_TEST(TestMaybe) {
  372. TMaybe<int> res;
  373. TString s1("100500");
  374. UNIT_CHECK_GENERATED_NO_EXCEPTION(res = TryFromString<int>(s1), yexception);
  375. UNIT_ASSERT_VALUES_EQUAL(res, 100500);
  376. UNIT_ASSERT_VALUES_EQUAL(TryFromString<int>("100500"), 100500);
  377. TString s2("100q500");
  378. UNIT_CHECK_GENERATED_NO_EXCEPTION(res = TryFromString<int>(s2), yexception);
  379. UNIT_ASSERT(res.Empty());
  380. TUtf16String s3 = u"-100500";
  381. UNIT_CHECK_GENERATED_NO_EXCEPTION(res = TryFromString<size_t>(s3), yexception);
  382. UNIT_ASSERT(res.Empty());
  383. TUtf16String s4 = u"-f100500";
  384. UNIT_CHECK_GENERATED_NO_EXCEPTION(res = TryFromString<int>(s4), yexception);
  385. UNIT_ASSERT(res.Empty());
  386. std::string s5 = "100500";
  387. UNIT_CHECK_GENERATED_NO_EXCEPTION(res = TryFromString<int>(s5), yexception);
  388. UNIT_ASSERT_VALUES_EQUAL(res, 100500);
  389. }
  390. Y_UNIT_TEST(TestBool) {
  391. // True cases
  392. UNIT_ASSERT_VALUES_EQUAL(FromString<bool>("yes"), true);
  393. UNIT_ASSERT_VALUES_EQUAL(FromString<bool>("1"), true);
  394. // False cases
  395. UNIT_ASSERT_VALUES_EQUAL(FromString<bool>("no"), false);
  396. UNIT_ASSERT_VALUES_EQUAL(FromString<bool>("0"), false);
  397. // Strange cases
  398. UNIT_ASSERT_EXCEPTION(FromString<bool>(""), yexception);
  399. UNIT_ASSERT_EXCEPTION(FromString<bool>("something"), yexception);
  400. }
  401. Y_UNIT_TEST(TestAutoDetectType) {
  402. UNIT_ASSERT_DOUBLES_EQUAL((float)FromString("0.0001"), 0.0001, EPS);
  403. UNIT_ASSERT_DOUBLES_EQUAL((double)FromString("0.0015", sizeof("0.0015") - 2), 0.001, EPS);
  404. UNIT_ASSERT_DOUBLES_EQUAL((long double)FromString(TStringBuf("0.0001")), 0.0001, EPS);
  405. UNIT_ASSERT_DOUBLES_EQUAL((float)FromString(TString("10E-5")), 10E-5, EPS);
  406. UNIT_ASSERT_VALUES_EQUAL((bool)FromString("da"), true);
  407. UNIT_ASSERT_VALUES_EQUAL((bool)FromString("no"), false);
  408. UNIT_ASSERT_VALUES_EQUAL((short)FromString(u"9000"), 9000);
  409. UNIT_ASSERT_VALUES_EQUAL((int)FromString(u"-100500"), -100500);
  410. UNIT_ASSERT_VALUES_EQUAL((unsigned long long)FromString(TWtringBuf(u"42", 1)), 4);
  411. int integer = FromString("125");
  412. ui16 wideCharacterCode = FromString(u"125");
  413. UNIT_ASSERT_VALUES_EQUAL(integer, wideCharacterCode);
  414. }
  415. Y_UNIT_TEST(ErrorMessages) {
  416. UNIT_ASSERT_EXCEPTION_CONTAINS(FromString<ui32>(""), TFromStringException, "empty string as number");
  417. UNIT_ASSERT_EXCEPTION_CONTAINS(FromString<ui32>("-"), TFromStringException, "Unexpected symbol \"-\" at pos 0 in string \"-\"");
  418. UNIT_ASSERT_EXCEPTION_CONTAINS(FromString<i32>("-"), TFromStringException, "Cannot parse string \"-\" as number");
  419. UNIT_ASSERT_EXCEPTION_CONTAINS(FromString<i32>("+"), TFromStringException, "Cannot parse string \"+\" as number");
  420. UNIT_ASSERT_EXCEPTION_CONTAINS(FromString<i32>("0.328413745072"), TFromStringException, "Unexpected symbol \".\" at pos 1 in string \"0.328413745072\"");
  421. }
  422. Y_UNIT_TEST(TryStringBuf) {
  423. {
  424. constexpr TStringBuf hello = "hello";
  425. TStringBuf out;
  426. UNIT_ASSERT(TryFromString(hello, out));
  427. UNIT_ASSERT_VALUES_EQUAL(hello, out);
  428. }
  429. {
  430. constexpr TStringBuf empty = "";
  431. TStringBuf out;
  432. UNIT_ASSERT(TryFromString(empty, out));
  433. UNIT_ASSERT_VALUES_EQUAL(empty, out);
  434. }
  435. {
  436. constexpr TStringBuf empty;
  437. TStringBuf out;
  438. UNIT_ASSERT(TryFromString(empty, out));
  439. UNIT_ASSERT_VALUES_EQUAL(empty, out);
  440. }
  441. {
  442. const auto hello = u"hello";
  443. TWtringBuf out;
  444. UNIT_ASSERT(TryFromString(hello, out));
  445. UNIT_ASSERT_VALUES_EQUAL(hello, out);
  446. }
  447. {
  448. const TUtf16String empty;
  449. TWtringBuf out;
  450. UNIT_ASSERT(TryFromString(empty, out));
  451. UNIT_ASSERT_VALUES_EQUAL(empty, out);
  452. }
  453. {
  454. constexpr TWtringBuf empty;
  455. TWtringBuf out;
  456. UNIT_ASSERT(TryFromString(empty, out));
  457. UNIT_ASSERT_VALUES_EQUAL(empty, out);
  458. }
  459. }
  460. Y_UNIT_TEST(Nan) {
  461. double xx = 0;
  462. UNIT_ASSERT(!TryFromString("NaN", xx));
  463. UNIT_ASSERT(!TryFromString("NAN", xx));
  464. UNIT_ASSERT(!TryFromString("nan", xx));
  465. }
  466. Y_UNIT_TEST(Infinity) {
  467. double xx = 0;
  468. UNIT_ASSERT(!TryFromString("Infinity", xx));
  469. UNIT_ASSERT(!TryFromString("INFINITY", xx));
  470. UNIT_ASSERT(!TryFromString("infinity", xx));
  471. }
  472. Y_UNIT_TEST(TestBorderCases) {
  473. UNIT_ASSERT_VALUES_EQUAL(ToString(0.0), "0");
  474. UNIT_ASSERT_VALUES_EQUAL(ToString(1.0), "1");
  475. UNIT_ASSERT_VALUES_EQUAL(ToString(10.0), "10");
  476. UNIT_ASSERT_VALUES_EQUAL(ToString(NAN), "nan");
  477. UNIT_ASSERT_VALUES_EQUAL(ToString(-NAN), "nan");
  478. UNIT_ASSERT_VALUES_EQUAL(ToString(INFINITY), "inf");
  479. UNIT_ASSERT_VALUES_EQUAL(ToString(-INFINITY), "-inf");
  480. UNIT_ASSERT_VALUES_EQUAL(ToString(1.1e+100), "1.1e+100");
  481. UNIT_ASSERT_VALUES_EQUAL(ToString(1e+100), "1e+100");
  482. UNIT_ASSERT_VALUES_EQUAL(ToString(87423.2031250000001), "87423.20313");
  483. UNIT_ASSERT_VALUES_EQUAL(FloatToString(1.0e60, PREC_POINT_DIGITS_STRIP_ZEROES, 0), "1e+60");
  484. }
  485. Y_UNIT_TEST(TestChar) {
  486. // Given a character ch, ToString(ch) returns
  487. // the decimal representation of its integral value
  488. // char
  489. UNIT_ASSERT_VALUES_EQUAL(ToString('\0'), "0");
  490. UNIT_ASSERT_VALUES_EQUAL(ToString('0'), "48");
  491. // wchar16
  492. UNIT_ASSERT_VALUES_EQUAL(ToString(u'\0'), "0");
  493. UNIT_ASSERT_VALUES_EQUAL(ToString(u'0'), "48");
  494. UNIT_ASSERT_VALUES_EQUAL(ToString(u'я'), "1103");
  495. UNIT_ASSERT_VALUES_EQUAL(ToString(u'\uFFFF'), "65535");
  496. // wchar32
  497. UNIT_ASSERT_VALUES_EQUAL(ToString(U'\0'), "0");
  498. UNIT_ASSERT_VALUES_EQUAL(ToString(U'0'), "48");
  499. UNIT_ASSERT_VALUES_EQUAL(ToString(U'я'), "1103");
  500. UNIT_ASSERT_VALUES_EQUAL(ToString(U'\U0001F600'), "128512"); // 'GRINNING FACE' (U+1F600)
  501. }
  502. Y_UNIT_TEST(TestTIntStringBuf) {
  503. static_assert(TStringBuf(TIntStringBuf(111)) == TStringBuf("111"));
  504. static_assert(TStringBuf(TIntStringBuf(-111)) == TStringBuf("-111"));
  505. UNIT_ASSERT_VALUES_EQUAL(TStringBuf(TIntStringBuf(0)), "0"sv);
  506. UNIT_ASSERT_VALUES_EQUAL(TStringBuf(TIntStringBuf(1111)), "1111"sv);
  507. UNIT_ASSERT_VALUES_EQUAL(TStringBuf(TIntStringBuf(-1)), "-1"sv);
  508. UNIT_ASSERT_VALUES_EQUAL(TStringBuf(TIntStringBuf(-1111)), "-1111"sv);
  509. constexpr auto v = TIntStringBuf(-1111);
  510. UNIT_ASSERT_VALUES_EQUAL(TStringBuf(v), TStringBuf(ToString(-1111)));
  511. UNIT_ASSERT_VALUES_EQUAL(TStringBuf(TIntStringBuf<ui16>(65535)), TStringBuf("65535"));
  512. UNIT_ASSERT_VALUES_EQUAL(TStringBuf(TIntStringBuf<i16>(32767)), TStringBuf("32767"));
  513. UNIT_ASSERT_VALUES_EQUAL(TStringBuf(TIntStringBuf<i32>(-32768)), TStringBuf("-32768"));
  514. UNIT_ASSERT_VALUES_EQUAL(TStringBuf(TIntStringBuf<i8, 2>(127)), TStringBuf("1111111"));
  515. UNIT_ASSERT_VALUES_EQUAL(TStringBuf(TIntStringBuf<i8, 2>(-128)), TStringBuf("-10000000"));
  516. }
  517. }