#include "gtest/gtest.h"
#include "source/table.h"
#include "spirv-tools/libspirv.h"
namespace spvtools {
namespace {
#ifndef SPIRV_TOOLS_SHAREDLIB
void SetContextMessageConsumer(spv_context context, MessageConsumer consumer) {
spvtools::SetContextMessageConsumer(context, consumer);
}
#else
void SetContextMessageConsumer(spv_context, MessageConsumer) {}
#endif
TEST(CInterface, DefaultConsumerNullDiagnosticForValidInput) {
auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1);
const char input_text[] =
"OpCapability Shader\n"
"OpCapability Linkage\n"
"OpMemoryModel Logical GLSL450";
spv_binary binary = nullptr;
EXPECT_EQ(SPV_SUCCESS, spvTextToBinary(context, input_text,
sizeof(input_text), &binary, nullptr));
{
spv_const_binary_t b{binary->code, binary->wordCount};
EXPECT_EQ(SPV_SUCCESS, spvValidate(context, &b, nullptr));
}
spv_text text = nullptr;
EXPECT_EQ(SPV_SUCCESS, spvBinaryToText(context, binary->code,
binary->wordCount, 0, &text, nullptr));
spvTextDestroy(text);
spvBinaryDestroy(binary);
spvContextDestroy(context);
}
TEST(CInterface, DefaultConsumerNullDiagnosticForInvalidAssembling) {
auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1);
const char input_text[] = "%1 = OpName";
spv_binary binary = nullptr;
EXPECT_EQ(SPV_ERROR_INVALID_TEXT,
spvTextToBinary(context, input_text, sizeof(input_text), &binary,
nullptr));
spvBinaryDestroy(binary);
spvContextDestroy(context);
}
TEST(CInterface, DefaultConsumerNullDiagnosticForInvalidDiassembling) {
auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1);
const char input_text[] = "OpNop";
spv_binary binary = nullptr;
ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(context, input_text,
sizeof(input_text), &binary, nullptr));
binary->code[binary->wordCount - 1] = 0xffffffff;
spv_text text = nullptr;
EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
spvBinaryToText(context, binary->code, binary->wordCount, 0, &text,
nullptr));
spvTextDestroy(text);
spvBinaryDestroy(binary);
spvContextDestroy(context);
}
TEST(CInterface, DefaultConsumerNullDiagnosticForInvalidValidating) {
auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1);
const char input_text[] = "OpNop";
spv_binary binary = nullptr;
ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(context, input_text,
sizeof(input_text), &binary, nullptr));
spv_const_binary_t b{binary->code, binary->wordCount};
EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT, spvValidate(context, &b, nullptr));
spvBinaryDestroy(binary);
spvContextDestroy(context);
}
TEST(CInterface, SpecifyConsumerNullDiagnosticForAssembling) {
const char input_text[] = " OpName\n";
auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1);
int invocation = 0;
SetContextMessageConsumer(
context,
[&invocation](spv_message_level_t level, const char* source,
const spv_position_t& position, const char* message) {
++invocation;
EXPECT_EQ(SPV_MSG_ERROR, level);
EXPECT_STREQ("input", source);
EXPECT_EQ(1u, position.line);
EXPECT_EQ(0u, position.column);
EXPECT_EQ(12u, position.index);
EXPECT_STREQ(
"Expected operand for OpName instruction, but found the end of the "
"stream.",
message);
});
spv_binary binary = nullptr;
EXPECT_EQ(SPV_ERROR_INVALID_TEXT,
spvTextToBinary(context, input_text, sizeof(input_text), &binary,
nullptr));
#ifndef SPIRV_TOOLS_SHAREDLIB
EXPECT_EQ(1, invocation);
#endif
spvBinaryDestroy(binary);
spvContextDestroy(context);
}
TEST(CInterface, SpecifyConsumerNullDiagnosticForDisassembling) {
const char input_text[] = "OpNop";
auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1);
int invocation = 0;
SetContextMessageConsumer(
context,
[&invocation](spv_message_level_t level, const char* source,
const spv_position_t& position, const char* message) {
++invocation;
EXPECT_EQ(SPV_MSG_ERROR, level);
EXPECT_STREQ("input", source);
EXPECT_EQ(0u, position.line);
EXPECT_EQ(0u, position.column);
EXPECT_EQ(1u, position.index);
EXPECT_STREQ("Invalid opcode: 65535", message);
});
spv_binary binary = nullptr;
ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(context, input_text,
sizeof(input_text), &binary, nullptr));
binary->code[binary->wordCount - 1] = 0xffffffff;
spv_text text = nullptr;
EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
spvBinaryToText(context, binary->code, binary->wordCount, 0, &text,
nullptr));
#ifndef SPIRV_TOOLS_SHAREDLIB
EXPECT_EQ(1, invocation);
#endif
spvTextDestroy(text);
spvBinaryDestroy(binary);
spvContextDestroy(context);
}
TEST(CInterface, SpecifyConsumerNullDiagnosticForValidating) {
const char input_text[] = "OpNop";
auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1);
int invocation = 0;
SetContextMessageConsumer(
context,
[&invocation](spv_message_level_t level, const char* source,
const spv_position_t& position, const char* message) {
++invocation;
EXPECT_EQ(SPV_MSG_ERROR, level);
EXPECT_STREQ("input", source);
EXPECT_EQ(0u, position.line);
EXPECT_EQ(0u, position.column);
EXPECT_EQ(1u, position.index);
EXPECT_STREQ(
"Nop cannot appear before the memory model instruction\n"
" OpNop\n",
message);
});
spv_binary binary = nullptr;
ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(context, input_text,
sizeof(input_text), &binary, nullptr));
spv_const_binary_t b{binary->code, binary->wordCount};
EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT, spvValidate(context, &b, nullptr));
#ifndef SPIRV_TOOLS_SHAREDLIB
EXPECT_EQ(1, invocation);
#endif
spvBinaryDestroy(binary);
spvContextDestroy(context);
}
TEST(CInterface, SpecifyConsumerSpecifyDiagnosticForAssembling) {
const char input_text[] = " OpName";
auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1);
int invocation = 0;
SetContextMessageConsumer(
context,
[&invocation](spv_message_level_t, const char*, const spv_position_t&,
const char*) { ++invocation; });
spv_binary binary = nullptr;
spv_diagnostic diagnostic = nullptr;
EXPECT_EQ(SPV_ERROR_INVALID_TEXT,
spvTextToBinary(context, input_text, sizeof(input_text), &binary,
&diagnostic));
EXPECT_EQ(0, invocation); EXPECT_STREQ(
"Expected operand for OpName instruction, but found the end of the "
"stream.",
diagnostic->error);
spvDiagnosticDestroy(diagnostic);
spvBinaryDestroy(binary);
spvContextDestroy(context);
}
TEST(CInterface, SpecifyConsumerSpecifyDiagnosticForDisassembling) {
const char input_text[] = "OpNop";
auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1);
int invocation = 0;
SetContextMessageConsumer(
context,
[&invocation](spv_message_level_t, const char*, const spv_position_t&,
const char*) { ++invocation; });
spv_binary binary = nullptr;
ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(context, input_text,
sizeof(input_text), &binary, nullptr));
binary->code[binary->wordCount - 1] = 0xffffffff;
spv_diagnostic diagnostic = nullptr;
spv_text text = nullptr;
EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
spvBinaryToText(context, binary->code, binary->wordCount, 0, &text,
&diagnostic));
EXPECT_EQ(0, invocation); EXPECT_STREQ("Invalid opcode: 65535", diagnostic->error);
spvTextDestroy(text);
spvDiagnosticDestroy(diagnostic);
spvBinaryDestroy(binary);
spvContextDestroy(context);
}
TEST(CInterface, SpecifyConsumerSpecifyDiagnosticForValidating) {
const char input_text[] = "OpNop";
auto context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1);
int invocation = 0;
SetContextMessageConsumer(
context,
[&invocation](spv_message_level_t, const char*, const spv_position_t&,
const char*) { ++invocation; });
spv_binary binary = nullptr;
ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(context, input_text,
sizeof(input_text), &binary, nullptr));
spv_diagnostic diagnostic = nullptr;
spv_const_binary_t b{binary->code, binary->wordCount};
EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT, spvValidate(context, &b, &diagnostic));
EXPECT_EQ(0, invocation); EXPECT_STREQ(
"Nop cannot appear before the memory model instruction\n"
" OpNop\n",
diagnostic->error);
spvDiagnosticDestroy(diagnostic);
spvBinaryDestroy(binary);
spvContextDestroy(context);
}
} }