| // Copyright 2022 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/strings/abseil_string_number_conversions.h" |
| |
| #include <stdint.h> |
| |
| #include <limits> |
| |
| #include "base/strings/string_piece.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "absl/numeric/int128.h" |
| |
| namespace gurl_base { |
| |
| TEST(AbseilStringNumberConversionsTest, StringToUint128) { |
| // Test cases adapted from `StringNumberConversionsTest.StringToUint64`. |
| static const struct { |
| std::string input; |
| absl::uint128 output; |
| bool success; |
| } cases[] = { |
| {"0", 0, true}, |
| {"42", 42, true}, |
| {"-2147483648", 0, false}, |
| {"2147483647", INT_MAX, true}, |
| {"-2147483649", 0, false}, |
| {"-99999999999", 0, false}, |
| {"2147483648", UINT64_C(2147483648), true}, |
| {"99999999999", UINT64_C(99999999999), true}, |
| {"9223372036854775807", std::numeric_limits<int64_t>::max(), true}, |
| {"-9223372036854775808", 0, false}, |
| {"09", 9, true}, |
| {"-09", 0, false}, |
| {"", 0, false}, |
| {" 42", 42, false}, |
| {"42 ", 42, false}, |
| {"0x42", 0, false}, |
| {"\t\n\v\f\r 42", 42, false}, |
| {"blah42", 0, false}, |
| {"42blah", 42, false}, |
| {"blah42blah", 0, false}, |
| {"-273.15", 0, false}, |
| {"+98.6", 98, false}, |
| {"--123", 0, false}, |
| {"++123", 0, false}, |
| {"-+123", 0, false}, |
| {"+-123", 0, false}, |
| {"-", 0, false}, |
| {"-9223372036854775809", 0, false}, |
| {"-99999999999999999999", 0, false}, |
| {"9223372036854775808", UINT64_C(9223372036854775808), true}, |
| {"99999999999999999999", |
| absl::MakeUint128(/*high=*/5, /*low=*/UINT64_C(7766279631452241919)), |
| true}, |
| {"18446744073709551615", std::numeric_limits<uint64_t>::max(), true}, |
| {"18446744073709551616", absl::MakeUint128(/*high=*/1, /*low=*/0), true}, |
| {"123456789012345678901234567890123456789", |
| absl::MakeUint128(/*high=*/UINT64_C(6692605942763486917), |
| /*low=*/UINT64_C(12312739301371248917)), |
| true}, |
| {"-170141183460469231731687303715884105728", 0, false}, |
| {"-170141183460469231731687303715884105729", 0, false}, |
| {"-999999999999999999999999999999999999999", 0, false}, |
| {"170141183460469231731687303715884105727", |
| std::numeric_limits<absl::int128>::max(), true}, |
| {"340282366920938463463374607431768211455", |
| std::numeric_limits<absl::uint128>::max(), true}, |
| {"340282366920938463463374607431768211456", |
| std::numeric_limits<absl::uint128>::max(), false}, |
| {"999999999999999999999999999999999999999", |
| std::numeric_limits<absl::uint128>::max(), false}, |
| }; |
| |
| for (const auto& i : cases) { |
| absl::uint128 output = 0; |
| EXPECT_EQ(i.success, StringToUint128(i.input, &output)) << i.input; |
| EXPECT_EQ(i.output, output); |
| } |
| |
| // One additional test to verify that conversion of numbers in strings with |
| // embedded NUL characters. The NUL and extra data after it should be |
| // interpreted as junk after the number. |
| const char input[] = |
| "6\0" |
| "6"; |
| std::string input_string(input, std::size(input) - 1); |
| absl::uint128 output; |
| EXPECT_FALSE(StringToUint128(input_string, &output)); |
| EXPECT_EQ(6U, output); |
| } |
| |
| TEST(AbseilStringNumberConversionsTest, HexStringToUInt128) { |
| // Test cases adapted from `StringNumberConversionsTest.HexStringToUint64`. |
| static const struct { |
| std::string input; |
| absl::uint128 output; |
| bool success; |
| } cases[] = { |
| {"0", 0, true}, |
| {"42", 66, true}, |
| {"-42", 0, false}, |
| {"+42", 66, true}, |
| {"ffffffffffffffff", |
| absl::MakeUint128(/*high=*/0, |
| /*low=*/std::numeric_limits<uint64_t>::max()), |
| true}, |
| {"1ffffffffffffffff", |
| absl::MakeUint128(/*high=*/1, |
| /*low=*/std::numeric_limits<uint64_t>::max()), |
| true}, |
| {"7fffffff", INT_MAX, true}, |
| {"-80000000", 0, false}, |
| {"ffffffff", 0xffffffff, true}, |
| {"DeadBeef", 0xdeadbeef, true}, |
| {"0x42", 66, true}, |
| {"-0x42", 0, false}, |
| {"+0x42", 66, true}, |
| {"0xffffffffffffffff", |
| absl::MakeUint128(/*high=*/0, |
| /*low=*/std::numeric_limits<uint64_t>::max()), |
| true}, |
| {"0x1ffffffffffffffff", |
| absl::MakeUint128(/*high=*/1, |
| /*low=*/std::numeric_limits<uint64_t>::max()), |
| true}, |
| {"0x7fffffff", INT_MAX, true}, |
| {"-0x80000000", 0, false}, |
| {"0xffffffff", 0xffffffff, true}, |
| {"0XDeadBeef", 0xdeadbeef, true}, |
| {"0x7fffffffffffffffffffffffffffffff", |
| std::numeric_limits<absl::int128>::max(), true}, |
| {"-0x8000000000000000", 0, false}, |
| {"0x8000000000000000", |
| absl::MakeUint128(/*high=*/0, UINT64_C(0x8000000000000000)), true}, |
| {"-0x8000000000000001", 0, false}, |
| {"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", |
| std::numeric_limits<absl::uint128>::max(), true}, |
| {"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", |
| std::numeric_limits<absl::uint128>::max(), true}, |
| {"0x0000000000000000", 0, true}, |
| {"0000000000000000", 0, true}, |
| {"1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", |
| std::numeric_limits<absl::uint128>::max(), false}, // Overflow test. |
| {"0x0f", 15, true}, |
| {"0f", 15, true}, |
| {" 45", 0x45, false}, |
| {"\t\n\v\f\r 0x45", 0x45, false}, |
| {" 45", 0x45, false}, |
| {"45 ", 0x45, false}, |
| {"45:", 0x45, false}, |
| {"efgh", 0xef, false}, |
| {"0xefgh", 0xef, false}, |
| {"hgfe", 0, false}, |
| {"-", 0, false}, |
| {"", 0, false}, |
| {"0x", 0, false}, |
| }; |
| |
| for (const auto& i : cases) { |
| absl::uint128 output = 0; |
| EXPECT_EQ(i.success, HexStringToUInt128(i.input, &output)) << i.input; |
| EXPECT_EQ(i.output, output) << i.input; |
| } |
| // One additional test to verify that conversion of numbers in strings with |
| // embedded NUL characters. The NUL and extra data after it should be |
| // interpreted as junk after the number. |
| const char input[] = |
| "0xc0ffee\0" |
| "9"; |
| std::string input_string(input, std::size(input) - 1); |
| absl::uint128 output; |
| EXPECT_FALSE(HexStringToUInt128(input_string, &output)); |
| EXPECT_EQ(0xc0ffeeU, output); |
| } |
| |
| } // namespace base |