Making the unit tests more robust.
authorEhsan Nasiri <ehsann@google.com>
Mon, 23 Jan 2017 23:31:14 +0000 (18:31 -0500)
committerDavid Neto <dneto@google.com>
Mon, 30 Jan 2017 03:50:37 +0000 (22:50 -0500)
It is best to check the error messages of unit tests that fail
validation. This will ensure that a validation failure is due to what we
expect and not due to some secondary reason.

Updating SPIR-V Validator unit tests with error message checks.

test/val/val_id_test.cpp
test/val/val_layout_test.cpp
test/val/val_storage_test.cpp

index 8855394..c8c72cf 100644 (file)
@@ -120,6 +120,8 @@ TEST_F(ValidateIdWithMessage, OpMemberNameTypeBad) {
 %1 = OpTypeInt 32 0)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpMemberName Type <id> '1' is not a struct type."));
 }
 TEST_F(ValidateIdWithMessage, OpMemberNameMemberBad) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -128,6 +130,9 @@ TEST_F(ValidateIdWithMessage, OpMemberNameMemberBad) {
 %2 = OpTypeStruct %1)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpMemberName Member <id> '1' index is larger than "
+                        "Type <id> '1's member count."));
 }
 
 TEST_F(ValidateIdWithMessage, OpLineGood) {
@@ -142,12 +147,13 @@ TEST_F(ValidateIdWithMessage, OpLineGood) {
 }
 TEST_F(ValidateIdWithMessage, OpLineFileBad) {
   string spirv = kGLSL450MemoryModel + R"(
-     OpLine %2 0 0
-%2 = OpTypeInt 32 0
-%3 = OpTypePointer Input %2
-%4 = OpVariable %3 Input)";
+  %1 = OpTypeInt 32 0
+     OpLine %1 0 0
+  )";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpLine Target <id> '1' is not an OpString."));
 }
 
 TEST_F(ValidateIdWithMessage, OpDecorateGood) {
@@ -300,6 +306,9 @@ TEST_F(ValidateIdWithMessage, OpEntryPointFunctionBad) {
 %1 = OpTypeVoid)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpEntryPoint Entry Point <id> '1' is not a function."));
 }
 TEST_F(ValidateIdWithMessage, OpEntryPointParameterCountBad) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -312,6 +321,9 @@ TEST_F(ValidateIdWithMessage, OpEntryPointParameterCountBad) {
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpEntryPoint Entry Point <id> '1's function parameter "
+                        "count is not zero"));
 }
 TEST_F(ValidateIdWithMessage, OpEntryPointReturnTypeBad) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -324,6 +336,9 @@ TEST_F(ValidateIdWithMessage, OpEntryPointReturnTypeBad) {
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpEntryPoint Entry Point <id> '1's function return "
+                        "type is not void."));
 }
 
 TEST_F(ValidateIdWithMessage, OpEntryPointInterfaceIsNotVariableTypeBad) {
@@ -402,6 +417,9 @@ TEST_F(ValidateIdWithMessage, OpExecutionModeEntryPointMissing) {
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpExecutionMode Entry Point <id> '1' is not the Entry "
+                        "Point operand of an OpEntryPoint."));
 }
 
 TEST_F(ValidateIdWithMessage, OpExecutionModeEntryPointBad) {
@@ -418,6 +436,9 @@ TEST_F(ValidateIdWithMessage, OpExecutionModeEntryPointBad) {
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpExecutionMode Entry Point <id> '2' is not the Entry "
+                        "Point operand of an OpEntryPoint."));
 }
 
 TEST_F(ValidateIdWithMessage, OpTypeVectorFloat) {
@@ -459,6 +480,9 @@ TEST_F(ValidateIdWithMessage, OpTypeVectorComponentTypeBad) {
 %3 = OpTypeVector %2 4)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpTypeVector Component Type <id> '2' is not a scalar type."));
 }
 
 TEST_F(ValidateIdWithMessage, OpTypeMatrixGood) {
@@ -475,6 +499,8 @@ TEST_F(ValidateIdWithMessage, OpTypeMatrixColumnTypeBad) {
 %2 = OpTypeMatrix %1 3)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Columns in a matrix must be of type vector."));
 }
 
 TEST_F(ValidateIdWithMessage, OpTypeSamplerGood) {
@@ -501,6 +527,8 @@ TEST_F(ValidateIdWithMessage, OpTypeArrayElementTypeBad) {
 %3 = OpTypeArray %2 %2)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpTypeArray Element Type <id> '2' is not a type."));
 }
 
 // Signed or unsigned.
