tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

iostream_state_saver_test.cc (11359B)


      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 
     15 #include "absl/random/internal/iostream_state_saver.h"
     16 
     17 #include <errno.h>
     18 #include <stdio.h>
     19 
     20 #include <sstream>
     21 #include <string>
     22 
     23 #include "gtest/gtest.h"
     24 
     25 namespace {
     26 
     27 using absl::random_internal::make_istream_state_saver;
     28 using absl::random_internal::make_ostream_state_saver;
     29 using absl::random_internal::stream_precision_helper;
     30 
     31 template <typename T>
     32 typename absl::enable_if_t<std::is_integral<T>::value, T>  //
     33 StreamRoundTrip(T t) {
     34  std::stringstream ss;
     35  {
     36    auto saver = make_ostream_state_saver(ss);
     37    ss.precision(stream_precision_helper<T>::kPrecision);
     38    ss << t;
     39  }
     40  T result = 0;
     41  {
     42    auto saver = make_istream_state_saver(ss);
     43    ss >> result;
     44  }
     45  EXPECT_FALSE(ss.fail())            //
     46      << ss.str() << " "             //
     47      << (ss.good() ? "good " : "")  //
     48      << (ss.bad() ? "bad " : "")    //
     49      << (ss.eof() ? "eof " : "")    //
     50      << (ss.fail() ? "fail " : "");
     51 
     52  return result;
     53 }
     54 
     55 template <typename T>
     56 typename absl::enable_if_t<std::is_floating_point<T>::value, T>  //
     57 StreamRoundTrip(T t) {
     58  std::stringstream ss;
     59  {
     60    auto saver = make_ostream_state_saver(ss);
     61    ss.precision(stream_precision_helper<T>::kPrecision);
     62    ss << t;
     63  }
     64  T result = 0;
     65  {
     66    auto saver = make_istream_state_saver(ss);
     67    result = absl::random_internal::read_floating_point<T>(ss);
     68  }
     69  EXPECT_FALSE(ss.fail())            //
     70      << ss.str() << " "             //
     71      << (ss.good() ? "good " : "")  //
     72      << (ss.bad() ? "bad " : "")    //
     73      << (ss.eof() ? "eof " : "")    //
     74      << (ss.fail() ? "fail " : "");
     75 
     76  return result;
     77 }
     78 
     79 TEST(IOStreamStateSaver, BasicSaverState) {
     80  std::stringstream ss;
     81  ss.precision(2);
     82  ss.fill('x');
     83  ss.flags(std::ios_base::dec | std::ios_base::right);
     84 
     85  {
     86    auto saver = make_ostream_state_saver(ss);
     87    ss.precision(10);
     88    EXPECT_NE('x', ss.fill());
     89    EXPECT_EQ(10, ss.precision());
     90    EXPECT_NE(std::ios_base::dec | std::ios_base::right, ss.flags());
     91 
     92    ss << 1.23;
     93  }
     94 
     95  EXPECT_EQ('x', ss.fill());
     96  EXPECT_EQ(2, ss.precision());
     97  EXPECT_EQ(std::ios_base::dec | std::ios_base::right, ss.flags());
     98 }
     99 
    100 TEST(IOStreamStateSaver, RoundTripInts) {
    101  const uint64_t kUintValues[] = {
    102      0,
    103      1,
    104      static_cast<uint64_t>(-1),
    105      2,
    106      static_cast<uint64_t>(-2),
    107 
    108      1 << 7,
    109      1 << 8,
    110      1 << 16,
    111      1ull << 32,
    112      1ull << 50,
    113      1ull << 62,
    114      1ull << 63,
    115 
    116      (1 << 7) - 1,
    117      (1 << 8) - 1,
    118      (1 << 16) - 1,
    119      (1ull << 32) - 1,
    120      (1ull << 50) - 1,
    121      (1ull << 62) - 1,
    122      (1ull << 63) - 1,
    123 
    124      static_cast<uint64_t>(-(1 << 8)),
    125      static_cast<uint64_t>(-(1 << 16)),
    126      static_cast<uint64_t>(-(1ll << 32)),
    127      static_cast<uint64_t>(-(1ll << 50)),
    128      static_cast<uint64_t>(-(1ll << 62)),
    129 
    130      static_cast<uint64_t>(-(1 << 8) - 1),
    131      static_cast<uint64_t>(-(1 << 16) - 1),
    132      static_cast<uint64_t>(-(1ll << 32) - 1),
    133      static_cast<uint64_t>(-(1ll << 50) - 1),
    134      static_cast<uint64_t>(-(1ll << 62) - 1),
    135  };
    136 
    137  for (const uint64_t u : kUintValues) {
    138    EXPECT_EQ(u, StreamRoundTrip<uint64_t>(u));
    139 
    140    int64_t x = static_cast<int64_t>(u);
    141    EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));
    142 
    143    double d = static_cast<double>(x);
    144    EXPECT_EQ(d, StreamRoundTrip<double>(d));
    145 
    146    float f = d;
    147    EXPECT_EQ(f, StreamRoundTrip<float>(f));
    148  }
    149 }
    150 
    151 TEST(IOStreamStateSaver, RoundTripFloats) {
    152  static_assert(
    153      stream_precision_helper<float>::kPrecision >= 9,
    154      "stream_precision_helper<float>::kPrecision should be at least 9");
    155 
    156  const float kValues[] = {
    157      1,
    158      std::nextafter(1.0f, 0.0f),  // 1 - epsilon
    159      std::nextafter(1.0f, 2.0f),  // 1 + epsilon
    160 
    161      1.0e+1f,
    162      1.0e-1f,
    163      1.0e+2f,
    164      1.0e-2f,
    165      1.0e+10f,
    166      1.0e-10f,
    167 
    168      0.00000051110000111311111111f,
    169      -0.00000051110000111211111111f,
    170 
    171      1.234678912345678912345e+6f,
    172      1.234678912345678912345e-6f,
    173      1.234678912345678912345e+30f,
    174      1.234678912345678912345e-30f,
    175      1.234678912345678912345e+38f,
    176      1.0234678912345678912345e-38f,
    177 
    178      // Boundary cases.
    179      std::numeric_limits<float>::max(),
    180      std::numeric_limits<float>::lowest(),
    181      std::numeric_limits<float>::epsilon(),
    182      std::nextafter(std::numeric_limits<float>::min(),
    183                     1.0f),               // min + epsilon
    184      std::numeric_limits<float>::min(),  // smallest normal
    185      // There are some errors dealing with denorms on apple platforms.
    186      std::numeric_limits<float>::denorm_min(),  // smallest denorm
    187      std::numeric_limits<float>::min() / 2,
    188      std::nextafter(std::numeric_limits<float>::min(),
    189                     0.0f),  // denorm_max
    190      std::nextafter(std::numeric_limits<float>::denorm_min(), 1.0f),
    191  };
    192 
    193  for (const float f : kValues) {
    194    EXPECT_EQ(f, StreamRoundTrip<float>(f));
    195    EXPECT_EQ(-f, StreamRoundTrip<float>(-f));
    196 
    197    double d = f;
    198    EXPECT_EQ(d, StreamRoundTrip<double>(d));
    199    EXPECT_EQ(-d, StreamRoundTrip<double>(-d));
    200 
    201    // Avoid undefined behavior (overflow/underflow).
    202    if (f <= static_cast<float>(std::numeric_limits<int64_t>::max()) &&
    203        f >= static_cast<float>(std::numeric_limits<int64_t>::lowest())) {
    204      int64_t x = static_cast<int64_t>(f);
    205      EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));
    206    }
    207  }
    208 }
    209 
    210 TEST(IOStreamStateSaver, RoundTripDoubles) {
    211  static_assert(
    212      stream_precision_helper<double>::kPrecision >= 17,
    213      "stream_precision_helper<double>::kPrecision should be at least 17");
    214 
    215  const double kValues[] = {
    216      1,
    217      std::nextafter(1.0, 0.0),  // 1 - epsilon
    218      std::nextafter(1.0, 2.0),  // 1 + epsilon
    219 
    220      1.0e+1,
    221      1.0e-1,
    222      1.0e+2,
    223      1.0e-2,
    224      1.0e+10,
    225      1.0e-10,
    226 
    227      0.00000051110000111311111111,
    228      -0.00000051110000111211111111,
    229 
    230      1.234678912345678912345e+6,
    231      1.234678912345678912345e-6,
    232      1.234678912345678912345e+30,
    233      1.234678912345678912345e-30,
    234      1.234678912345678912345e+38,
    235      1.0234678912345678912345e-38,
    236 
    237      1.0e+100,
    238      1.0e-100,
    239      1.234678912345678912345e+308,
    240      1.0234678912345678912345e-308,
    241      2.22507385850720138e-308,
    242 
    243      // Boundary cases.
    244      std::numeric_limits<double>::max(),
    245      std::numeric_limits<double>::lowest(),
    246      std::numeric_limits<double>::epsilon(),
    247      std::nextafter(std::numeric_limits<double>::min(),
    248                     1.0),                 // min + epsilon
    249      std::numeric_limits<double>::min(),  // smallest normal
    250      // There are some errors dealing with denorms on apple platforms.
    251      std::numeric_limits<double>::denorm_min(),  // smallest denorm
    252      std::numeric_limits<double>::min() / 2,
    253      std::nextafter(std::numeric_limits<double>::min(),
    254                     0.0),  // denorm_max
    255      std::nextafter(std::numeric_limits<double>::denorm_min(), 1.0f),
    256  };
    257 
    258  for (const double d : kValues) {
    259    EXPECT_EQ(d, StreamRoundTrip<double>(d));
    260    EXPECT_EQ(-d, StreamRoundTrip<double>(-d));
    261 
    262    // Avoid undefined behavior (overflow/underflow).
    263    if (d <= std::numeric_limits<float>::max() &&
    264        d >= std::numeric_limits<float>::lowest()) {
    265      float f = static_cast<float>(d);
    266      EXPECT_EQ(f, StreamRoundTrip<float>(f));
    267    }
    268 
    269    // Avoid undefined behavior (overflow/underflow).
    270    if (d <= static_cast<double>(std::numeric_limits<int64_t>::max()) &&
    271        d >= static_cast<double>(std::numeric_limits<int64_t>::lowest())) {
    272      int64_t x = static_cast<int64_t>(d);
    273      EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));
    274    }
    275  }
    276 }
    277 
    278 TEST(IOStreamStateSaver, RoundTripLongDoubles) {
    279  // Technically, C++ only guarantees that long double is at least as large as a
    280  // double.  Practically it varies from 64-bits to 128-bits.
    281  //
    282  // So it is best to consider long double a best-effort extended precision
    283  // type.
    284 
    285  static_assert(
    286      stream_precision_helper<long double>::kPrecision >= 36,
    287      "stream_precision_helper<long double>::kPrecision should be at least 36");
    288 
    289  using real_type = long double;
    290  const real_type kValues[] = {
    291      1,
    292      std::nextafter(1.0, 0.0),  // 1 - epsilon
    293      std::nextafter(1.0, 2.0),  // 1 + epsilon
    294 
    295      1.0e+1,
    296      1.0e-1,
    297      1.0e+2,
    298      1.0e-2,
    299      1.0e+10,
    300      1.0e-10,
    301 
    302      0.00000051110000111311111111,
    303      -0.00000051110000111211111111,
    304 
    305      1.2346789123456789123456789123456789e+6,
    306      1.2346789123456789123456789123456789e-6,
    307      1.2346789123456789123456789123456789e+30,
    308      1.2346789123456789123456789123456789e-30,
    309      1.2346789123456789123456789123456789e+38,
    310      1.2346789123456789123456789123456789e-38,
    311      1.2346789123456789123456789123456789e+308,
    312      1.2346789123456789123456789123456789e-308,
    313 
    314      1.0e+100,
    315      1.0e-100,
    316      1.234678912345678912345e+308,
    317      1.0234678912345678912345e-308,
    318 
    319      // Boundary cases.
    320      std::numeric_limits<real_type>::max(),
    321      std::numeric_limits<real_type>::lowest(),
    322      std::numeric_limits<real_type>::epsilon(),
    323      std::nextafter(std::numeric_limits<real_type>::min(),
    324                     real_type(1)),           // min + epsilon
    325      std::numeric_limits<real_type>::min(),  // smallest normal
    326      // There are some errors dealing with denorms on apple platforms.
    327      std::numeric_limits<real_type>::denorm_min(),  // smallest denorm
    328      std::numeric_limits<real_type>::min() / 2,
    329      std::nextafter(std::numeric_limits<real_type>::min(),
    330                     0.0),  // denorm_max
    331      std::nextafter(std::numeric_limits<real_type>::denorm_min(), 1.0f),
    332  };
    333 
    334  int index = -1;
    335  for (const long double dd : kValues) {
    336    index++;
    337    EXPECT_EQ(dd, StreamRoundTrip<real_type>(dd)) << index;
    338    EXPECT_EQ(-dd, StreamRoundTrip<real_type>(-dd)) << index;
    339 
    340    // Avoid undefined behavior (overflow/underflow).
    341    if (dd <= std::numeric_limits<double>::max() &&
    342        dd >= std::numeric_limits<double>::lowest()) {
    343      double d = static_cast<double>(dd);
    344      EXPECT_EQ(d, StreamRoundTrip<double>(d));
    345    }
    346 
    347    // Avoid undefined behavior (overflow/underflow).
    348    if (dd <= static_cast<long double>(std::numeric_limits<int64_t>::max()) &&
    349        dd >=
    350            static_cast<long double>(std::numeric_limits<int64_t>::lowest())) {
    351      int64_t x = static_cast<int64_t>(dd);
    352      EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));
    353    }
    354  }
    355 }
    356 
    357 TEST(StrToDTest, DoubleMin) {
    358  const char kV[] = "2.22507385850720138e-308";
    359  char* end;
    360  double x = std::strtod(kV, &end);
    361  EXPECT_EQ(std::numeric_limits<double>::min(), x);
    362  // errno may equal ERANGE.
    363 }
    364 
    365 TEST(StrToDTest, DoubleDenormMin) {
    366  const char kV[] = "4.94065645841246544e-324";
    367  char* end;
    368  double x = std::strtod(kV, &end);
    369  EXPECT_EQ(std::numeric_limits<double>::denorm_min(), x);
    370  // errno may equal ERANGE.
    371 }
    372 
    373 }  // namespace