[ir][spirv-writer] Add helper macro for unit tests

Adds an `EXPECT_INST` macro that checks for an instruction in the
output, dumping the full output if not found. Indentation and comments
are enabled in the disassembly to make it easier to see the issue.

Bug: tint:1906
Change-Id: I297207769ad992b22524c0f62fcb732e8bdd1a0f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/139481
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_access_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_access_test.cc
index 5b0d3f6..df494fb 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_access_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_access_test.cc
@@ -32,7 +32,7 @@
     });
 
     ASSERT_TRUE(Generate()) << Error();
-    EXPECT_THAT(output_, testing::HasSubstr(R"(%result = OpCompositeExtract %int %arr 1)"));
+    EXPECT_INST("%result = OpCompositeExtract %int %arr 1");
 }
 
 TEST_F(SpvGeneratorImplTest, Access_Array_Pointer_ConstantIndex) {
@@ -45,8 +45,7 @@
     });
 
     ASSERT_TRUE(Generate()) << Error();
-    EXPECT_THAT(output_,
-                testing::HasSubstr(R"(%result = OpAccessChain %_ptr_Function_int %arr %uint_1)"));
+    EXPECT_INST("%result = OpAccessChain %_ptr_Function_int %arr %uint_1");
 }
 
 TEST_F(SpvGeneratorImplTest, Access_Array_Pointer_DynamicIndex) {
@@ -61,8 +60,7 @@
     });
 
     ASSERT_TRUE(Generate()) << Error();
-    EXPECT_THAT(output_,
-                testing::HasSubstr(R"(%result = OpAccessChain %_ptr_Function_int %arr %idx)"));
+    EXPECT_INST("%result = OpAccessChain %_ptr_Function_int %arr %idx");
 }
 
 TEST_F(SpvGeneratorImplTest, Access_Matrix_Value_ConstantIndex) {
@@ -78,10 +76,8 @@
     });
 
     ASSERT_TRUE(Generate()) << Error();
-    EXPECT_THAT(output_,
-                testing::HasSubstr(R"(%result_vector = OpCompositeExtract %v2float %mat 1)"));
-    EXPECT_THAT(output_,
-                testing::HasSubstr(R"(%result_scalar = OpCompositeExtract %float %mat 1 0)"));
+    EXPECT_INST("%result_vector = OpCompositeExtract %v2float %mat 1");
+    EXPECT_INST("%result_scalar = OpCompositeExtract %float %mat 1 0");
 }
 
 TEST_F(SpvGeneratorImplTest, Access_Matrix_Pointer_ConstantIndex) {
@@ -96,12 +92,8 @@
     });
 
     ASSERT_TRUE(Generate()) << Error();
-    EXPECT_THAT(output_,
-                testing::HasSubstr(
-                    R"(%result_vector = OpAccessChain %_ptr_Function_v2float %mat %uint_1)"));
-    EXPECT_THAT(output_,
-                testing::HasSubstr(
-                    R"(%result_scalar = OpAccessChain %_ptr_Function_float %mat %uint_1 %uint_0)"));
+    EXPECT_INST("%result_vector = OpAccessChain %_ptr_Function_v2float %mat %uint_1");
+    EXPECT_INST("%result_scalar = OpAccessChain %_ptr_Function_float %mat %uint_1 %uint_0");
 }
 
 TEST_F(SpvGeneratorImplTest, Access_Matrix_Pointer_DynamicIndex) {
@@ -118,11 +110,8 @@
     });
 
     ASSERT_TRUE(Generate()) << Error();
-    EXPECT_THAT(output_, testing::HasSubstr(
-                             R"(%result_vector = OpAccessChain %_ptr_Function_v2float %mat %idx)"));
-    EXPECT_THAT(output_,
-                testing::HasSubstr(
-                    R"(%result_scalar = OpAccessChain %_ptr_Function_float %mat %idx %idx)"));
+    EXPECT_INST("%result_vector = OpAccessChain %_ptr_Function_v2float %mat %idx");
+    EXPECT_INST("%result_scalar = OpAccessChain %_ptr_Function_float %mat %idx %idx");
 }
 
 TEST_F(SpvGeneratorImplTest, Access_Vector_Value_ConstantIndex) {
@@ -136,7 +125,7 @@
     });
 
     ASSERT_TRUE(Generate()) << Error();
-    EXPECT_THAT(output_, testing::HasSubstr(R"(%result = OpCompositeExtract %int %vec 1)"));
+    EXPECT_INST("%result = OpCompositeExtract %int %vec 1");
 }
 
 TEST_F(SpvGeneratorImplTest, Access_Vector_Value_DynamicIndex) {
@@ -151,7 +140,7 @@
     });
 
     ASSERT_TRUE(Generate()) << Error();