@@ -527,12 +555,13 @@ class OpTypeArrayLengthTest
   ~OpTypeArrayLengthTest() { spvDiagnosticDestroy(diagnostic_); }
 
   // Runs spvValidate() on v, printing any errors via spvDiagnosticPrint().
-  spv_result_t Val(const SpirvVector& v) {
+  spv_result_t Val(const SpirvVector& v, const std::string &expected_err = "") {
     spv_const_binary_t cbinary{v.data(), v.size()};
     const auto status =
         spvValidate(ScopedContext().context, &cbinary, &diagnostic_);
     if (status != SPV_SUCCESS) {
       spvDiagnosticPrint(diagnostic_);
+      EXPECT_THAT(std::string(diagnostic_->error), HasSubstr(expected_err));
     }
     return status;
   }
@@ -566,23 +595,35 @@ TEST_P(OpTypeArrayLengthTest, LengthPositive) {
 
 TEST_P(OpTypeArrayLengthTest, LengthZero) {
   const int width = GetParam();
-  EXPECT_EQ(SPV_ERROR_INVALID_ID,
-            Val(CompileSuccessfully(MakeArrayLength("0", kSigned, width))));
-  EXPECT_EQ(SPV_ERROR_INVALID_ID,
-            Val(CompileSuccessfully(MakeArrayLength("0", kUnsigned, width))));
+  EXPECT_EQ(
+      SPV_ERROR_INVALID_ID,
+      Val(CompileSuccessfully(MakeArrayLength("0", kSigned, width)),
+          "OpTypeArray Length <id> '2' default value must be at least 1."));
+  EXPECT_EQ(
+      SPV_ERROR_INVALID_ID,
+      Val(CompileSuccessfully(MakeArrayLength("0", kUnsigned, width)),
+          "OpTypeArray Length <id> '2' default value must be at least 1."));
 }
 
 TEST_P(OpTypeArrayLengthTest, LengthNegative) {
   const int width = GetParam();
-  EXPECT_EQ(SPV_ERROR_INVALID_ID,
-            Val(CompileSuccessfully(MakeArrayLength("-1", kSigned, width))));
-  EXPECT_EQ(SPV_ERROR_INVALID_ID,
-            Val(CompileSuccessfully(MakeArrayLength("-2", kSigned, width))));
-  EXPECT_EQ(SPV_ERROR_INVALID_ID,
-            Val(CompileSuccessfully(MakeArrayLength("-123", kSigned, width))));
+  EXPECT_EQ(
+      SPV_ERROR_INVALID_ID,
+      Val(CompileSuccessfully(MakeArrayLength("-1", kSigned, width)),
+          "OpTypeArray Length <id> '2' default value must be at least 1."));
+  EXPECT_EQ(
+      SPV_ERROR_INVALID_ID,
+      Val(CompileSuccessfully(MakeArrayLength("-2", kSigned, width)),
+          "OpTypeArray Length <id> '2' default value must be at least 1."));
+  EXPECT_EQ(
+      SPV_ERROR_INVALID_ID,
+      Val(CompileSuccessfully(MakeArrayLength("-123", kSigned, width)),
+          "OpTypeArray Length <id> '2' default value must be at least 1."));
   const string neg_max = "0x8" + string(width / 4 - 1, '0');
-  EXPECT_EQ(SPV_ERROR_INVALID_ID,
-            Val(CompileSuccessfully(MakeArrayLength(neg_max, kSigned, width))));
+  EXPECT_EQ(
+      SPV_ERROR_INVALID_ID,
+      Val(CompileSuccessfully(MakeArrayLength(neg_max, kSigned, width)),
+          "OpTypeArray Length <id> '2' default value must be at least 1."));
 }
 
 // The only valid widths for integers are 8, 16, 32, and 64.
@@ -596,6 +637,10 @@ TEST_F(ValidateIdWithMessage, OpTypeArrayLengthNull) {
 %ary = OpTypeArray %i32 %len)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "OpTypeArray Length <id> '2' default value must be at least 1."));
 }
 
 TEST_F(ValidateIdWithMessage, OpTypeArrayLengthSpecConst) {
@@ -632,6 +677,9 @@ TEST_F(ValidateIdWithMessage, OpTypeRuntimeArrayBad) {
 %3 = OpTypeRuntimeArray %2)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpTypeRuntimeArray Element Type <id> '2' is not a type."));
 }
 // TODO: Object of this type can only be created with OpVariable using the
 // Unifrom Storage Class
