More parsing tests for literals with leading minus

Also checks some hex literal cases.

This addresses part of
https://github.com/KhronosGroup/SPIRV-Tools/issues/45
by removing the parseNumber case for "-0" on unsigned
integers.  We don't care about that platform difference
at the level of std::istringstream, since we reject it
at a higher parsing level.
This commit is contained in:
David Neto 2016-02-08 14:33:41 -05:00
parent 7ef6da7b7f
commit feda995c84
3 changed files with 178 additions and 7 deletions

View File

@ -291,6 +291,32 @@ INSTANTIATE_TEST_CASE_P(
}));
// clang-format on
using IntegerLeadingMinusTest =
spvtest::TextToBinaryTestBase<::testing::TestWithParam<TextLiteralCase>>;
TEST_P(IntegerLeadingMinusTest, CantHaveLeadingMinusOnUnsigned) {
EXPECT_FALSE(GetParam().success);
EXPECT_THAT(
failedEncode(GetParam(), libspirv::IdTypeClass::kScalarIntegerType),
Eq("Cannot put a negative number in an unsigned literal"));
}
// clang-format off
INSTANTIATE_TEST_CASE_P(
DecimalAndHexIntegers, IntegerLeadingMinusTest,
::testing::ValuesIn(std::vector<TextLiteralCase>{
// Unsigned numbers never allow a leading minus sign.
Make_Bad_Unsigned(16, "-0"),
Make_Bad_Unsigned(16, "-0x0"),
Make_Bad_Unsigned(16, "-0x1"),
Make_Bad_Unsigned(32, "-0"),
Make_Bad_Unsigned(32, "-0x0"),
Make_Bad_Unsigned(32, "-0x1"),
Make_Bad_Unsigned(64, "-0"),
Make_Bad_Unsigned(64, "-0x0"),
Make_Bad_Unsigned(64, "-0x1"),
}));
// clang-format off
INSTANTIATE_TEST_CASE_P(
HexIntegers, IntegerTest,

View File

@ -118,8 +118,9 @@ TEST_P(OpConstantValidTest, ValidTypes) {
"%2 = OpConstant %1 " +
GetParam().constant_value + "\n";
std::vector<uint32_t> instructions;
EXPECT_THAT(CompiledInstructions(input),
Eq(GetParam().expected_instructions));
EXPECT_THAT(CompiledInstructions(input), Eq(GetParam().expected_instructions))
<< " type: " << GetParam().constant_type
<< " literal: " << GetParam().constant_value;
}
// clang-format off
@ -133,12 +134,33 @@ INSTANTIATE_TEST_CASE_P(
{"OpTypeInt 16 0", "0x8000",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
MakeInstruction(SpvOpConstant, {1, 2, 0x8000})})},
{"OpTypeInt 16 0", "0",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
MakeInstruction(SpvOpConstant, {1, 2, 0})})},
{"OpTypeInt 16 0", "65535",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
MakeInstruction(SpvOpConstant, {1, 2, 65535})})},
{"OpTypeInt 16 0", "0xffff",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
MakeInstruction(SpvOpConstant, {1, 2, 65535})})},
{"OpTypeInt 16 1", "0x8000", // Test sign extension.
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
MakeInstruction(SpvOpConstant, {1, 2, 0xffff8000})})},
{"OpTypeInt 16 1", "-32",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32)})})},
{"OpTypeInt 16 1", "0",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
MakeInstruction(SpvOpConstant, {1, 2, 0})})},
{"OpTypeInt 16 1", "-0",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
MakeInstruction(SpvOpConstant, {1, 2, 0})})},
{"OpTypeInt 16 1", "-0x0",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
MakeInstruction(SpvOpConstant, {1, 2, 0})})},
{"OpTypeInt 16 1", "-32768",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32768)})})},
// Check 32 bits
{"OpTypeInt 32 0", "42",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 0}),
@ -146,6 +168,24 @@ INSTANTIATE_TEST_CASE_P(
{"OpTypeInt 32 1", "-32",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32)})})},
{"OpTypeInt 32 1", "0",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
MakeInstruction(SpvOpConstant, {1, 2, 0})})},
{"OpTypeInt 32 1", "-0",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
MakeInstruction(SpvOpConstant, {1, 2, 0})})},
{"OpTypeInt 32 1", "-0x0",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
MakeInstruction(SpvOpConstant, {1, 2, 0})})},
{"OpTypeInt 32 1", "-0x001",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-1)})})},
{"OpTypeInt 32 1", "2147483647",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
MakeInstruction(SpvOpConstant, {1, 2, 0x7fffffffu})})},
{"OpTypeInt 32 1", "-2147483648",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
MakeInstruction(SpvOpConstant, {1, 2, 0x80000000u})})},
{"OpTypeFloat 32", "1.0",
Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
MakeInstruction(SpvOpConstant, {1, 2, 0x3f800000})})},
@ -181,12 +221,61 @@ INSTANTIATE_TEST_CASE_P(
{"OpTypeInt 64 0", "0x1234",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
MakeInstruction(SpvOpConstant, {1, 2, 0x1234, 0})})},
{"OpTypeInt 64 0", "18446744073709551615",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
{"OpTypeInt 64 0", "0xffffffffffffffff",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
{"OpTypeInt 64 1", "0x1234",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
MakeInstruction(SpvOpConstant, {1, 2, 0x1234, 0})})},
{"OpTypeInt 64 1", "-42",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-42), uint32_t(-1)})})},
{"OpTypeInt 64 1", "-0x01",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
{"OpTypeInt 64 1", "9223372036854775807",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0x7fffffffu})})},
{"OpTypeInt 64 1", "0x7fffffff",
Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
MakeInstruction(SpvOpConstant, {1, 2, 0x7fffffffu, 0})})},
}));
// clang-format on
// A test case for checking OpConstant with invalid literals with a leading minus.
struct InvalidLeadingMinusCase {
std::string type;
std::string literal;
};
using OpConstantInvalidLeadingMinusTest =
spvtest::TextToBinaryTestBase<::testing::TestWithParam<InvalidLeadingMinusCase>>;
TEST_P(OpConstantInvalidLeadingMinusTest, InvalidCase) {
const std::string input = "%1 = " + GetParam().type +
"\n"
"%2 = OpConstant %1 " +
GetParam().literal;
EXPECT_THAT(CompileFailure(input),
Eq("Cannot put a negative number in an unsigned literal"));
}
// clang-format off
INSTANTIATE_TEST_CASE_P(
TextToBinaryOpConstantInvalidLeadingMinus, OpConstantInvalidLeadingMinusTest,
::testing::ValuesIn(std::vector<InvalidLeadingMinusCase>{
{"OpTypeInt 16 0", "-0"},
{"OpTypeInt 16 0", "-0x0"},
{"OpTypeInt 16 0", "-1"},
{"OpTypeInt 32 0", "-0"},
{"OpTypeInt 32 0", "-0x0"},
{"OpTypeInt 32 0", "-1"},
{"OpTypeInt 64 0", "-0"},
{"OpTypeInt 64 0", "-0x0"},
{"OpTypeInt 64 0", "-1"},
}));
// clang-format on

