1*6777b538SAndroid Build Coastguard Worker // Copyright 2016 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "net/base/parse_number.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <limits>
8*6777b538SAndroid Build Coastguard Worker #include <sstream>
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h"
11*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
12*6777b538SAndroid Build Coastguard Worker
13*6777b538SAndroid Build Coastguard Worker namespace net {
14*6777b538SAndroid Build Coastguard Worker namespace {
15*6777b538SAndroid Build Coastguard Worker
16*6777b538SAndroid Build Coastguard Worker // Returns a decimal string that is one larger than the maximum value that type
17*6777b538SAndroid Build Coastguard Worker // T can represent.
18*6777b538SAndroid Build Coastguard Worker template <typename T>
CreateOverflowString()19*6777b538SAndroid Build Coastguard Worker std::string CreateOverflowString() {
20*6777b538SAndroid Build Coastguard Worker const T value = std::numeric_limits<T>::max();
21*6777b538SAndroid Build Coastguard Worker std::string result = base::NumberToString(value);
22*6777b538SAndroid Build Coastguard Worker EXPECT_NE('9', result.back());
23*6777b538SAndroid Build Coastguard Worker result.back()++;
24*6777b538SAndroid Build Coastguard Worker return result;
25*6777b538SAndroid Build Coastguard Worker }
26*6777b538SAndroid Build Coastguard Worker
27*6777b538SAndroid Build Coastguard Worker // Returns a decimal string that is one less than the minimum value that
28*6777b538SAndroid Build Coastguard Worker // (signed) type T can represent.
29*6777b538SAndroid Build Coastguard Worker template <typename T>
CreateUnderflowString()30*6777b538SAndroid Build Coastguard Worker std::string CreateUnderflowString() {
31*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(std::numeric_limits<T>::is_signed);
32*6777b538SAndroid Build Coastguard Worker const T value = std::numeric_limits<T>::min();
33*6777b538SAndroid Build Coastguard Worker std::string result = base::NumberToString(value);
34*6777b538SAndroid Build Coastguard Worker EXPECT_EQ('-', result.front());
35*6777b538SAndroid Build Coastguard Worker EXPECT_NE('9', result.back());
36*6777b538SAndroid Build Coastguard Worker result.back()++;
37*6777b538SAndroid Build Coastguard Worker return result;
38*6777b538SAndroid Build Coastguard Worker }
39*6777b538SAndroid Build Coastguard Worker
40*6777b538SAndroid Build Coastguard Worker // These are potentially valid inputs, along with whether they're non-negative
41*6777b538SAndroid Build Coastguard Worker // or "strict" (minimal representations).
42*6777b538SAndroid Build Coastguard Worker const struct {
43*6777b538SAndroid Build Coastguard Worker const char* input;
44*6777b538SAndroid Build Coastguard Worker int expected_output;
45*6777b538SAndroid Build Coastguard Worker bool is_non_negative;
46*6777b538SAndroid Build Coastguard Worker bool is_strict;
47*6777b538SAndroid Build Coastguard Worker } kAnnotatedTests[] = {
48*6777b538SAndroid Build Coastguard Worker {"0", 0, /*is_non_negative=*/true, /*is_strict=*/true},
49*6777b538SAndroid Build Coastguard Worker {"10", 10, /*is_non_negative=*/true, /*is_strict=*/true},
50*6777b538SAndroid Build Coastguard Worker {"1234566", 1234566, /*is_non_negative=*/true, /*is_strict=*/true},
51*6777b538SAndroid Build Coastguard Worker {"00", 0, /*is_non_negative=*/true, /*is_strict=*/false},
52*6777b538SAndroid Build Coastguard Worker {"010", 10, /*is_non_negative=*/true, /*is_strict=*/false},
53*6777b538SAndroid Build Coastguard Worker {"0010", 10, /*is_non_negative=*/true, /*is_strict=*/false},
54*6777b538SAndroid Build Coastguard Worker {"-10", -10, /*is_non_negative=*/false, /*is_strict=*/true},
55*6777b538SAndroid Build Coastguard Worker {"-1234566", -1234566, /*is_non_negative=*/false, /*is_strict=*/true},
56*6777b538SAndroid Build Coastguard Worker {"-0", 0, /*is_non_negative=*/false, /*is_strict=*/false},
57*6777b538SAndroid Build Coastguard Worker {"-00", 0, /*is_non_negative=*/false, /*is_strict=*/false},
58*6777b538SAndroid Build Coastguard Worker {"-010", -10, /*is_non_negative=*/false, /*is_strict=*/false},
59*6777b538SAndroid Build Coastguard Worker {"-0000000000000000000000000000000000001234566", -1234566,
60*6777b538SAndroid Build Coastguard Worker /*is_non_negative=*/false, /*is_strict=*/false},
61*6777b538SAndroid Build Coastguard Worker };
62*6777b538SAndroid Build Coastguard Worker
63*6777b538SAndroid Build Coastguard Worker // These are invalid inputs that can not be parsed regardless of the format
64*6777b538SAndroid Build Coastguard Worker // used (they are neither valid negative or non-negative values).
65*6777b538SAndroid Build Coastguard Worker const char* kInvalidParseTests[] = {
66*6777b538SAndroid Build Coastguard Worker "", "-", "--", "23-", "134-34", "- ", " ", "+42",
67*6777b538SAndroid Build Coastguard Worker " 123", "123 ", "123\n", "0xFF", "-0xFF", "0x11", "-0x11", "x11",
68*6777b538SAndroid Build Coastguard Worker "-x11", "F11", "-F11", "AF", "-AF", "0AF", "0.0", "13.",
69*6777b538SAndroid Build Coastguard Worker "13,000", "13.000", "13/5", "Inf", "NaN", "null", "dog",
70*6777b538SAndroid Build Coastguard Worker };
71*6777b538SAndroid Build Coastguard Worker
72*6777b538SAndroid Build Coastguard Worker // This wrapper calls func() and expects the result to match |expected_output|.
73*6777b538SAndroid Build Coastguard Worker template <typename OutputType, typename ParseFunc, typename ExpectationType>
ExpectParseIntSuccess(ParseFunc func,std::string_view input,ParseIntFormat format,ExpectationType expected_output)74*6777b538SAndroid Build Coastguard Worker void ExpectParseIntSuccess(ParseFunc func,
75*6777b538SAndroid Build Coastguard Worker std::string_view input,
76*6777b538SAndroid Build Coastguard Worker ParseIntFormat format,
77*6777b538SAndroid Build Coastguard Worker ExpectationType expected_output) {
78*6777b538SAndroid Build Coastguard Worker // Try parsing without specifying an error output - expecting success.
79*6777b538SAndroid Build Coastguard Worker OutputType parsed_number1;
80*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(func(input, format, &parsed_number1, nullptr))
81*6777b538SAndroid Build Coastguard Worker << "Failed to parse: " << input;
82*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<OutputType>(expected_output), parsed_number1);
83*6777b538SAndroid Build Coastguard Worker
84*6777b538SAndroid Build Coastguard Worker // Try parsing with an error output - expecting success.
85*6777b538SAndroid Build Coastguard Worker ParseIntError kBogusError = static_cast<ParseIntError>(19);
86*6777b538SAndroid Build Coastguard Worker ParseIntError error = kBogusError;
87*6777b538SAndroid Build Coastguard Worker OutputType parsed_number2;
88*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(func(input, format, &parsed_number2, &error))
89*6777b538SAndroid Build Coastguard Worker << "Failed to parse: " << input;
90*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<OutputType>(expected_output), parsed_number2);
91*6777b538SAndroid Build Coastguard Worker // Check that the error output was not written to.
92*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(kBogusError, error);
93*6777b538SAndroid Build Coastguard Worker }
94*6777b538SAndroid Build Coastguard Worker
95*6777b538SAndroid Build Coastguard Worker // This wrapper calls func() and expects the failure to match |expected_error|.
96*6777b538SAndroid Build Coastguard Worker template <typename OutputType, typename ParseFunc>
ExpectParseIntFailure(ParseFunc func,std::string_view input,ParseIntFormat format,ParseIntError expected_error)97*6777b538SAndroid Build Coastguard Worker void ExpectParseIntFailure(ParseFunc func,
98*6777b538SAndroid Build Coastguard Worker std::string_view input,
99*6777b538SAndroid Build Coastguard Worker ParseIntFormat format,
100*6777b538SAndroid Build Coastguard Worker ParseIntError expected_error) {
101*6777b538SAndroid Build Coastguard Worker const OutputType kBogusOutput(23614);
102*6777b538SAndroid Build Coastguard Worker
103*6777b538SAndroid Build Coastguard Worker // Try parsing without specifying an error output - expecting failure.
104*6777b538SAndroid Build Coastguard Worker OutputType parsed_number1 = kBogusOutput;
105*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(func(input, format, &parsed_number1, nullptr))
106*6777b538SAndroid Build Coastguard Worker << "Succeded parsing: " << input;
107*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(kBogusOutput, parsed_number1)
108*6777b538SAndroid Build Coastguard Worker << "Modified output when failed parsing";
109*6777b538SAndroid Build Coastguard Worker
110*6777b538SAndroid Build Coastguard Worker // Try parsing with an error output - expecting failure.
111*6777b538SAndroid Build Coastguard Worker OutputType parsed_number2 = kBogusOutput;
112*6777b538SAndroid Build Coastguard Worker ParseIntError error;
113*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(func(input, format, &parsed_number2, &error))
114*6777b538SAndroid Build Coastguard Worker << "Succeded parsing: " << input;
115*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(kBogusOutput, parsed_number2)
116*6777b538SAndroid Build Coastguard Worker << "Modified output when failed parsing";
117*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(expected_error, error);
118*6777b538SAndroid Build Coastguard Worker }
119*6777b538SAndroid Build Coastguard Worker
120*6777b538SAndroid Build Coastguard Worker // Common tests for both ParseInt*() and ParseUint*()
121*6777b538SAndroid Build Coastguard Worker //
122*6777b538SAndroid Build Coastguard Worker // When testing ParseUint*() the |format| parameter is not applicable and
123*6777b538SAndroid Build Coastguard Worker // should be passed as NON_NEGATIVE.
124*6777b538SAndroid Build Coastguard Worker template <typename T, typename ParseFunc>
TestParseIntUsingFormat(ParseFunc func,ParseIntFormat format)125*6777b538SAndroid Build Coastguard Worker void TestParseIntUsingFormat(ParseFunc func, ParseIntFormat format) {
126*6777b538SAndroid Build Coastguard Worker bool is_format_non_negative = format == ParseIntFormat::NON_NEGATIVE ||
127*6777b538SAndroid Build Coastguard Worker format == ParseIntFormat::STRICT_NON_NEGATIVE;
128*6777b538SAndroid Build Coastguard Worker bool is_format_strict = format == ParseIntFormat::STRICT_NON_NEGATIVE ||
129*6777b538SAndroid Build Coastguard Worker format == ParseIntFormat::STRICT_OPTIONALLY_NEGATIVE;
130*6777b538SAndroid Build Coastguard Worker // Test annotated inputs, some of which may not be valid inputs when parsed
131*6777b538SAndroid Build Coastguard Worker // using `format`.
132*6777b538SAndroid Build Coastguard Worker for (const auto& test : kAnnotatedTests) {
133*6777b538SAndroid Build Coastguard Worker SCOPED_TRACE(test.input);
134*6777b538SAndroid Build Coastguard Worker if ((test.is_non_negative || !is_format_non_negative) &&
135*6777b538SAndroid Build Coastguard Worker (test.is_strict || !is_format_strict)) {
136*6777b538SAndroid Build Coastguard Worker ExpectParseIntSuccess<T>(func, test.input, format, test.expected_output);
137*6777b538SAndroid Build Coastguard Worker } else {
138*6777b538SAndroid Build Coastguard Worker ExpectParseIntFailure<T>(func, test.input, format,
139*6777b538SAndroid Build Coastguard Worker ParseIntError::FAILED_PARSE);
140*6777b538SAndroid Build Coastguard Worker }
141*6777b538SAndroid Build Coastguard Worker }
142*6777b538SAndroid Build Coastguard Worker
143*6777b538SAndroid Build Coastguard Worker // Test invalid inputs (invalid regardless of parsing format)
144*6777b538SAndroid Build Coastguard Worker for (auto* input : kInvalidParseTests) {
145*6777b538SAndroid Build Coastguard Worker ExpectParseIntFailure<T>(func, input, format, ParseIntError::FAILED_PARSE);
146*6777b538SAndroid Build Coastguard Worker }
147*6777b538SAndroid Build Coastguard Worker
148*6777b538SAndroid Build Coastguard Worker // Test parsing the largest possible value for output type.
149*6777b538SAndroid Build Coastguard Worker {
150*6777b538SAndroid Build Coastguard Worker const T value = std::numeric_limits<T>::max();
151*6777b538SAndroid Build Coastguard Worker ExpectParseIntSuccess<T>(func, base::NumberToString(value), format, value);
152*6777b538SAndroid Build Coastguard Worker }
153*6777b538SAndroid Build Coastguard Worker
154*6777b538SAndroid Build Coastguard Worker // Test parsing a number one larger than the output type can accomodate
155*6777b538SAndroid Build Coastguard Worker // (overflow).
156*6777b538SAndroid Build Coastguard Worker ExpectParseIntFailure<T>(func, CreateOverflowString<T>(), format,
157*6777b538SAndroid Build Coastguard Worker ParseIntError::FAILED_OVERFLOW);
158*6777b538SAndroid Build Coastguard Worker
159*6777b538SAndroid Build Coastguard Worker // Test parsing a number at least as large as the output allows AND contains
160*6777b538SAndroid Build Coastguard Worker // garbage at the end. This exercises an interesting internal quirk of
161*6777b538SAndroid Build Coastguard Worker // base::StringToInt*(), in that its result cannot distinguish this case
162*6777b538SAndroid Build Coastguard Worker // from overflow.
163*6777b538SAndroid Build Coastguard Worker ExpectParseIntFailure<T>(
164*6777b538SAndroid Build Coastguard Worker func, base::NumberToString(std::numeric_limits<T>::max()) + " ", format,
165*6777b538SAndroid Build Coastguard Worker ParseIntError::FAILED_PARSE);
166*6777b538SAndroid Build Coastguard Worker
167*6777b538SAndroid Build Coastguard Worker ExpectParseIntFailure<T>(func, CreateOverflowString<T>() + " ", format,
168*6777b538SAndroid Build Coastguard Worker ParseIntError::FAILED_PARSE);
169*6777b538SAndroid Build Coastguard Worker
170*6777b538SAndroid Build Coastguard Worker // Test parsing the smallest possible value for output type. Don't do the
171*6777b538SAndroid Build Coastguard Worker // test for unsigned types since the smallest number 0 is tested elsewhere.
172*6777b538SAndroid Build Coastguard Worker if (std::numeric_limits<T>::is_signed) {
173*6777b538SAndroid Build Coastguard Worker const T value = std::numeric_limits<T>::min();
174*6777b538SAndroid Build Coastguard Worker std::string str_value = base::NumberToString(value);
175*6777b538SAndroid Build Coastguard Worker
176*6777b538SAndroid Build Coastguard Worker // The minimal value is necessarily negative, since this function is
177*6777b538SAndroid Build Coastguard Worker // testing only signed output types.
178*6777b538SAndroid Build Coastguard Worker if (is_format_non_negative) {
179*6777b538SAndroid Build Coastguard Worker ExpectParseIntFailure<T>(func, str_value, format,
180*6777b538SAndroid Build Coastguard Worker ParseIntError::FAILED_PARSE);
181*6777b538SAndroid Build Coastguard Worker } else {
182*6777b538SAndroid Build Coastguard Worker ExpectParseIntSuccess<T>(func, str_value, format, value);
183*6777b538SAndroid Build Coastguard Worker }
184*6777b538SAndroid Build Coastguard Worker }
185*6777b538SAndroid Build Coastguard Worker
186*6777b538SAndroid Build Coastguard Worker // Test parsing a number one less than the output type can accomodate
187*6777b538SAndroid Build Coastguard Worker // (underflow).
188*6777b538SAndroid Build Coastguard Worker if (!is_format_non_negative) {
189*6777b538SAndroid Build Coastguard Worker ExpectParseIntFailure<T>(func, CreateUnderflowString<T>(), format,
190*6777b538SAndroid Build Coastguard Worker ParseIntError::FAILED_UNDERFLOW);
191*6777b538SAndroid Build Coastguard Worker }
192*6777b538SAndroid Build Coastguard Worker
193*6777b538SAndroid Build Coastguard Worker // Test parsing a string that contains a valid number followed by a NUL
194*6777b538SAndroid Build Coastguard Worker // character.
195*6777b538SAndroid Build Coastguard Worker ExpectParseIntFailure<T>(func, std::string_view("123\0", 4), format,
196*6777b538SAndroid Build Coastguard Worker ParseIntError::FAILED_PARSE);
197*6777b538SAndroid Build Coastguard Worker }
198*6777b538SAndroid Build Coastguard Worker
199*6777b538SAndroid Build Coastguard Worker // Common tests to run for each of the versions of ParseInt*().
200*6777b538SAndroid Build Coastguard Worker //
201*6777b538SAndroid Build Coastguard Worker // The `func` parameter should be a function pointer to the particular
202*6777b538SAndroid Build Coastguard Worker // ParseInt*() function to test.
203*6777b538SAndroid Build Coastguard Worker template <typename T, typename ParseFunc>
TestParseInt(ParseFunc func)204*6777b538SAndroid Build Coastguard Worker void TestParseInt(ParseFunc func) {
205*6777b538SAndroid Build Coastguard Worker // Test using each of the possible formats.
206*6777b538SAndroid Build Coastguard Worker ParseIntFormat kFormats[] = {ParseIntFormat::NON_NEGATIVE,
207*6777b538SAndroid Build Coastguard Worker ParseIntFormat::OPTIONALLY_NEGATIVE,
208*6777b538SAndroid Build Coastguard Worker ParseIntFormat::STRICT_NON_NEGATIVE,
209*6777b538SAndroid Build Coastguard Worker ParseIntFormat::STRICT_OPTIONALLY_NEGATIVE};
210*6777b538SAndroid Build Coastguard Worker
211*6777b538SAndroid Build Coastguard Worker for (const auto& format : kFormats) {
212*6777b538SAndroid Build Coastguard Worker TestParseIntUsingFormat<T>(func, format);
213*6777b538SAndroid Build Coastguard Worker }
214*6777b538SAndroid Build Coastguard Worker }
215*6777b538SAndroid Build Coastguard Worker
216*6777b538SAndroid Build Coastguard Worker // Common tests to run for each of the versions of ParseUint*().
217*6777b538SAndroid Build Coastguard Worker //
218*6777b538SAndroid Build Coastguard Worker // The `func` parameter should be a function pointer to the particular
219*6777b538SAndroid Build Coastguard Worker // ParseUint*() function to test.
220*6777b538SAndroid Build Coastguard Worker template <typename T, typename ParseFunc>
TestParseUint(ParseFunc func)221*6777b538SAndroid Build Coastguard Worker void TestParseUint(ParseFunc func) {
222*6777b538SAndroid Build Coastguard Worker // Test using each of the possible formats.
223*6777b538SAndroid Build Coastguard Worker ParseIntFormat kFormats[] = {
224*6777b538SAndroid Build Coastguard Worker ParseIntFormat::NON_NEGATIVE,
225*6777b538SAndroid Build Coastguard Worker ParseIntFormat::STRICT_NON_NEGATIVE,
226*6777b538SAndroid Build Coastguard Worker };
227*6777b538SAndroid Build Coastguard Worker
228*6777b538SAndroid Build Coastguard Worker for (const auto& format : kFormats) {
229*6777b538SAndroid Build Coastguard Worker TestParseIntUsingFormat<T>(func, format);
230*6777b538SAndroid Build Coastguard Worker }
231*6777b538SAndroid Build Coastguard Worker }
232*6777b538SAndroid Build Coastguard Worker
TEST(ParseNumberTest,ParseInt32)233*6777b538SAndroid Build Coastguard Worker TEST(ParseNumberTest, ParseInt32) {
234*6777b538SAndroid Build Coastguard Worker TestParseInt<int32_t>(ParseInt32);
235*6777b538SAndroid Build Coastguard Worker }
236*6777b538SAndroid Build Coastguard Worker
TEST(ParseNumberTest,ParseInt64)237*6777b538SAndroid Build Coastguard Worker TEST(ParseNumberTest, ParseInt64) {
238*6777b538SAndroid Build Coastguard Worker TestParseInt<int64_t>(ParseInt64);
239*6777b538SAndroid Build Coastguard Worker }
240*6777b538SAndroid Build Coastguard Worker
TEST(ParseNumberTest,ParseUint32)241*6777b538SAndroid Build Coastguard Worker TEST(ParseNumberTest, ParseUint32) {
242*6777b538SAndroid Build Coastguard Worker TestParseUint<uint32_t>(ParseUint32);
243*6777b538SAndroid Build Coastguard Worker }
244*6777b538SAndroid Build Coastguard Worker
TEST(ParseNumberTest,ParseUint64)245*6777b538SAndroid Build Coastguard Worker TEST(ParseNumberTest, ParseUint64) {
246*6777b538SAndroid Build Coastguard Worker TestParseUint<uint64_t>(ParseUint64);
247*6777b538SAndroid Build Coastguard Worker }
248*6777b538SAndroid Build Coastguard Worker
249*6777b538SAndroid Build Coastguard Worker } // namespace
250*6777b538SAndroid Build Coastguard Worker } // namespace net
251