@@ -653,6 +701,8 @@ TEST_F(ValidateIdWithMessage, OpTypeStructMemberTypeBad) {
 %4 = OpTypeStruct %1 %2 %3)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpTypeStruct Member Type <id> '3' is not a type."));
 }
 
 TEST_F(ValidateIdWithMessage, OpTypePointerGood) {
@@ -669,6 +719,8 @@ TEST_F(ValidateIdWithMessage, OpTypePointerBad) {
 %3 = OpTypePointer Input %2)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpTypePointer Type <id> '2' is not a type."));
 }
 
 TEST_F(ValidateIdWithMessage, OpTypeFunctionGood) {
@@ -685,6 +737,8 @@ TEST_F(ValidateIdWithMessage, OpTypeFunctionReturnTypeBad) {
 %3 = OpTypeFunction %2)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpTypeFunction Return Type <id> '2' is not a type."));
 }
 TEST_F(ValidateIdWithMessage, OpTypeFunctionParameterBad) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -694,6 +748,9 @@ TEST_F(ValidateIdWithMessage, OpTypeFunctionParameterBad) {
 %4 = OpTypeFunction %1 %2 %3)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpTypeFunction Parameter Type <id> '3' is not a type."));
 }
 
 TEST_F(ValidateIdWithMessage, OpTypePipeGood) {
@@ -718,6 +775,9 @@ TEST_F(ValidateIdWithMessage, OpConstantTrueBad) {
 %2 = OpConstantTrue %1)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpConstantTrue Result Type <id> '1' is not a boolean type."));
 }
 
 TEST_F(ValidateIdWithMessage, OpConstantFalseGood) {
@@ -733,6 +793,9 @@ TEST_F(ValidateIdWithMessage, OpConstantFalseBad) {
 %2 = OpConstantFalse %1)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpConstantFalse Result Type <id> '1' is not a boolean type."));
 }
 
 TEST_F(ValidateIdWithMessage, OpConstantGood) {
@@ -780,6 +843,10 @@ TEST_F(ValidateIdWithMessage, OpConstantCompositeVectorResultTypeBad) {
 %4 = OpConstantComposite %1 %3 %3 %3 %3)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "OpConstantComposite Result Type <id> '1' is not a composite type."));
 }
 TEST_F(ValidateIdWithMessage, OpConstantCompositeVectorConstituentTypeBad) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -791,6 +858,10 @@ TEST_F(ValidateIdWithMessage, OpConstantCompositeVectorConstituentTypeBad) {
 %6 = OpConstantComposite %2 %3 %5 %3 %3)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpConstantComposite Constituent <id> '5's type does not match "