View File

@ -319,15 +319,71 @@ TEST(AssemblyContextParseNarrowUnsignedIntegers, Sample) {
EXPECT_EQ(65535, u16);
EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("65536", ec, &u16, ""));
EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0", ec, &u16, ""));
EXPECT_EQ(0, u16);
// We don't care about -0 since it's rejected at a higher level.
EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("-1", ec, &u16, ""));
EXPECT_EQ(0, u16);
EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0xffff", ec, &u16, ""));
EXPECT_EQ(0xffff, u16);
EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0x10000", ec, &u16, ""));
}
TEST(AssemblyContextParseSignedIntegers, Sample) {
AssemblyContext context(AutoText(""), nullptr);
const spv_result_t ec = SPV_FAILED_MATCH;
int32_t i32;
// Invalid parse.
EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("", ec, &i32, ""));
EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0=", ec, &i32, ""));
// Decimal values.
EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0", ec, &i32, ""));
EXPECT_EQ(0, i32);
EXPECT_EQ(SPV_SUCCESS, context.parseNumber("2147483647", ec, &i32, ""));
EXPECT_EQ(std::numeric_limits<int32_t>::max(), i32);
EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("2147483648", ec, &i32, ""));
EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0", ec, &i32, ""));
EXPECT_EQ(0, i32);
EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-1", ec, &i32, ""));
EXPECT_EQ(-1, i32);
EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-2147483648", ec, &i32, ""));
EXPECT_EQ(std::numeric_limits<int32_t>::min(), i32);
// Hex values.
EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0x7fffffff", ec, &i32, ""));
EXPECT_EQ(std::numeric_limits<int32_t>::max(), i32);
EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0x80000000", ec, &i32, ""));
EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0x000", ec, &i32, ""));
EXPECT_EQ(0, i32);
EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0x001", ec, &i32, ""));
EXPECT_EQ(-1, i32);
EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0x80000000", ec, &i32, ""));
EXPECT_EQ(std::numeric_limits<int32_t>::min(), i32);
}
TEST(AssemblyContextParseUnsignedIntegers, Sample) {
AssemblyContext context(AutoText(""), nullptr);
const spv_result_t ec = SPV_FAILED_MATCH;
uint32_t u32;
// Invalid parse.
EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("", ec, &u32, ""));
EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0=", ec, &u32, ""));
// Valid values.
EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0", ec, &u32, ""));
EXPECT_EQ(0u, u32);
EXPECT_EQ(SPV_SUCCESS, context.parseNumber("4294967295", ec, &u32, ""));
EXPECT_EQ(std::numeric_limits<uint32_t>::max(), u32);
EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("4294967296", ec, &u32, ""));
// Hex values.
EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0xffffffff", ec, &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_EQ(SPV_FAILED_MATCH, context.parseNumber("-1", ec, &u32, ""));
}
TEST(AssemblyContextParseWideSignedIntegers, Sample) {
AssemblyContext context(AutoText(""), nullptr);
const spv_result_t ec = SPV_FAILED_MATCH;
@ -356,8 +412,8 @@ TEST(AssemblyContextParseWideUnsignedIntegers, Sample) {
EXPECT_EQ(SPV_SUCCESS,
context.parseNumber("0xffffffffffffffff", ec, &u64, ""));
EXPECT_EQ(0xffffffffffffffffULL, u64);
EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0", ec, &u64, ""));
EXPECT_EQ(0u, u64);
// We don't care about -0 since it's rejected at a higher level.
EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("-1", ec, &u64, ""));
}