Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(399)

Side by Side Diff: net/base/parse_number_unittest.cc

Issue 1828103002: Extend net/base/parse_number.h for parsing of negative numbers, and determining if there was overflo (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@proxy_num
Patch Set: Address remaining feedback Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/parse_number.h" 5 #include "net/base/parse_number.h"
6 6
7 #include <limits>
8
9 #include "base/strings/string_number_conversions.h"
7 #include "testing/gtest/include/gtest/gtest.h" 10 #include "testing/gtest/include/gtest/gtest.h"
8 11
9 namespace net { 12 namespace net {
10 namespace { 13 namespace {
11 14
12 TEST(ParseNumberTest, IntValidInputs) { 15 // Increments the final character in a string by 1. Used as a simplistic way to
13 const struct { 16 // increment a numeric string (flawed, but good enough for use case).
14 const char* input; 17 std::string IncrementLastChar(std::string value) {
15 int output; 18 value[value.size() - 1]++;
16 } kTests[] = { 19 return value;
17 {"0", 0}, {"00000", 0}, {"003", 3}, {"003", 3}, {"1234566", 1234566}, 20 }
18 {"987", 987}, {"010", 10}, 21
19 }; 22 // These are valid inputs representing non-negative integers. Note that these
20 23 // test inputs are re-used when constructing negative test cases, by simply
21 for (const auto& test : kTests) { 24 // prepending a '-'.
22 int result; 25 const struct {
23 ASSERT_TRUE(ParseNonNegativeDecimalInt(test.input, &result)) 26 const char* input;
24 << "Failed to parse: " << test.input; 27 int expected_output;
25 EXPECT_EQ(result, test.output) << "Failed to parse: " << test.input; 28 } kValidNonNegativeTests[] = {
26 } 29 {"0", 0}, {"00000", 0}, {"003", 3}, {"003", 3}, {"1234566", 1234566},
27 } 30 {"987", 987}, {"010", 10},
28 31 };
29 TEST(ParseNumberTest, IntInvalidInputs) { 32
30 const char* kTests[] = { 33 // These are invalid inputs that can not be parsed regardless of the policy
31 "", 34 // used (they are neither valid negative or non-negative values).
32 "-23", 35 const char* kInvalidParseTests[] = {
33 "+42", 36 "", "-", "--", "23-", "134-34", "- ", " ", "+42",
34 " 123", 37 " 123", "123 ", "123\n", "0xFF", "-0xFF", "0x11", "-0x11", "x11",
35 "123 ", 38 "-x11", "F11", "-F11", "AF", "-AF", "0AF", "0.0", "13.",
36 "123\n", 39 "13,000", "13.000", "13/5", "Inf", "NaN", "null", "dog",
37 "0xFF", 40 };
38 "0x11", 41
39 "x11", 42 // This wrapper calls ParseIntegerBase10() and expects the result to match
40 "F11", 43 // |expected_output|.
41 "AF", 44 template <typename OutputType, typename ExpectationType>
42 "0AF", 45 void ExpectParseIntegerBase10Success(const base::StringPiece& input,
43 "0.0", 46 ParseInteger policy,
44 "13.", 47 ExpectationType expected_output) {
45 "13,000", 48 // Try parsing without specifying an error output - expecting success.
46 "13.000", 49 OutputType parsed_number1;
47 "13/5", 50 EXPECT_TRUE(ParseIntegerBase10(input, policy, &parsed_number1))
48 "9999999999999999999999999999999999999999999999999999999999999999", 51 << "Failed to parse: " << input;
49 "Inf", 52 EXPECT_EQ(static_cast<OutputType>(expected_output), parsed_number1);
50 "NaN", 53
51 "null", 54 // Try parsing with an error output - expecting success.
52 "dog", 55 ParseIntegerError kBogusError = static_cast<ParseIntegerError>(19);
53 }; 56 ParseIntegerError error = kBogusError;
54 57 OutputType parsed_number2;
55 for (const auto& input : kTests) { 58 EXPECT_TRUE(ParseIntegerBase10(input, policy, &parsed_number2, &error))
56 int result = 0xDEAD; 59 << "Failed to parse: " << input;
57 ASSERT_FALSE(ParseNonNegativeDecimalInt(input, &result)) 60 EXPECT_EQ(static_cast<OutputType>(expected_output), parsed_number2);
58 << "Succeeded to parse: " << input; 61 // Check that the error output was not written to.
59 EXPECT_EQ(0xDEAD, result) << "Modified output for failed parsing"; 62 EXPECT_EQ(kBogusError, error);
60 } 63 }
61 } 64
62 65 // This wrapper calls ParseIntegerBase10() and expects the failure to match
63 TEST(ParseNumberTest, IntInvalidInputsContainsNul) { 66 // |expected_error|.
64 int result = 0xDEAD; 67 template <typename OutputType>
65 ASSERT_FALSE( 68 void ExpectParseIntegerBase10Failure(const base::StringPiece& input,
66 ParseNonNegativeDecimalInt(base::StringPiece("123\0", 4), &result)); 69 ParseInteger policy,
67 EXPECT_EQ(0xDEAD, result); 70 ParseIntegerError expected_error) {
71 const OutputType kBogusOutput = OutputType(23614);
72
73 // Try parsing without specifying an error output - expecting failure.
74 OutputType parsed_number1 = kBogusOutput;
75 EXPECT_FALSE(ParseIntegerBase10(input, policy, &parsed_number1))
76 << "Succeded parsing: " << input;
77 EXPECT_EQ(kBogusOutput, parsed_number1)
78 << "Modified output when failed parsing";
79
80 // Try parsing with an error output - expecting failure.
81 OutputType parsed_number2 = kBogusOutput;
82 ParseIntegerError error;
83 EXPECT_FALSE(ParseIntegerBase10(input, policy, &parsed_number2, &error))
84 << "Succeded parsing: " << input;
85 EXPECT_EQ(kBogusOutput, parsed_number2)
86 << "Modified output when failed parsing";
87 EXPECT_EQ(expected_error, error);
88 }
89
90 // Common tests to run for each of the overloaded versions of
91 // ParseIntegerBase10().
92 template <typename T>
93 void TestParseIntegerBase10() {
94 ParseInteger kPolicies[] = {ParseInteger::DISALLOW_NEGATIVE,
95 ParseInteger::ALLOW_NEGATIVE};
96
97 // Test valid non-negative inputs
98
99 for (const auto& policy : kPolicies) {
100 for (const auto& test : kValidNonNegativeTests) {
101 ExpectParseIntegerBase10Success<T>(test.input, policy,
102 test.expected_output);
103 }
104 }
105
106 // Test invalid inputs (invalid regardless of parsing policy)
107
108 for (const auto& policy : kPolicies) {
109 for (const auto& input : kInvalidParseTests) {
110 ExpectParseIntegerBase10Failure<T>(input, policy,
111 ParseIntegerError::FAILED_PARSE);
112 }
113 }
114
115 // Test valid negative inputs (constructed from the valid non-negative test
116 // cases).
117
118 for (const auto& policy : kPolicies) {
119 for (const auto& test : kValidNonNegativeTests) {
120 std::string negative_input = std::string("-") + test.input;
121 int expected_negative_output = -test.expected_output;
122
123 // The result depends on the policy.
124 if (policy == ParseInteger::DISALLOW_NEGATIVE) {
125 ExpectParseIntegerBase10Failure<T>(negative_input, policy,
126 ParseIntegerError::FAILED_PARSE);
127 } else {
128 ExpectParseIntegerBase10Success<T>(negative_input, policy,
129 expected_negative_output);
130 }
131 }
132 }
133
134 // Test parsing the largest possible value for output type.
135
136 for (const auto& policy : kPolicies) {
137 const T value = std::numeric_limits<T>::max();
138 ExpectParseIntegerBase10Success<T>(std::to_string(value), policy, value);
139 }
140
141 // Test parsing a number one larger than the output type can accomodate
142 // (overflow).
143
144 for (const auto& policy : kPolicies) {
145 const T value = std::numeric_limits<T>::max();
146 ExpectParseIntegerBase10Failure<T>(IncrementLastChar(std::to_string(value)),
147 policy,
148 ParseIntegerError::FAILED_OVERFLOW);
149 }
150
151 // Test parsing a number at least as large as the output allows AND contains
152 // garbage at the end. This exercises an interesting internal quirk of
153 // base::StringToInt*(), in that its result cannot distinguish this case
154 // from overflow.
155
156 for (const auto& policy : kPolicies) {
157 const T value = std::numeric_limits<T>::max();
158 ExpectParseIntegerBase10Failure<T>(std::to_string(value) + " ", policy,
159 ParseIntegerError::FAILED_PARSE);
160 }
161
162 // Test parsing the smallest possible value for output type.
163
164 for (const auto& policy : kPolicies) {
165 const T value = std::numeric_limits<T>::min();
166 auto str_value = std::to_string(value);
167
168 // The minimal value is necessarily negative, since this function is testing
169 // only signed output types.
170 if (policy == ParseInteger::DISALLOW_NEGATIVE) {
171 ExpectParseIntegerBase10Failure<T>(str_value, policy,
172 ParseIntegerError::FAILED_PARSE);
173 } else {
174 ExpectParseIntegerBase10Success<T>(str_value, policy, value);
175 }
176 }
177
178 // Test parsing a number one less than the output type can accomodate
179 // (underflow).
180
181 {
182 std::string str_value =
183 IncrementLastChar(std::to_string(std::numeric_limits<T>::min()));
184
185 ExpectParseIntegerBase10Failure<T>(str_value, ParseInteger::ALLOW_NEGATIVE,
186 ParseIntegerError::FAILED_UNDERFLOW);
187 }
188
189 // Test parsing a string that contains a valid number followed by a NUL
190 // character.
191
192 for (const auto& policy : kPolicies) {
193 ExpectParseIntegerBase10Failure<T>(base::StringPiece("123\0", 4), policy,
194 ParseIntegerError::FAILED_PARSE);
195 }
196 }
197
198 // This wrapper calls ParseUnsignedIntegerBase10() and expects the result to
199 // match |expected_output|.
200 template <typename OutputType, typename ExpectationType>
201 void ExpectParseUnsignedIntegerBase10Success(const base::StringPiece& input,
202 ExpectationType expected_output) {
203 // Try parsing without specifying an error output - expecting success.
204 OutputType parsed_number1;
205 EXPECT_TRUE(ParseUnsignedIntegerBase10(input, &parsed_number1))
206 << "Failed to parse: " << input;
207 EXPECT_EQ(static_cast<OutputType>(expected_output), parsed_number1);
208
209 // Try parsing with an error output - expecting success.
210 ParseIntegerError kBogusError = static_cast<ParseIntegerError>(19);
211 ParseIntegerError error = kBogusError;
212 OutputType parsed_number2;
213 EXPECT_TRUE(ParseUnsignedIntegerBase10(input, &parsed_number2, &error))
214 << "Failed to parse: " << input;
215 EXPECT_EQ(static_cast<OutputType>(expected_output), parsed_number2);
216 // Check that the error output was not written to.
217 EXPECT_EQ(kBogusError, error);
218 }
219
220 // This wrapper calls ParseUnsignedIntegerBase10() and expects the failure to
221 // match |expected_error|.
222 template <typename OutputType>
223 void ExpectParseUnsignedIntegerBase10Failure(const base::StringPiece& input,
224 ParseIntegerError expected_error) {
225 const OutputType kBogusOutput = OutputType(23614);
226
227 // Try parsing without specifying an error output - expecting failure.
228 OutputType parsed_number1 = kBogusOutput;
229 EXPECT_FALSE(ParseUnsignedIntegerBase10(input, &parsed_number1))
230 << "Succeded parsing: " << input;
231 EXPECT_EQ(kBogusOutput, parsed_number1)
232 << "Modified output when failed parsing";
233
234 // Try parsing with an error output - expecting failure.
235 OutputType parsed_number2 = kBogusOutput;
236 ParseIntegerError error;
237 EXPECT_FALSE(ParseUnsignedIntegerBase10(input, &parsed_number2, &error))
238 << "Succeded parsing: " << input;
239 EXPECT_EQ(kBogusOutput, parsed_number2)
240 << "Modified output when failed parsing";
241 EXPECT_EQ(expected_error, error);
242 }
243
244 // Common tests to run for each of the overloaded versions of
245 // ParseUnsignedIntegerBase10().
246 template <typename T>
247 void TestParseUnsignedIntegerBase10() {
248 // Test valid non-negative inputs
249 for (const auto& test : kValidNonNegativeTests) {
250 ExpectParseUnsignedIntegerBase10Success<T>(test.input,
251 test.expected_output);
252 }
253
254 // Test invalid inputs (invalid regardless of parsing policy)
255 for (const auto& input : kInvalidParseTests) {
256 ExpectParseUnsignedIntegerBase10Failure<T>(input,
257 ParseIntegerError::FAILED_PARSE);
258 }
259
260 // Test valid negative inputs (constructed from the valid non-negative test
261 // cases).
262 for (const auto& test : kValidNonNegativeTests) {
263 std::string negative_input = std::string("-") + test.input;
264
265 // The result depends on the policy.
266 ExpectParseUnsignedIntegerBase10Failure<T>(negative_input,
267 ParseIntegerError::FAILED_PARSE);
268 }
269
270 // Test parsing the largest possible value for output type.
271 {
272 const T value = std::numeric_limits<T>::max();
273 ExpectParseUnsignedIntegerBase10Success<T>(std::to_string(value), value);
274 }
275
276 // Test parsing a number one larger than the output type can accomodate
277 // (overflow).
278 {
279 const T value = std::numeric_limits<T>::max();
280 ExpectParseUnsignedIntegerBase10Failure<T>(
281 IncrementLastChar(std::to_string(value)),
282 ParseIntegerError::FAILED_OVERFLOW);
283 }
284
285 // Test parsing a number at least as large as the output allows AND contains
286 // garbage at the end. This exercises an interesting internal quirk of
287 // base::StringToInt*(), in that its result cannot distinguish this case
288 // from overflow.
289
290 {
291 const T value = std::numeric_limits<T>::max();
292 ExpectParseUnsignedIntegerBase10Failure<T>(std::to_string(value) + " ",
293 ParseIntegerError::FAILED_PARSE);
294 }
295
296 // Test parsing a string that contains a valid number followed by a NUL
297 // character.
298 ExpectParseUnsignedIntegerBase10Failure<T>(base::StringPiece("123\0", 4),
299 ParseIntegerError::FAILED_PARSE);
300 }
301
302 TEST(ParseNumberTest, ParseIntegerBase10Int32) {
303 TestParseIntegerBase10<int32_t>();
304 }
305
306 TEST(ParseNumberTest, ParseIntegerBase10Int64) {
307 TestParseIntegerBase10<int64_t>();
308 }
309
310 TEST(ParseNumberTest, ParseUnsignedIntegerBase10Uint32) {
311 TestParseUnsignedIntegerBase10<uint32_t>();
312 }
313
314 TEST(ParseNumberTest, ParseUnsignedIntegerBase10Uint64) {
315 TestParseUnsignedIntegerBase10<uint64_t>();
68 } 316 }
69 317
70 } // namespace 318 } // namespace
71 } // namespace net 319 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698