+                "Result Type <id> '2's vector element type."));
 }
 TEST_F(ValidateIdWithMessage,
        OpConstantCompositeVectorConstituentUndefTypeBad) {
@@ -803,6 +874,10 @@ TEST_F(ValidateIdWithMessage,
 %6 = OpConstantComposite %2 %3 %5 %3 %3)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpConstantComposite Constituent <id> '5's type does not match "
+                "Result Type <id> '2's vector element type."));
 }
 TEST_F(ValidateIdWithMessage, OpConstantCompositeMatrixGood) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -849,6 +924,10 @@ TEST_F(ValidateIdWithMessage, OpConstantCompositeMatrixConstituentTypeBad) {
 %10 = OpConstantComposite %3 %6 %7 %8 %9)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpConstantComposite Constituent <id> '10' vector "
+                        "component count does not match Result Type <id> '4's "
+                        "vector component count."));
 }
 TEST_F(ValidateIdWithMessage,
        OpConstantCompositeMatrixConstituentUndefTypeBad) {
@@ -866,6 +945,10 @@ TEST_F(ValidateIdWithMessage,
 %10 = OpConstantComposite %3 %6 %7 %8 %9)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpConstantComposite Constituent <id> '10' vector "
+                        "component count does not match Result Type <id> '4's "
+                        "vector component count."));
 }
 TEST_F(ValidateIdWithMessage, OpConstantCompositeMatrixColumnTypeBad) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -881,6 +964,8 @@ TEST_F(ValidateIdWithMessage, OpConstantCompositeMatrixColumnTypeBad) {
 %10 = OpConstantComposite %5 %8 %9)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Columns in a matrix must be of type vector."));
 }
 TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayGood) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -909,6 +994,9 @@ TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayConstConstituentBad) {
 %4 = OpConstantComposite %3 %2 %2 %2 %1)";  // Uses a type as operand
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpConstantComposite Constituent <id> '1' is not a "
+                        "constant or undef."));
 }
 TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayConstituentTypeBad) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -920,6 +1008,9 @@ TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayConstituentTypeBad) {
 %4 = OpConstantComposite %3 %2 %2 %2 %6)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpConstantComposite Constituent <id> '5's type does "
+                        "not match Result Type <id> '3's array element type."));
 }
 TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayConstituentUndefTypeBad) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -931,6 +1022,9 @@ TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayConstituentUndefTypeBad) {
 %4 = OpConstantComposite %3 %2 %2 %2 %6)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpConstantComposite Constituent <id> '5's type does "
+                        "not match Result Type <id> '3's array element type."));
 }
 TEST_F(ValidateIdWithMessage, OpConstantCompositeStructGood) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -964,6 +1058,9 @@ TEST_F(ValidateIdWithMessage, OpConstantCompositeStructMemberTypeBad) {
 %6 = OpConstantComposite %3 %4 %5 %4)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpConstantComposite Constituent <id> '5' type does "
