// Copyright (c) 2015-2016 The Khronos Group Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Common validation fixtures for unit tests #ifndef TEST_VAL_VAL_FIXTURES_H_ #define TEST_VAL_VAL_FIXTURES_H_ #include #include #include "source/val/validation_state.h" #include "spirv-tools/libspirv.h" #include "test/test_fixture.h" #include "test/unit_spirv.h" namespace spvtest { template class ValidateBase : public ::testing::Test, public ::testing::WithParamInterface { public: ValidateBase(); virtual void TearDown(); // Returns the a spv_const_binary struct spv_const_binary get_const_binary(); // Assembles the given SPIR-V text, checks that it fails to assemble, // and returns resulting diagnostic. No internal state is updated. std::string CompileFailure(std::string code, spv_target_env env = SPV_ENV_UNIVERSAL_1_0); // Checks that 'code' is valid SPIR-V text representation and stores the // binary version for further method calls. void CompileSuccessfully(std::string code, spv_target_env env = SPV_ENV_UNIVERSAL_1_0); // Overwrites the word at index 'index' with the given word. // For testing purposes, it is often useful to be able to manipulate the // assembled binary before running the validator on it. // This function overwrites the word at the given index with a new word. void OverwriteAssembledBinary(uint32_t index, uint32_t word); // Performs validation on the SPIR-V code. spv_result_t ValidateInstructions(spv_target_env env = SPV_ENV_UNIVERSAL_1_0); // Performs validation. Returns the status and stores validation state into // the vstate_ member. 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(); spv_binary binary_; spv_diagnostic diagnostic_; spv_validator_options options_; std::unique_ptr vstate_; }; template ValidateBase::ValidateBase() : binary_(nullptr), diagnostic_(nullptr) { // Initialize to default command line options. Different tests can then // specialize specific options as necessary. options_ = spvValidatorOptionsCreate(); } template spv_const_binary ValidateBase::get_const_binary() { return spv_const_binary(binary_); } template void ValidateBase::TearDown() { if (diagnostic_) { spvDiagnosticPrint(diagnostic_); } DestroyBinary(); DestroyDiagnostic(); spvValidatorOptionsDestroy(options_); } template std::string ValidateBase::CompileFailure(std::string code, spv_target_env env) { spv_diagnostic diagnostic = nullptr; EXPECT_NE(SPV_SUCCESS, spvTextToBinary(ScopedContext(env).context, code.c_str(), code.size(), &binary_, &diagnostic)); std::string result(diagnostic->error); spvDiagnosticDestroy(diagnostic); return result; } template void ValidateBase::CompileSuccessfully(std::string code, spv_target_env env) { DestroyBinary(); spv_diagnostic diagnostic = nullptr; ScopedContext context(env); auto status = spvTextToBinary(context.context, code.c_str(), code.size(), &binary_, &diagnostic); EXPECT_EQ(SPV_SUCCESS, status) << "ERROR: " << diagnostic->error << "\nSPIR-V could not be compiled into binary:\n" << code; ASSERT_EQ(SPV_SUCCESS, status); spvDiagnosticDestroy(diagnostic); } template void ValidateBase::OverwriteAssembledBinary(uint32_t index, uint32_t word) { ASSERT_TRUE(index < binary_->wordCount) << "OverwriteAssembledBinary: The given index is larger than the binary " "word count."; binary_->code[index] = word; } template spv_result_t ValidateBase::ValidateInstructions(spv_target_env env) { DestroyDiagnostic(); if (binary_ == nullptr) { fprintf(stderr, "ERROR: Attempting to validate a null binary, did you forget to " "call CompileSuccessfully?"); fflush(stderr); } assert(binary_ != nullptr); return spvValidateWithOptions(ScopedContext(env).context, options_, get_const_binary(), &diagnostic_); } template spv_result_t ValidateBase::ValidateAndRetrieveValidationState( spv_target_env env) { DestroyDiagnostic(); return spvtools::val::ValidateBinaryAndKeepValidationState( ScopedContext(env).context, options_, get_const_binary()->code, get_const_binary()->wordCount, &diagnostic_, &vstate_); } template std::string ValidateBase::getDiagnosticString() { return diagnostic_ == nullptr ? std::string() : std::string(diagnostic_->error); } template spv_validator_options ValidateBase::getValidatorOptions() { return options_; } template spv_position_t ValidateBase::getErrorPosition() { return diagnostic_ == nullptr ? spv_position_t() : diagnostic_->position; } } // namespace spvtest #endif // TEST_VAL_VAL_FIXTURES_H_