#ifndef TEST_VAL_VAL_FIXTURES_H_
#define TEST_VAL_VAL_FIXTURES_H_
#include <memory>
#include <string>
#include "source/val/validation_state.h"
#include "spirv-tools/libspirv.h"
#include "test/test_fixture.h"
#include "test/unit_spirv.h"
namespace spvtest {
template <typename T>
class ValidateBase : public ::testing::Test,
public ::testing::WithParamInterface<T> {
public:
ValidateBase();
virtual void TearDown();
spv_const_binary get_const_binary();
std::string CompileFailure(std::string code,
spv_target_env env = SPV_ENV_UNIVERSAL_1_0,
spv_result_t desired_result = SPV_SUCCESS);
void CompileSuccessfully(std::string code,
spv_target_env env = SPV_ENV_UNIVERSAL_1_0);
void OverwriteAssembledBinary(uint32_t index, uint32_t word);
spv_result_t ValidateInstructions(spv_target_env env = SPV_ENV_UNIVERSAL_1_0);
spv_result_t ValidateAndRetrieveValidationState(
spv_target_env env = SPV_ENV_UNIVERSAL_1_0);
void DestroyBinary() {
spvBinaryDestroy(binary_);
binary_ = nullptr;
}
void DestroyDiagnostic() {
spvDiagnosticDestroy(diagnostic_);
diagnostic_ = nullptr;
}
void SetAssembleOptions(uint32_t options) { assemble_options_ = options; }
std::string getDiagnosticString();
spv_position_t getErrorPosition();
spv_validator_options getValidatorOptions();
spv_binary binary_;
spv_diagnostic diagnostic_;
spv_validator_options options_;
std::unique_ptr<spvtools::val::ValidationState_t> vstate_;
uint32_t assemble_options_ = SPV_TEXT_TO_BINARY_OPTION_NONE;
};
template <typename T>
ValidateBase<T>::ValidateBase() : binary_(nullptr), diagnostic_(nullptr) {
options_ = spvValidatorOptionsCreate();
}
template <typename T>
spv_const_binary ValidateBase<T>::get_const_binary() {
return spv_const_binary(binary_);
}
template <typename T>
void ValidateBase<T>::TearDown() {
if (diagnostic_) {
spvDiagnosticPrint(diagnostic_);
}
DestroyBinary();
DestroyDiagnostic();
spvValidatorOptionsDestroy(options_);
}
template <typename T>
std::string ValidateBase<T>::CompileFailure(std::string code,
spv_target_env env,
spv_result_t desired_result) {
spv_diagnostic diagnostic = nullptr;
spv_result_t actual_result =
spvTextToBinary(ScopedContext(env).context, code.c_str(), code.size(),
&binary_, &diagnostic);
EXPECT_NE(SPV_SUCCESS, actual_result);
if (desired_result != SPV_SUCCESS) {
EXPECT_EQ(actual_result, desired_result);
}
std::string result(diagnostic->error);
spvDiagnosticDestroy(diagnostic);
return result;
}
template <typename T>
void ValidateBase<T>::CompileSuccessfully(std::string code,
spv_target_env env) {
DestroyBinary();
spv_diagnostic diagnostic = nullptr;
ScopedContext context(env);
auto status =
spvTextToBinaryWithOptions(context.context, code.c_str(), code.size(),
assemble_options_, &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 <typename T>
void ValidateBase<T>::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 <typename T>
spv_result_t ValidateBase<T>::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 <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_);
}
template <typename T>
std::string ValidateBase<T>::getDiagnosticString() {
return diagnostic_ == nullptr ? std::string()
: std::string(diagnostic_->error);
}
template <typename T>
spv_validator_options ValidateBase<T>::getValidatorOptions() {
return options_;
}
template <typename T>
spv_position_t ValidateBase<T>::getErrorPosition() {
return diagnostic_ == nullptr ? spv_position_t() : diagnostic_->position;
}
}
MATCHER_P(AnyVUID, vuid_set, "VUID from the set is in error message") {
std::string delimiter = " ";
std::string token;
std::string vuids = std::string(vuid_set);
size_t position;
vuids.erase(std::find_if(vuids.rbegin(), vuids.rend(), [](unsigned char c) {
return (c != ' ');
}).base(), vuids.end());
vuids.erase(vuids.begin(), std::find_if(vuids.begin(), vuids.end(), [](unsigned char c) {
return (c != ' ');
}));
do {
position = vuids.find(delimiter);
if (position != std::string::npos) {
token = vuids.substr(0, position);
vuids.erase(0, position + delimiter.length());
} else {
token = vuids.substr(0);
}
if (arg.find(token) != std::string::npos) {
return true;
}
} while (position != std::string::npos);
return false;
}
#endif