+                        "not match the Result Type <id> '3's member type."));
 }
 
 TEST_F(ValidateIdWithMessage, OpConstantCompositeStructMemberUndefTypeBad) {
@@ -976,6 +1073,9 @@ TEST_F(ValidateIdWithMessage, OpConstantCompositeStructMemberUndefTypeBad) {
 %6 = OpConstantComposite %3 %4 %5 %4)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpConstantComposite Constituent <id> '5' type does "
+                        "not match the Result Type <id> '3's member type."));
 }
 
 TEST_F(ValidateIdWithMessage, OpConstantSamplerGood) {
@@ -992,6 +1092,10 @@ TEST_F(ValidateIdWithMessage, OpConstantSamplerResultTypeBad) {
 %2 = OpConstantSampler %1 Clamp 0 Nearest)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "OpConstantSampler Result Type <id> '1' is not a sampler type."));
 }
 
 TEST_F(ValidateIdWithMessage, OpConstantNullGood) {
@@ -1036,6 +1140,10 @@ TEST_F(ValidateIdWithMessage, OpConstantNullBasicBad) {
 %2 = OpConstantNull %1)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "OpConstantNull Result Type <id> '1' cannot have a null value."));
 }
 
 TEST_F(ValidateIdWithMessage, OpConstantNullArrayBad) {
@@ -1047,6 +1155,10 @@ TEST_F(ValidateIdWithMessage, OpConstantNullArrayBad) {
 %6 = OpConstantNull %5)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "OpConstantNull Result Type <id> '4' cannot have a null value."));
 }
 
 TEST_F(ValidateIdWithMessage, OpConstantNullStructBad) {
@@ -1056,6 +1168,10 @@ TEST_F(ValidateIdWithMessage, OpConstantNullStructBad) {
 %4 = OpConstantNull %3)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "OpConstantNull Result Type <id> '2' cannot have a null value."));
 }
 
 TEST_F(ValidateIdWithMessage, OpConstantNullRuntimeArrayBad) {
@@ -1065,6 +1181,10 @@ TEST_F(ValidateIdWithMessage, OpConstantNullRuntimeArrayBad) {
 %null = OpConstantNull %array)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "OpConstantNull Result Type <id> '2' cannot have a null value."));
 }
 
 TEST_F(ValidateIdWithMessage, OpSpecConstantTrueGood) {
@@ -1080,6 +1200,8 @@ TEST_F(ValidateIdWithMessage, OpSpecConstantTrueBad) {
 %2 = OpSpecConstantTrue %1)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Specialization constant must be a boolean type."));
 }
 
 TEST_F(ValidateIdWithMessage, OpSpecConstantFalseGood) {
@@ -1095,6 +1217,8 @@ TEST_F(ValidateIdWithMessage, OpSpecConstantFalseBad) {
 %2 = OpSpecConstantFalse %1)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Specialization constant must be a boolean type."));
 }
 
 TEST_F(ValidateIdWithMessage, OpSpecConstantGood) {
@@ -1113,6 +1237,8 @@ TEST_F(ValidateIdWithMessage, OpSpecConstantBad) {
   // change over time, but this must always fail.
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Type Id 1 is not a scalar numeric type"));
 }
 
 // Valid: SpecConstantComposite specializes to a vector.
@@ -1596,6 +1722,9 @@ TEST_F(ValidateIdWithMessage, OpVariableResultTypeBad) {
 %2 = OpVariable %1 Input)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpVariable Result Type <id> '1' is not a pointer type."));
 }
 TEST_F(ValidateIdWithMessage, OpVariableInitializerIsTypeBad) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -1679,6 +1808,9 @@ TEST_F(ValidateIdWithMessage, OpLoadResultTypeBad) {
 )";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpLoad Result Type <id> '3' does not match Pointer "
+                        "<id> '5's type."));
 }
 TEST_F(ValidateIdWithMessage, OpLoadPointerBad) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -1695,6 +1827,8 @@ TEST_F(ValidateIdWithMessage, OpLoadPointerBad) {
 )";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpLoad Pointer <id> '4' is not a pointer."));
 }
 
 TEST_F(ValidateIdWithMessage, OpStoreGood) {
@@ -1728,6 +1862,8 @@ TEST_F(ValidateIdWithMessage, OpStorePointerBad) {
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpStore Pointer <id> '3' is not a pointer."));
 }
 TEST_F(ValidateIdWithMessage, OpStoreObjectGood) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -1744,6 +1880,8 @@ TEST_F(ValidateIdWithMessage, OpStoreObjectGood) {
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpStore Object <id> '7's type is void."));
 }
 TEST_F(ValidateIdWithMessage, OpStoreTypeBad) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -1761,6 +1899,9 @@ TEST_F(ValidateIdWithMessage, OpStoreTypeBad) {
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpStore Pointer <id> '7's type does not match Object "
+                        "<id> '3's type."));
 }
 
 TEST_F(ValidateIdWithMessage, OpStoreVoid) {
@@ -1778,6 +1919,8 @@ TEST_F(ValidateIdWithMessage, OpStoreVoid) {
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpStore Object <id> '8's type is void."));
 }
 
 TEST_F(ValidateIdWithMessage, OpStoreLabel) {
@@ -1794,6 +1937,8 @@ TEST_F(ValidateIdWithMessage, OpStoreLabel) {
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpStore Object <id> '7' is not an object."));
 }
 
 // TODO: enable when this bug is fixed:
@@ -1852,6 +1997,9 @@ TEST_F(ValidateIdWithMessage, OpCopyMemoryBad) {
 )";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpCopyMemory Target <id> '5's type does not match "
+                        "Source <id> '2's type."));
 }
 
 // TODO: OpCopyMemorySized
