1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/strings/abseil_string_number_conversions.h"
6
7 #include <stdint.h>
8
9 #include <limits>
10
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "third_party/abseil-cpp/absl/numeric/int128.h"
13
14 namespace base {
15
TEST(AbseilStringNumberConversionsTest,StringToUint128)16 TEST(AbseilStringNumberConversionsTest, StringToUint128) {
17 // Test cases adapted from `StringNumberConversionsTest.StringToUint64`.
18 static const struct {
19 std::string input;
20 absl::uint128 output;
21 bool success;
22 } cases[] = {
23 {"0", 0, true},
24 {"42", 42, true},
25 {"-2147483648", 0, false},
26 {"2147483647", INT_MAX, true},
27 {"-2147483649", 0, false},
28 {"-99999999999", 0, false},
29 {"2147483648", UINT64_C(2147483648), true},
30 {"99999999999", UINT64_C(99999999999), true},
31 {"9223372036854775807", std::numeric_limits<int64_t>::max(), true},
32 {"-9223372036854775808", 0, false},
33 {"09", 9, true},
34 {"-09", 0, false},
35 {"", 0, false},
36 {" 42", 42, false},
37 {"42 ", 42, false},
38 {"0x42", 0, false},
39 {"\t\n\v\f\r 42", 42, false},
40 {"blah42", 0, false},
41 {"42blah", 42, false},
42 {"blah42blah", 0, false},
43 {"-273.15", 0, false},
44 {"+98.6", 98, false},
45 {"--123", 0, false},
46 {"++123", 0, false},
47 {"-+123", 0, false},
48 {"+-123", 0, false},
49 {"-", 0, false},
50 {"-9223372036854775809", 0, false},
51 {"-99999999999999999999", 0, false},
52 {"9223372036854775808", UINT64_C(9223372036854775808), true},
53 {"99999999999999999999",
54 absl::MakeUint128(/*high=*/5, /*low=*/UINT64_C(7766279631452241919)),
55 true},
56 {"18446744073709551615", std::numeric_limits<uint64_t>::max(), true},
57 {"18446744073709551616", absl::MakeUint128(/*high=*/1, /*low=*/0), true},
58 {"123456789012345678901234567890123456789",
59 absl::MakeUint128(/*high=*/UINT64_C(6692605942763486917),
60 /*low=*/UINT64_C(12312739301371248917)),
61 true},
62 {"-170141183460469231731687303715884105728", 0, false},
63 {"-170141183460469231731687303715884105729", 0, false},
64 {"-999999999999999999999999999999999999999", 0, false},
65 {"170141183460469231731687303715884105727",
66 std::numeric_limits<absl::int128>::max(), true},
67 {"340282366920938463463374607431768211455",
68 std::numeric_limits<absl::uint128>::max(), true},
69 {"340282366920938463463374607431768211456",
70 std::numeric_limits<absl::uint128>::max(), false},
71 {"999999999999999999999999999999999999999",
72 std::numeric_limits<absl::uint128>::max(), false},
73 };
74
75 for (const auto& i : cases) {
76 absl::uint128 output = 0;
77 EXPECT_EQ(i.success, StringToUint128(i.input, &output)) << i.input;
78 EXPECT_EQ(i.output, output);
79 }
80
81 // One additional test to verify that conversion of numbers in strings with
82 // embedded NUL characters. The NUL and extra data after it should be
83 // interpreted as junk after the number.
84 const char input[] =
85 "6\0"
86 "6";
87 std::string input_string(input, std::size(input) - 1);
88 absl::uint128 output;
89 EXPECT_FALSE(StringToUint128(input_string, &output));
90 EXPECT_EQ(6U, output);
91 }
92
TEST(AbseilStringNumberConversionsTest,HexStringToUInt128)93 TEST(AbseilStringNumberConversionsTest, HexStringToUInt128) {
94 // Test cases adapted from `StringNumberConversionsTest.HexStringToUint64`.
95 static const struct {
96 std::string input;
97 absl::uint128 output;
98 bool success;
99 } cases[] = {
100 {"0", 0, true},
101 {"42", 66, true},
102 {"-42", 0, false},
103 {"+42", 66, true},
104 {"ffffffffffffffff",
105 absl::MakeUint128(/*high=*/0,
106 /*low=*/std::numeric_limits<uint64_t>::max()),
107 true},
108 {"1ffffffffffffffff",
109 absl::MakeUint128(/*high=*/1,
110 /*low=*/std::numeric_limits<uint64_t>::max()),
111 true},
112 {"7fffffff", INT_MAX, true},
113 {"-80000000", 0, false},
114 {"ffffffff", 0xffffffff, true},
115 {"DeadBeef", 0xdeadbeef, true},
116 {"0x42", 66, true},
117 {"-0x42", 0, false},
118 {"+0x42", 66, true},
119 {"0xffffffffffffffff",
120 absl::MakeUint128(/*high=*/0,
121 /*low=*/std::numeric_limits<uint64_t>::max()),
122 true},
123 {"0x1ffffffffffffffff",
124 absl::MakeUint128(/*high=*/1,
125 /*low=*/std::numeric_limits<uint64_t>::max()),
126 true},
127 {"0x7fffffff", INT_MAX, true},
128 {"-0x80000000", 0, false},
129 {"0xffffffff", 0xffffffff, true},
130 {"0XDeadBeef", 0xdeadbeef, true},
131 {"0x7fffffffffffffffffffffffffffffff",
132 std::numeric_limits<absl::int128>::max(), true},
133 {"-0x8000000000000000", 0, false},
134 {"0x8000000000000000",
135 absl::MakeUint128(/*high=*/0, UINT64_C(0x8000000000000000)), true},
136 {"-0x8000000000000001", 0, false},
137 {"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
138 std::numeric_limits<absl::uint128>::max(), true},
139 {"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
140 std::numeric_limits<absl::uint128>::max(), true},
141 {"0x0000000000000000", 0, true},
142 {"0000000000000000", 0, true},
143 {"1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
144 std::numeric_limits<absl::uint128>::max(), false}, // Overflow test.
145 {"0x0f", 15, true},
146 {"0f", 15, true},
147 {" 45", 0x45, false},
148 {"\t\n\v\f\r 0x45", 0x45, false},
149 {" 45", 0x45, false},
150 {"45 ", 0x45, false},
151 {"45:", 0x45, false},
152 {"efgh", 0xef, false},
153 {"0xefgh", 0xef, false},
154 {"hgfe", 0, false},
155 {"-", 0, false},
156 {"", 0, false},
157 {"0x", 0, false},
158 };
159
160 for (const auto& i : cases) {
161 absl::uint128 output = 0;
162 EXPECT_EQ(i.success, HexStringToUInt128(i.input, &output)) << i.input;
163 EXPECT_EQ(i.output, output) << i.input;
164 }
165 // One additional test to verify that conversion of numbers in strings with
166 // embedded NUL characters. The NUL and extra data after it should be
167 // interpreted as junk after the number.
168 const char input[] =
169 "0xc0ffee\0"
170 "9";
171 std::string input_string(input, std::size(input) - 1);
172 absl::uint128 output;
173 EXPECT_FALSE(HexStringToUInt128(input_string, &output));
174 EXPECT_EQ(0xc0ffeeU, output);
175 }
176
177 } // namespace base
178