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