SPIRV-Tools/test/parse_number_test.cpp

971 lines
39 KiB
C++
Raw Normal View History

Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
// Copyright (c) 2015-2016 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <limits>
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
#include <string>
#include <vector>
#include "gmock/gmock.h"
#include "source/util/parse_number.h"
#include "spirv-tools/libspirv.h"
namespace spvtools {
namespace utils {
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
namespace {
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
using testing::Eq;
using testing::IsNull;
using testing::NotNull;
TEST(ParseNarrowSignedIntegers, Sample) {
int16_t i16;
EXPECT_FALSE(ParseNumber(nullptr, &i16));
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
EXPECT_FALSE(ParseNumber("", &i16));
EXPECT_FALSE(ParseNumber("0=", &i16));
EXPECT_TRUE(ParseNumber("0", &i16));
EXPECT_EQ(0, i16);
EXPECT_TRUE(ParseNumber("32767", &i16));
EXPECT_EQ(32767, i16);
EXPECT_TRUE(ParseNumber("-32768", &i16));
EXPECT_EQ(-32768, i16);
EXPECT_TRUE(ParseNumber("-0", &i16));
EXPECT_EQ(0, i16);
// These are out of range, so they should return an error.
// The error code depends on whether this is an optional value.
EXPECT_FALSE(ParseNumber("32768", &i16));
EXPECT_FALSE(ParseNumber("65535", &i16));
// Check hex parsing.
EXPECT_TRUE(ParseNumber("0x7fff", &i16));
EXPECT_EQ(32767, i16);
// This is out of range.
EXPECT_FALSE(ParseNumber("0xffff", &i16));
}
TEST(ParseNarrowUnsignedIntegers, Sample) {
uint16_t u16;
EXPECT_FALSE(ParseNumber(nullptr, &u16));
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
EXPECT_FALSE(ParseNumber("", &u16));
EXPECT_FALSE(ParseNumber("0=", &u16));
EXPECT_TRUE(ParseNumber("0", &u16));
EXPECT_EQ(0, u16);
EXPECT_TRUE(ParseNumber("65535", &u16));
EXPECT_EQ(65535, u16);
EXPECT_FALSE(ParseNumber("65536", &u16));
// We don't care about -0 since it's rejected at a higher level.
EXPECT_FALSE(ParseNumber("-1", &u16));
EXPECT_TRUE(ParseNumber("0xffff", &u16));
EXPECT_EQ(0xffff, u16);
EXPECT_FALSE(ParseNumber("0x10000", &u16));
}
TEST(ParseSignedIntegers, Sample) {
int32_t i32;
// Invalid parse.
EXPECT_FALSE(ParseNumber(nullptr, &i32));
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
EXPECT_FALSE(ParseNumber("", &i32));
EXPECT_FALSE(ParseNumber("0=", &i32));
// Decimal values.
EXPECT_TRUE(ParseNumber("0", &i32));
EXPECT_EQ(0, i32);
EXPECT_TRUE(ParseNumber("2147483647", &i32));
EXPECT_EQ(std::numeric_limits<int32_t>::max(), i32);
EXPECT_FALSE(ParseNumber("2147483648", &i32));
EXPECT_TRUE(ParseNumber("-0", &i32));
EXPECT_EQ(0, i32);
EXPECT_TRUE(ParseNumber("-1", &i32));
EXPECT_EQ(-1, i32);
EXPECT_TRUE(ParseNumber("-2147483648", &i32));
EXPECT_EQ(std::numeric_limits<int32_t>::min(), i32);
// Hex values.
EXPECT_TRUE(ParseNumber("0x7fffffff", &i32));
EXPECT_EQ(std::numeric_limits<int32_t>::max(), i32);
EXPECT_FALSE(ParseNumber("0x80000000", &i32));
EXPECT_TRUE(ParseNumber("-0x000", &i32));
EXPECT_EQ(0, i32);
EXPECT_TRUE(ParseNumber("-0x001", &i32));
EXPECT_EQ(-1, i32);
EXPECT_TRUE(ParseNumber("-0x80000000", &i32));
EXPECT_EQ(std::numeric_limits<int32_t>::min(), i32);
}
TEST(ParseUnsignedIntegers, Sample) {
uint32_t u32;
// Invalid parse.
EXPECT_FALSE(ParseNumber(nullptr, &u32));
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
EXPECT_FALSE(ParseNumber("", &u32));
EXPECT_FALSE(ParseNumber("0=", &u32));
// Valid values.
EXPECT_TRUE(ParseNumber("0", &u32));
EXPECT_EQ(0u, u32);
EXPECT_TRUE(ParseNumber("4294967295", &u32));
EXPECT_EQ(std::numeric_limits<uint32_t>::max(), u32);
EXPECT_FALSE(ParseNumber("4294967296", &u32));
// Hex values.
EXPECT_TRUE(ParseNumber("0xffffffff", &u32));
EXPECT_EQ(std::numeric_limits<uint32_t>::max(), u32);
// We don't care about -0 since it's rejected at a higher level.
EXPECT_FALSE(ParseNumber("-1", &u32));
}
TEST(ParseWideSignedIntegers, Sample) {
int64_t i64;
EXPECT_FALSE(ParseNumber(nullptr, &i64));
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
EXPECT_FALSE(ParseNumber("", &i64));
EXPECT_FALSE(ParseNumber("0=", &i64));
EXPECT_TRUE(ParseNumber("0", &i64));
EXPECT_EQ(0, i64);
EXPECT_TRUE(ParseNumber("0x7fffffffffffffff", &i64));
EXPECT_EQ(0x7fffffffffffffff, i64);
EXPECT_TRUE(ParseNumber("-0", &i64));
EXPECT_EQ(0, i64);
EXPECT_TRUE(ParseNumber("-1", &i64));
EXPECT_EQ(-1, i64);
}
TEST(ParseWideUnsignedIntegers, Sample) {
uint64_t u64;
EXPECT_FALSE(ParseNumber(nullptr, &u64));
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
EXPECT_FALSE(ParseNumber("", &u64));
EXPECT_FALSE(ParseNumber("0=", &u64));
EXPECT_TRUE(ParseNumber("0", &u64));
EXPECT_EQ(0u, u64);
EXPECT_TRUE(ParseNumber("0xffffffffffffffff", &u64));
EXPECT_EQ(0xffffffffffffffffULL, u64);
// We don't care about -0 since it's rejected at a higher level.
EXPECT_FALSE(ParseNumber("-1", &u64));
}
TEST(ParseFloat, Sample) {
float f;
EXPECT_FALSE(ParseNumber(nullptr, &f));
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
EXPECT_FALSE(ParseNumber("", &f));
EXPECT_FALSE(ParseNumber("0=", &f));
// These values are exactly representatble.
EXPECT_TRUE(ParseNumber("0", &f));
EXPECT_EQ(0.0f, f);
EXPECT_TRUE(ParseNumber("42", &f));
EXPECT_EQ(42.0f, f);
EXPECT_TRUE(ParseNumber("2.5", &f));
EXPECT_EQ(2.5f, f);
EXPECT_TRUE(ParseNumber("-32.5", &f));
EXPECT_EQ(-32.5f, f);
EXPECT_TRUE(ParseNumber("1e38", &f));
EXPECT_EQ(1e38f, f);
EXPECT_TRUE(ParseNumber("-1e38", &f));
EXPECT_EQ(-1e38f, f);
}
TEST(ParseFloat, Overflow) {
// The assembler parses using HexFloat<FloatProxy<float>>. Make
// sure that succeeds for in-range values, and fails for out of
// range values. When it does overflow, the value is set to the
// nearest finite value, matching C++11 behavior for operator>>
// on floating point.
HexFloat<FloatProxy<float>> f(0.0f);
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
EXPECT_TRUE(ParseNumber("1e38", &f));
EXPECT_EQ(1e38f, f.value().getAsFloat());
EXPECT_TRUE(ParseNumber("-1e38", &f));
EXPECT_EQ(-1e38f, f.value().getAsFloat());
EXPECT_FALSE(ParseNumber("1e40", &f));
EXPECT_FALSE(ParseNumber("-1e40", &f));
EXPECT_FALSE(ParseNumber("1e400", &f));
EXPECT_FALSE(ParseNumber("-1e400", &f));
}
TEST(ParseDouble, Sample) {
double f;
EXPECT_FALSE(ParseNumber(nullptr, &f));
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
EXPECT_FALSE(ParseNumber("", &f));
EXPECT_FALSE(ParseNumber("0=", &f));
// These values are exactly representatble.
EXPECT_TRUE(ParseNumber("0", &f));
EXPECT_EQ(0.0, f);
EXPECT_TRUE(ParseNumber("42", &f));
EXPECT_EQ(42.0, f);
EXPECT_TRUE(ParseNumber("2.5", &f));
EXPECT_EQ(2.5, f);
EXPECT_TRUE(ParseNumber("-32.5", &f));
EXPECT_EQ(-32.5, f);
EXPECT_TRUE(ParseNumber("1e38", &f));
EXPECT_EQ(1e38, f);
EXPECT_TRUE(ParseNumber("-1e38", &f));
EXPECT_EQ(-1e38, f);
// These are out of range for 32-bit float, but in range for 64-bit float.
EXPECT_TRUE(ParseNumber("1e40", &f));
EXPECT_EQ(1e40, f);
EXPECT_TRUE(ParseNumber("-1e40", &f));
EXPECT_EQ(-1e40, f);
}
TEST(ParseDouble, Overflow) {
// The assembler parses using HexFloat<FloatProxy<double>>. Make
// sure that succeeds for in-range values, and fails for out of
// range values. When it does overflow, the value is set to the
// nearest finite value, matching C++11 behavior for operator>>
// on floating point.
HexFloat<FloatProxy<double>> f(0.0);
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
EXPECT_TRUE(ParseNumber("1e38", &f));
EXPECT_EQ(1e38, f.value().getAsFloat());
EXPECT_TRUE(ParseNumber("-1e38", &f));
EXPECT_EQ(-1e38, f.value().getAsFloat());
EXPECT_TRUE(ParseNumber("1e40", &f));
EXPECT_EQ(1e40, f.value().getAsFloat());
EXPECT_TRUE(ParseNumber("-1e40", &f));
EXPECT_EQ(-1e40, f.value().getAsFloat());
EXPECT_FALSE(ParseNumber("1e400", &f));
EXPECT_FALSE(ParseNumber("-1e400", &f));
}
TEST(ParseFloat16, Overflow) {
// The assembler parses using HexFloat<FloatProxy<Float16>>. Make
// sure that succeeds for in-range values, and fails for out of
// range values. When it does overflow, the value is set to the
// nearest finite value, matching C++11 behavior for operator>>
// on floating point.
HexFloat<FloatProxy<Float16>> f(0);
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
EXPECT_FALSE(ParseNumber(nullptr, &f));
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
EXPECT_TRUE(ParseNumber("-0.0", &f));
EXPECT_EQ(uint16_t{0x8000}, f.value().getAsFloat().get_value());
EXPECT_TRUE(ParseNumber("1.0", &f));
EXPECT_EQ(uint16_t{0x3c00}, f.value().getAsFloat().get_value());
// Overflows 16-bit but not 32-bit
EXPECT_FALSE(ParseNumber("1e38", &f));
EXPECT_FALSE(ParseNumber("-1e38", &f));
// Overflows 32-bit but not 64-bit
EXPECT_FALSE(ParseNumber("1e40", &f));
EXPECT_FALSE(ParseNumber("-1e40", &f));
// Overflows 64-bit
EXPECT_FALSE(ParseNumber("1e400", &f));
EXPECT_FALSE(ParseNumber("-1e400", &f));
}
void AssertEmitFunc(uint32_t) {
ASSERT_FALSE(true)
<< "Should not call emit() function when the number can not be parsed.";
return;
}
TEST(ParseAndEncodeNarrowSignedIntegers, Invalid) {
// The error message should be overwritten after each parsing call.
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
std::string err_msg;
NumberType type = {16, SPV_NUMBER_SIGNED_INT};
rc = ParseAndEncodeIntegerNumber(nullptr, type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("The given text is a nullptr", err_msg);
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
rc = ParseAndEncodeIntegerNumber("", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: ", err_msg);
rc = ParseAndEncodeIntegerNumber("=", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: =", err_msg);
rc = ParseAndEncodeIntegerNumber("-", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid signed integer literal: -", err_msg);
rc = ParseAndEncodeIntegerNumber("0=", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: 0=", err_msg);
}
TEST(ParseAndEncodeNarrowSignedIntegers, Overflow) {
// The error message should be overwritten after each parsing call.
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
std::string err_msg;
NumberType type = {16, SPV_NUMBER_SIGNED_INT};
rc = ParseAndEncodeIntegerNumber("32768", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Integer 32768 does not fit in a 16-bit signed integer", err_msg);
rc = ParseAndEncodeIntegerNumber("-32769", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Integer -32769 does not fit in a 16-bit signed integer", err_msg);
}
TEST(ParseAndEncodeNarrowSignedIntegers, Success) {
// Don't care the error message in this case.
EncodeNumberStatus rc = EncodeNumberStatus::kInvalidText;
NumberType type = {16, SPV_NUMBER_SIGNED_INT};
// Zero, maximum, and minimum value
rc = ParseAndEncodeIntegerNumber(
"0", type, [](uint32_t word) { EXPECT_EQ(0u, word); }, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeIntegerNumber(
"-0", type, [](uint32_t word) { EXPECT_EQ(0u, word); }, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeIntegerNumber(
"32767", type, [](uint32_t word) { EXPECT_EQ(0x00007fffu, word); },
nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeIntegerNumber(
"-32768", type, [](uint32_t word) { EXPECT_EQ(0xffff8000u, word); },
nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
// Hex parsing
rc = ParseAndEncodeIntegerNumber(
"0x7fff", type, [](uint32_t word) { EXPECT_EQ(0x00007fffu, word); },
nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeIntegerNumber(
"0xffff", type, [](uint32_t word) { EXPECT_EQ(0xffffffffu, word); },
nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
}
TEST(ParseAndEncodeNarrowUnsignedIntegers, Invalid) {
// The error message should be overwritten after each parsing call.
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
std::string err_msg;
NumberType type = {16, SPV_NUMBER_UNSIGNED_INT};
rc = ParseAndEncodeIntegerNumber(nullptr, type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("The given text is a nullptr", err_msg);
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
rc = ParseAndEncodeIntegerNumber("", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: ", err_msg);
rc = ParseAndEncodeIntegerNumber("=", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: =", err_msg);
rc = ParseAndEncodeIntegerNumber("-", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc);
EXPECT_EQ("Cannot put a negative number in an unsigned literal", err_msg);
rc = ParseAndEncodeIntegerNumber("0=", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: 0=", err_msg);
rc = ParseAndEncodeIntegerNumber("-0", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc);
EXPECT_EQ("Cannot put a negative number in an unsigned literal", err_msg);
rc = ParseAndEncodeIntegerNumber("-1", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc);
EXPECT_EQ("Cannot put a negative number in an unsigned literal", err_msg);
}
TEST(ParseAndEncodeNarrowUnsignedIntegers, Overflow) {
// The error message should be overwritten after each parsing call.
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
std::string err_msg("random content");
NumberType type = {16, SPV_NUMBER_UNSIGNED_INT};
// Overflow
rc = ParseAndEncodeIntegerNumber("65536", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Integer 65536 does not fit in a 16-bit unsigned integer", err_msg);
}
TEST(ParseAndEncodeNarrowUnsignedIntegers, Success) {
// Don't care the error message in this case.
EncodeNumberStatus rc = EncodeNumberStatus::kInvalidText;
NumberType type = {16, SPV_NUMBER_UNSIGNED_INT};
// Zero, maximum, and minimum value
rc = ParseAndEncodeIntegerNumber(
"0", type, [](uint32_t word) { EXPECT_EQ(0u, word); }, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeIntegerNumber(
"65535", type, [](uint32_t word) { EXPECT_EQ(0x0000ffffu, word); },
nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
// Hex parsing
rc = ParseAndEncodeIntegerNumber(
"0xffff", type, [](uint32_t word) { EXPECT_EQ(0x0000ffffu, word); },
nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
}
TEST(ParseAndEncodeSignedIntegers, Invalid) {
// The error message should be overwritten after each parsing call.
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
std::string err_msg;
NumberType type = {32, SPV_NUMBER_SIGNED_INT};
rc = ParseAndEncodeIntegerNumber(nullptr, type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("The given text is a nullptr", err_msg);
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
rc = ParseAndEncodeIntegerNumber("", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: ", err_msg);
rc = ParseAndEncodeIntegerNumber("=", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: =", err_msg);
rc = ParseAndEncodeIntegerNumber("-", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid signed integer literal: -", err_msg);
rc = ParseAndEncodeIntegerNumber("0=", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: 0=", err_msg);
}
TEST(ParseAndEncodeSignedIntegers, Overflow) {
// The error message should be overwritten after each parsing call.
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
std::string err_msg;
NumberType type = {32, SPV_NUMBER_SIGNED_INT};
rc =
ParseAndEncodeIntegerNumber("2147483648", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Integer 2147483648 does not fit in a 32-bit signed integer",
err_msg);
rc = ParseAndEncodeIntegerNumber("-2147483649", type, AssertEmitFunc,
&err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Integer -2147483649 does not fit in a 32-bit signed integer",
err_msg);
}
TEST(ParseAndEncodeSignedIntegers, Success) {
// Don't care the error message in this case.
EncodeNumberStatus rc = EncodeNumberStatus::kInvalidText;
NumberType type = {32, SPV_NUMBER_SIGNED_INT};
// Zero, maximum, and minimum value
rc = ParseAndEncodeIntegerNumber(
"0", type, [](uint32_t word) { EXPECT_EQ(0u, word); }, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeIntegerNumber(
"-0", type, [](uint32_t word) { EXPECT_EQ(0u, word); }, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeIntegerNumber(
"2147483647", type, [](uint32_t word) { EXPECT_EQ(0x7fffffffu, word); },
nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeIntegerNumber(
"-2147483648", type, [](uint32_t word) { EXPECT_EQ(0x80000000u, word); },
nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
// Hex parsing
rc = ParseAndEncodeIntegerNumber(
"0x7fffffff", type, [](uint32_t word) { EXPECT_EQ(0x7fffffffu, word); },
nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeIntegerNumber(
"0xffffffff", type, [](uint32_t word) { EXPECT_EQ(0xffffffffu, word); },
nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
}
TEST(ParseAndEncodeUnsignedIntegers, Invalid) {
// The error message should be overwritten after each parsing call.
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
std::string err_msg;
NumberType type = {32, SPV_NUMBER_UNSIGNED_INT};
rc = ParseAndEncodeIntegerNumber(nullptr, type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("The given text is a nullptr", err_msg);
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
rc = ParseAndEncodeIntegerNumber("", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: ", err_msg);
rc = ParseAndEncodeIntegerNumber("=", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: =", err_msg);
rc = ParseAndEncodeIntegerNumber("-", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc);
EXPECT_EQ("Cannot put a negative number in an unsigned literal", err_msg);
rc = ParseAndEncodeIntegerNumber("0=", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: 0=", err_msg);
rc = ParseAndEncodeIntegerNumber("-0", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc);
EXPECT_EQ("Cannot put a negative number in an unsigned literal", err_msg);
rc = ParseAndEncodeIntegerNumber("-1", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc);
EXPECT_EQ("Cannot put a negative number in an unsigned literal", err_msg);
}
TEST(ParseAndEncodeUnsignedIntegers, Overflow) {
// The error message should be overwritten after each parsing call.
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
std::string err_msg("random content");
NumberType type = {32, SPV_NUMBER_UNSIGNED_INT};
// Overflow
rc =
ParseAndEncodeIntegerNumber("4294967296", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Integer 4294967296 does not fit in a 32-bit unsigned integer",
err_msg);
}
TEST(ParseAndEncodeUnsignedIntegers, Success) {
// Don't care the error message in this case.
EncodeNumberStatus rc = EncodeNumberStatus::kInvalidText;
NumberType type = {32, SPV_NUMBER_UNSIGNED_INT};
// Zero, maximum, and minimum value
rc = ParseAndEncodeIntegerNumber(
"0", type, [](uint32_t word) { EXPECT_EQ(0u, word); }, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeIntegerNumber(
"4294967295", type, [](uint32_t word) { EXPECT_EQ(0xffffffffu, word); },
nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
// Hex parsing
rc = ParseAndEncodeIntegerNumber(
"0xffffffff", type, [](uint32_t word) { EXPECT_EQ(0xffffffffu, word); },
nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
}
TEST(ParseAndEncodeWideSignedIntegers, Invalid) {
// The error message should be overwritten after each parsing call.
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
std::string err_msg;
NumberType type = {64, SPV_NUMBER_SIGNED_INT};
rc = ParseAndEncodeIntegerNumber(nullptr, type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("The given text is a nullptr", err_msg);
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
rc = ParseAndEncodeIntegerNumber("", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: ", err_msg);
rc = ParseAndEncodeIntegerNumber("=", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: =", err_msg);
rc = ParseAndEncodeIntegerNumber("-", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid signed integer literal: -", err_msg);
rc = ParseAndEncodeIntegerNumber("0=", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: 0=", err_msg);
}
TEST(ParseAndEncodeWideSignedIntegers, Overflow) {
// The error message should be overwritten after each parsing call.
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
std::string err_msg;
NumberType type = {64, SPV_NUMBER_SIGNED_INT};
rc = ParseAndEncodeIntegerNumber("9223372036854775808", type, AssertEmitFunc,
&err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ(
"Integer 9223372036854775808 does not fit in a 64-bit signed integer",
err_msg);
rc = ParseAndEncodeIntegerNumber("-9223372036854775809", type, AssertEmitFunc,
&err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid signed integer literal: -9223372036854775809", err_msg);
}
TEST(ParseAndEncodeWideSignedIntegers, Success) {
// Don't care the error message in this case.
EncodeNumberStatus rc = EncodeNumberStatus::kInvalidText;
NumberType type = {64, SPV_NUMBER_SIGNED_INT};
std::vector<uint32_t> word_buffer;
auto emit = [&word_buffer](uint32_t word) {
if (word_buffer.size() == 2) word_buffer.clear();
word_buffer.push_back(word);
};
// Zero, maximum, and minimum value
rc = ParseAndEncodeIntegerNumber("0", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0u, 0u}));
rc = ParseAndEncodeIntegerNumber("-0", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0u, 0u}));
rc = ParseAndEncodeIntegerNumber("9223372036854775807", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0xffffffffu, 0x7fffffffu}));
rc = ParseAndEncodeIntegerNumber("-9223372036854775808", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0u, 0x80000000u}));
rc = ParseAndEncodeIntegerNumber("-1", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0xffffffffu, 0xffffffffu}));
// Hex parsing
rc = ParseAndEncodeIntegerNumber("0x7fffffffffffffff", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0xffffffffu, 0x7fffffffu}));
rc = ParseAndEncodeIntegerNumber("0xffffffffffffffff", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0xffffffffu, 0xffffffffu}));
}
TEST(ParseAndEncodeWideUnsignedIntegers, Invalid) {
// The error message should be overwritten after each parsing call.
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
std::string err_msg;
NumberType type = {64, SPV_NUMBER_UNSIGNED_INT};
// Invalid
rc = ParseAndEncodeIntegerNumber(nullptr, type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("The given text is a nullptr", err_msg);
Pull out the number parsing logic Pull out the number parsing logic from AssemblyContext::binaryEncodeNumericLiteral() to utilities. The new utility function: `ParseAndEncodeNumber()` now accepts: * number text to parse * number type * a emit function, which is a function which will be called with each parsed uint32 word. * a pointer to std::string to be overwritten with error messages. (pass nullptr if expect no error message) and returns: * an enum result type to indicate the status Type/Structs moved to utility: * template<typename T> class ClampToZeroIfUnsignedType New type: * enum EncodeNumberStatus: success or error code * NumberType: hold the number type information for the number to be parsed. * several helper functions are also added for NumberType. Functions moved to utility: * Helpers: * template<typename T> checkRangeAndIfHexThenSignExtend() -> CheckRangeAndIfHex....() * Interfaces: * template<typename T> parseNumber() -> ParseNumber() * binaryEncodeIntegerLiteral() -> ParseAndEncodeIntegerNumber() * binaryEncodeFloatingPointLiteral() -> ParseAndEncodeFloatingPointNumber() * binaryEncodeNumericLiteral() -> ParseAndEncodeNumber() Tests added/moved to test/ParseNumber.cpp, including tests for: * ParseNumber(): This is moved from TextToBinary.cpp to ParseNumber.cpp * ParseAndEncodeIntegerNumber(): New added * ParseAndEncodeFloatingPointNumber(): New added * ParseAndEncodeNumber(): New added Note that the error messages are kept almost the same as before, but they may be inappropriate for an utility function. Those will be fixed in another CL.
2016-09-01 18:27:04 +00:00
rc = ParseAndEncodeIntegerNumber("", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: ", err_msg);
rc = ParseAndEncodeIntegerNumber("=", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: =", err_msg);
rc = ParseAndEncodeIntegerNumber("-", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc);
EXPECT_EQ("Cannot put a negative number in an unsigned literal", err_msg);
rc = ParseAndEncodeIntegerNumber("0=", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: 0=", err_msg);
rc = ParseAndEncodeIntegerNumber("-0", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc);
EXPECT_EQ("Cannot put a negative number in an unsigned literal", err_msg);
rc = ParseAndEncodeIntegerNumber("-1", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc);
EXPECT_EQ("Cannot put a negative number in an unsigned literal", err_msg);
}
TEST(ParseAndEncodeWideUnsignedIntegers, Overflow) {
// The error message should be overwritten after each parsing call.
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
std::string err_msg;
NumberType type = {64, SPV_NUMBER_UNSIGNED_INT};
// Overflow
rc = ParseAndEncodeIntegerNumber("18446744073709551616", type, AssertEmitFunc,
&err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: 18446744073709551616", err_msg);
}
TEST(ParseAndEncodeWideUnsignedIntegers, Success) {
// Don't care the error message in this case.
EncodeNumberStatus rc = EncodeNumberStatus::kInvalidText;
NumberType type = {64, SPV_NUMBER_UNSIGNED_INT};
std::vector<uint32_t> word_buffer;
auto emit = [&word_buffer](uint32_t word) {
if (word_buffer.size() == 2) word_buffer.clear();
word_buffer.push_back(word);
};
// Zero, maximum, and minimum value
rc = ParseAndEncodeIntegerNumber("0", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0u, 0u}));
rc = ParseAndEncodeIntegerNumber("18446744073709551615", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0xffffffffu, 0xffffffffu}));
// Hex parsing
rc = ParseAndEncodeIntegerNumber("0xffffffffffffffff", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0xffffffffu, 0xffffffffu}));
}
TEST(ParseAndEncodeIntegerNumber, TypeNone) {
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
std::string err_msg;
NumberType type = {32, SPV_NUMBER_NONE};
rc = ParseAndEncodeIntegerNumber(
"0.0", type, [](uint32_t word) { EXPECT_EQ(0x0u, word); }, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc);
EXPECT_EQ("The expected type is not a integer type", err_msg);
}
TEST(ParseAndEncodeIntegerNumber, InvalidCaseWithoutErrorMessageString) {
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
NumberType type = {32, SPV_NUMBER_SIGNED_INT};
rc = ParseAndEncodeIntegerNumber("invalid", type, AssertEmitFunc, nullptr);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
}
TEST(ParseAndEncodeIntegerNumber, DoNotTouchErrorMessageStringOnSuccess) {
EncodeNumberStatus rc = EncodeNumberStatus::kInvalidText;
std::string err_msg("random content");
NumberType type = {32, SPV_NUMBER_SIGNED_INT};
rc = ParseAndEncodeIntegerNumber(
"100", type, [](uint32_t word) { EXPECT_EQ(100u, word); }, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_EQ("random content", err_msg);
}
TEST(ParseAndEncodeFloat, Sample) {
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
std::string err_msg;
NumberType type = {32, SPV_NUMBER_FLOATING};
// Invalid
rc = ParseAndEncodeFloatingPointNumber("", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid 32-bit float literal: ", err_msg);
rc = ParseAndEncodeFloatingPointNumber("0=", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid 32-bit float literal: 0=", err_msg);
// Representative samples
rc = ParseAndEncodeFloatingPointNumber(
"0.0", type, [](uint32_t word) { EXPECT_EQ(0x0u, word); }, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeFloatingPointNumber(
"-0.0", type, [](uint32_t word) { EXPECT_EQ(0x80000000u, word); },
nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeFloatingPointNumber(
"42", type, [](uint32_t word) { EXPECT_EQ(0x42280000u, word); }, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeFloatingPointNumber(
"2.5", type, [](uint32_t word) { EXPECT_EQ(0x40200000u, word); },
nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeFloatingPointNumber(
"-32.5", type, [](uint32_t word) { EXPECT_EQ(0xc2020000u, word); },
nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeFloatingPointNumber(
"1e38", type, [](uint32_t word) { EXPECT_EQ(0x7e967699u, word); },
nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeFloatingPointNumber(
"-1e38", type, [](uint32_t word) { EXPECT_EQ(0xfe967699u, word); },
nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
// Overflow
rc =
ParseAndEncodeFloatingPointNumber("1e40", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid 32-bit float literal: 1e40", err_msg);
rc = ParseAndEncodeFloatingPointNumber("-1e40", type, AssertEmitFunc,
&err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid 32-bit float literal: -1e40", err_msg);
rc = ParseAndEncodeFloatingPointNumber("1e400", type, AssertEmitFunc,
&err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid 32-bit float literal: 1e400", err_msg);
rc = ParseAndEncodeFloatingPointNumber("-1e400", type, AssertEmitFunc,
&err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid 32-bit float literal: -1e400", err_msg);
}
TEST(ParseAndEncodeDouble, Sample) {
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
std::string err_msg;
NumberType type = {64, SPV_NUMBER_FLOATING};
std::vector<uint32_t> word_buffer;
auto emit = [&word_buffer](uint32_t word) {
if (word_buffer.size() == 2) word_buffer.clear();
word_buffer.push_back(word);
};
// Invalid
rc = ParseAndEncodeFloatingPointNumber("", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid 64-bit float literal: ", err_msg);
rc = ParseAndEncodeFloatingPointNumber("0=", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid 64-bit float literal: 0=", err_msg);
// Representative samples
rc = ParseAndEncodeFloatingPointNumber("0.0", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0u, 0u}));
rc = ParseAndEncodeFloatingPointNumber("-0.0", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0u, 0x80000000u}));
rc = ParseAndEncodeFloatingPointNumber("42", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0u, 0x40450000u}));
rc = ParseAndEncodeFloatingPointNumber("2.5", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0u, 0x40040000u}));
rc = ParseAndEncodeFloatingPointNumber("32.5", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0u, 0x40404000u}));
rc = ParseAndEncodeFloatingPointNumber("1e38", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0x2a16a1b1u, 0x47d2ced3u}));
rc = ParseAndEncodeFloatingPointNumber("-1e38", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0x2a16a1b1u, 0xc7d2ced3u}));
rc = ParseAndEncodeFloatingPointNumber("1e40", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0xf1c35ca5u, 0x483d6329u}));
rc = ParseAndEncodeFloatingPointNumber("-1e40", type, emit, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_THAT(word_buffer, Eq(std::vector<uint32_t>{0xf1c35ca5u, 0xc83d6329u}));
// Overflow
rc = ParseAndEncodeFloatingPointNumber("1e400", type, AssertEmitFunc,
&err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid 64-bit float literal: 1e400", err_msg);
rc = ParseAndEncodeFloatingPointNumber("-1e400", type, AssertEmitFunc,
&err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid 64-bit float literal: -1e400", err_msg);
}
TEST(ParseAndEncodeFloat16, Sample) {
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
std::string err_msg;
NumberType type = {16, SPV_NUMBER_FLOATING};
// Invalid
rc = ParseAndEncodeFloatingPointNumber("", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid 16-bit float literal: ", err_msg);
rc = ParseAndEncodeFloatingPointNumber("0=", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid 16-bit float literal: 0=", err_msg);
// Representative samples
rc = ParseAndEncodeFloatingPointNumber(
"0.0", type, [](uint32_t word) { EXPECT_EQ(0x0u, word); }, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeFloatingPointNumber(
"-0.0", type, [](uint32_t word) { EXPECT_EQ(0x8000u, word); }, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeFloatingPointNumber(
"1.0", type, [](uint32_t word) { EXPECT_EQ(0x3c00u, word); }, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeFloatingPointNumber(
"2.5", type, [](uint32_t word) { EXPECT_EQ(0x4100u, word); }, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
rc = ParseAndEncodeFloatingPointNumber(
"32.5", type, [](uint32_t word) { EXPECT_EQ(0x5010u, word); }, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
// Overflow
rc =
ParseAndEncodeFloatingPointNumber("1e38", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid 16-bit float literal: 1e38", err_msg);
rc = ParseAndEncodeFloatingPointNumber("-1e38", type, AssertEmitFunc,
&err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid 16-bit float literal: -1e38", err_msg);
rc =
ParseAndEncodeFloatingPointNumber("1e40", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid 16-bit float literal: 1e40", err_msg);
rc = ParseAndEncodeFloatingPointNumber("-1e40", type, AssertEmitFunc,
&err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid 16-bit float literal: -1e40", err_msg);
rc = ParseAndEncodeFloatingPointNumber("1e400", type, AssertEmitFunc,
&err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid 16-bit float literal: 1e400", err_msg);
rc = ParseAndEncodeFloatingPointNumber("-1e400", type, AssertEmitFunc,
&err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid 16-bit float literal: -1e400", err_msg);
}
TEST(ParseAndEncodeFloatingPointNumber, TypeNone) {
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
std::string err_msg;
NumberType type = {32, SPV_NUMBER_NONE};
rc = ParseAndEncodeFloatingPointNumber(
"0.0", type, [](uint32_t word) { EXPECT_EQ(0x0u, word); }, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidUsage, rc);
EXPECT_EQ("The expected type is not a float type", err_msg);
}
TEST(ParseAndEncodeFloatingPointNumber, InvalidCaseWithoutErrorMessageString) {
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
NumberType type = {32, SPV_NUMBER_FLOATING};
rc = ParseAndEncodeFloatingPointNumber("invalid", type, AssertEmitFunc,
nullptr);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
}
TEST(ParseAndEncodeFloatingPointNumber, DoNotTouchErrorMessageStringOnSuccess) {
EncodeNumberStatus rc = EncodeNumberStatus::kInvalidText;
std::string err_msg("random content");
NumberType type = {32, SPV_NUMBER_FLOATING};
rc = ParseAndEncodeFloatingPointNumber(
"0.0", type, [](uint32_t word) { EXPECT_EQ(0x0u, word); }, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_EQ("random content", err_msg);
}
TEST(ParseAndEncodeNumber, Sample) {
EncodeNumberStatus rc = EncodeNumberStatus::kSuccess;
std::string err_msg;
NumberType type = {32, SPV_NUMBER_SIGNED_INT};
// Invalid with error message string
rc = ParseAndEncodeNumber("something wrong", type, AssertEmitFunc, &err_msg);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
EXPECT_EQ("Invalid unsigned integer literal: something wrong", err_msg);
// Invalid without error message string
rc = ParseAndEncodeNumber("something wrong", type, AssertEmitFunc, nullptr);
EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc);
// Signed integer, should not touch the error message string.
err_msg = "random content";
rc = ParseAndEncodeNumber("-1", type,
[](uint32_t word) { EXPECT_EQ(0xffffffffu, word); },
&err_msg);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
EXPECT_EQ("random content", err_msg);
// Unsigned integer
type = {32, SPV_NUMBER_UNSIGNED_INT};
rc = ParseAndEncodeNumber(
"1", type, [](uint32_t word) { EXPECT_EQ(1u, word); }, nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
// Float
type = {32, SPV_NUMBER_FLOATING};
rc = ParseAndEncodeNumber("-1.0", type,
[](uint32_t word) { EXPECT_EQ(0xbf800000, word); },
nullptr);
EXPECT_EQ(EncodeNumberStatus::kSuccess, rc);
}
} // namespace
} // namespace utils
} // namespace spvtools