Fix leaks in tests (#2295)

Generally, a test fixture in a method that can generate a binary
should release any previously cached binary.  Similarly for diagnostics.
diff --git a/test/binary_parse_test.cpp b/test/binary_parse_test.cpp
index dfff79d..749e12f 100644
--- a/test/binary_parse_test.cpp
+++ b/test/binary_parse_test.cpp
@@ -197,6 +197,8 @@
 
 class BinaryParseTest : public spvtest::TextToBinaryTestBase<::testing::Test> {
  protected:
+  ~BinaryParseTest() { spvDiagnosticDestroy(diagnostic_); }
+
   void Parse(const SpirvVector& words, spv_result_t expected_result,
              bool flip_words = false) {
     SpirvVector flipped_words(words);
diff --git a/test/binary_to_text_test.cpp b/test/binary_to_text_test.cpp
index 016041f..00ac86b 100644
--- a/test/binary_to_text_test.cpp
+++ b/test/binary_to_text_test.cpp
@@ -34,8 +34,12 @@
 
 class BinaryToText : public ::testing::Test {
  public:
-  BinaryToText() : context(spvContextCreate(SPV_ENV_UNIVERSAL_1_0)) {}
-  ~BinaryToText() { spvContextDestroy(context); }
+  BinaryToText()
+      : context(spvContextCreate(SPV_ENV_UNIVERSAL_1_0)), binary(nullptr) {}
+  ~BinaryToText() {
+    spvBinaryDestroy(binary);
+    spvContextDestroy(context);
+  }
 
   virtual void SetUp() {
     const char* textStr = R"(
@@ -63,17 +67,20 @@
     spv_diagnostic diagnostic = nullptr;
     spv_result_t error =
         spvTextToBinary(context, text.str, text.length, &binary, &diagnostic);
-    if (error) {
-      spvDiagnosticPrint(diagnostic);
-      spvDiagnosticDestroy(diagnostic);
-      ASSERT_EQ(SPV_SUCCESS, error);
-    }
+    spvDiagnosticPrint(diagnostic);
+    spvDiagnosticDestroy(diagnostic);
+    ASSERT_EQ(SPV_SUCCESS, error);
   }
 
-  virtual void TearDown() { spvBinaryDestroy(binary); }
+  virtual void TearDown() {
+    spvBinaryDestroy(binary);
+    binary = nullptr;
+  }
 
   // Compiles the given assembly text, and saves it into 'binary'.
   void CompileSuccessfully(std::string text) {
+    spvBinaryDestroy(binary);
+    binary = nullptr;
     spv_diagnostic diagnostic = nullptr;
     EXPECT_EQ(SPV_SUCCESS, spvTextToBinary(context, text.c_str(), text.size(),
                                            &binary, &diagnostic));
diff --git a/test/ext_inst.glsl_test.cpp b/test/ext_inst.glsl_test.cpp
index 991c487..f52337c 100644
--- a/test/ext_inst.glsl_test.cpp
+++ b/test/ext_inst.glsl_test.cpp
@@ -61,7 +61,7 @@
 ; Generator: Khronos SPIR-V Tools Assembler; 0
 ; Bound: 9
 ; Schema: 0)";
-  spv_binary binary;
+  spv_binary binary = nullptr;
   spv_diagnostic diagnostic;
   spv_result_t error = spvTextToBinary(context, spirv.c_str(), spirv.size(),
                                        &binary, &diagnostic);
@@ -102,6 +102,7 @@
   }
   EXPECT_EQ(spirv_header + spirv, output_text->str);
   spvTextDestroy(output_text);
+  spvBinaryDestroy(binary);
   spvContextDestroy(context);
 }
 
diff --git a/test/test_fixture.h b/test/test_fixture.h
index e85015c..436993e 100644
--- a/test/test_fixture.h
+++ b/test/test_fixture.h
@@ -61,6 +61,8 @@
   // compilation success. Returns the compiled code.
   SpirvVector CompileSuccessfully(const std::string& txt,
                                   spv_target_env env = SPV_ENV_UNIVERSAL_1_0) {
+    DestroyBinary();
+    DestroyDiagnostic();
     spv_result_t status =
         spvTextToBinary(ScopedContext(env).context, txt.c_str(), txt.size(),
                         &binary, &diagnostic);
@@ -79,6 +81,8 @@
   // Returns the error message(s).
   std::string CompileFailure(const std::string& txt,
                              spv_target_env env = SPV_ENV_UNIVERSAL_1_0) {
+    DestroyBinary();
+    DestroyDiagnostic();
     EXPECT_NE(SPV_SUCCESS,
               spvTextToBinary(ScopedContext(env).context, txt.c_str(),
                               txt.size(), &binary, &diagnostic))
@@ -94,6 +98,7 @@
       uint32_t disassemble_options = SPV_BINARY_TO_TEXT_OPTION_NONE,
       spv_target_env env = SPV_ENV_UNIVERSAL_1_0) {
     DestroyBinary();
+    DestroyDiagnostic();
     ScopedContext context(env);
     disassemble_options |= SPV_BINARY_TO_TEXT_OPTION_NO_HEADER;
     spv_result_t error = spvTextToBinary(context.context, txt.c_str(),
@@ -126,6 +131,8 @@
   // Returns the error message.
   std::string EncodeSuccessfullyDecodeFailed(
       const std::string& txt, const SpirvVector& words_to_append) {
+    DestroyBinary();
+    DestroyDiagnostic();
     SpirvVector code =
         spvtest::Concatenate({CompileSuccessfully(txt), words_to_append});
 
@@ -169,6 +176,12 @@
     binary = nullptr;
   }
 
+  // Destroys the diagnostic, if it exists.
+  void DestroyDiagnostic() {
+    spvDiagnosticDestroy(diagnostic);
+    diagnostic = nullptr;
+  }
+
   spv_diagnostic diagnostic;
 
   std::string textString;
diff --git a/test/val/val_fixtures.h b/test/val/val_fixtures.h
index 73a0cc6..69bc9d8 100644
--- a/test/val/val_fixtures.h
+++ b/test/val/val_fixtures.h
@@ -56,6 +56,18 @@
   spv_result_t ValidateAndRetrieveValidationState(
       spv_target_env env = SPV_ENV_UNIVERSAL_1_0);
 
+  // Destroys the stored binary.
+  void DestroyBinary() {
+    spvBinaryDestroy(binary_);
+    binary_ = nullptr;
+  }
+
+  // Destroys the stored diagnostic.
+  void DestroyDiagnostic() {
+    spvDiagnosticDestroy(diagnostic_);
+    diagnostic_ = nullptr;
+  }
+
   std::string getDiagnosticString();
   spv_position_t getErrorPosition();
   spv_validator_options getValidatorOptions();
@@ -67,7 +79,7 @@
 };
 
 template <typename T>
-ValidateBase<T>::ValidateBase() : binary_(), diagnostic_() {
+ValidateBase<T>::ValidateBase() : binary_(nullptr), diagnostic_(nullptr) {
   // Initialize to default command line options. Different tests can then
   // specialize specific options as necessary.
   options_ = spvValidatorOptionsCreate();
@@ -83,14 +95,15 @@
   if (diagnostic_) {
     spvDiagnosticPrint(diagnostic_);
   }
-  spvDiagnosticDestroy(diagnostic_);
-  spvBinaryDestroy(binary_);
+  DestroyBinary();
+  DestroyDiagnostic();
   spvValidatorOptionsDestroy(options_);
 }
 
 template <typename T>
 void ValidateBase<T>::CompileSuccessfully(std::string code,
                                           spv_target_env env) {
+  DestroyBinary();
   spv_diagnostic diagnostic = nullptr;
   ASSERT_EQ(SPV_SUCCESS,
             spvTextToBinary(ScopedContext(env).context, code.c_str(),
@@ -98,6 +111,7 @@
       << "ERROR: " << diagnostic->error
       << "\nSPIR-V could not be compiled into binary:\n"
       << code;
+  spvDiagnosticDestroy(diagnostic);
 }
 
 template <typename T>
@@ -110,6 +124,7 @@
 
 template <typename T>
 spv_result_t ValidateBase<T>::ValidateInstructions(spv_target_env env) {
+  DestroyDiagnostic();
   return spvValidateWithOptions(ScopedContext(env).context, options_,
                                 get_const_binary(), &diagnostic_);
 }
@@ -117,6 +132,7 @@
 template <typename T>
 spv_result_t ValidateBase<T>::ValidateAndRetrieveValidationState(
     spv_target_env env) {
+  DestroyDiagnostic();
   return spvtools::val::ValidateBinaryAndKeepValidationState(
       ScopedContext(env).context, options_, get_const_binary()->code,
       get_const_binary()->wordCount, &diagnostic_, &vstate_);
diff --git a/test/val/val_id_test.cpp b/test/val/val_id_test.cpp
index 25fac88..a09761e 100644
--- a/test/val/val_id_test.cpp
+++ b/test/val/val_id_test.cpp
@@ -780,6 +780,8 @@
   // Runs spvValidate() on v, printing any errors via spvDiagnosticPrint().
   spv_result_t Val(const SpirvVector& v, const std::string& expected_err = "") {
     spv_const_binary_t cbinary{v.data(), v.size()};
+    spvDiagnosticDestroy(diagnostic_);
+    diagnostic_ = nullptr;
     const auto status =
         spvValidate(ScopedContext().context, &cbinary, &diagnostic_);
     if (status != SPV_SUCCESS) {