From ebef6a104fc3104cedca8f6aa4dff4725eaf4b25 Mon Sep 17 00:00:00 2001 From: David Neto Date: Mon, 8 Feb 2016 14:33:41 -0500 Subject: [PATCH] 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. --- test/TextLiteral.cpp | 26 ++++++++++ test/TextToBinary.Constant.cpp | 93 +++++++++++++++++++++++++++++++++- test/TextToBinary.cpp | 66 ++++++++++++++++++++++-- 3 files changed, 178 insertions(+), 7 deletions(-) diff --git a/test/TextLiteral.cpp b/test/TextLiteral.cpp index f286635df9..48c3162907 100644 --- a/test/TextLiteral.cpp +++ b/test/TextLiteral.cpp @@ -291,6 +291,32 @@ INSTANTIATE_TEST_CASE_P( })); // clang-format on +using IntegerLeadingMinusTest = + spvtest::TextToBinaryTestBase<::testing::TestWithParam>; + +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{ + // 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, diff --git a/test/TextToBinary.Constant.cpp b/test/TextToBinary.Constant.cpp index 4c7190c005..4fabba719b 100644 --- a/test/TextToBinary.Constant.cpp +++ b/test/TextToBinary.Constant.cpp @@ -118,8 +118,9 @@ TEST_P(OpConstantValidTest, ValidTypes) { "%2 = OpConstant %1 " + GetParam().constant_value + "\n"; std::vector 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>; + +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{ + {"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 diff --git a/test/TextToBinary.cpp b/test/TextToBinary.cpp index 91f1ca5252..5074098259 100644 --- a/test/TextToBinary.cpp +++ b/test/TextToBinary.cpp @@ -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::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::min(), i32); + + // Hex values. + EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0x7fffffff", ec, &i32, "")); + EXPECT_EQ(std::numeric_limits::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::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::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::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, "")); }