-    EXPECT_THAT(output_, testing::HasSubstr(R"(%result = OpVectorExtractDynamic %int %vec %idx)"));
+    EXPECT_INST("%result = OpVectorExtractDynamic %int %vec %idx");
 }
 
 TEST_F(SpvGeneratorImplTest, Access_Vector_Pointer_ConstantIndex) {
@@ -164,8 +153,7 @@
     });
 
     ASSERT_TRUE(Generate()) << Error();
-    EXPECT_THAT(output_,
-                testing::HasSubstr(R"(%result = OpAccessChain %_ptr_Function_int %vec %uint_1)"));
+    EXPECT_INST("%result = OpAccessChain %_ptr_Function_int %vec %uint_1");
 }
 
 TEST_F(SpvGeneratorImplTest, Access_Vector_Pointer_DynamicIndex) {
@@ -180,8 +168,7 @@
     });
 
     ASSERT_TRUE(Generate()) << Error();
-    EXPECT_THAT(output_,
-                testing::HasSubstr(R"(%result = OpAccessChain %_ptr_Function_int %vec %idx)"));
+    EXPECT_INST("%result = OpAccessChain %_ptr_Function_int %vec %idx");
 }
 
 TEST_F(SpvGeneratorImplTest, Access_NestedVector_Value_DynamicIndex) {
@@ -196,8 +183,8 @@
     });
 
     ASSERT_TRUE(Generate()) << Error();
-    EXPECT_THAT(output_, testing::HasSubstr(R"(%14 = OpCompositeExtract %v4int %arr 1 2)"));
-    EXPECT_THAT(output_, testing::HasSubstr(R"(%result = OpVectorExtractDynamic %int %14 %idx)"));
+    EXPECT_INST("%14 = OpCompositeExtract %v4int %arr 1 2");
+    EXPECT_INST("%result = OpVectorExtractDynamic %int %14 %idx");
 }
 
 TEST_F(SpvGeneratorImplTest, Access_Struct_Value_ConstantIndex) {
@@ -218,8 +205,8 @@
     });
 
     ASSERT_TRUE(Generate()) << Error();
-    EXPECT_THAT(output_, testing::HasSubstr(R"(%result_a = OpCompositeExtract %float %str 0)"));
-    EXPECT_THAT(output_, testing::HasSubstr(R"(%result_b = OpCompositeExtract %int %str 1 2)"));
+    EXPECT_INST("%result_a = OpCompositeExtract %float %str 0");
+    EXPECT_INST("%result_b = OpCompositeExtract %int %str 1 2");
 }
 
 TEST_F(SpvGeneratorImplTest, Access_Struct_Pointer_ConstantIndex) {
@@ -239,11 +226,8 @@
     });
 
     ASSERT_TRUE(Generate()) << Error();
-    EXPECT_THAT(output_, testing::HasSubstr(
-                             R"(%result_a = OpAccessChain %_ptr_Function_float %str %uint_0)"));
-    EXPECT_THAT(
-        output_,
-        testing::HasSubstr(R"(%result_b = OpAccessChain %_ptr_Function_int %str %uint_1 %uint_2)"));
+    EXPECT_INST("%result_a = OpAccessChain %_ptr_Function_float %str %uint_0");
+    EXPECT_INST("%result_b = OpAccessChain %_ptr_Function_int %str %uint_1 %uint_2");
 }
 
 }  // namespace
diff --git a/src/tint/writer/spirv/ir/test_helper_ir.h b/src/tint/writer/spirv/ir/test_helper_ir.h
index debe5d8..27559be 100644
--- a/src/tint/writer/spirv/ir/test_helper_ir.h
+++ b/src/tint/writer/spirv/ir/test_helper_ir.h
@@ -27,6 +27,10 @@
 
 namespace tint::writer::spirv {
 
+// Helper macro to check whether the SPIR-V output contains an instruction, dumping the full output
+// if the instruction was not present.
+#define EXPECT_INST(inst) ASSERT_THAT(output_, testing::HasSubstr(inst)) << output_
+
 /// The element type of a test.
 enum TestElementType {
     kBool,
@@ -83,7 +87,9 @@
             return false;
         }
 
-        output_ = Disassemble(generator_.Result(), SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
+        output_ = Disassemble(generator_.Result(), SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES |
+                                                       SPV_BINARY_TO_TEXT_OPTION_INDENT |
+                                                       SPV_BINARY_TO_TEXT_OPTION_COMMENT);
         return true;
     }