@@ -1889,6 +2037,8 @@ TEST_F(ValidateIdWithMessage, OpCopyMemorySizedTargetBad) {
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpCopyMemorySized Target <id> '9' is not a pointer."));
 }
 TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSourceBad) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -1906,6 +2056,8 @@ TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSourceBad) {
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpCopyMemorySized Source <id> '6' is not a pointer."));
 }
 TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeBad) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -1924,6 +2076,9 @@ TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeBad) {
       OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpCopyMemorySized Size <id> '6's variable type is not "
+                        "an integer type."));
 }
 TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeTypeBad) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -1944,6 +2099,10 @@ TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeTypeBad) {
       OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "OpCopyMemorySized Size <id> '9's type is not an integer type."));
 }
 
 const char kDeeplyNestedStructureSetup[] = R"(
@@ -2451,6 +2610,9 @@ TEST_F(ValidateIdWithMessage, OpFunctionResultTypeBad) {
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpFunction Result Type <id> '2' does not match the "
+                        "Function Type <id> '2's return type."));
 }
 TEST_F(ValidateIdWithMessage, OpFunctionFunctionTypeBad) {
   string spirv = kGLSL450MemoryModel + R"(
@@ -2460,6 +2622,9 @@ TEST_F(ValidateIdWithMessage, OpFunctionFunctionTypeBad) {
 OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpFunction Function Type <id> '2' is not a function type."));
 }
 
 TEST_F(ValidateIdWithMessage, OpFunctionParameterGood) {
@@ -2501,6 +2666,10 @@ TEST_F(ValidateIdWithMessage, OpFunctionParameterResultTypeBad) {
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpFunctionParameter Result Type <id> '1' does not match the "
+                "OpTypeFunction parameter type of the same index."));
 }
 
 TEST_F(ValidateIdWithMessage, OpFunctionCallGood) {
@@ -3234,6 +3403,9 @@ TEST_F(ValidateIdWithMessage, OpReturnValueIsType) {
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpReturnValue Value <id> '1' does not represent a value."));
 }
 
 TEST_F(ValidateIdWithMessage, OpReturnValueIsLabel) {
@@ -3247,6 +3419,9 @@ TEST_F(ValidateIdWithMessage, OpReturnValueIsLabel) {
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpReturnValue Value <id> '5' does not represent a value."));
 }
 
 TEST_F(ValidateIdWithMessage, OpReturnValueIsVoid) {
@@ -3261,6 +3436,9 @@ TEST_F(ValidateIdWithMessage, OpReturnValueIsVoid) {
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpReturnValue value's type <id> '1' is missing or void."));
 }
 
 TEST_F(ValidateIdWithMessage, OpReturnValueIsVariableInPhysical) {
@@ -3295,6 +3473,9 @@ TEST_F(ValidateIdWithMessage, OpReturnValueIsVariableInLogical) {
      OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpReturnValue value's type <id> '3' is a pointer, "
+                        "which is invalid in the Logical addressing model."));
 }
 
 // TODO: enable when this bug is fixed:
@@ -3318,6 +3499,9 @@ TEST_F(ValidateIdWithMessage, UndefinedTypeId) {
 )";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Forward reference operands in an OpTypeStruct must "
+                        "first be declared using OpTypeForwardPointer."));
 }
 
 TEST_F(ValidateIdWithMessage, UndefinedIdScope) {
@@ -3334,6 +3518,7 @@ TEST_F(ValidateIdWithMessage, UndefinedIdScope) {
 )";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(), HasSubstr("ID 7 has not been defined"));
 }
 
 TEST_F(ValidateIdWithMessage, UndefinedIdMemSem) {
@@ -3350,6 +3535,7 @@ TEST_F(ValidateIdWithMessage, UndefinedIdMemSem) {
 )";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(), HasSubstr("ID 7 has not been defined"));
 }
 
 TEST_F(ValidateIdWithMessage,
@@ -3455,6 +3641,9 @@ TEST_F(ValidateIdWithMessage, OpLoadBitcastNonPointerBad) {
       OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpLoad type for pointer <id> '11' is not a pointer type."));
 }
 TEST_F(ValidateIdWithMessage, OpStoreBitcastPointerGood) {
   string spirv = kOpenCLMemoryModel64 + R"(
@@ -3492,6 +3681,9 @@ TEST_F(ValidateIdWithMessage, OpStoreBitcastNonPointerBad) {
       OpFunctionEnd)";
   CompileSuccessfully(spirv.c_str());
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("OpStore type for pointer <id> '11' is not a pointer type."));
 }
 
 // Result <id> resulting from an instruction within a function may not be used
