| Index: net/base/parse_number_unittest.cc
|
| diff --git a/net/base/parse_number_unittest.cc b/net/base/parse_number_unittest.cc
|
| index 79cac9f43ba211b26aa8d58d1c943154b387f911..270b7bf7e967aa93386bf3c3e2ce4f6e970c8a16 100644
|
| --- a/net/base/parse_number_unittest.cc
|
| +++ b/net/base/parse_number_unittest.cc
|
| @@ -4,67 +4,315 @@
|
|
|
| #include "net/base/parse_number.h"
|
|
|
| +#include <limits>
|
| +
|
| +#include "base/strings/string_number_conversions.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| namespace net {
|
| namespace {
|
|
|
| -TEST(ParseNumberTest, IntValidInputs) {
|
| - const struct {
|
| - const char* input;
|
| - int output;
|
| - } kTests[] = {
|
| - {"0", 0}, {"00000", 0}, {"003", 3}, {"003", 3}, {"1234566", 1234566},
|
| - {"987", 987}, {"010", 10},
|
| - };
|
| -
|
| - for (const auto& test : kTests) {
|
| - int result;
|
| - ASSERT_TRUE(ParseNonNegativeDecimalInt(test.input, &result))
|
| - << "Failed to parse: " << test.input;
|
| - EXPECT_EQ(result, test.output) << "Failed to parse: " << test.input;
|
| +// Increments the final character in a string by 1. Used as a simplistic way to
|
| +// increment a numeric string (flawed, but good enough for use case).
|
| +std::string IncrementLastChar(std::string value) {
|
| + value[value.size() - 1]++;
|
| + return value;
|
| +}
|
| +
|
| +// These are valid inputs representing non-negative integers. Note that these
|
| +// test inputs are re-used when constructing negative test cases, by simply
|
| +// prepending a '-'.
|
| +const struct {
|
| + const char* input;
|
| + int expected_output;
|
| +} kValidNonNegativeTests[] = {
|
| + {"0", 0}, {"00000", 0}, {"003", 3}, {"003", 3}, {"1234566", 1234566},
|
| + {"987", 987}, {"010", 10},
|
| +};
|
| +
|
| +// These are invalid inputs that can not be parsed regardless of the policy
|
| +// used (they are neither valid negative or non-negative values).
|
| +const char* kInvalidParseTests[] = {
|
| + "", "-", "--", "23-", "134-34", "- ", " ", "+42",
|
| + " 123", "123 ", "123\n", "0xFF", "-0xFF", "0x11", "-0x11", "x11",
|
| + "-x11", "F11", "-F11", "AF", "-AF", "0AF", "0.0", "13.",
|
| + "13,000", "13.000", "13/5", "Inf", "NaN", "null", "dog",
|
| +};
|
| +
|
| +// This wrapper calls ParseIntegerBase10() and expects the result to match
|
| +// |expected_output|.
|
| +template <typename OutputType, typename ExpectationType>
|
| +void ExpectParseIntegerBase10Success(const base::StringPiece& input,
|
| + ParseInteger policy,
|
| + ExpectationType expected_output) {
|
| + // Try parsing without specifying an error output - expecting success.
|
| + OutputType parsed_number1;
|
| + EXPECT_TRUE(ParseIntegerBase10(input, policy, &parsed_number1))
|
| + << "Failed to parse: " << input;
|
| + EXPECT_EQ(static_cast<OutputType>(expected_output), parsed_number1);
|
| +
|
| + // Try parsing with an error output - expecting success.
|
| + ParseIntegerError kBogusError = static_cast<ParseIntegerError>(19);
|
| + ParseIntegerError error = kBogusError;
|
| + OutputType parsed_number2;
|
| + EXPECT_TRUE(ParseIntegerBase10(input, policy, &parsed_number2, &error))
|
| + << "Failed to parse: " << input;
|
| + EXPECT_EQ(static_cast<OutputType>(expected_output), parsed_number2);
|
| + // Check that the error output was not written to.
|
| + EXPECT_EQ(kBogusError, error);
|
| +}
|
| +
|
| +// This wrapper calls ParseIntegerBase10() and expects the failure to match
|
| +// |expected_error|.
|
| +template <typename OutputType>
|
| +void ExpectParseIntegerBase10Failure(const base::StringPiece& input,
|
| + ParseInteger policy,
|
| + ParseIntegerError expected_error) {
|
| + const OutputType kBogusOutput = OutputType(23614);
|
| +
|
| + // Try parsing without specifying an error output - expecting failure.
|
| + OutputType parsed_number1 = kBogusOutput;
|
| + EXPECT_FALSE(ParseIntegerBase10(input, policy, &parsed_number1))
|
| + << "Succeded parsing: " << input;
|
| + EXPECT_EQ(kBogusOutput, parsed_number1)
|
| + << "Modified output when failed parsing";
|
| +
|
| + // Try parsing with an error output - expecting failure.
|
| + OutputType parsed_number2 = kBogusOutput;
|
| + ParseIntegerError error;
|
| + EXPECT_FALSE(ParseIntegerBase10(input, policy, &parsed_number2, &error))
|
| + << "Succeded parsing: " << input;
|
| + EXPECT_EQ(kBogusOutput, parsed_number2)
|
| + << "Modified output when failed parsing";
|
| + EXPECT_EQ(expected_error, error);
|
| +}
|
| +
|
| +// Common tests to run for each of the overloaded versions of
|
| +// ParseIntegerBase10().
|
| +template <typename T>
|
| +void TestParseIntegerBase10() {
|
| + ParseInteger kPolicies[] = {ParseInteger::DISALLOW_NEGATIVE,
|
| + ParseInteger::ALLOW_NEGATIVE};
|
| +
|
| + // Test valid non-negative inputs
|
| +
|
| + for (const auto& policy : kPolicies) {
|
| + for (const auto& test : kValidNonNegativeTests) {
|
| + ExpectParseIntegerBase10Success<T>(test.input, policy,
|
| + test.expected_output);
|
| + }
|
| + }
|
| +
|
| + // Test invalid inputs (invalid regardless of parsing policy)
|
| +
|
| + for (const auto& policy : kPolicies) {
|
| + for (const auto& input : kInvalidParseTests) {
|
| + ExpectParseIntegerBase10Failure<T>(input, policy,
|
| + ParseIntegerError::FAILED_PARSE);
|
| + }
|
| + }
|
| +
|
| + // Test valid negative inputs (constructed from the valid non-negative test
|
| + // cases).
|
| +
|
| + for (const auto& policy : kPolicies) {
|
| + for (const auto& test : kValidNonNegativeTests) {
|
| + std::string negative_input = std::string("-") + test.input;
|
| + int expected_negative_output = -test.expected_output;
|
| +
|
| + // The result depends on the policy.
|
| + if (policy == ParseInteger::DISALLOW_NEGATIVE) {
|
| + ExpectParseIntegerBase10Failure<T>(negative_input, policy,
|
| + ParseIntegerError::FAILED_PARSE);
|
| + } else {
|
| + ExpectParseIntegerBase10Success<T>(negative_input, policy,
|
| + expected_negative_output);
|
| + }
|
| + }
|
| + }
|
| +
|
| + // Test parsing the largest possible value for output type.
|
| +
|
| + for (const auto& policy : kPolicies) {
|
| + const T value = std::numeric_limits<T>::max();
|
| + ExpectParseIntegerBase10Success<T>(std::to_string(value), policy, value);
|
| + }
|
| +
|
| + // Test parsing a number one larger than the output type can accomodate
|
| + // (overflow).
|
| +
|
| + for (const auto& policy : kPolicies) {
|
| + const T value = std::numeric_limits<T>::max();
|
| + ExpectParseIntegerBase10Failure<T>(IncrementLastChar(std::to_string(value)),
|
| + policy,
|
| + ParseIntegerError::FAILED_OVERFLOW);
|
| + }
|
| +
|
| + // Test parsing a number at least as large as the output allows AND contains
|
| + // garbage at the end. This exercises an interesting internal quirk of
|
| + // base::StringToInt*(), in that its result cannot distinguish this case
|
| + // from overflow.
|
| +
|
| + for (const auto& policy : kPolicies) {
|
| + const T value = std::numeric_limits<T>::max();
|
| + ExpectParseIntegerBase10Failure<T>(std::to_string(value) + " ", policy,
|
| + ParseIntegerError::FAILED_PARSE);
|
| + }
|
| +
|
| + // Test parsing the smallest possible value for output type.
|
| +
|
| + for (const auto& policy : kPolicies) {
|
| + const T value = std::numeric_limits<T>::min();
|
| + auto str_value = std::to_string(value);
|
| +
|
| + // The minimal value is necessarily negative, since this function is testing
|
| + // only signed output types.
|
| + if (policy == ParseInteger::DISALLOW_NEGATIVE) {
|
| + ExpectParseIntegerBase10Failure<T>(str_value, policy,
|
| + ParseIntegerError::FAILED_PARSE);
|
| + } else {
|
| + ExpectParseIntegerBase10Success<T>(str_value, policy, value);
|
| + }
|
| + }
|
| +
|
| + // Test parsing a number one less than the output type can accomodate
|
| + // (underflow).
|
| +
|
| + {
|
| + std::string str_value =
|
| + IncrementLastChar(std::to_string(std::numeric_limits<T>::min()));
|
| +
|
| + ExpectParseIntegerBase10Failure<T>(str_value, ParseInteger::ALLOW_NEGATIVE,
|
| + ParseIntegerError::FAILED_UNDERFLOW);
|
| + }
|
| +
|
| + // Test parsing a string that contains a valid number followed by a NUL
|
| + // character.
|
| +
|
| + for (const auto& policy : kPolicies) {
|
| + ExpectParseIntegerBase10Failure<T>(base::StringPiece("123\0", 4), policy,
|
| + ParseIntegerError::FAILED_PARSE);
|
| }
|
| }
|
|
|
| -TEST(ParseNumberTest, IntInvalidInputs) {
|
| - const char* kTests[] = {
|
| - "",
|
| - "-23",
|
| - "+42",
|
| - " 123",
|
| - "123 ",
|
| - "123\n",
|
| - "0xFF",
|
| - "0x11",
|
| - "x11",
|
| - "F11",
|
| - "AF",
|
| - "0AF",
|
| - "0.0",
|
| - "13.",
|
| - "13,000",
|
| - "13.000",
|
| - "13/5",
|
| - "9999999999999999999999999999999999999999999999999999999999999999",
|
| - "Inf",
|
| - "NaN",
|
| - "null",
|
| - "dog",
|
| - };
|
| -
|
| - for (const auto& input : kTests) {
|
| - int result = 0xDEAD;
|
| - ASSERT_FALSE(ParseNonNegativeDecimalInt(input, &result))
|
| - << "Succeeded to parse: " << input;
|
| - EXPECT_EQ(0xDEAD, result) << "Modified output for failed parsing";
|
| +// This wrapper calls ParseUnsignedIntegerBase10() and expects the result to
|
| +// match |expected_output|.
|
| +template <typename OutputType, typename ExpectationType>
|
| +void ExpectParseUnsignedIntegerBase10Success(const base::StringPiece& input,
|
| + ExpectationType expected_output) {
|
| + // Try parsing without specifying an error output - expecting success.
|
| + OutputType parsed_number1;
|
| + EXPECT_TRUE(ParseUnsignedIntegerBase10(input, &parsed_number1))
|
| + << "Failed to parse: " << input;
|
| + EXPECT_EQ(static_cast<OutputType>(expected_output), parsed_number1);
|
| +
|
| + // Try parsing with an error output - expecting success.
|
| + ParseIntegerError kBogusError = static_cast<ParseIntegerError>(19);
|
| + ParseIntegerError error = kBogusError;
|
| + OutputType parsed_number2;
|
| + EXPECT_TRUE(ParseUnsignedIntegerBase10(input, &parsed_number2, &error))
|
| + << "Failed to parse: " << input;
|
| + EXPECT_EQ(static_cast<OutputType>(expected_output), parsed_number2);
|
| + // Check that the error output was not written to.
|
| + EXPECT_EQ(kBogusError, error);
|
| +}
|
| +
|
| +// This wrapper calls ParseUnsignedIntegerBase10() and expects the failure to
|
| +// match |expected_error|.
|
| +template <typename OutputType>
|
| +void ExpectParseUnsignedIntegerBase10Failure(const base::StringPiece& input,
|
| + ParseIntegerError expected_error) {
|
| + const OutputType kBogusOutput = OutputType(23614);
|
| +
|
| + // Try parsing without specifying an error output - expecting failure.
|
| + OutputType parsed_number1 = kBogusOutput;
|
| + EXPECT_FALSE(ParseUnsignedIntegerBase10(input, &parsed_number1))
|
| + << "Succeded parsing: " << input;
|
| + EXPECT_EQ(kBogusOutput, parsed_number1)
|
| + << "Modified output when failed parsing";
|
| +
|
| + // Try parsing with an error output - expecting failure.
|
| + OutputType parsed_number2 = kBogusOutput;
|
| + ParseIntegerError error;
|
| + EXPECT_FALSE(ParseUnsignedIntegerBase10(input, &parsed_number2, &error))
|
| + << "Succeded parsing: " << input;
|
| + EXPECT_EQ(kBogusOutput, parsed_number2)
|
| + << "Modified output when failed parsing";
|
| + EXPECT_EQ(expected_error, error);
|
| +}
|
| +
|
| +// Common tests to run for each of the overloaded versions of
|
| +// ParseUnsignedIntegerBase10().
|
| +template <typename T>
|
| +void TestParseUnsignedIntegerBase10() {
|
| + // Test valid non-negative inputs
|
| + for (const auto& test : kValidNonNegativeTests) {
|
| + ExpectParseUnsignedIntegerBase10Success<T>(test.input,
|
| + test.expected_output);
|
| + }
|
| +
|
| + // Test invalid inputs (invalid regardless of parsing policy)
|
| + for (const auto& input : kInvalidParseTests) {
|
| + ExpectParseUnsignedIntegerBase10Failure<T>(input,
|
| + ParseIntegerError::FAILED_PARSE);
|
| }
|
| +
|
| + // Test valid negative inputs (constructed from the valid non-negative test
|
| + // cases).
|
| + for (const auto& test : kValidNonNegativeTests) {
|
| + std::string negative_input = std::string("-") + test.input;
|
| +
|
| + // The result depends on the policy.
|
| + ExpectParseUnsignedIntegerBase10Failure<T>(negative_input,
|
| + ParseIntegerError::FAILED_PARSE);
|
| + }
|
| +
|
| + // Test parsing the largest possible value for output type.
|
| + {
|
| + const T value = std::numeric_limits<T>::max();
|
| + ExpectParseUnsignedIntegerBase10Success<T>(std::to_string(value), value);
|
| + }
|
| +
|
| + // Test parsing a number one larger than the output type can accomodate
|
| + // (overflow).
|
| + {
|
| + const T value = std::numeric_limits<T>::max();
|
| + ExpectParseUnsignedIntegerBase10Failure<T>(
|
| + IncrementLastChar(std::to_string(value)),
|
| + ParseIntegerError::FAILED_OVERFLOW);
|
| + }
|
| +
|
| + // Test parsing a number at least as large as the output allows AND contains
|
| + // garbage at the end. This exercises an interesting internal quirk of
|
| + // base::StringToInt*(), in that its result cannot distinguish this case
|
| + // from overflow.
|
| +
|
| + {
|
| + const T value = std::numeric_limits<T>::max();
|
| + ExpectParseUnsignedIntegerBase10Failure<T>(std::to_string(value) + " ",
|
| + ParseIntegerError::FAILED_PARSE);
|
| + }
|
| +
|
| + // Test parsing a string that contains a valid number followed by a NUL
|
| + // character.
|
| + ExpectParseUnsignedIntegerBase10Failure<T>(base::StringPiece("123\0", 4),
|
| + ParseIntegerError::FAILED_PARSE);
|
| +}
|
| +
|
| +TEST(ParseNumberTest, ParseIntegerBase10Int32) {
|
| + TestParseIntegerBase10<int32_t>();
|
| +}
|
| +
|
| +TEST(ParseNumberTest, ParseIntegerBase10Int64) {
|
| + TestParseIntegerBase10<int64_t>();
|
| +}
|
| +
|
| +TEST(ParseNumberTest, ParseUnsignedIntegerBase10Uint32) {
|
| + TestParseUnsignedIntegerBase10<uint32_t>();
|
| }
|
|
|
| -TEST(ParseNumberTest, IntInvalidInputsContainsNul) {
|
| - int result = 0xDEAD;
|
| - ASSERT_FALSE(
|
| - ParseNonNegativeDecimalInt(base::StringPiece("123\0", 4), &result));
|
| - EXPECT_EQ(0xDEAD, result);
|
| +TEST(ParseNumberTest, ParseUnsignedIntegerBase10Uint64) {
|
| + TestParseUnsignedIntegerBase10<uint64_t>();
|
| }
|
|
|
| } // namespace
|
|
|