More parsing tests for literals with leading minus
authorDavid Neto <dneto@google.com>
Mon, 8 Feb 2016 19:33:41 +0000 (14:33 -0500)
committerDavid Neto <dneto@google.com>
Mon, 8 Feb 2016 21:56:41 +0000 (16:56 -0500)
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
test/TextToBinary.Constant.cpp
test/TextToBinary.cpp

index f286635..48c3162 100644 (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,
index 4c7190c..4fabba7 100644 (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
 
index 91f1ca5..20f8916 100644 (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, ""));
 }