Skip to content

Commit

Permalink
More parsing tests for literals with leading minus
Browse files Browse the repository at this point in the history
Also checks some hex literal cases.

This addresses part of
KhronosGroup#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.
  • Loading branch information
dneto0 committed Feb 8, 2016
1 parent 7ef6da7 commit ebef6a1
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 7 deletions.
26 changes: 26 additions & 0 deletions test/TextLiteral.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
93 changes: 91 additions & 2 deletions test/TextToBinary.Constant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -133,19 +134,58 @@ 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}),
MakeInstruction(SpvOpConstant, {1, 2, 42})})},
{"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})})},
Expand Down Expand Up @@ -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

Expand Down
66 changes: 61 additions & 5 deletions test/TextToBinary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(0, 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;
Expand Down Expand Up @@ -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, ""));
}

Expand Down

0 comments on commit ebef6a1

Please sign in to comment.