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

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: fix comments Created 4 years, 8 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
« no previous file with comments | « net/base/parse_number.cc ('k') | net/base/sdch_manager.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #include <sstream>
9
10 #include "base/strings/string_number_conversions.h"
7 #include "testing/gtest/include/gtest/gtest.h" 11 #include "testing/gtest/include/gtest/gtest.h"
8 12
9 namespace net { 13 namespace net {
10 namespace { 14 namespace {
11 15
12 TEST(ParseNumberTest, IntValidInputs) { 16 template <typename T>
13 const struct { 17 std::string ToString(T number) {
14 const char* input; 18 // TODO(eroman): Just use std::to_string() instead (Currently chromium's
15 int output; 19 // C++11 guide hasn't taken a stance on it).
16 } kTests[] = { 20 std::stringstream s;
17 {"0", 0}, {"00000", 0}, {"003", 3}, {"003", 3}, {"1234566", 1234566}, 21 s << number;
18 {"987", 987}, {"010", 10}, 22 return s.str();
23 }
24
25 // Returns a decimal string that is one larger than the maximum value that type
26 // T can represent.
27 template <typename T>
28 std::string CreateOverflowString() {
29 const T value = std::numeric_limits<T>::max();
30 std::string result = ToString(value);
31 EXPECT_NE('9', result.back());
32 result.back()++;
33 return result;
34 }
35
36 // Returns a decimal string that is one less than the minimum value that
37 // (signed) type T can represent.
38 template <typename T>
39 std::string CreateUnderflowString() {
40 EXPECT_TRUE(std::numeric_limits<T>::is_signed);
41 const T value = std::numeric_limits<T>::min();
42 std::string result = ToString(value);
43 EXPECT_EQ('-', result.front());
44 EXPECT_NE('9', result.back());
45 result.back()++;
46 return result;
47 }
48
49 // These are valid inputs representing non-negative integers. Note that these
50 // test inputs are re-used when constructing negative test cases, by simply
51 // prepending a '-'.
52 const struct {
53 const char* input;
54 int expected_output;
55 } kValidNonNegativeTests[] = {
56 {"0", 0}, {"00000", 0}, {"003", 3}, {"003", 3}, {"1234566", 1234566},
57 {"987", 987}, {"010", 10},
58 };
59
60 // These are invalid inputs that can not be parsed regardless of the format
61 // used (they are neither valid negative or non-negative values).
62 const char* kInvalidParseTests[] = {
63 "", "-", "--", "23-", "134-34", "- ", " ", "+42",
64 " 123", "123 ", "123\n", "0xFF", "-0xFF", "0x11", "-0x11", "x11",
65 "-x11", "F11", "-F11", "AF", "-AF", "0AF", "0.0", "13.",
66 "13,000", "13.000", "13/5", "Inf", "NaN", "null", "dog",
67 };
68
69 // This wrapper calls func() and expects the result to match |expected_output|.
70 template <typename OutputType, typename ParseFunc, typename ExpectationType>
71 void ExpectParseIntSuccess(ParseFunc func,
72 const base::StringPiece& input,
73 ParseIntFormat format,
74 ExpectationType expected_output) {
75 // Try parsing without specifying an error output - expecting success.
76 OutputType parsed_number1;
77 EXPECT_TRUE(func(input, format, &parsed_number1, nullptr))
78 << "Failed to parse: " << input;
79 EXPECT_EQ(static_cast<OutputType>(expected_output), parsed_number1);
80
81 // Try parsing with an error output - expecting success.
82 ParseIntError kBogusError = static_cast<ParseIntError>(19);
83 ParseIntError error = kBogusError;
84 OutputType parsed_number2;
85 EXPECT_TRUE(func(input, format, &parsed_number2, &error))
86 << "Failed to parse: " << input;
87 EXPECT_EQ(static_cast<OutputType>(expected_output), parsed_number2);
88 // Check that the error output was not written to.
89 EXPECT_EQ(kBogusError, error);
90 }
91
92 // This wrapper calls func() and expects the failure to match |expected_error|.
93 template <typename OutputType, typename ParseFunc>
94 void ExpectParseIntFailure(ParseFunc func,
95 const base::StringPiece& input,
96 ParseIntFormat format,
97 ParseIntError expected_error) {
98 const OutputType kBogusOutput(23614);
99
100 // Try parsing without specifying an error output - expecting failure.
101 OutputType parsed_number1 = kBogusOutput;
102 EXPECT_FALSE(func(input, format, &parsed_number1, nullptr))
103 << "Succeded parsing: " << input;
104 EXPECT_EQ(kBogusOutput, parsed_number1)
105 << "Modified output when failed parsing";
106
107 // Try parsing with an error output - expecting failure.
108 OutputType parsed_number2 = kBogusOutput;
109 ParseIntError error;
110 EXPECT_FALSE(func(input, format, &parsed_number2, &error))
111 << "Succeded parsing: " << input;
112 EXPECT_EQ(kBogusOutput, parsed_number2)
113 << "Modified output when failed parsing";
114 EXPECT_EQ(expected_error, error);
115 }
116
117 // Common tests for both ParseInt*() and ParseUint*()
118 //
119 // When testing ParseUint*() the |format| parameter is not applicable and
120 // should be passed as NON_NEGATIVE.
121 template <typename T, typename ParseFunc>
122 void TestParseIntUsingFormat(ParseFunc func, ParseIntFormat format) {
123 // Test valid non-negative inputs
124 for (const auto& test : kValidNonNegativeTests) {
125 ExpectParseIntSuccess<T>(func, test.input, format, test.expected_output);
126 }
127
128 // Test invalid inputs (invalid regardless of parsing format)
129 for (const auto& input : kInvalidParseTests) {
130 ExpectParseIntFailure<T>(func, input, format, ParseIntError::FAILED_PARSE);
131 }
132
133 // Test valid negative inputs (constructed from the valid non-negative test
134 // cases).
135 for (const auto& test : kValidNonNegativeTests) {
136 std::string negative_input = std::string("-") + test.input;
137 int expected_negative_output = -test.expected_output;
138
139 // The result depends on the format.
140 if (format == ParseIntFormat::NON_NEGATIVE) {
141 ExpectParseIntFailure<T>(func, negative_input, format,
142 ParseIntError::FAILED_PARSE);
143 } else {
144 ExpectParseIntSuccess<T>(func, negative_input, format,
145 expected_negative_output);
146 }
147 }
148
149 // Test parsing the largest possible value for output type.
150 {
151 const T value = std::numeric_limits<T>::max();
152 ExpectParseIntSuccess<T>(func, ToString(value), format, value);
153 }
154
155 // Test parsing a number one larger than the output type can accomodate
156 // (overflow).
157 ExpectParseIntFailure<T>(func, CreateOverflowString<T>(), format,
158 ParseIntError::FAILED_OVERFLOW);
159
160 // Test parsing a number at least as large as the output allows AND contains
161 // garbage at the end. This exercises an interesting internal quirk of
162 // base::StringToInt*(), in that its result cannot distinguish this case
163 // from overflow.
164 ExpectParseIntFailure<T>(func, ToString(std::numeric_limits<T>::max()) + " ",
165 format, ParseIntError::FAILED_PARSE);
166
167 ExpectParseIntFailure<T>(func, CreateOverflowString<T>() + " ", format,
168 ParseIntError::FAILED_PARSE);
169
170 // Test parsing the smallest possible value for output type. Don't do the
171 // test for unsigned types since the smallest number 0 is tested elsewhere.
172 if (std::numeric_limits<T>::is_signed) {
173 const T value = std::numeric_limits<T>::min();
174 std::string str_value = ToString(value);
175
176 // The minimal value is necessarily negative, since this function is
177 // testing only signed output types.
178 if (format == ParseIntFormat::NON_NEGATIVE) {
179 ExpectParseIntFailure<T>(func, str_value, format,
180 ParseIntError::FAILED_PARSE);
181 } else {
182 ExpectParseIntSuccess<T>(func, str_value, format, value);
183 }
184 }
185
186 // Test parsing a number one less than the output type can accomodate
187 // (underflow).
188 if (format == ParseIntFormat::OPTIONALLY_NEGATIVE) {
189 ExpectParseIntFailure<T>(func, CreateUnderflowString<T>(),
190 ParseIntFormat::OPTIONALLY_NEGATIVE,
191 ParseIntError::FAILED_UNDERFLOW);
192 }
193
194 // Test parsing a string that contains a valid number followed by a NUL
195 // character.
196 ExpectParseIntFailure<T>(func, base::StringPiece("123\0", 4), format,
197 ParseIntError::FAILED_PARSE);
198 }
199
200 // Common tests to run for each of the versions of ParseInt*().
201 //
202 // The |func| parameter should be a function pointer to the particular
203 // ParseInt*() function to test.
204 template <typename T, typename ParseFunc>
205 void TestParseInt(ParseFunc func) {
206 // Test using each of the possible formats.
207 ParseIntFormat kFormats[] = {ParseIntFormat::NON_NEGATIVE,
208 ParseIntFormat::OPTIONALLY_NEGATIVE};
209
210 for (const auto& format : kFormats) {
211 TestParseIntUsingFormat<T>(func, format);
212 }
213 }
214
215 // Common tests to run for each of the versions of ParseUint*().
216 //
217 // The |func| parameter should be a function pointer to the particular
218 // ParseUint*() function to test.
219 template <typename T, typename ParseFunc>
220 void TestParseUint(ParseFunc func) {
221 // TestParseIntUsingFormat() expects a functor that has a |format|
222 // parameter. For ParseUint*() there is no such parameter. For all intents
223 // and purposes can just fix it to NON_NEGATIVE and re-use that test driver.
224 auto func_adapter = [&func](const base::StringPiece& input,
225 ParseIntFormat format, T* output,
226 ParseIntError* optional_error) {
227 EXPECT_EQ(ParseIntFormat::NON_NEGATIVE, format);
228 return func(input, output, optional_error);
19 }; 229 };
20 230
21 for (const auto& test : kTests) { 231 TestParseIntUsingFormat<T>(func_adapter, ParseIntFormat::NON_NEGATIVE);
22 int result; 232 }
23 ASSERT_TRUE(ParseNonNegativeDecimalInt(test.input, &result)) 233
24 << "Failed to parse: " << test.input; 234 TEST(ParseNumberTest, ParseInt32) {
25 EXPECT_EQ(result, test.output) << "Failed to parse: " << test.input; 235 TestParseInt<int32_t>(ParseInt32);
26 } 236 }
27 } 237
28 238 TEST(ParseNumberTest, ParseInt64) {
29 TEST(ParseNumberTest, IntInvalidInputs) { 239 TestParseInt<int64_t>(ParseInt64);
30 const char* kTests[] = { 240 }
31 "", 241
32 "-23", 242 TEST(ParseNumberTest, ParseUint32) {
33 "+42", 243 TestParseUint<uint32_t>(ParseUint32);
34 " 123", 244 }
35 "123 ", 245
36 "123\n", 246 TEST(ParseNumberTest, ParseUint64) {
37 "0xFF", 247 TestParseUint<uint64_t>(ParseUint64);
38 "0x11",
39 "x11",
40 "F11",
41 "AF",
42 "0AF",
43 "0.0",
44 "13.",
45 "13,000",
46 "13.000",
47 "13/5",
48 "9999999999999999999999999999999999999999999999999999999999999999",
49 "Inf",
50 "NaN",
51 "null",
52 "dog",
53 };
54
55 for (const auto& input : kTests) {
56 int result = 0xDEAD;
57 ASSERT_FALSE(ParseNonNegativeDecimalInt(input, &result))
58 << "Succeeded to parse: " << input;
59 EXPECT_EQ(0xDEAD, result) << "Modified output for failed parsing";
60 }
61 }
62
63 TEST(ParseNumberTest, IntInvalidInputsContainsNul) {
64 int result = 0xDEAD;
65 ASSERT_FALSE(
66 ParseNonNegativeDecimalInt(base::StringPiece("123\0", 4), &result));
67 EXPECT_EQ(0xDEAD, result);
68 } 248 }
69 249
70 } // namespace 250 } // namespace
71 } // namespace net 251 } // namespace net
OLDNEW
« no previous file with comments | « net/base/parse_number.cc ('k') | net/base/sdch_manager.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698