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