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

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

Powered by Google App Engine
This is Rietveld 408576698