test_string_conversion.cxx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #include <cstdint>
  2. #include <variant>
  3. #include <pqxx/connection>
  4. #include <pqxx/transaction>
  5. #include "../test_helpers.hxx"
  6. // Some enums with string conversions.
  7. enum EnumA
  8. {
  9. ea0,
  10. ea1,
  11. ea2
  12. };
  13. enum EnumB
  14. {
  15. eb0,
  16. eb1,
  17. eb2
  18. };
  19. namespace pqxx
  20. {
  21. PQXX_DECLARE_ENUM_CONVERSION(EnumA);
  22. PQXX_DECLARE_ENUM_CONVERSION(EnumB);
  23. } // namespace pqxx
  24. namespace
  25. {
  26. // "A minimal difference."
  27. constexpr double thres{0.00001};
  28. void test_string_conversion()
  29. {
  30. PQXX_CHECK_EQUAL(
  31. "C string array", pqxx::to_string("C string array"),
  32. "C-style string constant does not convert to string properly.");
  33. char text_array[]{"C char array"};
  34. PQXX_CHECK_EQUAL(
  35. "C char array", pqxx::to_string(text_array),
  36. "C-style non-const char array does not convert to string properly.");
  37. char const *text_ptr{"C string pointer"};
  38. PQXX_CHECK_EQUAL(
  39. "C string pointer", pqxx::to_string(text_ptr),
  40. "C-style string pointer does not convert to string properly.");
  41. std::string const cxx_string{"C++ string"};
  42. PQXX_CHECK_EQUAL(
  43. "C++ string", pqxx::to_string(cxx_string),
  44. "C++-style string object does not convert to string properly.");
  45. PQXX_CHECK_EQUAL("0", pqxx::to_string(0), "Zero does not convert right.");
  46. PQXX_CHECK_EQUAL(
  47. "1", pqxx::to_string(1), "Basic integer does not convert right.");
  48. PQXX_CHECK_EQUAL("-1", pqxx::to_string(-1), "Negative numbers don't work.");
  49. PQXX_CHECK_EQUAL(
  50. "9999", pqxx::to_string(9999), "Larger numbers don't work.");
  51. PQXX_CHECK_EQUAL(
  52. "-9999", pqxx::to_string(-9999), "Larger negative numbers don't work.");
  53. int x;
  54. pqxx::from_string("0", x);
  55. PQXX_CHECK_EQUAL(0, x, "Zero does not parse right.");
  56. pqxx::from_string("1", x);
  57. PQXX_CHECK_EQUAL(1, x, "Basic integer does not parse right.");
  58. pqxx::from_string("-1", x);
  59. PQXX_CHECK_EQUAL(-1, x, "Negative numbers don't work.");
  60. pqxx::from_string("9999", x);
  61. PQXX_CHECK_EQUAL(9999, x, "Larger numbers don't work.");
  62. pqxx::from_string("-9999", x);
  63. PQXX_CHECK_EQUAL(-9999, x, "Larger negative numbers don't work.");
  64. // Bug #263 describes a case where this kind of overflow went undetected.
  65. if (sizeof(unsigned int) == 4)
  66. {
  67. std::uint32_t u;
  68. PQXX_CHECK_THROWS(
  69. pqxx::from_string("4772185884", u), pqxx::conversion_error,
  70. "Overflow not detected.");
  71. }
  72. // We can convert to and from long double. The implementation may fall
  73. // back on a thread-local std::stringstream. Each call does its own
  74. // cleanup, so the conversion works multiple times.
  75. constexpr long double ld1{123456789.25}, ld2{9876543210.5};
  76. constexpr char lds1[]{"123456789.25"}, lds2[]{"9876543210.5"};
  77. PQXX_CHECK_EQUAL(
  78. pqxx::to_string(ld1).substr(0, 12), lds1,
  79. "Wrong conversion from long double.");
  80. PQXX_CHECK_EQUAL(
  81. pqxx::to_string(ld2).substr(0, 12), lds2,
  82. "Wrong value on repeated conversion from long double.");
  83. long double ldi1, ldi2;
  84. pqxx::from_string(lds1, ldi1);
  85. PQXX_CHECK_BOUNDS(
  86. ldi1, ld1 - thres, ld1 + thres, "Wrong conversion to long double.");
  87. pqxx::from_string(lds2, ldi2);
  88. PQXX_CHECK_BOUNDS(
  89. ldi2, ld2 - thres, ld2 + thres,
  90. "Wrong repeated conversion to long double.");
  91. // We can define string conversions for enums.
  92. PQXX_CHECK_EQUAL(
  93. pqxx::to_string(ea0), "0", "Enum-to-string conversion is broken.");
  94. PQXX_CHECK_EQUAL(
  95. pqxx::to_string(eb0), "0",
  96. "Enum-to-string conversion is inconsistent between enum types.");
  97. PQXX_CHECK_EQUAL(
  98. pqxx::to_string(ea1), "1",
  99. "Enum-to-string conversion breaks for nonzero value.");
  100. EnumA ea;
  101. pqxx::from_string("2", ea);
  102. PQXX_CHECK_EQUAL(ea, ea2, "String-to-enum conversion is broken.");
  103. }
  104. void test_convert_variant_to_string()
  105. {
  106. PQXX_CHECK_EQUAL(
  107. pqxx::to_string(std::variant<int, std::string>{99}), "99",
  108. "First variant field did not convert right.");
  109. PQXX_CHECK_EQUAL(
  110. pqxx::to_string(std::variant<int, std::string>{"Text"}), "Text",
  111. "Second variant field did not convert right.");
  112. }
  113. void test_integer_conversion()
  114. {
  115. PQXX_CHECK_EQUAL(
  116. pqxx::from_string<int>("12"), 12, "Basic integer conversion failed.");
  117. PQXX_CHECK_EQUAL(
  118. pqxx::from_string<int>(" 12"), 12,
  119. "Leading whitespace confused integer conversion.");
  120. PQXX_CHECK_THROWS(
  121. pqxx::ignore_unused(pqxx::from_string<int>("")), pqxx::conversion_error,
  122. "Converting empty string to integer did not throw conversion error.");
  123. PQXX_CHECK_THROWS(
  124. pqxx::ignore_unused(pqxx::from_string<int>(" ")), pqxx::conversion_error,
  125. "Converting whitespace to integer did not throw conversion error.");
  126. PQXX_CHECK_EQUAL(
  127. pqxx::from_string<int>("-6"), -6,
  128. "Leading whitespace did not work with negative number.");
  129. PQXX_CHECK_THROWS(
  130. pqxx::ignore_unused(pqxx::from_string<int>("- 3")), pqxx::conversion_error,
  131. "A space between negation and number was not properly flagged.");
  132. PQXX_CHECK_THROWS(
  133. pqxx::ignore_unused(pqxx::from_string<int>("-")), pqxx::conversion_error,
  134. "Just a minus sign should not parse as an integer.");
  135. }
  136. void test_convert_null()
  137. {
  138. pqxx::connection conn;
  139. pqxx::work tx{conn};
  140. PQXX_CHECK_EQUAL(
  141. tx.quote(nullptr), "NULL", "Null pointer did not come out as SQL 'null'.");
  142. PQXX_CHECK_EQUAL(
  143. tx.quote(std::nullopt), "NULL",
  144. "std::nullopt did not come out as SQL 'null'.");
  145. PQXX_CHECK_EQUAL(
  146. tx.quote(std::monostate{}), "NULL",
  147. "std::monostate did not come out as SQL 'null'.");
  148. }
  149. PQXX_REGISTER_TEST(test_string_conversion);
  150. PQXX_REGISTER_TEST(test_convert_variant_to_string);
  151. PQXX_REGISTER_TEST(test_integer_conversion);
  152. PQXX_REGISTER_TEST(test_convert_null);
  153. } // namespace