iostream_state_saver_test.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. // Copyright 2017 The Abseil Authors.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // https://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "absl/random/internal/iostream_state_saver.h"
  15. #include <errno.h>
  16. #include <stdio.h>
  17. #include <sstream>
  18. #include <string>
  19. #include "gtest/gtest.h"
  20. namespace {
  21. using absl::random_internal::make_istream_state_saver;
  22. using absl::random_internal::make_ostream_state_saver;
  23. using absl::random_internal::stream_precision_helper;
  24. template <typename T>
  25. typename absl::enable_if_t<std::is_integral<T>::value, T> //
  26. StreamRoundTrip(T t) {
  27. std::stringstream ss;
  28. {
  29. auto saver = make_ostream_state_saver(ss);
  30. ss.precision(stream_precision_helper<T>::kPrecision);
  31. ss << t;
  32. }
  33. T result = 0;
  34. {
  35. auto saver = make_istream_state_saver(ss);
  36. ss >> result;
  37. }
  38. EXPECT_FALSE(ss.fail()) //
  39. << ss.str() << " " //
  40. << (ss.good() ? "good " : "") //
  41. << (ss.bad() ? "bad " : "") //
  42. << (ss.eof() ? "eof " : "") //
  43. << (ss.fail() ? "fail " : "");
  44. return result;
  45. }
  46. template <typename T>
  47. typename absl::enable_if_t<std::is_floating_point<T>::value, T> //
  48. StreamRoundTrip(T t) {
  49. std::stringstream ss;
  50. {
  51. auto saver = make_ostream_state_saver(ss);
  52. ss.precision(stream_precision_helper<T>::kPrecision);
  53. ss << t;
  54. }
  55. T result = 0;
  56. {
  57. auto saver = make_istream_state_saver(ss);
  58. result = absl::random_internal::read_floating_point<T>(ss);
  59. }
  60. EXPECT_FALSE(ss.fail()) //
  61. << ss.str() << " " //
  62. << (ss.good() ? "good " : "") //
  63. << (ss.bad() ? "bad " : "") //
  64. << (ss.eof() ? "eof " : "") //
  65. << (ss.fail() ? "fail " : "");
  66. return result;
  67. }
  68. TEST(IOStreamStateSaver, BasicSaverState) {
  69. std::stringstream ss;
  70. ss.precision(2);
  71. ss.fill('x');
  72. ss.flags(std::ios_base::dec | std::ios_base::right);
  73. {
  74. auto saver = make_ostream_state_saver(ss);
  75. ss.precision(10);
  76. EXPECT_NE('x', ss.fill());
  77. EXPECT_EQ(10, ss.precision());
  78. EXPECT_NE(std::ios_base::dec | std::ios_base::right, ss.flags());
  79. ss << 1.23;
  80. }
  81. EXPECT_EQ('x', ss.fill());
  82. EXPECT_EQ(2, ss.precision());
  83. EXPECT_EQ(std::ios_base::dec | std::ios_base::right, ss.flags());
  84. }
  85. TEST(IOStreamStateSaver, RoundTripInts) {
  86. const uint64_t kUintValues[] = {
  87. 0,
  88. 1,
  89. static_cast<uint64_t>(-1),
  90. 2,
  91. static_cast<uint64_t>(-2),
  92. 1 << 7,
  93. 1 << 8,
  94. 1 << 16,
  95. 1ull << 32,
  96. 1ull << 50,
  97. 1ull << 62,
  98. 1ull << 63,
  99. (1 << 7) - 1,
  100. (1 << 8) - 1,
  101. (1 << 16) - 1,
  102. (1ull << 32) - 1,
  103. (1ull << 50) - 1,
  104. (1ull << 62) - 1,
  105. (1ull << 63) - 1,
  106. static_cast<uint64_t>(-(1 << 8)),
  107. static_cast<uint64_t>(-(1 << 16)),
  108. static_cast<uint64_t>(-(1ll << 32)),
  109. static_cast<uint64_t>(-(1ll << 50)),
  110. static_cast<uint64_t>(-(1ll << 62)),
  111. static_cast<uint64_t>(-(1 << 8) - 1),
  112. static_cast<uint64_t>(-(1 << 16) - 1),
  113. static_cast<uint64_t>(-(1ll << 32) - 1),
  114. static_cast<uint64_t>(-(1ll << 50) - 1),
  115. static_cast<uint64_t>(-(1ll << 62) - 1),
  116. };
  117. for (const uint64_t u : kUintValues) {
  118. EXPECT_EQ(u, StreamRoundTrip<uint64_t>(u));
  119. int64_t x = static_cast<int64_t>(u);
  120. EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));
  121. double d = static_cast<double>(x);
  122. EXPECT_EQ(d, StreamRoundTrip<double>(d));
  123. float f = d;
  124. EXPECT_EQ(f, StreamRoundTrip<float>(f));
  125. }
  126. }
  127. TEST(IOStreamStateSaver, RoundTripFloats) {
  128. static_assert(
  129. stream_precision_helper<float>::kPrecision >= 9,
  130. "stream_precision_helper<float>::kPrecision should be at least 9");
  131. const float kValues[] = {
  132. 1,
  133. std::nextafter(1.0f, 0.0f), // 1 - epsilon
  134. std::nextafter(1.0f, 2.0f), // 1 + epsilon
  135. 1.0e+1f,
  136. 1.0e-1f,
  137. 1.0e+2f,
  138. 1.0e-2f,
  139. 1.0e+10f,
  140. 1.0e-10f,
  141. 0.00000051110000111311111111f,
  142. -0.00000051110000111211111111f,
  143. 1.234678912345678912345e+6f,
  144. 1.234678912345678912345e-6f,
  145. 1.234678912345678912345e+30f,
  146. 1.234678912345678912345e-30f,
  147. 1.234678912345678912345e+38f,
  148. 1.0234678912345678912345e-38f,
  149. // Boundary cases.
  150. std::numeric_limits<float>::max(),
  151. std::numeric_limits<float>::lowest(),
  152. std::numeric_limits<float>::epsilon(),
  153. std::nextafter(std::numeric_limits<float>::min(),
  154. 1.0f), // min + epsilon
  155. std::numeric_limits<float>::min(), // smallest normal
  156. // There are some errors dealing with denorms on apple platforms.
  157. std::numeric_limits<float>::denorm_min(), // smallest denorm
  158. std::numeric_limits<float>::min() / 2,
  159. std::nextafter(std::numeric_limits<float>::min(),
  160. 0.0f), // denorm_max
  161. std::nextafter(std::numeric_limits<float>::denorm_min(), 1.0f),
  162. };
  163. for (const float f : kValues) {
  164. EXPECT_EQ(f, StreamRoundTrip<float>(f));
  165. EXPECT_EQ(-f, StreamRoundTrip<float>(-f));
  166. double d = f;
  167. EXPECT_EQ(d, StreamRoundTrip<double>(d));
  168. EXPECT_EQ(-d, StreamRoundTrip<double>(-d));
  169. // Avoid undefined behavior (overflow/underflow).
  170. if (f <= static_cast<float>(std::numeric_limits<int64_t>::max()) &&
  171. f >= static_cast<float>(std::numeric_limits<int64_t>::lowest())) {
  172. int64_t x = static_cast<int64_t>(f);
  173. EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));
  174. }
  175. }
  176. }
  177. TEST(IOStreamStateSaver, RoundTripDoubles) {
  178. static_assert(
  179. stream_precision_helper<double>::kPrecision >= 17,
  180. "stream_precision_helper<double>::kPrecision should be at least 17");
  181. const double kValues[] = {
  182. 1,
  183. std::nextafter(1.0, 0.0), // 1 - epsilon
  184. std::nextafter(1.0, 2.0), // 1 + epsilon
  185. 1.0e+1,
  186. 1.0e-1,
  187. 1.0e+2,
  188. 1.0e-2,
  189. 1.0e+10,
  190. 1.0e-10,
  191. 0.00000051110000111311111111,
  192. -0.00000051110000111211111111,
  193. 1.234678912345678912345e+6,
  194. 1.234678912345678912345e-6,
  195. 1.234678912345678912345e+30,
  196. 1.234678912345678912345e-30,
  197. 1.234678912345678912345e+38,
  198. 1.0234678912345678912345e-38,
  199. 1.0e+100,
  200. 1.0e-100,
  201. 1.234678912345678912345e+308,
  202. 1.0234678912345678912345e-308,
  203. 2.22507385850720138e-308,
  204. // Boundary cases.
  205. std::numeric_limits<double>::max(),
  206. std::numeric_limits<double>::lowest(),
  207. std::numeric_limits<double>::epsilon(),
  208. std::nextafter(std::numeric_limits<double>::min(),
  209. 1.0), // min + epsilon
  210. std::numeric_limits<double>::min(), // smallest normal
  211. // There are some errors dealing with denorms on apple platforms.
  212. std::numeric_limits<double>::denorm_min(), // smallest denorm
  213. std::numeric_limits<double>::min() / 2,
  214. std::nextafter(std::numeric_limits<double>::min(),
  215. 0.0), // denorm_max
  216. std::nextafter(std::numeric_limits<double>::denorm_min(), 1.0f),
  217. };
  218. for (const double d : kValues) {
  219. EXPECT_EQ(d, StreamRoundTrip<double>(d));
  220. EXPECT_EQ(-d, StreamRoundTrip<double>(-d));
  221. // Avoid undefined behavior (overflow/underflow).
  222. if (d <= std::numeric_limits<float>::max() &&
  223. d >= std::numeric_limits<float>::lowest()) {
  224. float f = static_cast<float>(d);
  225. EXPECT_EQ(f, StreamRoundTrip<float>(f));
  226. }
  227. // Avoid undefined behavior (overflow/underflow).
  228. if (d <= static_cast<double>(std::numeric_limits<int64_t>::max()) &&
  229. d >= static_cast<double>(std::numeric_limits<int64_t>::lowest())) {
  230. int64_t x = static_cast<int64_t>(d);
  231. EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));
  232. }
  233. }
  234. }
  235. TEST(IOStreamStateSaver, RoundTripLongDoubles) {
  236. // Technically, C++ only guarantees that long double is at least as large as a
  237. // double. Practically it varies from 64-bits to 128-bits.
  238. //
  239. // So it is best to consider long double a best-effort extended precision
  240. // type.
  241. static_assert(
  242. stream_precision_helper<long double>::kPrecision >= 36,
  243. "stream_precision_helper<long double>::kPrecision should be at least 36");
  244. using real_type = long double;
  245. const real_type kValues[] = {
  246. 1,
  247. std::nextafter(1.0, 0.0), // 1 - epsilon
  248. std::nextafter(1.0, 2.0), // 1 + epsilon
  249. 1.0e+1,
  250. 1.0e-1,
  251. 1.0e+2,
  252. 1.0e-2,
  253. 1.0e+10,
  254. 1.0e-10,
  255. 0.00000051110000111311111111,
  256. -0.00000051110000111211111111,
  257. 1.2346789123456789123456789123456789e+6,
  258. 1.2346789123456789123456789123456789e-6,
  259. 1.2346789123456789123456789123456789e+30,
  260. 1.2346789123456789123456789123456789e-30,
  261. 1.2346789123456789123456789123456789e+38,
  262. 1.2346789123456789123456789123456789e-38,
  263. 1.2346789123456789123456789123456789e+308,
  264. 1.2346789123456789123456789123456789e-308,
  265. 1.0e+100,
  266. 1.0e-100,
  267. 1.234678912345678912345e+308,
  268. 1.0234678912345678912345e-308,
  269. // Boundary cases.
  270. std::numeric_limits<real_type>::max(),
  271. std::numeric_limits<real_type>::lowest(),
  272. std::numeric_limits<real_type>::epsilon(),
  273. std::nextafter(std::numeric_limits<real_type>::min(),
  274. real_type(1)), // min + epsilon
  275. std::numeric_limits<real_type>::min(), // smallest normal
  276. // There are some errors dealing with denorms on apple platforms.
  277. std::numeric_limits<real_type>::denorm_min(), // smallest denorm
  278. std::numeric_limits<real_type>::min() / 2,
  279. std::nextafter(std::numeric_limits<real_type>::min(),
  280. 0.0), // denorm_max
  281. std::nextafter(std::numeric_limits<real_type>::denorm_min(), 1.0f),
  282. };
  283. int index = -1;
  284. for (const long double dd : kValues) {
  285. index++;
  286. EXPECT_EQ(dd, StreamRoundTrip<real_type>(dd)) << index;
  287. EXPECT_EQ(-dd, StreamRoundTrip<real_type>(-dd)) << index;
  288. // Avoid undefined behavior (overflow/underflow).
  289. if (dd <= std::numeric_limits<double>::max() &&
  290. dd >= std::numeric_limits<double>::lowest()) {
  291. double d = static_cast<double>(dd);
  292. EXPECT_EQ(d, StreamRoundTrip<double>(d));
  293. }
  294. // Avoid undefined behavior (overflow/underflow).
  295. if (dd <= std::numeric_limits<int64_t>::max() &&
  296. dd >= std::numeric_limits<int64_t>::lowest()) {
  297. int64_t x = static_cast<int64_t>(dd);
  298. EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));
  299. }
  300. }
  301. }
  302. TEST(StrToDTest, DoubleMin) {
  303. const char kV[] = "2.22507385850720138e-308";
  304. char* end;
  305. double x = std::strtod(kV, &end);
  306. EXPECT_EQ(std::numeric_limits<double>::min(), x);
  307. // errno may equal ERANGE.
  308. }
  309. TEST(StrToDTest, DoubleDenormMin) {
  310. const char kV[] = "4.94065645841246544e-324";
  311. char* end;
  312. double x = std::strtod(kV, &end);
  313. EXPECT_EQ(std::numeric_limits<double>::denorm_min(), x);
  314. // errno may equal ERANGE.
  315. }
  316. } // namespace