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

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: update interface only (didn't address other comments yet) 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
16 // increment a numeric string (flawed, but good enough for use case).
17 std::string IncrementLastChar(std::string value) {
18 value[value.size() - 1]++;
19 return value;
20 }
21
22 // Common tests to run for each of the overloaded versions of
23 // ParseIntegerBase10(). Most checks are the same, however there
24 // are differences based on the signedness of the output type T,
25 // and its range.
26 template <typename T>
27 void TestParseIntegerBase10() {
28 ParseInteger kPolicies[] = {ParseInteger::DISALLOW_NEGATIVE,
29 ParseInteger::ALLOW_NEGATIVE};
30
31 // Arbitrary constant, used to test if failure modifies the output parameter.
32 const T kFailResult = T(23614);
33
34 // ------------------------------------
35 // Valid (non-negative) inputs
36 // ------------------------------------
13 const struct { 37 const struct {
14 const char* input; 38 const char* input;
15 int output; 39 T output;
16 } kTests[] = { 40 } kValidTests[] = {
17 {"0", 0}, {"00000", 0}, {"003", 3}, {"003", 3}, {"1234566", 1234566}, 41 {"0", 0}, {"00000", 0}, {"003", 3}, {"003", 3}, {"1234566", 1234566},
18 {"987", 987}, {"010", 10}, 42 {"987", 987}, {"010", 10},
19 }; 43 };
20 44
21 for (const auto& test : kTests) { 45 for (const auto& policy : kPolicies) {
22 int result; 46 for (const auto& test : kValidTests) {
23 ASSERT_TRUE(ParseNonNegativeDecimalInt(test.input, &result)) 47 T result;
24 << "Failed to parse: " << test.input; 48
25 EXPECT_EQ(result, test.output) << "Failed to parse: " << test.input; 49 EXPECT_TRUE(ParseIntegerBase10(test.input, policy, &result, nullptr))
26 } 50 << "Failed to parse: " << test.input;
27 } 51
28 52 EXPECT_EQ(result, test.output) << "Failed to parse: " << test.input;
29 TEST(ParseNumberTest, IntInvalidInputs) { 53 }
30 const char* kTests[] = { 54 }
31 "", 55
32 "-23", 56 // ------------------------------------
33 "+42", 57 // Invalid inputs (regardless of sign policy)
34 " 123", 58 // ------------------------------------
35 "123 ", 59
36 "123\n", 60 const char* kInvalidParseTests[] = {
37 "0xFF", 61 "", "-", "--", "23-", "134-34", "- ", " ", "+42",
38 "0x11", 62 " 123", "123 ", "123\n", "0xFF", "-0xFF", "0x11", "-0x11", "x11",
39 "x11", 63 "-x11", "F11", "-F11", "AF", "-AF", "0AF", "0.0", "13.",
40 "F11", 64 "13,000", "13.000", "13/5", "Inf", "NaN", "null", "dog",
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 }; 65 };
54 66
55 for (const auto& input : kTests) { 67 for (const auto& policy : kPolicies) {
56 int result = 0xDEAD; 68 for (const auto& input : kInvalidParseTests) {
57 ASSERT_FALSE(ParseNonNegativeDecimalInt(input, &result)) 69 T result = kFailResult;
58 << "Succeeded to parse: " << input; 70
59 EXPECT_EQ(0xDEAD, result) << "Modified output for failed parsing"; 71 ParseIntegerError error;
60 } 72 EXPECT_FALSE(ParseIntegerBase10(input, policy, &result, &error));
61 } 73 EXPECT_EQ(ParseIntegerError::FAILED_PARSE, error)
62 74 << "Unexpected error parsing: " << input;
63 TEST(ParseNumberTest, IntInvalidInputsContainsNul) { 75
64 int result = 0xDEAD; 76 // On failure the output should not have been changed.
65 ASSERT_FALSE( 77 EXPECT_EQ(kFailResult, result) << "Modified output for failed parsing";
66 ParseNonNegativeDecimalInt(base::StringPiece("123\0", 4), &result)); 78 }
67 EXPECT_EQ(0xDEAD, result); 79 }
68 } 80
81 // ------------------------------------
82 // Valid negative inputs.
83 // ------------------------------------
84
85 const struct {
86 const char* input;
87 int output; // Using |int| rather than T because T may be unsigned.
88 } kValidNegativeTests[] = {
89 {"-0", 0}, {"-0001", -1}, {"-134", -134}, {"-4135", -4135},
90 };
91
92 for (const auto& policy : kPolicies) {
93 for (const auto& test : kValidNegativeTests) {
94 T result = kFailResult;
95 ParseIntegerError error;
96 bool success = ParseIntegerBase10(test.input, policy, &result, &error);
97
98 // The result depends on the sign policy, and the signedness of the
99 // output type.
100 if (policy == ParseInteger::DISALLOW_NEGATIVE) {
101 // If non-negative numbers were requested, should result in parse
102 // failure (even for "-0" which is in some sense non-negative).
103 EXPECT_FALSE(success);
104 EXPECT_EQ(ParseIntegerError::FAILED_PARSE, error);
105 EXPECT_EQ(kFailResult, result);
106 } else if (!std::numeric_limits<T>::is_signed) {
107 // If the output type was unsigned but the the input was negative,
108 // can't have succeeded.
109 // TODO(eroman): This applies even to "-0" even though it technically
110 // could have been parsed without "underflow". This is a consequence of
111 // how base::StringToIntXXX() works for unsigned types. Meh.
112 EXPECT_FALSE(success);
113 EXPECT_EQ(ParseIntegerError::FAILED_UNDERFLOW, error);
114 EXPECT_EQ(kFailResult, result);
115 } else {
116 // Otherwise success.
117 EXPECT_TRUE(success);
118 EXPECT_EQ(test.output, static_cast<int>(result));
119 }
120 }
121 }
122
123 // ------------------------------------
124 // Parse maximal value
125 // ------------------------------------
126
127 for (const auto& policy : kPolicies) {
128 const T value = std::numeric_limits<T>::max();
129 T result;
130 EXPECT_TRUE(
131 ParseIntegerBase10(std::to_string(value), policy, &result, nullptr));
132 EXPECT_EQ(value, result);
133 }
134
135 // ------------------------------------
136 // Parse one beyond maximal value (overflow)
137 // ------------------------------------
138
139 for (const auto& policy : kPolicies) {
140 const T value = std::numeric_limits<T>::max();
141 T result = kFailResult;
142 ParseIntegerError error;
143 EXPECT_FALSE(ParseIntegerBase10(IncrementLastChar(std::to_string(value)),
144 policy, &result, &error));
145 EXPECT_EQ(ParseIntegerError::FAILED_OVERFLOW, error);
146 EXPECT_EQ(kFailResult, result);
147 }
148
149 // ------------------------------------
150 // Parse maximal value with trailing whitespace
151 // ------------------------------------
152
153 // base::StringToIntXXX() has weird quirks dealing with whitespace. This
154 // exercises an incorrect way to detect overflow from base::StringToInt().
155
156 for (const auto& policy : kPolicies) {
157 const T value = std::numeric_limits<T>::max();
158 T result = kFailResult;
159 ParseIntegerError error;
160 EXPECT_FALSE(ParseIntegerBase10(std::to_string(value) + " ", policy,
161 &result, &error));
162 EXPECT_EQ(ParseIntegerError::FAILED_PARSE, error);
163 EXPECT_EQ(kFailResult, result);
164 }
165
166 // ------------------------------------
167 // Parse minimal value
168 // ------------------------------------
169
170 for (const auto& policy : kPolicies) {
171 const T value = std::numeric_limits<T>::min();
172 T result = kFailResult;
173 ParseIntegerError error;
174 auto success =
175 ParseIntegerBase10(std::to_string(value), policy, &result, &error);
176
177 if (std::numeric_limits<T>::is_signed &&
178 policy == ParseInteger::DISALLOW_NEGATIVE) {
179 EXPECT_FALSE(success);
180 EXPECT_EQ(ParseIntegerError::FAILED_PARSE, error);
181 EXPECT_EQ(kFailResult, result);
182 } else {
183 EXPECT_TRUE(success);
184 EXPECT_EQ(value, result);
185 }
186 }
187
188 // ------------------------------------
189 // Parse one less than minimal value
190 // ------------------------------------
191 {
192 std::string value_str;
193
194 if (std::numeric_limits<T>::is_signed) {
195 value_str =
196 IncrementLastChar(std::to_string(std::numeric_limits<T>::min()));
197 } else {
198 value_str = "-1";
199 }
200
201 T result = kFailResult;
202 ParseIntegerError error;
203 EXPECT_FALSE(ParseIntegerBase10(value_str, ParseInteger::ALLOW_NEGATIVE,
204 &result, &error));
205 EXPECT_EQ(ParseIntegerError::FAILED_UNDERFLOW, error);
206 EXPECT_EQ(kFailResult, result);
207 }
208
209 // ------------------------------------
210 // Parse a value containing embedded NUL
211 // ------------------------------------
212
213 for (const auto& policy : kPolicies) {
214 T result = kFailResult;
215 ParseIntegerError error;
216 ASSERT_FALSE(ParseIntegerBase10(base::StringPiece("123\0", 4), policy,
217 &result, &error));
218 EXPECT_EQ(kFailResult, result);
219 EXPECT_EQ(ParseIntegerError::FAILED_PARSE, error);
220 }
221 }
222
223 TEST(ParseNumberTest, ParseIntegerBase10Int32) {
224 TestParseIntegerBase10<int32_t>();
225 }
226
227 /*
228 * TODO(eroman):
229 TEST(ParseNumberTest, ParseIntegerBase10Uint32) {
230 TestParseIntegerBase10<uint32_t>();
231 }
232 */
233
234 TEST(ParseNumberTest, ParseIntegerBase10Int64) {
235 TestParseIntegerBase10<int64_t>();
236 }
237
238 /*
239 * TODO(eroman):
240 TEST(ParseNumberTest, ParseIntegerBase10Uint64) {
241 TestParseIntegerBase10<uint64_t>();
242 }
243 */
69 244
70 } // namespace 245 } // namespace
71 } // namespace net 246 } // namespace net
OLDNEW
« no previous file with comments | « net/base/parse_number.cc ('k') | net/base/sdch_manager.cc » ('j') | net/base/sdch_manager.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698