Abseil Common Libraries (C++) (grcp 依赖) https://abseil.io/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1522 lines
56 KiB

Export of internal Abseil changes -- f012012ef78234a6a4585321b67d7b7c92ebc266 by Laramie Leavitt <lar@google.com>: Slight restructuring of absl/random/internal randen implementation. Convert round-keys.inc into randen_round_keys.cc file. Consistently use a 128-bit pointer type for internal method parameters. This allows simpler pointer arithmetic in C++ & permits removal of some constants and casts. Remove some redundancy in comments & constexpr variables. Specifically, all references to Randen algorithm parameters use RandenTraits; duplication in RandenSlow removed. PiperOrigin-RevId: 312190313 -- dc8b42e054046741e9ed65335bfdface997c6063 by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 312167304 -- f13d248fafaf206492c1362c3574031aea3abaf7 by Matthew Brown <matthewbr@google.com>: Cleanup StrFormat extensions a little. PiperOrigin-RevId: 312166336 -- 9d9117589667afe2332bb7ad42bc967ca7c54502 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 312105213 -- 9a12b9b3aa0e59b8ee6cf9408ed0029045543a9b by Abseil Team <absl-team@google.com>: Complete IGNORE_TYPE macro renaming. PiperOrigin-RevId: 311999699 -- 64756f20d61021d999bd0d4c15e9ad3857382f57 by Gennadiy Rozental <rogeeff@google.com>: Switch to fixed bytes specific default value. This fixes the Abseil Flags for big endian platforms. PiperOrigin-RevId: 311844448 -- bdbe6b5b29791dbc3816ada1828458b3010ff1e9 by Laramie Leavitt <lar@google.com>: Change many distribution tests to use pcg_engine as a deterministic source of entropy. It's reasonable to test that the BitGen itself has good entropy, however when testing the cross product of all random distributions x all the architecture variations x all submitted changes results in a large number of tests. In order to account for these failures while still using good entropy requires that our allowed sigma need to account for all of these independent tests. Our current sigma values are too restrictive, and we see a lot of failures, so we have to either relax the sigma values or convert some of the statistical tests to use deterministic values. This changelist does the latter. PiperOrigin-RevId: 311840096 GitOrigin-RevId: f012012ef78234a6a4585321b67d7b7c92ebc266 Change-Id: Ic84886f38ff30d7d72c126e9b63c9a61eb729a1a
5 years ago
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file tests string processing functions related to numeric values.
#include "absl/strings/numbers.h"
#include <sys/types.h>
#include <cfenv> // NOLINT(build/c++11)
#include <cinttypes>
#include <climits>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <limits>
#include <numeric>
#include <random>
#include <set>
#include <string>
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/random/distributions.h"
#include "absl/random/random.h"
#include "absl/strings/internal/numbers_test_common.h"
#include "absl/strings/internal/ostringstream.h"
#include "absl/strings/internal/pow10_helper.h"
#include "absl/strings/str_cat.h"
namespace {
using absl::SimpleAtoi;
Export of internal Abseil changes -- f49e405201d2ffd5955503fa8ad0f08ec0cdfb2b by Martijn Vels <mvels@google.com>: Add common [container.requirements] type definitions to `CharRange` and `ChunkRange` The presence of these allow these range classes to be used in various utility functions which require some minimum type of container. For example, this change allows tests to use `EXPECT_THAT(cord.Chunks(), ElementsAre(...))` PiperOrigin-RevId: 406941278 -- 0c195f073632e21d9a4bce158047b2ba8551c2d1 by Evan Brown <ezb@google.com>: Use explicit exponential growth in SubstituteAndAppendArray. PiperOrigin-RevId: 406931952 -- afb043bccd809a55cab78abadb7548a057d9eda0 by Jorg Brown <jorg@google.com>: Use longer var names in macro to avoid clang-tidy warning PiperOrigin-RevId: 406930978 -- 80397e2604e6b3d929a34742c3a32581b34d3ac4 by Martijn Vels <mvels@google.com>: Add future kAppendBuffer and kPrependBuffer API trackers for Cordz sampling PiperOrigin-RevId: 406912759 -- e910ce919ef83933f08a690e8b7325c7cc5b6d5d by Martijn Vels <mvels@google.com>: Implement Prepend(string_view) in terms of PrependArray(string_view, MethodIdentifier). PiperOrigin-RevId: 406891665 -- c9cff43d4c0568ed01f2fca0f6ef038ae03112b5 by Martijn Vels <mvels@google.com>: Add 'Rebuild' logic to CordRepBtree There are btree hostile scenarios where an application could perform repeated split/insert/merge operations on a cord leading to a tree exceeding the maximum height. While this should be rare in practice, this change adds a Rebuild() method that will rebuild a tree with a 100% fill factor, and we will invoke this rebuild when a tree exceeds the maximum height. This basically follows the similar 'balance' logic in Concat trees (although the latter is common in Concat uses) PiperOrigin-RevId: 406875739 -- 5b2b8fb88f1ebfdc1c670088152da2cb2ea4c376 by Martijn Vels <mvels@google.com>: Add 'in place' enabled RemoveSuffix An in-place RemoveSuffix is more efficient than SubTree() as it can directly modify privately owned nodes and flats allowing easy re-use of free capacity in right-most flats that may turn into Substring edges when using SubTree. PiperOrigin-RevId: 406431230 -- f09903c0a3d7344f59aaf1380a16ea10829217d4 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 406430373 -- 9957af575c33bb18dc170572a4ee8cc5901df6b2 by Greg Falcon <gfalcon@google.com>: Initial groundwork to allow storing checksum data inside CordRep instances. This uses a RefcountAndFlags bit that was reserved for this purpose, and will be leveraged in a follow-up change to allow attaching checksums to a Cord's value. This change splits RefcountAndFlags::IsOne() into two distinct operations: * IsOne(): This returns true when the associated CordRep is not shared with other threads. This is useful for functions that consume CordRep instances; for example, code that consumes an unshared CordRep can assume ownership of its children without modifying those refcounts. * IsMutable(): This returns true when the associated CordRep reference is not shared with other threads, *and* does not store an associated checksum value. This is useful for functions that modify a CordRep's contents: code may modify the bytes of a mutable-unshared CordRep without fear of races with other threads, or of invalidating a stored checksum. The tricky part of this CL is ensuring that the correct choice between IsMutable() and IsOne() was made at each point. An incorrect application of IsOne() could lead to correctness bugs in the future. Code conditioned on IsOne() may delete the CordRep in question, or assume ownership of its children, but must not modify the CordRep's data without explicitly adjusting the CRC. PiperOrigin-RevId: 406191103 -- 686544814079e5ab6d4593cca0c068b510be400a by Martijn Vels <mvels@google.com>: Reduce the size in the LargeString test when running with Sanitizers PiperOrigin-RevId: 406186945 -- 735b4490bdb695c35731f06ce4b8de14ce2be6ed by Alex Strelnikov <strel@google.com>: Release absl::SimpleHexAtoi. PiperOrigin-RevId: 406143188 GitOrigin-RevId: f49e405201d2ffd5955503fa8ad0f08ec0cdfb2b Change-Id: Ic6527ac40fa03ea02ca813e8bb7868a219544de4
3 years ago
using absl::SimpleHexAtoi;
Export of internal Abseil changes -- f012012ef78234a6a4585321b67d7b7c92ebc266 by Laramie Leavitt <lar@google.com>: Slight restructuring of absl/random/internal randen implementation. Convert round-keys.inc into randen_round_keys.cc file. Consistently use a 128-bit pointer type for internal method parameters. This allows simpler pointer arithmetic in C++ & permits removal of some constants and casts. Remove some redundancy in comments & constexpr variables. Specifically, all references to Randen algorithm parameters use RandenTraits; duplication in RandenSlow removed. PiperOrigin-RevId: 312190313 -- dc8b42e054046741e9ed65335bfdface997c6063 by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 312167304 -- f13d248fafaf206492c1362c3574031aea3abaf7 by Matthew Brown <matthewbr@google.com>: Cleanup StrFormat extensions a little. PiperOrigin-RevId: 312166336 -- 9d9117589667afe2332bb7ad42bc967ca7c54502 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 312105213 -- 9a12b9b3aa0e59b8ee6cf9408ed0029045543a9b by Abseil Team <absl-team@google.com>: Complete IGNORE_TYPE macro renaming. PiperOrigin-RevId: 311999699 -- 64756f20d61021d999bd0d4c15e9ad3857382f57 by Gennadiy Rozental <rogeeff@google.com>: Switch to fixed bytes specific default value. This fixes the Abseil Flags for big endian platforms. PiperOrigin-RevId: 311844448 -- bdbe6b5b29791dbc3816ada1828458b3010ff1e9 by Laramie Leavitt <lar@google.com>: Change many distribution tests to use pcg_engine as a deterministic source of entropy. It's reasonable to test that the BitGen itself has good entropy, however when testing the cross product of all random distributions x all the architecture variations x all submitted changes results in a large number of tests. In order to account for these failures while still using good entropy requires that our allowed sigma need to account for all of these independent tests. Our current sigma values are too restrictive, and we see a lot of failures, so we have to either relax the sigma values or convert some of the statistical tests to use deterministic values. This changelist does the latter. PiperOrigin-RevId: 311840096 GitOrigin-RevId: f012012ef78234a6a4585321b67d7b7c92ebc266 Change-Id: Ic84886f38ff30d7d72c126e9b63c9a61eb729a1a
5 years ago
using absl::numbers_internal::kSixDigitsToBufferSize;
using absl::numbers_internal::safe_strto32_base;
using absl::numbers_internal::safe_strto64_base;
using absl::numbers_internal::safe_strtou32_base;
using absl::numbers_internal::safe_strtou64_base;
using absl::numbers_internal::SixDigitsToBuffer;
using absl::strings_internal::Itoa;
using absl::strings_internal::strtouint32_test_cases;
using absl::strings_internal::strtouint64_test_cases;
using testing::Eq;
using testing::MatchesRegex;
// Number of floats to test with.
// 5,000,000 is a reasonable default for a test that only takes a few seconds.
// 1,000,000,000+ triggers checking for all possible mantissa values for
// double-precision tests. 2,000,000,000+ triggers checking for every possible
// single-precision float.
const int kFloatNumCases = 5000000;
// This is a slow, brute-force routine to compute the exact base-10
// representation of a double-precision floating-point number. It
// is useful for debugging only.
std::string PerfectDtoa(double d) {
if (d == 0) return "0";
if (d < 0) return "-" + PerfectDtoa(-d);
// Basic theory: decompose d into mantissa and exp, where
// d = mantissa * 2^exp, and exp is as close to zero as possible.
int64_t mantissa, exp = 0;
while (d >= 1ULL << 63) ++exp, d *= 0.5;
while ((mantissa = d) != d) --exp, d *= 2.0;
// Then convert mantissa to ASCII, and either double it (if
// exp > 0) or halve it (if exp < 0) repeatedly. "halve it"
// in this case means multiplying it by five and dividing by 10.
constexpr int maxlen = 1100; // worst case is actually 1030 or so.
char buf[maxlen + 5];
for (int64_t num = mantissa, pos = maxlen; --pos >= 0;) {
buf[pos] = '0' + (num % 10);
num /= 10;
}
char* begin = &buf[0];
char* end = buf + maxlen;
for (int i = 0; i != exp; i += (exp > 0) ? 1 : -1) {
int carry = 0;
for (char* p = end; --p != begin;) {
int dig = *p - '0';
dig = dig * (exp > 0 ? 2 : 5) + carry;
carry = dig / 10;
dig %= 10;
*p = '0' + dig;
}
}
if (exp < 0) {
// "dividing by 10" above means we have to add the decimal point.
memmove(end + 1 + exp, end + exp, 1 - exp);
end[exp] = '.';
++end;
}
while (*begin == '0' && begin[1] != '.') ++begin;
return {begin, end};
}
TEST(ToString, PerfectDtoa) {
EXPECT_THAT(PerfectDtoa(1), Eq("1"));
EXPECT_THAT(PerfectDtoa(0.1),
Eq("0.1000000000000000055511151231257827021181583404541015625"));
EXPECT_THAT(PerfectDtoa(1e24), Eq("999999999999999983222784"));
EXPECT_THAT(PerfectDtoa(5e-324), MatchesRegex("0.0000.*625"));
for (int i = 0; i < 100; ++i) {
for (double multiplier :
{1e-300, 1e-200, 1e-100, 0.1, 1.0, 10.0, 1e100, 1e300}) {
double d = multiplier * i;
std::string s = PerfectDtoa(d);
EXPECT_DOUBLE_EQ(d, strtod(s.c_str(), nullptr));
}
}
}
template <typename integer>
struct MyInteger {
integer i;
explicit constexpr MyInteger(integer i) : i(i) {}
constexpr operator integer() const { return i; }
constexpr MyInteger operator+(MyInteger other) const { return i + other.i; }
constexpr MyInteger operator-(MyInteger other) const { return i - other.i; }
constexpr MyInteger operator*(MyInteger other) const { return i * other.i; }
constexpr MyInteger operator/(MyInteger other) const { return i / other.i; }
constexpr bool operator<(MyInteger other) const { return i < other.i; }
constexpr bool operator<=(MyInteger other) const { return i <= other.i; }
constexpr bool operator==(MyInteger other) const { return i == other.i; }
constexpr bool operator>=(MyInteger other) const { return i >= other.i; }
constexpr bool operator>(MyInteger other) const { return i > other.i; }
constexpr bool operator!=(MyInteger other) const { return i != other.i; }
integer as_integer() const { return i; }
};
typedef MyInteger<int64_t> MyInt64;
typedef MyInteger<uint64_t> MyUInt64;
void CheckInt32(int32_t x) {
char buffer[absl::numbers_internal::kFastToBufferSize];
char* actual = absl::numbers_internal::FastIntToBuffer(x, buffer);
std::string expected = std::to_string(x);
EXPECT_EQ(expected, std::string(buffer, actual)) << " Input " << x;
char* generic_actual = absl::numbers_internal::FastIntToBuffer(x, buffer);
EXPECT_EQ(expected, std::string(buffer, generic_actual)) << " Input " << x;
}
void CheckInt64(int64_t x) {
char buffer[absl::numbers_internal::kFastToBufferSize + 3];
buffer[0] = '*';
buffer[23] = '*';
buffer[24] = '*';
char* actual = absl::numbers_internal::FastIntToBuffer(x, &buffer[1]);
std::string expected = std::to_string(x);
EXPECT_EQ(expected, std::string(&buffer[1], actual)) << " Input " << x;
EXPECT_EQ(buffer[0], '*');
EXPECT_EQ(buffer[23], '*');
EXPECT_EQ(buffer[24], '*');
char* my_actual =
absl::numbers_internal::FastIntToBuffer(MyInt64(x), &buffer[1]);
EXPECT_EQ(expected, std::string(&buffer[1], my_actual)) << " Input " << x;
}
void CheckUInt32(uint32_t x) {
char buffer[absl::numbers_internal::kFastToBufferSize];
char* actual = absl::numbers_internal::FastIntToBuffer(x, buffer);
std::string expected = std::to_string(x);
EXPECT_EQ(expected, std::string(buffer, actual)) << " Input " << x;
char* generic_actual = absl::numbers_internal::FastIntToBuffer(x, buffer);
EXPECT_EQ(expected, std::string(buffer, generic_actual)) << " Input " << x;
}
void CheckUInt64(uint64_t x) {
char buffer[absl::numbers_internal::kFastToBufferSize + 1];
char* actual = absl::numbers_internal::FastIntToBuffer(x, &buffer[1]);
std::string expected = std::to_string(x);
EXPECT_EQ(expected, std::string(&buffer[1], actual)) << " Input " << x;
char* generic_actual = absl::numbers_internal::FastIntToBuffer(x, &buffer[1]);
EXPECT_EQ(expected, std::string(&buffer[1], generic_actual))
<< " Input " << x;
char* my_actual =
absl::numbers_internal::FastIntToBuffer(MyUInt64(x), &buffer[1]);
EXPECT_EQ(expected, std::string(&buffer[1], my_actual)) << " Input " << x;
}
void CheckHex64(uint64_t v) {
char expected[16 + 1];
std::string actual = absl::StrCat(absl::Hex(v, absl::kZeroPad16));
snprintf(expected, sizeof(expected), "%016" PRIx64, static_cast<uint64_t>(v));
EXPECT_EQ(expected, actual) << " Input " << v;
actual = absl::StrCat(absl::Hex(v, absl::kSpacePad16));
snprintf(expected, sizeof(expected), "%16" PRIx64, static_cast<uint64_t>(v));
EXPECT_EQ(expected, actual) << " Input " << v;
}
TEST(Numbers, TestFastPrints) {
for (int i = -100; i <= 100; i++) {
CheckInt32(i);
CheckInt64(i);
}
for (int i = 0; i <= 100; i++) {
CheckUInt32(i);
CheckUInt64(i);
}
// Test min int to make sure that works
CheckInt32(INT_MIN);
CheckInt32(INT_MAX);
CheckInt64(LONG_MIN);
CheckInt64(uint64_t{1000000000});
CheckInt64(uint64_t{9999999999});
CheckInt64(uint64_t{100000000000000});
CheckInt64(uint64_t{999999999999999});
CheckInt64(uint64_t{1000000000000000000});
CheckInt64(uint64_t{1199999999999999999});
CheckInt64(int64_t{-700000000000000000});
CheckInt64(LONG_MAX);
CheckUInt32(std::numeric_limits<uint32_t>::max());
CheckUInt64(uint64_t{1000000000});
CheckUInt64(uint64_t{9999999999});
CheckUInt64(uint64_t{100000000000000});
CheckUInt64(uint64_t{999999999999999});
CheckUInt64(uint64_t{1000000000000000000});
CheckUInt64(uint64_t{1199999999999999999});
CheckUInt64(std::numeric_limits<uint64_t>::max());
for (int i = 0; i < 10000; i++) {
CheckHex64(i);
}
CheckHex64(uint64_t{0x123456789abcdef0});
}
template <typename int_type, typename in_val_type>
void VerifySimpleAtoiGood(in_val_type in_value, int_type exp_value) {
std::string s;
// (u)int128 can be streamed but not StrCat'd.
Export of internal Abseil changes -- f012012ef78234a6a4585321b67d7b7c92ebc266 by Laramie Leavitt <lar@google.com>: Slight restructuring of absl/random/internal randen implementation. Convert round-keys.inc into randen_round_keys.cc file. Consistently use a 128-bit pointer type for internal method parameters. This allows simpler pointer arithmetic in C++ & permits removal of some constants and casts. Remove some redundancy in comments & constexpr variables. Specifically, all references to Randen algorithm parameters use RandenTraits; duplication in RandenSlow removed. PiperOrigin-RevId: 312190313 -- dc8b42e054046741e9ed65335bfdface997c6063 by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 312167304 -- f13d248fafaf206492c1362c3574031aea3abaf7 by Matthew Brown <matthewbr@google.com>: Cleanup StrFormat extensions a little. PiperOrigin-RevId: 312166336 -- 9d9117589667afe2332bb7ad42bc967ca7c54502 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 312105213 -- 9a12b9b3aa0e59b8ee6cf9408ed0029045543a9b by Abseil Team <absl-team@google.com>: Complete IGNORE_TYPE macro renaming. PiperOrigin-RevId: 311999699 -- 64756f20d61021d999bd0d4c15e9ad3857382f57 by Gennadiy Rozental <rogeeff@google.com>: Switch to fixed bytes specific default value. This fixes the Abseil Flags for big endian platforms. PiperOrigin-RevId: 311844448 -- bdbe6b5b29791dbc3816ada1828458b3010ff1e9 by Laramie Leavitt <lar@google.com>: Change many distribution tests to use pcg_engine as a deterministic source of entropy. It's reasonable to test that the BitGen itself has good entropy, however when testing the cross product of all random distributions x all the architecture variations x all submitted changes results in a large number of tests. In order to account for these failures while still using good entropy requires that our allowed sigma need to account for all of these independent tests. Our current sigma values are too restrictive, and we see a lot of failures, so we have to either relax the sigma values or convert some of the statistical tests to use deterministic values. This changelist does the latter. PiperOrigin-RevId: 311840096 GitOrigin-RevId: f012012ef78234a6a4585321b67d7b7c92ebc266 Change-Id: Ic84886f38ff30d7d72c126e9b63c9a61eb729a1a
5 years ago
absl::strings_internal::OStringStream(&s) << in_value;
int_type x = static_cast<int_type>(~exp_value);
EXPECT_TRUE(SimpleAtoi(s, &x))
<< "in_value=" << in_value << " s=" << s << " x=" << x;
EXPECT_EQ(exp_value, x);
x = static_cast<int_type>(~exp_value);
EXPECT_TRUE(SimpleAtoi(s.c_str(), &x));
EXPECT_EQ(exp_value, x);
}
template <typename int_type, typename in_val_type>
void VerifySimpleAtoiBad(in_val_type in_value) {
std::string s;
// (u)int128 can be streamed but not StrCat'd.
absl::strings_internal::OStringStream(&s) << in_value;
Export of internal Abseil changes -- f012012ef78234a6a4585321b67d7b7c92ebc266 by Laramie Leavitt <lar@google.com>: Slight restructuring of absl/random/internal randen implementation. Convert round-keys.inc into randen_round_keys.cc file. Consistently use a 128-bit pointer type for internal method parameters. This allows simpler pointer arithmetic in C++ & permits removal of some constants and casts. Remove some redundancy in comments & constexpr variables. Specifically, all references to Randen algorithm parameters use RandenTraits; duplication in RandenSlow removed. PiperOrigin-RevId: 312190313 -- dc8b42e054046741e9ed65335bfdface997c6063 by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 312167304 -- f13d248fafaf206492c1362c3574031aea3abaf7 by Matthew Brown <matthewbr@google.com>: Cleanup StrFormat extensions a little. PiperOrigin-RevId: 312166336 -- 9d9117589667afe2332bb7ad42bc967ca7c54502 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 312105213 -- 9a12b9b3aa0e59b8ee6cf9408ed0029045543a9b by Abseil Team <absl-team@google.com>: Complete IGNORE_TYPE macro renaming. PiperOrigin-RevId: 311999699 -- 64756f20d61021d999bd0d4c15e9ad3857382f57 by Gennadiy Rozental <rogeeff@google.com>: Switch to fixed bytes specific default value. This fixes the Abseil Flags for big endian platforms. PiperOrigin-RevId: 311844448 -- bdbe6b5b29791dbc3816ada1828458b3010ff1e9 by Laramie Leavitt <lar@google.com>: Change many distribution tests to use pcg_engine as a deterministic source of entropy. It's reasonable to test that the BitGen itself has good entropy, however when testing the cross product of all random distributions x all the architecture variations x all submitted changes results in a large number of tests. In order to account for these failures while still using good entropy requires that our allowed sigma need to account for all of these independent tests. Our current sigma values are too restrictive, and we see a lot of failures, so we have to either relax the sigma values or convert some of the statistical tests to use deterministic values. This changelist does the latter. PiperOrigin-RevId: 311840096 GitOrigin-RevId: f012012ef78234a6a4585321b67d7b7c92ebc266 Change-Id: Ic84886f38ff30d7d72c126e9b63c9a61eb729a1a
5 years ago
int_type x;
EXPECT_FALSE(SimpleAtoi(s, &x));
EXPECT_FALSE(SimpleAtoi(s.c_str(), &x));
}
TEST(NumbersTest, Atoi) {
// SimpleAtoi(absl::string_view, int32_t)
VerifySimpleAtoiGood<int32_t>(0, 0);
VerifySimpleAtoiGood<int32_t>(42, 42);
VerifySimpleAtoiGood<int32_t>(-42, -42);
VerifySimpleAtoiGood<int32_t>(std::numeric_limits<int32_t>::min(),
std::numeric_limits<int32_t>::min());
VerifySimpleAtoiGood<int32_t>(std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::max());
// SimpleAtoi(absl::string_view, uint32_t)
VerifySimpleAtoiGood<uint32_t>(0, 0);
VerifySimpleAtoiGood<uint32_t>(42, 42);
VerifySimpleAtoiBad<uint32_t>(-42);
VerifySimpleAtoiBad<uint32_t>(std::numeric_limits<int32_t>::min());
VerifySimpleAtoiGood<uint32_t>(std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::max());
VerifySimpleAtoiGood<uint32_t>(std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::max());
VerifySimpleAtoiBad<uint32_t>(std::numeric_limits<int64_t>::min());
VerifySimpleAtoiBad<uint32_t>(std::numeric_limits<int64_t>::max());
VerifySimpleAtoiBad<uint32_t>(std::numeric_limits<uint64_t>::max());
// SimpleAtoi(absl::string_view, int64_t)
VerifySimpleAtoiGood<int64_t>(0, 0);
VerifySimpleAtoiGood<int64_t>(42, 42);
VerifySimpleAtoiGood<int64_t>(-42, -42);
VerifySimpleAtoiGood<int64_t>(std::numeric_limits<int32_t>::min(),
std::numeric_limits<int32_t>::min());
VerifySimpleAtoiGood<int64_t>(std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::max());
VerifySimpleAtoiGood<int64_t>(std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::max());
VerifySimpleAtoiGood<int64_t>(std::numeric_limits<int64_t>::min(),
std::numeric_limits<int64_t>::min());
VerifySimpleAtoiGood<int64_t>(std::numeric_limits<int64_t>::max(),
std::numeric_limits<int64_t>::max());
VerifySimpleAtoiBad<int64_t>(std::numeric_limits<uint64_t>::max());
// SimpleAtoi(absl::string_view, uint64_t)
VerifySimpleAtoiGood<uint64_t>(0, 0);
VerifySimpleAtoiGood<uint64_t>(42, 42);
VerifySimpleAtoiBad<uint64_t>(-42);
VerifySimpleAtoiBad<uint64_t>(std::numeric_limits<int32_t>::min());
VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::max());
VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::max());
VerifySimpleAtoiBad<uint64_t>(std::numeric_limits<int64_t>::min());
VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<int64_t>::max(),
std::numeric_limits<int64_t>::max());
VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<uint64_t>::max(),
std::numeric_limits<uint64_t>::max());
// SimpleAtoi(absl::string_view, absl::uint128)
VerifySimpleAtoiGood<absl::uint128>(0, 0);
VerifySimpleAtoiGood<absl::uint128>(42, 42);
VerifySimpleAtoiBad<absl::uint128>(-42);
VerifySimpleAtoiBad<absl::uint128>(std::numeric_limits<int32_t>::min());
VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::max());
VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::max());
VerifySimpleAtoiBad<absl::uint128>(std::numeric_limits<int64_t>::min());
VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<int64_t>::max(),
std::numeric_limits<int64_t>::max());
VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<uint64_t>::max(),
std::numeric_limits<uint64_t>::max());
VerifySimpleAtoiGood<absl::uint128>(
std::numeric_limits<absl::uint128>::max(),
std::numeric_limits<absl::uint128>::max());
// SimpleAtoi(absl::string_view, absl::int128)
VerifySimpleAtoiGood<absl::int128>(0, 0);
VerifySimpleAtoiGood<absl::int128>(42, 42);
VerifySimpleAtoiGood<absl::int128>(-42, -42);
VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int32_t>::min(),
std::numeric_limits<int32_t>::min());
VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::max());
VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::max());
VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int64_t>::min(),
std::numeric_limits<int64_t>::min());
VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int64_t>::max(),
std::numeric_limits<int64_t>::max());
VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<uint64_t>::max(),
std::numeric_limits<uint64_t>::max());
VerifySimpleAtoiGood<absl::int128>(
std::numeric_limits<absl::int128>::min(),
std::numeric_limits<absl::int128>::min());
VerifySimpleAtoiGood<absl::int128>(
std::numeric_limits<absl::int128>::max(),
std::numeric_limits<absl::int128>::max());
VerifySimpleAtoiBad<absl::int128>(std::numeric_limits<absl::uint128>::max());
Export of internal Abseil changes -- f012012ef78234a6a4585321b67d7b7c92ebc266 by Laramie Leavitt <lar@google.com>: Slight restructuring of absl/random/internal randen implementation. Convert round-keys.inc into randen_round_keys.cc file. Consistently use a 128-bit pointer type for internal method parameters. This allows simpler pointer arithmetic in C++ & permits removal of some constants and casts. Remove some redundancy in comments & constexpr variables. Specifically, all references to Randen algorithm parameters use RandenTraits; duplication in RandenSlow removed. PiperOrigin-RevId: 312190313 -- dc8b42e054046741e9ed65335bfdface997c6063 by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 312167304 -- f13d248fafaf206492c1362c3574031aea3abaf7 by Matthew Brown <matthewbr@google.com>: Cleanup StrFormat extensions a little. PiperOrigin-RevId: 312166336 -- 9d9117589667afe2332bb7ad42bc967ca7c54502 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 312105213 -- 9a12b9b3aa0e59b8ee6cf9408ed0029045543a9b by Abseil Team <absl-team@google.com>: Complete IGNORE_TYPE macro renaming. PiperOrigin-RevId: 311999699 -- 64756f20d61021d999bd0d4c15e9ad3857382f57 by Gennadiy Rozental <rogeeff@google.com>: Switch to fixed bytes specific default value. This fixes the Abseil Flags for big endian platforms. PiperOrigin-RevId: 311844448 -- bdbe6b5b29791dbc3816ada1828458b3010ff1e9 by Laramie Leavitt <lar@google.com>: Change many distribution tests to use pcg_engine as a deterministic source of entropy. It's reasonable to test that the BitGen itself has good entropy, however when testing the cross product of all random distributions x all the architecture variations x all submitted changes results in a large number of tests. In order to account for these failures while still using good entropy requires that our allowed sigma need to account for all of these independent tests. Our current sigma values are too restrictive, and we see a lot of failures, so we have to either relax the sigma values or convert some of the statistical tests to use deterministic values. This changelist does the latter. PiperOrigin-RevId: 311840096 GitOrigin-RevId: f012012ef78234a6a4585321b67d7b7c92ebc266 Change-Id: Ic84886f38ff30d7d72c126e9b63c9a61eb729a1a
5 years ago
// Some other types
VerifySimpleAtoiGood<int>(-42, -42);
VerifySimpleAtoiGood<int32_t>(-42, -42);
VerifySimpleAtoiGood<uint32_t>(42, 42);
VerifySimpleAtoiGood<unsigned int>(42, 42);
VerifySimpleAtoiGood<int64_t>(-42, -42);
VerifySimpleAtoiGood<long>(-42, -42); // NOLINT: runtime-int
Export of internal Abseil changes -- f012012ef78234a6a4585321b67d7b7c92ebc266 by Laramie Leavitt <lar@google.com>: Slight restructuring of absl/random/internal randen implementation. Convert round-keys.inc into randen_round_keys.cc file. Consistently use a 128-bit pointer type for internal method parameters. This allows simpler pointer arithmetic in C++ & permits removal of some constants and casts. Remove some redundancy in comments & constexpr variables. Specifically, all references to Randen algorithm parameters use RandenTraits; duplication in RandenSlow removed. PiperOrigin-RevId: 312190313 -- dc8b42e054046741e9ed65335bfdface997c6063 by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 312167304 -- f13d248fafaf206492c1362c3574031aea3abaf7 by Matthew Brown <matthewbr@google.com>: Cleanup StrFormat extensions a little. PiperOrigin-RevId: 312166336 -- 9d9117589667afe2332bb7ad42bc967ca7c54502 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 312105213 -- 9a12b9b3aa0e59b8ee6cf9408ed0029045543a9b by Abseil Team <absl-team@google.com>: Complete IGNORE_TYPE macro renaming. PiperOrigin-RevId: 311999699 -- 64756f20d61021d999bd0d4c15e9ad3857382f57 by Gennadiy Rozental <rogeeff@google.com>: Switch to fixed bytes specific default value. This fixes the Abseil Flags for big endian platforms. PiperOrigin-RevId: 311844448 -- bdbe6b5b29791dbc3816ada1828458b3010ff1e9 by Laramie Leavitt <lar@google.com>: Change many distribution tests to use pcg_engine as a deterministic source of entropy. It's reasonable to test that the BitGen itself has good entropy, however when testing the cross product of all random distributions x all the architecture variations x all submitted changes results in a large number of tests. In order to account for these failures while still using good entropy requires that our allowed sigma need to account for all of these independent tests. Our current sigma values are too restrictive, and we see a lot of failures, so we have to either relax the sigma values or convert some of the statistical tests to use deterministic values. This changelist does the latter. PiperOrigin-RevId: 311840096 GitOrigin-RevId: f012012ef78234a6a4585321b67d7b7c92ebc266 Change-Id: Ic84886f38ff30d7d72c126e9b63c9a61eb729a1a
5 years ago
VerifySimpleAtoiGood<uint64_t>(42, 42);
VerifySimpleAtoiGood<size_t>(42, 42);
VerifySimpleAtoiGood<std::string::size_type>(42, 42);
}
Export of internal Abseil changes -- 517dc7eba9878290fc93c6523dc6d6e2c49b8c1e by Abseil Team <absl-team@google.com>: Handle 'nan' in HumanReadableInt::ToInt64. PiperOrigin-RevId: 318121226 -- 4fa6103b46dbc1375d416810dba591ab4f4898d1 by Abseil Team <absl-team@google.com>: Promote `float`s to `double`s before formatting. This will bring StrFormat behavior more in line with that of sprintf. PiperOrigin-RevId: 318091841 -- e4083a4b64b077d8520ccd8e0ca90da24f4ea24d by Abseil Team <absl-team@google.com>: Google-internal changes only. PiperOrigin-RevId: 318069900 -- ab24f60127db089bccaf5fb7d2d1967c76f34768 by Greg Falcon <gfalcon@google.com>: Inclusive language fix: Stop using blacklist/whitelist terminology in Abseil. PiperOrigin-RevId: 317925379 -- 52b56a27a773ea7c10ea8fd456ed606b9d778947 by Abseil Team <absl-team@google.com>: Add test for floats and label tests for double properly. PiperOrigin-RevId: 317916380 -- 0f405960ab5b34d673244fda8bb9141c8f5c1a4f by Abseil Team <absl-team@google.com>: Remove the static initialization of global variables used by absl::Mutex as requested by Chromium PiperOrigin-RevId: 317911430 -- ce8cb49d8f4f68950fd111682657ba57d5a09ca0 by Abseil Team <absl-team@google.com>: Internal Change PiperOrigin-RevId: 317864956 -- a781948e09fb8406d21a494b2fa4f78edaf9c2ea by Abseil Team <absl-team@google.com>: Swap ABSL_DLL / ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES order to fix clang-cl builds. PiperOrigin-RevId: 317858053 -- 4ba197f0dd2cbf8f9b96cebffd878c8847d6ce8d by Gennadiy Rozental <rogeeff@google.com>: Migrate use of annotation macros to ABSL namespaced names PiperOrigin-RevId: 317792057 GitOrigin-RevId: 517dc7eba9878290fc93c6523dc6d6e2c49b8c1e Change-Id: I1a0c04d01adbdc5106b68fd69c97c31f822e11dc
5 years ago
TEST(NumbersTest, Atod) {
double d;
EXPECT_TRUE(absl::SimpleAtod("nan", &d));
EXPECT_TRUE(std::isnan(d));
}
TEST(NumbersTest, Prefixes) {
double d;
EXPECT_FALSE(absl::SimpleAtod("++1", &d));
EXPECT_FALSE(absl::SimpleAtod("+-1", &d));
EXPECT_FALSE(absl::SimpleAtod("-+1", &d));
EXPECT_FALSE(absl::SimpleAtod("--1", &d));
EXPECT_TRUE(absl::SimpleAtod("-1", &d));
EXPECT_EQ(d, -1.);
EXPECT_TRUE(absl::SimpleAtod("+1", &d));
EXPECT_EQ(d, +1.);
float f;
EXPECT_FALSE(absl::SimpleAtof("++1", &f));
EXPECT_FALSE(absl::SimpleAtof("+-1", &f));
EXPECT_FALSE(absl::SimpleAtof("-+1", &f));
EXPECT_FALSE(absl::SimpleAtof("--1", &f));
EXPECT_TRUE(absl::SimpleAtof("-1", &f));
EXPECT_EQ(f, -1.f);
EXPECT_TRUE(absl::SimpleAtof("+1", &f));
EXPECT_EQ(f, +1.f);
}
Export of internal Abseil changes -- f012012ef78234a6a4585321b67d7b7c92ebc266 by Laramie Leavitt <lar@google.com>: Slight restructuring of absl/random/internal randen implementation. Convert round-keys.inc into randen_round_keys.cc file. Consistently use a 128-bit pointer type for internal method parameters. This allows simpler pointer arithmetic in C++ & permits removal of some constants and casts. Remove some redundancy in comments & constexpr variables. Specifically, all references to Randen algorithm parameters use RandenTraits; duplication in RandenSlow removed. PiperOrigin-RevId: 312190313 -- dc8b42e054046741e9ed65335bfdface997c6063 by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 312167304 -- f13d248fafaf206492c1362c3574031aea3abaf7 by Matthew Brown <matthewbr@google.com>: Cleanup StrFormat extensions a little. PiperOrigin-RevId: 312166336 -- 9d9117589667afe2332bb7ad42bc967ca7c54502 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 312105213 -- 9a12b9b3aa0e59b8ee6cf9408ed0029045543a9b by Abseil Team <absl-team@google.com>: Complete IGNORE_TYPE macro renaming. PiperOrigin-RevId: 311999699 -- 64756f20d61021d999bd0d4c15e9ad3857382f57 by Gennadiy Rozental <rogeeff@google.com>: Switch to fixed bytes specific default value. This fixes the Abseil Flags for big endian platforms. PiperOrigin-RevId: 311844448 -- bdbe6b5b29791dbc3816ada1828458b3010ff1e9 by Laramie Leavitt <lar@google.com>: Change many distribution tests to use pcg_engine as a deterministic source of entropy. It's reasonable to test that the BitGen itself has good entropy, however when testing the cross product of all random distributions x all the architecture variations x all submitted changes results in a large number of tests. In order to account for these failures while still using good entropy requires that our allowed sigma need to account for all of these independent tests. Our current sigma values are too restrictive, and we see a lot of failures, so we have to either relax the sigma values or convert some of the statistical tests to use deterministic values. This changelist does the latter. PiperOrigin-RevId: 311840096 GitOrigin-RevId: f012012ef78234a6a4585321b67d7b7c92ebc266 Change-Id: Ic84886f38ff30d7d72c126e9b63c9a61eb729a1a
5 years ago
TEST(NumbersTest, Atoenum) {
enum E01 {
E01_zero = 0,
E01_one = 1,
};
VerifySimpleAtoiGood<E01>(E01_zero, E01_zero);
VerifySimpleAtoiGood<E01>(E01_one, E01_one);
enum E_101 {
E_101_minusone = -1,
E_101_zero = 0,
E_101_one = 1,
};
VerifySimpleAtoiGood<E_101>(E_101_minusone, E_101_minusone);
VerifySimpleAtoiGood<E_101>(E_101_zero, E_101_zero);
VerifySimpleAtoiGood<E_101>(E_101_one, E_101_one);
enum E_bigint {
E_bigint_zero = 0,
E_bigint_one = 1,
E_bigint_max31 = static_cast<int32_t>(0x7FFFFFFF),
};
VerifySimpleAtoiGood<E_bigint>(E_bigint_zero, E_bigint_zero);
VerifySimpleAtoiGood<E_bigint>(E_bigint_one, E_bigint_one);
VerifySimpleAtoiGood<E_bigint>(E_bigint_max31, E_bigint_max31);
enum E_fullint {
E_fullint_zero = 0,
E_fullint_one = 1,
E_fullint_max31 = static_cast<int32_t>(0x7FFFFFFF),
E_fullint_min32 = INT32_MIN,
};
VerifySimpleAtoiGood<E_fullint>(E_fullint_zero, E_fullint_zero);
VerifySimpleAtoiGood<E_fullint>(E_fullint_one, E_fullint_one);
VerifySimpleAtoiGood<E_fullint>(E_fullint_max31, E_fullint_max31);
VerifySimpleAtoiGood<E_fullint>(E_fullint_min32, E_fullint_min32);
enum E_biguint {
E_biguint_zero = 0,
E_biguint_one = 1,
E_biguint_max31 = static_cast<uint32_t>(0x7FFFFFFF),
E_biguint_max32 = static_cast<uint32_t>(0xFFFFFFFF),
};
VerifySimpleAtoiGood<E_biguint>(E_biguint_zero, E_biguint_zero);
VerifySimpleAtoiGood<E_biguint>(E_biguint_one, E_biguint_one);
VerifySimpleAtoiGood<E_biguint>(E_biguint_max31, E_biguint_max31);
VerifySimpleAtoiGood<E_biguint>(E_biguint_max32, E_biguint_max32);
}
Export of internal Abseil changes -- f49e405201d2ffd5955503fa8ad0f08ec0cdfb2b by Martijn Vels <mvels@google.com>: Add common [container.requirements] type definitions to `CharRange` and `ChunkRange` The presence of these allow these range classes to be used in various utility functions which require some minimum type of container. For example, this change allows tests to use `EXPECT_THAT(cord.Chunks(), ElementsAre(...))` PiperOrigin-RevId: 406941278 -- 0c195f073632e21d9a4bce158047b2ba8551c2d1 by Evan Brown <ezb@google.com>: Use explicit exponential growth in SubstituteAndAppendArray. PiperOrigin-RevId: 406931952 -- afb043bccd809a55cab78abadb7548a057d9eda0 by Jorg Brown <jorg@google.com>: Use longer var names in macro to avoid clang-tidy warning PiperOrigin-RevId: 406930978 -- 80397e2604e6b3d929a34742c3a32581b34d3ac4 by Martijn Vels <mvels@google.com>: Add future kAppendBuffer and kPrependBuffer API trackers for Cordz sampling PiperOrigin-RevId: 406912759 -- e910ce919ef83933f08a690e8b7325c7cc5b6d5d by Martijn Vels <mvels@google.com>: Implement Prepend(string_view) in terms of PrependArray(string_view, MethodIdentifier). PiperOrigin-RevId: 406891665 -- c9cff43d4c0568ed01f2fca0f6ef038ae03112b5 by Martijn Vels <mvels@google.com>: Add 'Rebuild' logic to CordRepBtree There are btree hostile scenarios where an application could perform repeated split/insert/merge operations on a cord leading to a tree exceeding the maximum height. While this should be rare in practice, this change adds a Rebuild() method that will rebuild a tree with a 100% fill factor, and we will invoke this rebuild when a tree exceeds the maximum height. This basically follows the similar 'balance' logic in Concat trees (although the latter is common in Concat uses) PiperOrigin-RevId: 406875739 -- 5b2b8fb88f1ebfdc1c670088152da2cb2ea4c376 by Martijn Vels <mvels@google.com>: Add 'in place' enabled RemoveSuffix An in-place RemoveSuffix is more efficient than SubTree() as it can directly modify privately owned nodes and flats allowing easy re-use of free capacity in right-most flats that may turn into Substring edges when using SubTree. PiperOrigin-RevId: 406431230 -- f09903c0a3d7344f59aaf1380a16ea10829217d4 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 406430373 -- 9957af575c33bb18dc170572a4ee8cc5901df6b2 by Greg Falcon <gfalcon@google.com>: Initial groundwork to allow storing checksum data inside CordRep instances. This uses a RefcountAndFlags bit that was reserved for this purpose, and will be leveraged in a follow-up change to allow attaching checksums to a Cord's value. This change splits RefcountAndFlags::IsOne() into two distinct operations: * IsOne(): This returns true when the associated CordRep is not shared with other threads. This is useful for functions that consume CordRep instances; for example, code that consumes an unshared CordRep can assume ownership of its children without modifying those refcounts. * IsMutable(): This returns true when the associated CordRep reference is not shared with other threads, *and* does not store an associated checksum value. This is useful for functions that modify a CordRep's contents: code may modify the bytes of a mutable-unshared CordRep without fear of races with other threads, or of invalidating a stored checksum. The tricky part of this CL is ensuring that the correct choice between IsMutable() and IsOne() was made at each point. An incorrect application of IsOne() could lead to correctness bugs in the future. Code conditioned on IsOne() may delete the CordRep in question, or assume ownership of its children, but must not modify the CordRep's data without explicitly adjusting the CRC. PiperOrigin-RevId: 406191103 -- 686544814079e5ab6d4593cca0c068b510be400a by Martijn Vels <mvels@google.com>: Reduce the size in the LargeString test when running with Sanitizers PiperOrigin-RevId: 406186945 -- 735b4490bdb695c35731f06ce4b8de14ce2be6ed by Alex Strelnikov <strel@google.com>: Release absl::SimpleHexAtoi. PiperOrigin-RevId: 406143188 GitOrigin-RevId: f49e405201d2ffd5955503fa8ad0f08ec0cdfb2b Change-Id: Ic6527ac40fa03ea02ca813e8bb7868a219544de4
3 years ago
template <typename int_type, typename in_val_type>
void VerifySimpleHexAtoiGood(in_val_type in_value, int_type exp_value) {
std::string s;
// uint128 can be streamed but not StrCat'd
absl::strings_internal::OStringStream strm(&s);
if (in_value >= 0) {
strm << std::hex << in_value;
} else {
// Inefficient for small integers, but works with all integral types.
strm << "-" << std::hex << -absl::uint128(in_value);
}
int_type x = static_cast<int_type>(~exp_value);
EXPECT_TRUE(SimpleHexAtoi(s, &x))
<< "in_value=" << std::hex << in_value << " s=" << s << " x=" << x;
EXPECT_EQ(exp_value, x);
x = static_cast<int_type>(~exp_value);
EXPECT_TRUE(SimpleHexAtoi(
s.c_str(), &x)); // NOLINT: readability-redundant-string-conversions
EXPECT_EQ(exp_value, x);
}
template <typename int_type, typename in_val_type>
void VerifySimpleHexAtoiBad(in_val_type in_value) {
std::string s;
// uint128 can be streamed but not StrCat'd
absl::strings_internal::OStringStream strm(&s);
if (in_value >= 0) {
strm << std::hex << in_value;
} else {
// Inefficient for small integers, but works with all integral types.
strm << "-" << std::hex << -absl::uint128(in_value);
}
int_type x;
EXPECT_FALSE(SimpleHexAtoi(s, &x));
EXPECT_FALSE(SimpleHexAtoi(
s.c_str(), &x)); // NOLINT: readability-redundant-string-conversions
}
TEST(NumbersTest, HexAtoi) {
// SimpleHexAtoi(absl::string_view, int32_t)
VerifySimpleHexAtoiGood<int32_t>(0, 0);
VerifySimpleHexAtoiGood<int32_t>(0x42, 0x42);
VerifySimpleHexAtoiGood<int32_t>(-0x42, -0x42);
VerifySimpleHexAtoiGood<int32_t>(std::numeric_limits<int32_t>::min(),
std::numeric_limits<int32_t>::min());
VerifySimpleHexAtoiGood<int32_t>(std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::max());
// SimpleHexAtoi(absl::string_view, uint32_t)
VerifySimpleHexAtoiGood<uint32_t>(0, 0);
VerifySimpleHexAtoiGood<uint32_t>(0x42, 0x42);
VerifySimpleHexAtoiBad<uint32_t>(-0x42);
VerifySimpleHexAtoiBad<uint32_t>(std::numeric_limits<int32_t>::min());
VerifySimpleHexAtoiGood<uint32_t>(std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::max());
VerifySimpleHexAtoiGood<uint32_t>(std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::max());
VerifySimpleHexAtoiBad<uint32_t>(std::numeric_limits<int64_t>::min());
VerifySimpleHexAtoiBad<uint32_t>(std::numeric_limits<int64_t>::max());
VerifySimpleHexAtoiBad<uint32_t>(std::numeric_limits<uint64_t>::max());
// SimpleHexAtoi(absl::string_view, int64_t)
VerifySimpleHexAtoiGood<int64_t>(0, 0);
VerifySimpleHexAtoiGood<int64_t>(0x42, 0x42);
VerifySimpleHexAtoiGood<int64_t>(-0x42, -0x42);
VerifySimpleHexAtoiGood<int64_t>(std::numeric_limits<int32_t>::min(),
std::numeric_limits<int32_t>::min());
VerifySimpleHexAtoiGood<int64_t>(std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::max());
VerifySimpleHexAtoiGood<int64_t>(std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::max());
VerifySimpleHexAtoiGood<int64_t>(std::numeric_limits<int64_t>::min(),
std::numeric_limits<int64_t>::min());
VerifySimpleHexAtoiGood<int64_t>(std::numeric_limits<int64_t>::max(),
std::numeric_limits<int64_t>::max());
VerifySimpleHexAtoiBad<int64_t>(std::numeric_limits<uint64_t>::max());
// SimpleHexAtoi(absl::string_view, uint64_t)
VerifySimpleHexAtoiGood<uint64_t>(0, 0);
VerifySimpleHexAtoiGood<uint64_t>(0x42, 0x42);
VerifySimpleHexAtoiBad<uint64_t>(-0x42);
VerifySimpleHexAtoiBad<uint64_t>(std::numeric_limits<int32_t>::min());
VerifySimpleHexAtoiGood<uint64_t>(std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::max());
VerifySimpleHexAtoiGood<uint64_t>(std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::max());
VerifySimpleHexAtoiBad<uint64_t>(std::numeric_limits<int64_t>::min());
VerifySimpleHexAtoiGood<uint64_t>(std::numeric_limits<int64_t>::max(),
std::numeric_limits<int64_t>::max());
VerifySimpleHexAtoiGood<uint64_t>(std::numeric_limits<uint64_t>::max(),
std::numeric_limits<uint64_t>::max());
// SimpleHexAtoi(absl::string_view, absl::uint128)
VerifySimpleHexAtoiGood<absl::uint128>(0, 0);
VerifySimpleHexAtoiGood<absl::uint128>(0x42, 0x42);
VerifySimpleHexAtoiBad<absl::uint128>(-0x42);
VerifySimpleHexAtoiBad<absl::uint128>(std::numeric_limits<int32_t>::min());
VerifySimpleHexAtoiGood<absl::uint128>(std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::max());
VerifySimpleHexAtoiGood<absl::uint128>(std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::max());
VerifySimpleHexAtoiBad<absl::uint128>(std::numeric_limits<int64_t>::min());
VerifySimpleHexAtoiGood<absl::uint128>(std::numeric_limits<int64_t>::max(),
std::numeric_limits<int64_t>::max());
VerifySimpleHexAtoiGood<absl::uint128>(std::numeric_limits<uint64_t>::max(),
std::numeric_limits<uint64_t>::max());
VerifySimpleHexAtoiGood<absl::uint128>(
std::numeric_limits<absl::uint128>::max(),
std::numeric_limits<absl::uint128>::max());
// Some other types
VerifySimpleHexAtoiGood<int>(-0x42, -0x42);
VerifySimpleHexAtoiGood<int32_t>(-0x42, -0x42);
VerifySimpleHexAtoiGood<uint32_t>(0x42, 0x42);
VerifySimpleHexAtoiGood<unsigned int>(0x42, 0x42);
VerifySimpleHexAtoiGood<int64_t>(-0x42, -0x42);
VerifySimpleHexAtoiGood<long>(-0x42, -0x42); // NOLINT: runtime-int
VerifySimpleHexAtoiGood<uint64_t>(0x42, 0x42);
VerifySimpleHexAtoiGood<size_t>(0x42, 0x42);
VerifySimpleHexAtoiGood<std::string::size_type>(0x42, 0x42);
// Number prefix
int32_t value;
EXPECT_TRUE(safe_strto32_base("0x34234324", &value, 16));
EXPECT_EQ(0x34234324, value);
EXPECT_TRUE(safe_strto32_base("0X34234324", &value, 16));
EXPECT_EQ(0x34234324, value);
// ASCII whitespace
EXPECT_TRUE(safe_strto32_base(" \t\n 34234324", &value, 16));
EXPECT_EQ(0x34234324, value);
EXPECT_TRUE(safe_strto32_base("34234324 \t\n ", &value, 16));
EXPECT_EQ(0x34234324, value);
}
Export of internal Abseil changes -- f012012ef78234a6a4585321b67d7b7c92ebc266 by Laramie Leavitt <lar@google.com>: Slight restructuring of absl/random/internal randen implementation. Convert round-keys.inc into randen_round_keys.cc file. Consistently use a 128-bit pointer type for internal method parameters. This allows simpler pointer arithmetic in C++ & permits removal of some constants and casts. Remove some redundancy in comments & constexpr variables. Specifically, all references to Randen algorithm parameters use RandenTraits; duplication in RandenSlow removed. PiperOrigin-RevId: 312190313 -- dc8b42e054046741e9ed65335bfdface997c6063 by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 312167304 -- f13d248fafaf206492c1362c3574031aea3abaf7 by Matthew Brown <matthewbr@google.com>: Cleanup StrFormat extensions a little. PiperOrigin-RevId: 312166336 -- 9d9117589667afe2332bb7ad42bc967ca7c54502 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 312105213 -- 9a12b9b3aa0e59b8ee6cf9408ed0029045543a9b by Abseil Team <absl-team@google.com>: Complete IGNORE_TYPE macro renaming. PiperOrigin-RevId: 311999699 -- 64756f20d61021d999bd0d4c15e9ad3857382f57 by Gennadiy Rozental <rogeeff@google.com>: Switch to fixed bytes specific default value. This fixes the Abseil Flags for big endian platforms. PiperOrigin-RevId: 311844448 -- bdbe6b5b29791dbc3816ada1828458b3010ff1e9 by Laramie Leavitt <lar@google.com>: Change many distribution tests to use pcg_engine as a deterministic source of entropy. It's reasonable to test that the BitGen itself has good entropy, however when testing the cross product of all random distributions x all the architecture variations x all submitted changes results in a large number of tests. In order to account for these failures while still using good entropy requires that our allowed sigma need to account for all of these independent tests. Our current sigma values are too restrictive, and we see a lot of failures, so we have to either relax the sigma values or convert some of the statistical tests to use deterministic values. This changelist does the latter. PiperOrigin-RevId: 311840096 GitOrigin-RevId: f012012ef78234a6a4585321b67d7b7c92ebc266 Change-Id: Ic84886f38ff30d7d72c126e9b63c9a61eb729a1a
5 years ago
TEST(stringtest, safe_strto32_base) {
int32_t value;
EXPECT_TRUE(safe_strto32_base("0x34234324", &value, 16));
EXPECT_EQ(0x34234324, value);
EXPECT_TRUE(safe_strto32_base("0X34234324", &value, 16));
EXPECT_EQ(0x34234324, value);
EXPECT_TRUE(safe_strto32_base("34234324", &value, 16));
EXPECT_EQ(0x34234324, value);
EXPECT_TRUE(safe_strto32_base("0", &value, 16));
EXPECT_EQ(0, value);
EXPECT_TRUE(safe_strto32_base(" \t\n -0x34234324", &value, 16));
EXPECT_EQ(-0x34234324, value);
EXPECT_TRUE(safe_strto32_base(" \t\n -34234324", &value, 16));
EXPECT_EQ(-0x34234324, value);
EXPECT_TRUE(safe_strto32_base("7654321", &value, 8));
EXPECT_EQ(07654321, value);
EXPECT_TRUE(safe_strto32_base("-01234", &value, 8));
EXPECT_EQ(-01234, value);
EXPECT_FALSE(safe_strto32_base("1834", &value, 8));
// Autodetect base.
EXPECT_TRUE(safe_strto32_base("0", &value, 0));
EXPECT_EQ(0, value);
EXPECT_TRUE(safe_strto32_base("077", &value, 0));
EXPECT_EQ(077, value); // Octal interpretation
// Leading zero indicates octal, but then followed by invalid digit.
EXPECT_FALSE(safe_strto32_base("088", &value, 0));
// Leading 0x indicated hex, but then followed by invalid digit.
EXPECT_FALSE(safe_strto32_base("0xG", &value, 0));
// Base-10 version.
EXPECT_TRUE(safe_strto32_base("34234324", &value, 10));
EXPECT_EQ(34234324, value);
EXPECT_TRUE(safe_strto32_base("0", &value, 10));
EXPECT_EQ(0, value);
EXPECT_TRUE(safe_strto32_base(" \t\n -34234324", &value, 10));
EXPECT_EQ(-34234324, value);
EXPECT_TRUE(safe_strto32_base("34234324 \n\t ", &value, 10));
EXPECT_EQ(34234324, value);
// Invalid ints.
EXPECT_FALSE(safe_strto32_base("", &value, 10));
EXPECT_FALSE(safe_strto32_base(" ", &value, 10));
EXPECT_FALSE(safe_strto32_base("abc", &value, 10));
EXPECT_FALSE(safe_strto32_base("34234324a", &value, 10));
EXPECT_FALSE(safe_strto32_base("34234.3", &value, 10));
// Out of bounds.
EXPECT_FALSE(safe_strto32_base("2147483648", &value, 10));
EXPECT_FALSE(safe_strto32_base("-2147483649", &value, 10));
// String version.
EXPECT_TRUE(safe_strto32_base(std::string("0x1234"), &value, 16));
EXPECT_EQ(0x1234, value);
// Base-10 string version.
EXPECT_TRUE(safe_strto32_base("1234", &value, 10));
EXPECT_EQ(1234, value);
}
TEST(stringtest, safe_strto32_range) {
// These tests verify underflow/overflow behaviour.
int32_t value;
EXPECT_FALSE(safe_strto32_base("2147483648", &value, 10));
EXPECT_EQ(std::numeric_limits<int32_t>::max(), value);
EXPECT_TRUE(safe_strto32_base("-2147483648", &value, 10));
EXPECT_EQ(std::numeric_limits<int32_t>::min(), value);
EXPECT_FALSE(safe_strto32_base("-2147483649", &value, 10));
EXPECT_EQ(std::numeric_limits<int32_t>::min(), value);
}
TEST(stringtest, safe_strto64_range) {
// These tests verify underflow/overflow behaviour.
int64_t value;
EXPECT_FALSE(safe_strto64_base("9223372036854775808", &value, 10));
EXPECT_EQ(std::numeric_limits<int64_t>::max(), value);
EXPECT_TRUE(safe_strto64_base("-9223372036854775808", &value, 10));
EXPECT_EQ(std::numeric_limits<int64_t>::min(), value);
EXPECT_FALSE(safe_strto64_base("-9223372036854775809", &value, 10));
EXPECT_EQ(std::numeric_limits<int64_t>::min(), value);
}
TEST(stringtest, safe_strto32_leading_substring) {
// These tests verify this comment in numbers.h:
// On error, returns false, and sets *value to: [...]
// conversion of leading substring if available ("123@@@" -> 123)
// 0 if no leading substring available
int32_t value;
EXPECT_FALSE(safe_strto32_base("04069@@@", &value, 10));
EXPECT_EQ(4069, value);
EXPECT_FALSE(safe_strto32_base("04069@@@", &value, 8));
EXPECT_EQ(0406, value);
EXPECT_FALSE(safe_strto32_base("04069balloons", &value, 10));
EXPECT_EQ(4069, value);
EXPECT_FALSE(safe_strto32_base("04069balloons", &value, 16));
EXPECT_EQ(0x4069ba, value);
EXPECT_FALSE(safe_strto32_base("@@@", &value, 10));
EXPECT_EQ(0, value); // there was no leading substring
}
TEST(stringtest, safe_strto64_leading_substring) {
// These tests verify this comment in numbers.h:
// On error, returns false, and sets *value to: [...]
// conversion of leading substring if available ("123@@@" -> 123)
// 0 if no leading substring available
int64_t value;
EXPECT_FALSE(safe_strto64_base("04069@@@", &value, 10));
EXPECT_EQ(4069, value);
EXPECT_FALSE(safe_strto64_base("04069@@@", &value, 8));
EXPECT_EQ(0406, value);
EXPECT_FALSE(safe_strto64_base("04069balloons", &value, 10));
EXPECT_EQ(4069, value);
EXPECT_FALSE(safe_strto64_base("04069balloons", &value, 16));
EXPECT_EQ(0x4069ba, value);
EXPECT_FALSE(safe_strto64_base("@@@", &value, 10));
EXPECT_EQ(0, value); // there was no leading substring
}
TEST(stringtest, safe_strto64_base) {
int64_t value;
EXPECT_TRUE(safe_strto64_base("0x3423432448783446", &value, 16));
EXPECT_EQ(int64_t{0x3423432448783446}, value);
EXPECT_TRUE(safe_strto64_base("3423432448783446", &value, 16));
EXPECT_EQ(int64_t{0x3423432448783446}, value);
EXPECT_TRUE(safe_strto64_base("0", &value, 16));
EXPECT_EQ(0, value);
EXPECT_TRUE(safe_strto64_base(" \t\n -0x3423432448783446", &value, 16));
EXPECT_EQ(int64_t{-0x3423432448783446}, value);
EXPECT_TRUE(safe_strto64_base(" \t\n -3423432448783446", &value, 16));
EXPECT_EQ(int64_t{-0x3423432448783446}, value);
EXPECT_TRUE(safe_strto64_base("123456701234567012", &value, 8));
EXPECT_EQ(int64_t{0123456701234567012}, value);
EXPECT_TRUE(safe_strto64_base("-017777777777777", &value, 8));
EXPECT_EQ(int64_t{-017777777777777}, value);
EXPECT_FALSE(safe_strto64_base("19777777777777", &value, 8));
// Autodetect base.
EXPECT_TRUE(safe_strto64_base("0", &value, 0));
EXPECT_EQ(0, value);
EXPECT_TRUE(safe_strto64_base("077", &value, 0));
EXPECT_EQ(077, value); // Octal interpretation
// Leading zero indicates octal, but then followed by invalid digit.
EXPECT_FALSE(safe_strto64_base("088", &value, 0));
// Leading 0x indicated hex, but then followed by invalid digit.
EXPECT_FALSE(safe_strto64_base("0xG", &value, 0));
// Base-10 version.
EXPECT_TRUE(safe_strto64_base("34234324487834466", &value, 10));
EXPECT_EQ(int64_t{34234324487834466}, value);
EXPECT_TRUE(safe_strto64_base("0", &value, 10));
EXPECT_EQ(0, value);
EXPECT_TRUE(safe_strto64_base(" \t\n -34234324487834466", &value, 10));
EXPECT_EQ(int64_t{-34234324487834466}, value);
EXPECT_TRUE(safe_strto64_base("34234324487834466 \n\t ", &value, 10));
EXPECT_EQ(int64_t{34234324487834466}, value);
// Invalid ints.
EXPECT_FALSE(safe_strto64_base("", &value, 10));
EXPECT_FALSE(safe_strto64_base(" ", &value, 10));
EXPECT_FALSE(safe_strto64_base("abc", &value, 10));
EXPECT_FALSE(safe_strto64_base("34234324487834466a", &value, 10));
EXPECT_FALSE(safe_strto64_base("34234487834466.3", &value, 10));
// Out of bounds.
EXPECT_FALSE(safe_strto64_base("9223372036854775808", &value, 10));
EXPECT_FALSE(safe_strto64_base("-9223372036854775809", &value, 10));
// String version.
EXPECT_TRUE(safe_strto64_base(std::string("0x1234"), &value, 16));
EXPECT_EQ(0x1234, value);
// Base-10 string version.
EXPECT_TRUE(safe_strto64_base("1234", &value, 10));
EXPECT_EQ(1234, value);
}
const size_t kNumRandomTests = 10000;
template <typename IntType>
void test_random_integer_parse_base(bool (*parse_func)(absl::string_view,
IntType* value,
int base)) {
using RandomEngine = std::minstd_rand0;
std::random_device rd;
RandomEngine rng(rd());
std::uniform_int_distribution<IntType> random_int(
std::numeric_limits<IntType>::min());
std::uniform_int_distribution<int> random_base(2, 35);
for (size_t i = 0; i < kNumRandomTests; i++) {
IntType value = random_int(rng);
int base = random_base(rng);
std::string str_value;
EXPECT_TRUE(Itoa<IntType>(value, base, &str_value));
IntType parsed_value;
// Test successful parse
EXPECT_TRUE(parse_func(str_value, &parsed_value, base));
EXPECT_EQ(parsed_value, value);
// Test overflow
EXPECT_FALSE(
parse_func(absl::StrCat(std::numeric_limits<IntType>::max(), value),
&parsed_value, base));
// Test underflow
if (std::numeric_limits<IntType>::min() < 0) {
EXPECT_FALSE(
parse_func(absl::StrCat(std::numeric_limits<IntType>::min(), value),
&parsed_value, base));
} else {
EXPECT_FALSE(parse_func(absl::StrCat("-", value), &parsed_value, base));
}
}
}
TEST(stringtest, safe_strto32_random) {
test_random_integer_parse_base<int32_t>(&safe_strto32_base);
}
TEST(stringtest, safe_strto64_random) {
test_random_integer_parse_base<int64_t>(&safe_strto64_base);
}
TEST(stringtest, safe_strtou32_random) {
test_random_integer_parse_base<uint32_t>(&safe_strtou32_base);
}
TEST(stringtest, safe_strtou64_random) {
test_random_integer_parse_base<uint64_t>(&safe_strtou64_base);
}
TEST(stringtest, safe_strtou128_random) {
// random number generators don't work for uint128, and
// uint128 can be streamed but not StrCat'd, so this code must be custom
// implemented for uint128, but is generally the same as what's above.
// test_random_integer_parse_base<absl::uint128>(
// &absl::numbers_internal::safe_strtou128_base);
using RandomEngine = std::minstd_rand0;
using IntType = absl::uint128;
constexpr auto parse_func = &absl::numbers_internal::safe_strtou128_base;
std::random_device rd;
RandomEngine rng(rd());
std::uniform_int_distribution<uint64_t> random_uint64(
std::numeric_limits<uint64_t>::min());
std::uniform_int_distribution<int> random_base(2, 35);
for (size_t i = 0; i < kNumRandomTests; i++) {
IntType value = random_uint64(rng);
value = (value << 64) + random_uint64(rng);
int base = random_base(rng);
std::string str_value;
EXPECT_TRUE(Itoa<IntType>(value, base, &str_value));
IntType parsed_value;
// Test successful parse
EXPECT_TRUE(parse_func(str_value, &parsed_value, base));
EXPECT_EQ(parsed_value, value);
// Test overflow
std::string s;
absl::strings_internal::OStringStream(&s)
<< std::numeric_limits<IntType>::max() << value;
EXPECT_FALSE(parse_func(s, &parsed_value, base));
// Test underflow
s.clear();
absl::strings_internal::OStringStream(&s) << "-" << value;
EXPECT_FALSE(parse_func(s, &parsed_value, base));
}
}
TEST(stringtest, safe_strto128_random) {
// random number generators don't work for int128, and
// int128 can be streamed but not StrCat'd, so this code must be custom
// implemented for int128, but is generally the same as what's above.
// test_random_integer_parse_base<absl::int128>(
// &absl::numbers_internal::safe_strto128_base);
using RandomEngine = std::minstd_rand0;
using IntType = absl::int128;
constexpr auto parse_func = &absl::numbers_internal::safe_strto128_base;
std::random_device rd;
RandomEngine rng(rd());
std::uniform_int_distribution<int64_t> random_int64(
std::numeric_limits<int64_t>::min());
std::uniform_int_distribution<uint64_t> random_uint64(
std::numeric_limits<uint64_t>::min());
std::uniform_int_distribution<int> random_base(2, 35);
for (size_t i = 0; i < kNumRandomTests; ++i) {
int64_t high = random_int64(rng);
uint64_t low = random_uint64(rng);
IntType value = absl::MakeInt128(high, low);
int base = random_base(rng);
std::string str_value;
EXPECT_TRUE(Itoa<IntType>(value, base, &str_value));
IntType parsed_value;
// Test successful parse
EXPECT_TRUE(parse_func(str_value, &parsed_value, base));
EXPECT_EQ(parsed_value, value);
// Test overflow
std::string s;
absl::strings_internal::OStringStream(&s)
<< std::numeric_limits<IntType>::max() << value;
EXPECT_FALSE(parse_func(s, &parsed_value, base));
// Test underflow
s.clear();
absl::strings_internal::OStringStream(&s)
<< std::numeric_limits<IntType>::min() << value;
EXPECT_FALSE(parse_func(s, &parsed_value, base));
}
}
Export of internal Abseil changes -- f012012ef78234a6a4585321b67d7b7c92ebc266 by Laramie Leavitt <lar@google.com>: Slight restructuring of absl/random/internal randen implementation. Convert round-keys.inc into randen_round_keys.cc file. Consistently use a 128-bit pointer type for internal method parameters. This allows simpler pointer arithmetic in C++ & permits removal of some constants and casts. Remove some redundancy in comments & constexpr variables. Specifically, all references to Randen algorithm parameters use RandenTraits; duplication in RandenSlow removed. PiperOrigin-RevId: 312190313 -- dc8b42e054046741e9ed65335bfdface997c6063 by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 312167304 -- f13d248fafaf206492c1362c3574031aea3abaf7 by Matthew Brown <matthewbr@google.com>: Cleanup StrFormat extensions a little. PiperOrigin-RevId: 312166336 -- 9d9117589667afe2332bb7ad42bc967ca7c54502 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 312105213 -- 9a12b9b3aa0e59b8ee6cf9408ed0029045543a9b by Abseil Team <absl-team@google.com>: Complete IGNORE_TYPE macro renaming. PiperOrigin-RevId: 311999699 -- 64756f20d61021d999bd0d4c15e9ad3857382f57 by Gennadiy Rozental <rogeeff@google.com>: Switch to fixed bytes specific default value. This fixes the Abseil Flags for big endian platforms. PiperOrigin-RevId: 311844448 -- bdbe6b5b29791dbc3816ada1828458b3010ff1e9 by Laramie Leavitt <lar@google.com>: Change many distribution tests to use pcg_engine as a deterministic source of entropy. It's reasonable to test that the BitGen itself has good entropy, however when testing the cross product of all random distributions x all the architecture variations x all submitted changes results in a large number of tests. In order to account for these failures while still using good entropy requires that our allowed sigma need to account for all of these independent tests. Our current sigma values are too restrictive, and we see a lot of failures, so we have to either relax the sigma values or convert some of the statistical tests to use deterministic values. This changelist does the latter. PiperOrigin-RevId: 311840096 GitOrigin-RevId: f012012ef78234a6a4585321b67d7b7c92ebc266 Change-Id: Ic84886f38ff30d7d72c126e9b63c9a61eb729a1a
5 years ago
TEST(stringtest, safe_strtou32_base) {
for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) {
const auto& e = strtouint32_test_cases()[i];
uint32_t value;
EXPECT_EQ(e.expect_ok, safe_strtou32_base(e.str, &value, e.base))
<< "str=\"" << e.str << "\" base=" << e.base;
if (e.expect_ok) {
EXPECT_EQ(e.expected, value) << "i=" << i << " str=\"" << e.str
<< "\" base=" << e.base;
}
}
}
TEST(stringtest, safe_strtou32_base_length_delimited) {
for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) {
const auto& e = strtouint32_test_cases()[i];
std::string tmp(e.str);
tmp.append("12"); // Adds garbage at the end.
uint32_t value;
EXPECT_EQ(e.expect_ok,
safe_strtou32_base(absl::string_view(tmp.data(), strlen(e.str)),
&value, e.base))
<< "str=\"" << e.str << "\" base=" << e.base;
if (e.expect_ok) {
EXPECT_EQ(e.expected, value) << "i=" << i << " str=" << e.str
<< " base=" << e.base;
}
}
}
TEST(stringtest, safe_strtou64_base) {
for (int i = 0; strtouint64_test_cases()[i].str != nullptr; ++i) {
const auto& e = strtouint64_test_cases()[i];
uint64_t value;
EXPECT_EQ(e.expect_ok, safe_strtou64_base(e.str, &value, e.base))
<< "str=\"" << e.str << "\" base=" << e.base;
if (e.expect_ok) {
EXPECT_EQ(e.expected, value) << "str=" << e.str << " base=" << e.base;
}
}
}
TEST(stringtest, safe_strtou64_base_length_delimited) {
for (int i = 0; strtouint64_test_cases()[i].str != nullptr; ++i) {
const auto& e = strtouint64_test_cases()[i];
std::string tmp(e.str);
tmp.append("12"); // Adds garbage at the end.
uint64_t value;
EXPECT_EQ(e.expect_ok,
safe_strtou64_base(absl::string_view(tmp.data(), strlen(e.str)),
&value, e.base))
<< "str=\"" << e.str << "\" base=" << e.base;
if (e.expect_ok) {
EXPECT_EQ(e.expected, value) << "str=\"" << e.str << "\" base=" << e.base;
}
}
}
// feenableexcept() and fedisableexcept() are extensions supported by some libc
// implementations.
#if defined(__GLIBC__) || defined(__BIONIC__)
#define ABSL_HAVE_FEENABLEEXCEPT 1
#define ABSL_HAVE_FEDISABLEEXCEPT 1
#endif
class SimpleDtoaTest : public testing::Test {
protected:
void SetUp() override {
// Store the current floating point env & clear away any pending exceptions.
feholdexcept(&fp_env_);
#ifdef ABSL_HAVE_FEENABLEEXCEPT
// Turn on floating point exceptions.
feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
#endif
}
void TearDown() override {
// Restore the floating point environment to the original state.
// In theory fedisableexcept is unnecessary; fesetenv will also do it.
// In practice, our toolchains have subtle bugs.
#ifdef ABSL_HAVE_FEDISABLEEXCEPT
fedisableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
#endif
fesetenv(&fp_env_);
}
std::string ToNineDigits(double value) {
char buffer[16]; // more than enough for %.9g
snprintf(buffer, sizeof(buffer), "%.9g", value);
return buffer;
}
fenv_t fp_env_;
};
// Run the given runnable functor for "cases" test cases, chosen over the
// available range of float. pi and e and 1/e are seeded, and then all
// available integer powers of 2 and 10 are multiplied against them. In
// addition to trying all those values, we try the next higher and next lower
// float, and then we add additional test cases evenly distributed between them.
// Each test case is passed to runnable as both a positive and negative value.
template <typename R>
void ExhaustiveFloat(uint32_t cases, R&& runnable) {
runnable(0.0f);
runnable(-0.0f);
if (cases >= 2e9) { // more than 2 billion? Might as well run them all.
for (float f = 0; f < std::numeric_limits<float>::max(); ) {
f = nextafterf(f, std::numeric_limits<float>::max());
runnable(-f);
runnable(f);
}
return;
}
std::set<float> floats = {3.4028234e38f};
for (float f : {1.0, 3.14159265, 2.718281828, 1 / 2.718281828}) {
for (float testf = f; testf != 0; testf *= 0.1f) floats.insert(testf);
for (float testf = f; testf != 0; testf *= 0.5f) floats.insert(testf);
for (float testf = f; testf < 3e38f / 2; testf *= 2.0f)
floats.insert(testf);
for (float testf = f; testf < 3e38f / 10; testf *= 10) floats.insert(testf);
}
float last = *floats.begin();
runnable(last);
runnable(-last);
int iters_per_float = cases / floats.size();
if (iters_per_float == 0) iters_per_float = 1;
for (float f : floats) {
if (f == last) continue;
float testf = std::nextafter(last, std::numeric_limits<float>::max());
runnable(testf);
runnable(-testf);
last = testf;
if (f == last) continue;
double step = (double{f} - last) / iters_per_float;
for (double d = last + step; d < f; d += step) {
testf = d;
if (testf != last) {
runnable(testf);
runnable(-testf);
last = testf;
}
}
testf = std::nextafter(f, 0.0f);
if (testf > last) {
runnable(testf);
runnable(-testf);
last = testf;
}
if (f != last) {
runnable(f);
runnable(-f);
last = f;
}
}
}
TEST_F(SimpleDtoaTest, ExhaustiveDoubleToSixDigits) {
uint64_t test_count = 0;
std::vector<double> mismatches;
auto checker = [&](double d) {
if (d != d) return; // rule out NaNs
++test_count;
char sixdigitsbuf[kSixDigitsToBufferSize] = {0};
SixDigitsToBuffer(d, sixdigitsbuf);
char snprintfbuf[kSixDigitsToBufferSize] = {0};
snprintf(snprintfbuf, kSixDigitsToBufferSize, "%g", d);
if (strcmp(sixdigitsbuf, snprintfbuf) != 0) {
mismatches.push_back(d);
if (mismatches.size() < 10) {
ABSL_RAW_LOG(ERROR, "%s",
absl::StrCat("Six-digit failure with double. ", "d=", d,
"=", d, " sixdigits=", sixdigitsbuf,
" printf(%g)=", snprintfbuf)
.c_str());
}
}
};
// Some quick sanity checks...
checker(5e-324);
checker(1e-308);
checker(1.0);
checker(1.000005);
checker(1.7976931348623157e308);
checker(0.00390625);
#ifndef _MSC_VER
// on MSVC, snprintf() rounds it to 0.00195313. SixDigitsToBuffer() rounds it
// to 0.00195312 (round half to even).
checker(0.001953125);
#endif
checker(0.005859375);
// Some cases where the rounding is very very close
checker(1.089095e-15);
checker(3.274195e-55);
checker(6.534355e-146);
checker(2.920845e+234);
if (mismatches.empty()) {
test_count = 0;
ExhaustiveFloat(kFloatNumCases, checker);
test_count = 0;
std::vector<int> digit_testcases{
100000, 100001, 100002, 100005, 100010, 100020, 100050, 100100, // misc
195312, 195313, // 1.953125 is a case where we round down, just barely.
200000, 500000, 800000, // misc mid-range cases
585937, 585938, // 5.859375 is a case where we round up, just barely.
900000, 990000, 999000, 999900, 999990, 999996, 999997, 999998, 999999};
if (kFloatNumCases >= 1e9) {
// If at least 1 billion test cases were requested, user wants an
// exhaustive test. So let's test all mantissas, too.
constexpr int min_mantissa = 100000, max_mantissa = 999999;
digit_testcases.resize(max_mantissa - min_mantissa + 1);
std::iota(digit_testcases.begin(), digit_testcases.end(), min_mantissa);
}
for (int exponent = -324; exponent <= 308; ++exponent) {
double powten = absl::strings_internal::Pow10(exponent);
if (powten == 0) powten = 5e-324;
if (kFloatNumCases >= 1e9) {
// The exhaustive test takes a very long time, so log progress.
char buf[kSixDigitsToBufferSize];
ABSL_RAW_LOG(
INFO, "%s",
absl::StrCat("Exp ", exponent, " powten=", powten, "(", powten,
") (",
std::string(buf, SixDigitsToBuffer(powten, buf)), ")")
.c_str());
}
for (int digits : digit_testcases) {
if (exponent == 308 && digits >= 179769) break; // don't overflow!
double digiform = (digits + 0.5) * 0.00001;
double testval = digiform * powten;
double pretestval = nextafter(testval, 0);
double posttestval = nextafter(testval, 1.7976931348623157e308);
checker(testval);
checker(pretestval);
checker(posttestval);
}
}
} else {
EXPECT_EQ(mismatches.size(), 0);
for (size_t i = 0; i < mismatches.size(); ++i) {
if (i > 100) i = mismatches.size() - 1;
double d = mismatches[i];
char sixdigitsbuf[kSixDigitsToBufferSize] = {0};
SixDigitsToBuffer(d, sixdigitsbuf);
char snprintfbuf[kSixDigitsToBufferSize] = {0};
snprintf(snprintfbuf, kSixDigitsToBufferSize, "%g", d);
double before = nextafter(d, 0.0);
double after = nextafter(d, 1.7976931348623157e308);
char b1[32], b2[kSixDigitsToBufferSize];
ABSL_RAW_LOG(
ERROR, "%s",
absl::StrCat(
"Mismatch #", i, " d=", d, " (", ToNineDigits(d), ")",
" sixdigits='", sixdigitsbuf, "'", " snprintf='", snprintfbuf,
"'", " Before.=", PerfectDtoa(before), " ",
(SixDigitsToBuffer(before, b2), b2),
" vs snprintf=", (snprintf(b1, sizeof(b1), "%g", before), b1),
" Perfect=", PerfectDtoa(d), " ", (SixDigitsToBuffer(d, b2), b2),
" vs snprintf=", (snprintf(b1, sizeof(b1), "%g", d), b1),
" After.=.", PerfectDtoa(after), " ",
(SixDigitsToBuffer(after, b2), b2),
" vs snprintf=", (snprintf(b1, sizeof(b1), "%g", after), b1))
.c_str());
}
}
}
TEST(StrToInt32, Partial) {
struct Int32TestLine {
std::string input;
bool status;
int32_t value;
};
const int32_t int32_min = std::numeric_limits<int32_t>::min();
const int32_t int32_max = std::numeric_limits<int32_t>::max();
Int32TestLine int32_test_line[] = {
{"", false, 0},
{" ", false, 0},
{"-", false, 0},
{"123@@@", false, 123},
{absl::StrCat(int32_min, int32_max), false, int32_min},
{absl::StrCat(int32_max, int32_max), false, int32_max},
};
for (const Int32TestLine& test_line : int32_test_line) {
int32_t value = -2;
bool status = safe_strto32_base(test_line.input, &value, 10);
EXPECT_EQ(test_line.status, status) << test_line.input;
EXPECT_EQ(test_line.value, value) << test_line.input;
value = -2;
status = safe_strto32_base(test_line.input, &value, 10);
EXPECT_EQ(test_line.status, status) << test_line.input;
EXPECT_EQ(test_line.value, value) << test_line.input;
value = -2;
status = safe_strto32_base(absl::string_view(test_line.input), &value, 10);
EXPECT_EQ(test_line.status, status) << test_line.input;
EXPECT_EQ(test_line.value, value) << test_line.input;
}
}
TEST(StrToUint32, Partial) {
struct Uint32TestLine {
std::string input;
bool status;
uint32_t value;
};
const uint32_t uint32_max = std::numeric_limits<uint32_t>::max();
Uint32TestLine uint32_test_line[] = {
{"", false, 0},
{" ", false, 0},
{"-", false, 0},
{"123@@@", false, 123},
{absl::StrCat(uint32_max, uint32_max), false, uint32_max},
};
for (const Uint32TestLine& test_line : uint32_test_line) {
uint32_t value = 2;
bool status = safe_strtou32_base(test_line.input, &value, 10);
EXPECT_EQ(test_line.status, status) << test_line.input;
EXPECT_EQ(test_line.value, value) << test_line.input;
value = 2;
status = safe_strtou32_base(test_line.input, &value, 10);
EXPECT_EQ(test_line.status, status) << test_line.input;
EXPECT_EQ(test_line.value, value) << test_line.input;
value = 2;
status = safe_strtou32_base(absl::string_view(test_line.input), &value, 10);
EXPECT_EQ(test_line.status, status) << test_line.input;
EXPECT_EQ(test_line.value, value) << test_line.input;
}
}
TEST(StrToInt64, Partial) {
struct Int64TestLine {
std::string input;
bool status;
int64_t value;
};
const int64_t int64_min = std::numeric_limits<int64_t>::min();
const int64_t int64_max = std::numeric_limits<int64_t>::max();
Int64TestLine int64_test_line[] = {
{"", false, 0},
{" ", false, 0},
{"-", false, 0},
{"123@@@", false, 123},
{absl::StrCat(int64_min, int64_max), false, int64_min},
{absl::StrCat(int64_max, int64_max), false, int64_max},
};
for (const Int64TestLine& test_line : int64_test_line) {
int64_t value = -2;
bool status = safe_strto64_base(test_line.input, &value, 10);
EXPECT_EQ(test_line.status, status) << test_line.input;
EXPECT_EQ(test_line.value, value) << test_line.input;
value = -2;
status = safe_strto64_base(test_line.input, &value, 10);
EXPECT_EQ(test_line.status, status) << test_line.input;
EXPECT_EQ(test_line.value, value) << test_line.input;
value = -2;
status = safe_strto64_base(absl::string_view(test_line.input), &value, 10);
EXPECT_EQ(test_line.status, status) << test_line.input;
EXPECT_EQ(test_line.value, value) << test_line.input;
}
}
TEST(StrToUint64, Partial) {
struct Uint64TestLine {
std::string input;
bool status;
uint64_t value;
};
const uint64_t uint64_max = std::numeric_limits<uint64_t>::max();
Uint64TestLine uint64_test_line[] = {
{"", false, 0},
{" ", false, 0},
{"-", false, 0},
{"123@@@", false, 123},
{absl::StrCat(uint64_max, uint64_max), false, uint64_max},
};
for (const Uint64TestLine& test_line : uint64_test_line) {
uint64_t value = 2;
bool status = safe_strtou64_base(test_line.input, &value, 10);
EXPECT_EQ(test_line.status, status) << test_line.input;
EXPECT_EQ(test_line.value, value) << test_line.input;
value = 2;
status = safe_strtou64_base(test_line.input, &value, 10);
EXPECT_EQ(test_line.status, status) << test_line.input;
EXPECT_EQ(test_line.value, value) << test_line.input;
value = 2;
status = safe_strtou64_base(absl::string_view(test_line.input), &value, 10);
EXPECT_EQ(test_line.status, status) << test_line.input;
EXPECT_EQ(test_line.value, value) << test_line.input;
}
}
TEST(StrToInt32Base, PrefixOnly) {
struct Int32TestLine {
std::string input;
bool status;
int32_t value;
};
Int32TestLine int32_test_line[] = {
{ "", false, 0 },
{ "-", false, 0 },
{ "-0", true, 0 },
{ "0", true, 0 },
{ "0x", false, 0 },
{ "-0x", false, 0 },
};
const int base_array[] = { 0, 2, 8, 10, 16 };
for (const Int32TestLine& line : int32_test_line) {
for (const int base : base_array) {
int32_t value = 2;
bool status = safe_strto32_base(line.input.c_str(), &value, base);
EXPECT_EQ(line.status, status) << line.input << " " << base;
EXPECT_EQ(line.value, value) << line.input << " " << base;
value = 2;
status = safe_strto32_base(line.input, &value, base);
EXPECT_EQ(line.status, status) << line.input << " " << base;
EXPECT_EQ(line.value, value) << line.input << " " << base;
value = 2;
status = safe_strto32_base(absl::string_view(line.input), &value, base);
EXPECT_EQ(line.status, status) << line.input << " " << base;
EXPECT_EQ(line.value, value) << line.input << " " << base;
}
}
}
TEST(StrToUint32Base, PrefixOnly) {
struct Uint32TestLine {
std::string input;
bool status;
uint32_t value;
};
Uint32TestLine uint32_test_line[] = {
{ "", false, 0 },
{ "0", true, 0 },
{ "0x", false, 0 },
};
const int base_array[] = { 0, 2, 8, 10, 16 };
for (const Uint32TestLine& line : uint32_test_line) {
for (const int base : base_array) {
uint32_t value = 2;
bool status = safe_strtou32_base(line.input.c_str(), &value, base);
EXPECT_EQ(line.status, status) << line.input << " " << base;
EXPECT_EQ(line.value, value) << line.input << " " << base;
value = 2;
status = safe_strtou32_base(line.input, &value, base);
EXPECT_EQ(line.status, status) << line.input << " " << base;
EXPECT_EQ(line.value, value) << line.input << " " << base;
value = 2;
status = safe_strtou32_base(absl::string_view(line.input), &value, base);
EXPECT_EQ(line.status, status) << line.input << " " << base;
EXPECT_EQ(line.value, value) << line.input << " " << base;
}
}
}
TEST(StrToInt64Base, PrefixOnly) {
struct Int64TestLine {
std::string input;
bool status;
int64_t value;
};
Int64TestLine int64_test_line[] = {
{ "", false, 0 },
{ "-", false, 0 },
{ "-0", true, 0 },
{ "0", true, 0 },
{ "0x", false, 0 },
{ "-0x", false, 0 },
};
const int base_array[] = { 0, 2, 8, 10, 16 };
for (const Int64TestLine& line : int64_test_line) {
for (const int base : base_array) {
int64_t value = 2;
bool status = safe_strto64_base(line.input.c_str(), &value, base);
EXPECT_EQ(line.status, status) << line.input << " " << base;
EXPECT_EQ(line.value, value) << line.input << " " << base;
value = 2;
status = safe_strto64_base(line.input, &value, base);
EXPECT_EQ(line.status, status) << line.input << " " << base;
EXPECT_EQ(line.value, value) << line.input << " " << base;
value = 2;
status = safe_strto64_base(absl::string_view(line.input), &value, base);
EXPECT_EQ(line.status, status) << line.input << " " << base;
EXPECT_EQ(line.value, value) << line.input << " " << base;
}
}
}
TEST(StrToUint64Base, PrefixOnly) {
struct Uint64TestLine {
std::string input;
bool status;
uint64_t value;
};
Uint64TestLine uint64_test_line[] = {
{ "", false, 0 },
{ "0", true, 0 },
{ "0x", false, 0 },
};
const int base_array[] = { 0, 2, 8, 10, 16 };
for (const Uint64TestLine& line : uint64_test_line) {
for (const int base : base_array) {
uint64_t value = 2;
bool status = safe_strtou64_base(line.input.c_str(), &value, base);
EXPECT_EQ(line.status, status) << line.input << " " << base;
EXPECT_EQ(line.value, value) << line.input << " " << base;
value = 2;
status = safe_strtou64_base(line.input, &value, base);
EXPECT_EQ(line.status, status) << line.input << " " << base;
EXPECT_EQ(line.value, value) << line.input << " " << base;
value = 2;
status = safe_strtou64_base(absl::string_view(line.input), &value, base);
EXPECT_EQ(line.status, status) << line.input << " " << base;
EXPECT_EQ(line.value, value) << line.input << " " << base;
}
}
}
void TestFastHexToBufferZeroPad16(uint64_t v) {
char buf[16];
auto digits = absl::numbers_internal::FastHexToBufferZeroPad16(v, buf);
absl::string_view res(buf, 16);
char buf2[17];
snprintf(buf2, sizeof(buf2), "%016" PRIx64, v);
EXPECT_EQ(res, buf2) << v;
size_t expected_digits = snprintf(buf2, sizeof(buf2), "%" PRIx64, v);
EXPECT_EQ(digits, expected_digits) << v;
}
TEST(FastHexToBufferZeroPad16, Smoke) {
TestFastHexToBufferZeroPad16(std::numeric_limits<uint64_t>::min());
TestFastHexToBufferZeroPad16(std::numeric_limits<uint64_t>::max());
TestFastHexToBufferZeroPad16(std::numeric_limits<int64_t>::min());
TestFastHexToBufferZeroPad16(std::numeric_limits<int64_t>::max());
absl::BitGen rng;
for (int i = 0; i < 100000; ++i) {
TestFastHexToBufferZeroPad16(
absl::LogUniform(rng, std::numeric_limits<uint64_t>::min(),
std::numeric_limits<uint64_t>::max()));
}
}
} // namespace