blob: 5873e79aee7eda087edfdf9b48cf2942dbb4886a [file] [log] [blame]
// 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