| OLD | NEW |
| 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 |
| OLD | NEW |