tvl-depot/absl/strings/numbers_test.cc

1188 lines
42 KiB
C++
Raw Normal View History

// 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.
2017-09-19 22:54:40 +02:00
#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/strings/str_cat.h"
- e2f6b8ac647271815b4fed2991f405524dd762c3 Release cctz microbenchmarks. by Alex Strelnikov <strel@google.com> - 924ba2a3f9fca695d73c6bf491d20669e2b96b8e Changed RawPtr to use std::addressof() instead of operato... by Abseil Team <absl-team@google.com> - e8cf67f9fa74d4c5632da35547025ad2301c6819 Import of CCTZ from GitHub. by Alex Strelnikov <strel@google.com> - 2ece8a96611afcddd7b91e0197dadb896248250c Abandon ".inc" files in favor of ".h" headers. by Jorg Brown <jorg@google.com> - 37f5ed5da4058f90fb3e6a2733fce5b1fd0aaedf Add exception safety tests for absl::optional<T> by Abseil Team <absl-team@google.com> - 337f995a866b8f905f64ca6b271b5fec8f248a60 Update WORKSPACE to grab specific commits of dependencies... by Alex Strelnikov <strel@google.com> - 93e5b134607a554993387ad913e6c1621606004b Release Charmap microbenchmark. by Alex Strelnikov <strel@google.com> - 95c2e29b6d93ec1334484ee37d91f63101c45307 Release OStringStream microbenchmarks. by Alex Strelnikov <strel@google.com> - 250f51839ed26dd1e6b658d35aa291413e5f4825 Internal change by Greg Falcon <gfalcon@google.com> - ce34900fa3d1a95a8446bc943cdd801fac95be25 Improve compatibility of cctz cc_test targets for portabl... by Shaindel Schwartz <shaindel@google.com> - ce7e31dbf2c1ee93c79aae5b7dc7c603cb4babcf Improve portability of cc_tests. (Mark more tests that ca... by Abseil Team <absl-team@google.com> - dfcd4e455923703c1a1dcd523c5f915f7990fa2a Accept strings with custom allocators as arguments to abs... by Greg Falcon <gfalcon@google.com> - 2946b41ed3d5b8b5a8dc11182e443cf1ab6e3bde Link against benchmark_main instead of using BENCHMARK_MA... by Alex Strelnikov <strel@google.com> - f09de9e03bf8edd363069c4b352d8009423f531c Adds link to doc about the formats allowed by SimpleAtof(... by Greg Miller <jgm@google.com> - 59b0977e7a308e0800277886cf60226b2cc426a1 Simplify the HideMask() calculation so that it doesn't us... by Jorg Brown <jorg@google.com> GitOrigin-RevId: e2f6b8ac647271815b4fed2991f405524dd762c3 Change-Id: Ib9c8547ed7fe217fad6cb3ab1362e96181aa5cfa
2018-05-31 21:26:35 +02:00
#include "absl/strings/internal/numbers_test_common.h"
Export of internal Abseil changes. -- cd076f55c1fa600131f6dda392533dfe61679fc0 by Abseil Team <absl-team@google.com>: Internal change PiperOrigin-RevId: 224008762 -- e05f62b01286d51044ff86ec6ef565749b9faf82 by Abseil Team <absl-team@google.com>: Create a pow10() test helper function to compute guaranteed-precise double values of 10^x. Not all standard libraries ship bit-accurate pow() functions, causing tests to fail that rely on expected values generated by it. PiperOrigin-RevId: 223883762 -- fd88e5e3f7ab80f7f5df9fd1488cd58b4573be69 by Abseil Team <absl-team@google.com>: Remove some absl:: qualifications to work around inline namespace bugs on MSVC 2015. PiperOrigin-RevId: 223869642 -- 6276cfff969d596edd36a2bbaba65ee045808903 by Abseil Team <absl-team@google.com>: Update absl/memory/CMakeLists.txt to use new functions i.e. absl_cc_(library|test) PiperOrigin-RevId: 223854224 -- 359de9afc7a34c975fd3e0cbc52afd96637d97bd by Chris Kennelly <ckennelly@google.com>: Mark spinlock_benchmark_common as alwayslink = 1. PiperOrigin-RevId: 223844536 -- 450cd8cbe2789a6d54ed1eb87170259bb334f8b9 by Abseil Team <absl-team@google.com>: Support .* (pointer-to-member dereference) expressions in demangle.cc. PiperOrigin-RevId: 223826797 -- 772ca92179c3634f3e31a80bbc272ed8022e3572 by Abseil Team <absl-team@google.com>: Fix misspellings in absl::variant comments and replace a ' with a `. PiperOrigin-RevId: 223807911 -- 35dcdc2fbf299d195658aac101887f6dcad1de2f by Abseil Team <absl-team@google.com>: Bug fix in CMakeLists.txt file (SRCS --> HDRS). The compressed_tuple header-only library is being defined with the SRCS parameter instead of the HDRS parameter and this has been observed to cause some builds on some platforms to attempt to create a static library from it which fails since there are no .cc sources. PiperOrigin-RevId: 223805367 -- 4a57a3d2045bb137c0c97958e45ce425190b8d3e by Chris Kennelly <ckennelly@google.com>: Add test that absl::make_unique value initializes memory. PiperOrigin-RevId: 223801819 -- dfe8289d7f4dcc6bb568a26aaf192a89e896bdfd by Chris Kennelly <ckennelly@google.com>: SpinLock: Use exchange to avoid missing wakeups. The default fast path for SpinLock::Unlock does not use an atomic. If the SpinLock becomes contended while we are unlocking between lockword_.load and lockword_.store, we will fail to wake up the new waiter. This can cause unexpected latency spikes. PiperOrigin-RevId: 223800369 -- 9b9d35df786482f0016f77dd31691eff81503d23 by Abseil Team <absl-team@google.com>: Update absl/hash/CMakeLists.txt to use new functions i.e. absl_cc_(library|test) PiperOrigin-RevId: 223755819 -- c2014e2704b87e7cdce2d2a0287c7e2397752296 by Abseil Team <absl-team@google.com>: Update absl/debugging/CMakeLists.txt to use new functions i.e. absl_cc_(library|test) PiperOrigin-RevId: 223751986 -- d83a4e09126400e3fd80645cb03ee558f532271e by Derek Mauro <dmauro@google.com>: Cleanup synchronization benchmarks. PiperOrigin-RevId: 223589416 -- fad140b473586531b5b12843f942ec27dfcf5e93 by CJ Johnson <johnsoncj@google.com>: Makes unifies the order of forward_iterator and input_iterator overloads PiperOrigin-RevId: 223580660 -- 6cd7c96faa7cc5f79f574e35a1b13837ef187d05 by Abseil Team <absl-team@google.com>: Internal Change. PiperOrigin-RevId: 223561629 -- bd2e545356b0f548af0e3c14bb2f7f0e712e49d0 by Shaindel Schwartz <shaindel@google.com>: Remove misleading comments. try_emplace() does not exist for the hash_set containers. PiperOrigin-RevId: 223543089 -- 0cd380a53b587eb7aacc4003a4a3bbb6c78d7c10 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 223512551 -- 7156dfee599cb72e9adddfe0e6ae07a95ddf10bb by Greg Miller <jgm@google.com>: Fixes UB that would result from constructing, multiplying, or dividing a Duration with a double "NaN" value. This CL changes the absl::Duration *implementation* to return an InfiniteDuration value that has the same sign as the given NaN. PiperOrigin-RevId: 223407499 -- 196b7d18609958267951882baf7f9429e49bcafa by CJ Johnson <johnsoncj@google.com>: Addresses NVCC+MSVC compilation bug where `inlined_capacity()` was not considered valid in constexpr PiperOrigin-RevId: 223397718 GitOrigin-RevId: cd076f55c1fa600131f6dda392533dfe61679fc0 Change-Id: I5423ca6470f661a7c6f73aa8fee49990446f157f
2018-12-04 20:01:12 +01:00
#include "absl/strings/internal/pow10_helper.h"
2017-09-19 22:54:40 +02:00
namespace {
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;
- e2f6b8ac647271815b4fed2991f405524dd762c3 Release cctz microbenchmarks. by Alex Strelnikov <strel@google.com> - 924ba2a3f9fca695d73c6bf491d20669e2b96b8e Changed RawPtr to use std::addressof() instead of operato... by Abseil Team <absl-team@google.com> - e8cf67f9fa74d4c5632da35547025ad2301c6819 Import of CCTZ from GitHub. by Alex Strelnikov <strel@google.com> - 2ece8a96611afcddd7b91e0197dadb896248250c Abandon ".inc" files in favor of ".h" headers. by Jorg Brown <jorg@google.com> - 37f5ed5da4058f90fb3e6a2733fce5b1fd0aaedf Add exception safety tests for absl::optional<T> by Abseil Team <absl-team@google.com> - 337f995a866b8f905f64ca6b271b5fec8f248a60 Update WORKSPACE to grab specific commits of dependencies... by Alex Strelnikov <strel@google.com> - 93e5b134607a554993387ad913e6c1621606004b Release Charmap microbenchmark. by Alex Strelnikov <strel@google.com> - 95c2e29b6d93ec1334484ee37d91f63101c45307 Release OStringStream microbenchmarks. by Alex Strelnikov <strel@google.com> - 250f51839ed26dd1e6b658d35aa291413e5f4825 Internal change by Greg Falcon <gfalcon@google.com> - ce34900fa3d1a95a8446bc943cdd801fac95be25 Improve compatibility of cctz cc_test targets for portabl... by Shaindel Schwartz <shaindel@google.com> - ce7e31dbf2c1ee93c79aae5b7dc7c603cb4babcf Improve portability of cc_tests. (Mark more tests that ca... by Abseil Team <absl-team@google.com> - dfcd4e455923703c1a1dcd523c5f915f7990fa2a Accept strings with custom allocators as arguments to abs... by Greg Falcon <gfalcon@google.com> - 2946b41ed3d5b8b5a8dc11182e443cf1ab6e3bde Link against benchmark_main instead of using BENCHMARK_MA... by Alex Strelnikov <strel@google.com> - f09de9e03bf8edd363069c4b352d8009423f531c Adds link to doc about the formats allowed by SimpleAtof(... by Greg Miller <jgm@google.com> - 59b0977e7a308e0800277886cf60226b2cc426a1 Simplify the HideMask() calculation so that it doesn't us... by Jorg Brown <jorg@google.com> GitOrigin-RevId: e2f6b8ac647271815b4fed2991f405524dd762c3 Change-Id: Ib9c8547ed7fe217fad6cb3ab1362e96181aa5cfa
2018-05-31 21:26:35 +02:00
using absl::strings_internal::Itoa;
using absl::strings_internal::strtouint32_test_cases;
using absl::strings_internal::strtouint64_test_cases;
2017-09-19 22:54:40 +02:00
using absl::SimpleAtoi;
using testing::Eq;
using testing::MatchesRegex;
// Number of floats to test with.
Export of internal Abseil changes. -- ac7508120c60dfe689c40929e416b6a486f83ee3 by Gennadiy Rozental <rogeeff@google.com>: Internal change PiperOrigin-RevId: 206912089 -- bd709faba88565367b6d337466e6456481b5f3e8 by Matt Calabrese <calabrese@google.com>: Implement `std::experimental::is_detected` in type_traits internals and move `is_detected_convertible` from variant's internals to type_traits internals. This is in preparation of creating workarounds for broken standard traits. PiperOrigin-RevId: 206825598 -- 0dbddea569370eb9b6348cee172d1874f9046eb4 by Jorg Brown <jorg@google.com>: Support users who turn on floating-point conversion warnings PiperOrigin-RevId: 206813209 -- 30991f757c8f0100584619d8a9c41897d029f112 by Jorg Brown <jorg@google.com>: Speed up the absl::Seconds() function for floating-point values, roughly by 4.5x, since we can take advantage of the fact that we're just taking a floating-point number and splitting it into its integral and fractional parts. PiperOrigin-RevId: 206806270 -- 6883837176838aa5a517e7a8cb4c99afd24c0d12 by Jon Cohen <cohenjon@google.com>: Remove the DISABLE_INSTALL from absl_container. It doesn't do anything. PiperOrigin-RevId: 206802544 -- 92ab14fed06e6dd1f01a0284bd7f95d3e2c0c3d8 by Jon Cohen <cohenjon@google.com>: Internal change PiperOrigin-RevId: 206776244 -- 17b76c7f364ac562d9e0faeca0320f63aa3fdb85 by Jorg Brown <jorg@google.com>: Fix absl/strings:numbers_test flakiness due to exceeding the 1-minute timeout PiperOrigin-RevId: 206763175 -- 6637843f2e198b8efd90e5577fbc86bdea43b2cc by Abseil Team <absl-team@google.com>: Adds templated allocator to absl::FixedArray with corresponding tests PiperOrigin-RevId: 206354178 -- bced22f81add828c9b4c60eb45554d36c22e2f96 by Abseil Team <absl-team@google.com>: Adds templated allocator to absl::FixedArray with corresponding tests PiperOrigin-RevId: 206347377 -- 75be14a71d2d5e335812d5b7670120271fb5bd79 by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 206326935 -- 6929e43f4c7898b1f51e441911a19092a06fbf97 by Abseil Team <absl-team@google.com>: Adds templated allocator to absl::FixedArray with corresponding tests PiperOrigin-RevId: 206326368 -- 55ae34b75ff029eb267f9519e577bab8a575b487 by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 206233448 -- 6950a8ccddf35d451eec2d02cd28a797c8b7cf6a by Matt Kulukundis <kfm@google.com>: Internal change PiperOrigin-RevId: 206035613 GitOrigin-RevId: ac7508120c60dfe689c40929e416b6a486f83ee3 Change-Id: I675605abbedab6b3ac9aa82195cbd059ff7c82b1
2018-08-01 13:34:12 +02:00
// 5,000,000 is a reasonable default for a test that only takes a few seconds.
2017-09-19 22:54:40 +02:00
// 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));
2017-09-19 22:54:40 +02:00
}
}
}
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;
2017-09-19 22:54:40 +02:00
void CheckInt32(int32_t x) {
char buffer[absl::numbers_internal::kFastToBufferSize];
char* actual = absl::numbers_internal::FastIntToBuffer(x, buffer);
2017-09-19 22:54:40 +02:00
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;
2017-09-19 22:54:40 +02:00
}
void CheckInt64(int64_t x) {
char buffer[absl::numbers_internal::kFastToBufferSize + 3];
2017-09-19 22:54:40 +02:00
buffer[0] = '*';
buffer[23] = '*';
buffer[24] = '*';
char* actual = absl::numbers_internal::FastIntToBuffer(x, &buffer[1]);
2017-09-19 22:54:40 +02:00
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;
2017-09-19 22:54:40 +02:00
}
void CheckUInt32(uint32_t x) {
char buffer[absl::numbers_internal::kFastToBufferSize];
char* actual = absl::numbers_internal::FastIntToBuffer(x, buffer);
2017-09-19 22:54:40 +02:00
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;
2017-09-19 22:54:40 +02:00
}
void CheckUInt64(uint64_t x) {
char buffer[absl::numbers_internal::kFastToBufferSize + 1];
char* actual = absl::numbers_internal::FastIntToBuffer(x, &buffer[1]);
2017-09-19 22:54:40 +02:00
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;
2017-09-19 22:54:40 +02:00
}
void CheckHex64(uint64_t v) {
char expected[16 + 1];
2017-09-19 22:54:40 +02:00
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;
2017-09-19 22:54:40 +02:00
}
TEST(Numbers, TestFastPrints) {
2017-09-19 22:54:40 +02:00
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 = absl::StrCat(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 = absl::StrCat(in_value);
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());
// 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)
VerifySimpleAtoiGood<uint64_t>(42, 42);
VerifySimpleAtoiGood<size_t>(42, 42);
VerifySimpleAtoiGood<std::string::size_type>(42, 42);
}
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);
}
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 std::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 std::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_strtou32_base) {
- e2f6b8ac647271815b4fed2991f405524dd762c3 Release cctz microbenchmarks. by Alex Strelnikov <strel@google.com> - 924ba2a3f9fca695d73c6bf491d20669e2b96b8e Changed RawPtr to use std::addressof() instead of operato... by Abseil Team <absl-team@google.com> - e8cf67f9fa74d4c5632da35547025ad2301c6819 Import of CCTZ from GitHub. by Alex Strelnikov <strel@google.com> - 2ece8a96611afcddd7b91e0197dadb896248250c Abandon ".inc" files in favor of ".h" headers. by Jorg Brown <jorg@google.com> - 37f5ed5da4058f90fb3e6a2733fce5b1fd0aaedf Add exception safety tests for absl::optional<T> by Abseil Team <absl-team@google.com> - 337f995a866b8f905f64ca6b271b5fec8f248a60 Update WORKSPACE to grab specific commits of dependencies... by Alex Strelnikov <strel@google.com> - 93e5b134607a554993387ad913e6c1621606004b Release Charmap microbenchmark. by Alex Strelnikov <strel@google.com> - 95c2e29b6d93ec1334484ee37d91f63101c45307 Release OStringStream microbenchmarks. by Alex Strelnikov <strel@google.com> - 250f51839ed26dd1e6b658d35aa291413e5f4825 Internal change by Greg Falcon <gfalcon@google.com> - ce34900fa3d1a95a8446bc943cdd801fac95be25 Improve compatibility of cctz cc_test targets for portabl... by Shaindel Schwartz <shaindel@google.com> - ce7e31dbf2c1ee93c79aae5b7dc7c603cb4babcf Improve portability of cc_tests. (Mark more tests that ca... by Abseil Team <absl-team@google.com> - dfcd4e455923703c1a1dcd523c5f915f7990fa2a Accept strings with custom allocators as arguments to abs... by Greg Falcon <gfalcon@google.com> - 2946b41ed3d5b8b5a8dc11182e443cf1ab6e3bde Link against benchmark_main instead of using BENCHMARK_MA... by Alex Strelnikov <strel@google.com> - f09de9e03bf8edd363069c4b352d8009423f531c Adds link to doc about the formats allowed by SimpleAtof(... by Greg Miller <jgm@google.com> - 59b0977e7a308e0800277886cf60226b2cc426a1 Simplify the HideMask() calculation so that it doesn't us... by Jorg Brown <jorg@google.com> GitOrigin-RevId: e2f6b8ac647271815b4fed2991f405524dd762c3 Change-Id: Ib9c8547ed7fe217fad6cb3ab1362e96181aa5cfa
2018-05-31 21:26:35 +02:00
for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) {
const auto& e = strtouint32_test_cases()[i];
2017-09-19 22:54:40 +02:00
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) {
- e2f6b8ac647271815b4fed2991f405524dd762c3 Release cctz microbenchmarks. by Alex Strelnikov <strel@google.com> - 924ba2a3f9fca695d73c6bf491d20669e2b96b8e Changed RawPtr to use std::addressof() instead of operato... by Abseil Team <absl-team@google.com> - e8cf67f9fa74d4c5632da35547025ad2301c6819 Import of CCTZ from GitHub. by Alex Strelnikov <strel@google.com> - 2ece8a96611afcddd7b91e0197dadb896248250c Abandon ".inc" files in favor of ".h" headers. by Jorg Brown <jorg@google.com> - 37f5ed5da4058f90fb3e6a2733fce5b1fd0aaedf Add exception safety tests for absl::optional<T> by Abseil Team <absl-team@google.com> - 337f995a866b8f905f64ca6b271b5fec8f248a60 Update WORKSPACE to grab specific commits of dependencies... by Alex Strelnikov <strel@google.com> - 93e5b134607a554993387ad913e6c1621606004b Release Charmap microbenchmark. by Alex Strelnikov <strel@google.com> - 95c2e29b6d93ec1334484ee37d91f63101c45307 Release OStringStream microbenchmarks. by Alex Strelnikov <strel@google.com> - 250f51839ed26dd1e6b658d35aa291413e5f4825 Internal change by Greg Falcon <gfalcon@google.com> - ce34900fa3d1a95a8446bc943cdd801fac95be25 Improve compatibility of cctz cc_test targets for portabl... by Shaindel Schwartz <shaindel@google.com> - ce7e31dbf2c1ee93c79aae5b7dc7c603cb4babcf Improve portability of cc_tests. (Mark more tests that ca... by Abseil Team <absl-team@google.com> - dfcd4e455923703c1a1dcd523c5f915f7990fa2a Accept strings with custom allocators as arguments to abs... by Greg Falcon <gfalcon@google.com> - 2946b41ed3d5b8b5a8dc11182e443cf1ab6e3bde Link against benchmark_main instead of using BENCHMARK_MA... by Alex Strelnikov <strel@google.com> - f09de9e03bf8edd363069c4b352d8009423f531c Adds link to doc about the formats allowed by SimpleAtof(... by Greg Miller <jgm@google.com> - 59b0977e7a308e0800277886cf60226b2cc426a1 Simplify the HideMask() calculation so that it doesn't us... by Jorg Brown <jorg@google.com> GitOrigin-RevId: e2f6b8ac647271815b4fed2991f405524dd762c3 Change-Id: Ib9c8547ed7fe217fad6cb3ab1362e96181aa5cfa
2018-05-31 21:26:35 +02:00
for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) {
const auto& e = strtouint32_test_cases()[i];
2017-09-19 22:54:40 +02:00
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) {
- e2f6b8ac647271815b4fed2991f405524dd762c3 Release cctz microbenchmarks. by Alex Strelnikov <strel@google.com> - 924ba2a3f9fca695d73c6bf491d20669e2b96b8e Changed RawPtr to use std::addressof() instead of operato... by Abseil Team <absl-team@google.com> - e8cf67f9fa74d4c5632da35547025ad2301c6819 Import of CCTZ from GitHub. by Alex Strelnikov <strel@google.com> - 2ece8a96611afcddd7b91e0197dadb896248250c Abandon ".inc" files in favor of ".h" headers. by Jorg Brown <jorg@google.com> - 37f5ed5da4058f90fb3e6a2733fce5b1fd0aaedf Add exception safety tests for absl::optional<T> by Abseil Team <absl-team@google.com> - 337f995a866b8f905f64ca6b271b5fec8f248a60 Update WORKSPACE to grab specific commits of dependencies... by Alex Strelnikov <strel@google.com> - 93e5b134607a554993387ad913e6c1621606004b Release Charmap microbenchmark. by Alex Strelnikov <strel@google.com> - 95c2e29b6d93ec1334484ee37d91f63101c45307 Release OStringStream microbenchmarks. by Alex Strelnikov <strel@google.com> - 250f51839ed26dd1e6b658d35aa291413e5f4825 Internal change by Greg Falcon <gfalcon@google.com> - ce34900fa3d1a95a8446bc943cdd801fac95be25 Improve compatibility of cctz cc_test targets for portabl... by Shaindel Schwartz <shaindel@google.com> - ce7e31dbf2c1ee93c79aae5b7dc7c603cb4babcf Improve portability of cc_tests. (Mark more tests that ca... by Abseil Team <absl-team@google.com> - dfcd4e455923703c1a1dcd523c5f915f7990fa2a Accept strings with custom allocators as arguments to abs... by Greg Falcon <gfalcon@google.com> - 2946b41ed3d5b8b5a8dc11182e443cf1ab6e3bde Link against benchmark_main instead of using BENCHMARK_MA... by Alex Strelnikov <strel@google.com> - f09de9e03bf8edd363069c4b352d8009423f531c Adds link to doc about the formats allowed by SimpleAtof(... by Greg Miller <jgm@google.com> - 59b0977e7a308e0800277886cf60226b2cc426a1 Simplify the HideMask() calculation so that it doesn't us... by Jorg Brown <jorg@google.com> GitOrigin-RevId: e2f6b8ac647271815b4fed2991f405524dd762c3 Change-Id: Ib9c8547ed7fe217fad6cb3ab1362e96181aa5cfa
2018-05-31 21:26:35 +02:00
for (int i = 0; strtouint64_test_cases()[i].str != nullptr; ++i) {
const auto& e = strtouint64_test_cases()[i];
2017-09-19 22:54:40 +02:00
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) {
- e2f6b8ac647271815b4fed2991f405524dd762c3 Release cctz microbenchmarks. by Alex Strelnikov <strel@google.com> - 924ba2a3f9fca695d73c6bf491d20669e2b96b8e Changed RawPtr to use std::addressof() instead of operato... by Abseil Team <absl-team@google.com> - e8cf67f9fa74d4c5632da35547025ad2301c6819 Import of CCTZ from GitHub. by Alex Strelnikov <strel@google.com> - 2ece8a96611afcddd7b91e0197dadb896248250c Abandon ".inc" files in favor of ".h" headers. by Jorg Brown <jorg@google.com> - 37f5ed5da4058f90fb3e6a2733fce5b1fd0aaedf Add exception safety tests for absl::optional<T> by Abseil Team <absl-team@google.com> - 337f995a866b8f905f64ca6b271b5fec8f248a60 Update WORKSPACE to grab specific commits of dependencies... by Alex Strelnikov <strel@google.com> - 93e5b134607a554993387ad913e6c1621606004b Release Charmap microbenchmark. by Alex Strelnikov <strel@google.com> - 95c2e29b6d93ec1334484ee37d91f63101c45307 Release OStringStream microbenchmarks. by Alex Strelnikov <strel@google.com> - 250f51839ed26dd1e6b658d35aa291413e5f4825 Internal change by Greg Falcon <gfalcon@google.com> - ce34900fa3d1a95a8446bc943cdd801fac95be25 Improve compatibility of cctz cc_test targets for portabl... by Shaindel Schwartz <shaindel@google.com> - ce7e31dbf2c1ee93c79aae5b7dc7c603cb4babcf Improve portability of cc_tests. (Mark more tests that ca... by Abseil Team <absl-team@google.com> - dfcd4e455923703c1a1dcd523c5f915f7990fa2a Accept strings with custom allocators as arguments to abs... by Greg Falcon <gfalcon@google.com> - 2946b41ed3d5b8b5a8dc11182e443cf1ab6e3bde Link against benchmark_main instead of using BENCHMARK_MA... by Alex Strelnikov <strel@google.com> - f09de9e03bf8edd363069c4b352d8009423f531c Adds link to doc about the formats allowed by SimpleAtof(... by Greg Miller <jgm@google.com> - 59b0977e7a308e0800277886cf60226b2cc426a1 Simplify the HideMask() calculation so that it doesn't us... by Jorg Brown <jorg@google.com> GitOrigin-RevId: e2f6b8ac647271815b4fed2991f405524dd762c3 Change-Id: Ib9c8547ed7fe217fad6cb3ab1362e96181aa5cfa
2018-05-31 21:26:35 +02:00
for (int i = 0; strtouint64_test_cases()[i].str != nullptr; ++i) {
const auto& e = strtouint64_test_cases()[i];
2017-09-19 22:54:40 +02:00
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 missing on Mac OS X, MSVC,
// and WebAssembly.
#if defined(_MSC_VER) || defined(__APPLE__) || defined(__EMSCRIPTEN__)
2017-09-19 22:54:40 +02:00
#define ABSL_MISSING_FEENABLEEXCEPT 1
#define ABSL_MISSING_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_);
#ifndef ABSL_MISSING_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.
#ifndef ABSL_MISSING_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
2017-09-19 22:54:40 +02:00
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;
Export of internal Abseil changes. -- 89b5e681db1d4f0b039daebb86c49bda77c8931b by Tom Manshreck <shreck@google.com>: Add clarification that absl::Hash does not produce stable values across instances. PiperOrigin-RevId: 238316564 -- 56dec1d1e37fb2a02aa10d7c81bcd78f8486c093 by Eric Fiselier <ericwf@google.com>: Add SFINAE to absl::optional::optional(in_place_t, Args...) This constructor previously didn't have SFINAE because the SFINAE acted badly when Clang was trying to figure out what special members to declare. Specifically, while considering copy constructors it would attempt to call `optional(in_place_t) [ with Args = <> ]`, which evaluated `is_constructible<T>`, which shouldn't have been evaluated. This patch avoids the eager SFINAE bug by deducing the in_place_t tag and short-circuting the SFINAE if the argument passed is not exactly in_place_t. I fixed the same bug in libc++ in the same way. PiperOrigin-RevId: 238290810 -- ffe6d087df495f7f990c89b0a4e1f1664c2c4f9d by Jon Cohen <cohenjon@google.com>: Remove absl_internal_blah names form CMake. We are always creating the alias target now, since use of these targets still requires including a header with internal in the name. This simplifies target naming a bit, especially for installation where we have to generate non-prefixed target names to export in the absl:: namespace. PiperOrigin-RevId: 238280135 -- 9d8ae92ff8727fa49391f7f5386810ff81e80aa7 by Derek Mauro <dmauro@google.com>: Use ABSL_TEST_COPTS for spinlock_benchmark_common and mutex_benchmark_common. Despite being cc_library, these are really tests and the warning for the used-but-marked-unused iterator in Google Benchmark needs to be supressed. PiperOrigin-RevId: 238225200 -- fcde1a79420ce15c8925944c45b69f9fd5226f12 by Matt Armstrong <marmstrong@google.com>: Qualify calls to certain functions from the cmath library. PiperOrigin-RevId: 238163972 -- 4b931e5ef4ba76961b0e2a9edab1e586ba12dfd4 by Tom Manshreck <shreck@google.com>: Add clarification that absl::Hash does not produce stable values across instances. PiperOrigin-RevId: 238125817 -- 8963ea8c65cac1e396a72fe77d6eb6a7313d76db by Derek Mauro <dmauro@google.com>: Fix -Wc++14-binary-literal warning. PiperOrigin-RevId: 238069157 GitOrigin-RevId: 89b5e681db1d4f0b039daebb86c49bda77c8931b Change-Id: Ib06f1ee8efcddb7e2f332bc5bf1c1325458e1073
2019-03-13 22:59:43 +01:00
float testf = std::nextafter(last, std::numeric_limits<float>::max());
2017-09-19 22:54:40 +02:00
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;
}
}
Export of internal Abseil changes. -- 89b5e681db1d4f0b039daebb86c49bda77c8931b by Tom Manshreck <shreck@google.com>: Add clarification that absl::Hash does not produce stable values across instances. PiperOrigin-RevId: 238316564 -- 56dec1d1e37fb2a02aa10d7c81bcd78f8486c093 by Eric Fiselier <ericwf@google.com>: Add SFINAE to absl::optional::optional(in_place_t, Args...) This constructor previously didn't have SFINAE because the SFINAE acted badly when Clang was trying to figure out what special members to declare. Specifically, while considering copy constructors it would attempt to call `optional(in_place_t) [ with Args = <> ]`, which evaluated `is_constructible<T>`, which shouldn't have been evaluated. This patch avoids the eager SFINAE bug by deducing the in_place_t tag and short-circuting the SFINAE if the argument passed is not exactly in_place_t. I fixed the same bug in libc++ in the same way. PiperOrigin-RevId: 238290810 -- ffe6d087df495f7f990c89b0a4e1f1664c2c4f9d by Jon Cohen <cohenjon@google.com>: Remove absl_internal_blah names form CMake. We are always creating the alias target now, since use of these targets still requires including a header with internal in the name. This simplifies target naming a bit, especially for installation where we have to generate non-prefixed target names to export in the absl:: namespace. PiperOrigin-RevId: 238280135 -- 9d8ae92ff8727fa49391f7f5386810ff81e80aa7 by Derek Mauro <dmauro@google.com>: Use ABSL_TEST_COPTS for spinlock_benchmark_common and mutex_benchmark_common. Despite being cc_library, these are really tests and the warning for the used-but-marked-unused iterator in Google Benchmark needs to be supressed. PiperOrigin-RevId: 238225200 -- fcde1a79420ce15c8925944c45b69f9fd5226f12 by Matt Armstrong <marmstrong@google.com>: Qualify calls to certain functions from the cmath library. PiperOrigin-RevId: 238163972 -- 4b931e5ef4ba76961b0e2a9edab1e586ba12dfd4 by Tom Manshreck <shreck@google.com>: Add clarification that absl::Hash does not produce stable values across instances. PiperOrigin-RevId: 238125817 -- 8963ea8c65cac1e396a72fe77d6eb6a7313d76db by Derek Mauro <dmauro@google.com>: Fix -Wc++14-binary-literal warning. PiperOrigin-RevId: 238069157 GitOrigin-RevId: 89b5e681db1d4f0b039daebb86c49bda77c8931b Change-Id: Ib06f1ee8efcddb7e2f332bc5bf1c1325458e1073
2019-03-13 22:59:43 +01:00
testf = std::nextafter(f, 0.0f);
2017-09-19 22:54:40 +02:00
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) {
Export of internal Abseil changes. -- cd076f55c1fa600131f6dda392533dfe61679fc0 by Abseil Team <absl-team@google.com>: Internal change PiperOrigin-RevId: 224008762 -- e05f62b01286d51044ff86ec6ef565749b9faf82 by Abseil Team <absl-team@google.com>: Create a pow10() test helper function to compute guaranteed-precise double values of 10^x. Not all standard libraries ship bit-accurate pow() functions, causing tests to fail that rely on expected values generated by it. PiperOrigin-RevId: 223883762 -- fd88e5e3f7ab80f7f5df9fd1488cd58b4573be69 by Abseil Team <absl-team@google.com>: Remove some absl:: qualifications to work around inline namespace bugs on MSVC 2015. PiperOrigin-RevId: 223869642 -- 6276cfff969d596edd36a2bbaba65ee045808903 by Abseil Team <absl-team@google.com>: Update absl/memory/CMakeLists.txt to use new functions i.e. absl_cc_(library|test) PiperOrigin-RevId: 223854224 -- 359de9afc7a34c975fd3e0cbc52afd96637d97bd by Chris Kennelly <ckennelly@google.com>: Mark spinlock_benchmark_common as alwayslink = 1. PiperOrigin-RevId: 223844536 -- 450cd8cbe2789a6d54ed1eb87170259bb334f8b9 by Abseil Team <absl-team@google.com>: Support .* (pointer-to-member dereference) expressions in demangle.cc. PiperOrigin-RevId: 223826797 -- 772ca92179c3634f3e31a80bbc272ed8022e3572 by Abseil Team <absl-team@google.com>: Fix misspellings in absl::variant comments and replace a ' with a `. PiperOrigin-RevId: 223807911 -- 35dcdc2fbf299d195658aac101887f6dcad1de2f by Abseil Team <absl-team@google.com>: Bug fix in CMakeLists.txt file (SRCS --> HDRS). The compressed_tuple header-only library is being defined with the SRCS parameter instead of the HDRS parameter and this has been observed to cause some builds on some platforms to attempt to create a static library from it which fails since there are no .cc sources. PiperOrigin-RevId: 223805367 -- 4a57a3d2045bb137c0c97958e45ce425190b8d3e by Chris Kennelly <ckennelly@google.com>: Add test that absl::make_unique value initializes memory. PiperOrigin-RevId: 223801819 -- dfe8289d7f4dcc6bb568a26aaf192a89e896bdfd by Chris Kennelly <ckennelly@google.com>: SpinLock: Use exchange to avoid missing wakeups. The default fast path for SpinLock::Unlock does not use an atomic. If the SpinLock becomes contended while we are unlocking between lockword_.load and lockword_.store, we will fail to wake up the new waiter. This can cause unexpected latency spikes. PiperOrigin-RevId: 223800369 -- 9b9d35df786482f0016f77dd31691eff81503d23 by Abseil Team <absl-team@google.com>: Update absl/hash/CMakeLists.txt to use new functions i.e. absl_cc_(library|test) PiperOrigin-RevId: 223755819 -- c2014e2704b87e7cdce2d2a0287c7e2397752296 by Abseil Team <absl-team@google.com>: Update absl/debugging/CMakeLists.txt to use new functions i.e. absl_cc_(library|test) PiperOrigin-RevId: 223751986 -- d83a4e09126400e3fd80645cb03ee558f532271e by Derek Mauro <dmauro@google.com>: Cleanup synchronization benchmarks. PiperOrigin-RevId: 223589416 -- fad140b473586531b5b12843f942ec27dfcf5e93 by CJ Johnson <johnsoncj@google.com>: Makes unifies the order of forward_iterator and input_iterator overloads PiperOrigin-RevId: 223580660 -- 6cd7c96faa7cc5f79f574e35a1b13837ef187d05 by Abseil Team <absl-team@google.com>: Internal Change. PiperOrigin-RevId: 223561629 -- bd2e545356b0f548af0e3c14bb2f7f0e712e49d0 by Shaindel Schwartz <shaindel@google.com>: Remove misleading comments. try_emplace() does not exist for the hash_set containers. PiperOrigin-RevId: 223543089 -- 0cd380a53b587eb7aacc4003a4a3bbb6c78d7c10 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 223512551 -- 7156dfee599cb72e9adddfe0e6ae07a95ddf10bb by Greg Miller <jgm@google.com>: Fixes UB that would result from constructing, multiplying, or dividing a Duration with a double "NaN" value. This CL changes the absl::Duration *implementation* to return an InfiniteDuration value that has the same sign as the given NaN. PiperOrigin-RevId: 223407499 -- 196b7d18609958267951882baf7f9429e49bcafa by CJ Johnson <johnsoncj@google.com>: Addresses NVCC+MSVC compilation bug where `inlined_capacity()` was not considered valid in constexpr PiperOrigin-RevId: 223397718 GitOrigin-RevId: cd076f55c1fa600131f6dda392533dfe61679fc0 Change-Id: I5423ca6470f661a7c6f73aa8fee49990446f157f
2018-12-04 20:01:12 +01:00
double powten = absl::strings_internal::Pow10(exponent);
2017-09-19 22:54:40 +02:00
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,
") (",
2017-09-19 22:54:40 +02:00
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;
}
}
}
} // namespace