index e8b4247..172f14a 100644 (file)
@@ -225,6 +225,10 @@ TEST_F(ValidateLayout, MemoryModelMissing) {
 
   CompileSuccessfully(str);
   ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "EntryPoint cannot appear before the memory model instruction"));
 }
 
 TEST_F(ValidateLayout, FunctionDefinitionBeforeDeclarationBad) {
@@ -249,6 +253,10 @@ TEST_F(ValidateLayout, FunctionDefinitionBeforeDeclarationBad) {
 
   CompileSuccessfully(str);
   ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "Function declarations must appear before function definitions."));
 }
 
 // TODO(umar): Passes but gives incorrect error message. Should be fixed after
@@ -273,6 +281,9 @@ TEST_F(ValidateLayout, LabelBeforeFunctionParameterBad) {
 
   CompileSuccessfully(str);
   ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Function parameters must only appear immediately "
+                        "after the function definition"));
 }
 
 TEST_F(ValidateLayout, FuncParameterNotImmediatlyAfterFuncBad) {
@@ -298,6 +309,9 @@ TEST_F(ValidateLayout, FuncParameterNotImmediatlyAfterFuncBad) {
 
   CompileSuccessfully(str);
   ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Function parameters must only appear immediately "
+                        "after the function definition"));
 }
 
 TEST_F(ValidateLayout, OpUndefCanAppearInTypeDeclarationSection) {
index d26a860..5c7a4e3 100644 (file)
@@ -21,6 +21,8 @@
 #include "gmock/gmock.h"
 #include "val_fixtures.h"
 
+using ::testing::HasSubstr;
+
 using ValidateStorage = spvtest::ValidateBase<std::string>;
 
 namespace {
@@ -63,6 +65,9 @@ TEST_F(ValidateStorage, FunctionStorageOutsideFunction) {
 
   CompileSuccessfully(str);
   ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Variables can not have a function[7] storage class "
+                        "outside of a function"));
 }
 
 TEST_F(ValidateStorage, OtherStorageOutsideFunction) {
@@ -118,6 +123,8 @@ TEST_P(ValidateStorage, OtherStorageInsideFunction) {
 
   CompileSuccessfully(ss.str());
   ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(), HasSubstr(
+      "Variables must have a function[7] storage class inside of a function"));
 }
 
 INSTANTIATE_TEST_CASE_P(MatrixOp, ValidateStorage,
@@ -144,6 +151,8 @@ TEST_F(ValidateStorage, GenericVariableOutsideFunction) {
 )";
   CompileSuccessfully(str);
   ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpVariable storage class cannot be Generic"));
 }
 
 TEST_F(ValidateStorage, GenericVariableInsideFunction) {
@@ -163,5 +172,7 @@ TEST_F(ValidateStorage, GenericVariableInsideFunction) {
 )";
   CompileSuccessfully(str);
   ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpVariable storage class cannot be Generic"));
 }
 }