AngelscriptLanguageServer/server/src/tests/AsTypeDefTests/TypeDefTests.cpp

441 lines
14 KiB
C++

#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "../../extern/doctest.hpp"
#include "../../src/ASTypeDefParser/Parser.hpp"
TEST_CASE("Register Empty Type") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, "type foo{}");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
REQUIRE(engine->GetTypeInfoByName("foo") != nullptr);
engine->Release();
}
void MessageCallback(const asSMessageInfo *msg, void *param)
{
const char *type = "ERR ";
if( msg->type == asMSGTYPE_WARNING )
type = "WARN";
else if( msg->type == asMSGTYPE_INFORMATION )
type = "INFO";
printf("%s (%d, %d) : %s : %s\n", msg->section, msg->row, msg->col, type, msg->message);
}
TEST_CASE("Register Empty Value Type") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, "valuetype foo{}");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
REQUIRE(engine->GetTypeInfoByName("foo") != nullptr);
engine->Release();
}
TEST_CASE("Register Empty Type With Semicolon") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, "type foo;");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
REQUIRE(engine->GetTypeInfoByName("foo") != nullptr);
engine->Release();
}
TEST_CASE("Register Multiple Empty Types") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, "type foo{} type bar{}");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
REQUIRE(engine->GetTypeInfoByName("foo") != nullptr);
REQUIRE(engine->GetTypeInfoByName("bar") != nullptr);
engine->Release();
}
TEST_CASE("Register Type With Method") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
type foo {
int Bar(int a, int b);
}
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto type = engine->GetTypeInfoByName("foo");
REQUIRE(type != nullptr);
auto method = type->GetMethodByName("Bar");
REQUIRE(method != nullptr);
REQUIRE_EQ(method->GetParamCount(), 2);
REQUIRE_EQ(std::string(method->GetDeclaration(false, false, true)), "int Bar(int a, int b)");
engine->Release();
}
TEST_CASE("Register Type With Multiple Methods") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
type foo {
int Bar(int a, int b);
int Zet(int a, int b);
}
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto type = engine->GetTypeInfoByName("foo");
REQUIRE(type != nullptr);
auto method = type->GetMethodByName("Bar");
REQUIRE(method != nullptr);
REQUIRE_EQ(method->GetParamCount(), 2);
REQUIRE_EQ(std::string(method->GetDeclaration(false, false, true)), "int Bar(int a, int b)");
method = type->GetMethodByName("Zet");
REQUIRE(method != nullptr);
engine->Release();
}
TEST_CASE("Register Generic Type With Method") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
type foo<class T> {
T@ Bar(int a, int b);
}
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto type = engine->GetTypeInfoByName("foo");
REQUIRE(type != nullptr);
REQUIRE(type == engine->GetTypeInfoByDecl("foo<T>"));
auto method = type->GetMethodByName("Bar");
REQUIRE(method != nullptr);
REQUIRE_EQ(method->GetParamCount(), 2);
REQUIRE_EQ(std::string(method->GetDeclaration(false, false, true)), "T@ Bar(int a, int b)");
engine->Release();
}
TEST_CASE("Register Generic Type With Multiple implementations") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
type foo<class T> {
T@ Bar(int a, int b);
}
type a {
foo<int> GetFoo();
}
type b {
foo<int> GetBar();
}
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto type = engine->GetTypeInfoByName("foo");
REQUIRE(type != nullptr);
REQUIRE(type == engine->GetTypeInfoByDecl("foo<T>"));
auto method = type->GetMethodByName("Bar");
REQUIRE(method != nullptr);
REQUIRE_EQ(method->GetParamCount(), 2);
REQUIRE_EQ(std::string(method->GetDeclaration(false, false, true)), "T@ Bar(int a, int b)");
engine->Release();
}
TEST_CASE("Register Type With Get Property") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
type foo {
int Bar { get; };
}
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto type = engine->GetTypeInfoByName("foo");
REQUIRE(type != nullptr);
auto method = type->GetMethodByName("get_Bar");
REQUIRE(method != nullptr);
REQUIRE_EQ(std::string(method->GetDeclaration(false, false, true)), "int get_Bar()");
engine->Release();
}
TEST_CASE("Register Type With Get Const Property") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
type foo {
int Bar { get const; };
}
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto type = engine->GetTypeInfoByName("foo");
REQUIRE(type != nullptr);
auto method = type->GetMethodByName("get_Bar");
REQUIRE(method != nullptr);
REQUIRE_EQ(std::string(method->GetDeclaration(false, false, true)), "int get_Bar() const");
engine->Release();
}
TEST_CASE("Register Type With Set Property") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
type foo {
int Bar { set; };
}
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto type = engine->GetTypeInfoByName("foo");
REQUIRE(type != nullptr);
auto method = type->GetMethodByName("set_Bar");
REQUIRE(method != nullptr);
REQUIRE_EQ(std::string(method->GetDeclaration(false, false, true)), "void set_Bar(int value)");
engine->Release();
}
TEST_CASE("Register Type With Set Const Property") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
type foo {
int Bar { set const; };
}
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto type = engine->GetTypeInfoByName("foo");
REQUIRE(type != nullptr);
auto method = type->GetMethodByName("set_Bar");
REQUIRE(method != nullptr);
REQUIRE_EQ(std::string(method->GetDeclaration(false, false, true)), "void set_Bar(int value) const");
engine->Release();
}
TEST_CASE("Register Type With Set Property") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
type foo {
int Bar { set; };
}
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto type = engine->GetTypeInfoByName("foo");
REQUIRE(type != nullptr);
auto method = type->GetMethodByName("set_Bar");
REQUIRE(method != nullptr);
REQUIRE_EQ(std::string(method->GetDeclaration(false, false, true)), "void set_Bar(int value)");
engine->Release();
}
TEST_CASE("Register Type With Getter and Setter Property") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
type foo {
int Bar { get; set; };
}
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto type = engine->GetTypeInfoByName("foo");
REQUIRE(type != nullptr);
auto method = type->GetMethodByName("get_Bar");
REQUIRE(method != nullptr);
REQUIRE_EQ(std::string(method->GetDeclaration(false, false, true)), "int get_Bar()");
method = type->GetMethodByName("set_Bar");
REQUIRE(method != nullptr);
REQUIRE_EQ(std::string(method->GetDeclaration(false, false, true)), "void set_Bar(int value)");
engine->Release();
}
TEST_CASE("Register Type With Multiple Getter and Setter Properties") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
type foo {
int Bar { get; set; };
int Zet { get; set; };
}
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto type = engine->GetTypeInfoByName("foo");
REQUIRE(type != nullptr);
auto method = type->GetMethodByName("get_Bar");
REQUIRE(method != nullptr);
REQUIRE_EQ(std::string(method->GetDeclaration(false, false, true)), "int get_Bar()");
method = type->GetMethodByName("set_Bar");
REQUIRE(method != nullptr);
REQUIRE_EQ(std::string(method->GetDeclaration(false, false, true)), "void set_Bar(int value)");
method = type->GetMethodByName("get_Zet");
REQUIRE(method != nullptr);
REQUIRE_EQ(std::string(method->GetDeclaration(false, false, true)), "int get_Zet()");
method = type->GetMethodByName("set_Zet");
REQUIRE(method != nullptr);
REQUIRE_EQ(std::string(method->GetDeclaration(false, false, true)), "void set_Zet(int value)");
engine->Release();
}
TEST_CASE("Register Empty Enum") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
enum foo {
}
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto type = engine->GetTypeInfoByName("foo");
REQUIRE(type != nullptr);
REQUIRE(type->GetTypeId() % asOBJ_ENUM != 0);
engine->Release();
}
TEST_CASE("Register Enum with value") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
enum foo {
One
}
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto type = engine->GetTypeInfoByName("foo");
REQUIRE(type != nullptr);
REQUIRE(type->GetTypeId() % asOBJ_ENUM != 0);
int i = -1;
REQUIRE_EQ(std::string(type->GetEnumValueByIndex(0, &i)), "One");
REQUIRE_EQ(i, 0);
engine->Release();
}
TEST_CASE("Register Enum with multiple values") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
enum foo {
One,
Two
}
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto type = engine->GetTypeInfoByName("foo");
REQUIRE(type != nullptr);
REQUIRE(type->GetTypeId() % asOBJ_ENUM != 0);
int i = -1;
REQUIRE_EQ(std::string(type->GetEnumValueByIndex(0, &i)), "One");
REQUIRE_EQ(i, 0);
REQUIRE_EQ(std::string(type->GetEnumValueByIndex(1, &i)), "Two");
REQUIRE_EQ(i, 1);
engine->Release();
}
TEST_CASE("Register Enum with explicit value") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
enum foo {
One = 5
}
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto type = engine->GetTypeInfoByName("foo");
REQUIRE(type != nullptr);
REQUIRE(type->GetTypeId() % asOBJ_ENUM != 0);
int i = -1;
REQUIRE_EQ(std::string(type->GetEnumValueByIndex(0, &i)), "One");
REQUIRE_EQ(i, 5);
engine->Release();
}
TEST_CASE("Register Enum with multiple explicit values") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
enum foo {
One = 5,
Two = 1,
Three = -1000,
}
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto type = engine->GetTypeInfoByName("foo");
REQUIRE(type != nullptr);
REQUIRE(type->GetTypeId() % asOBJ_ENUM != 0);
int i = -1;
REQUIRE_EQ(std::string(type->GetEnumValueByIndex(0, &i)), "One");
REQUIRE_EQ(i, 5);
REQUIRE_EQ(std::string(type->GetEnumValueByIndex(1, &i)), "Two");
REQUIRE_EQ(i, 1);
REQUIRE_EQ(std::string(type->GetEnumValueByIndex(2, &i)), "Three");
REQUIRE_EQ(i, -1000);
engine->Release();
}
TEST_CASE("Register Global Function") {
asIScriptEngine* engine = asCreateScriptEngine();
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
func void print(int i);
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto func = engine->GetGlobalFunctionByDecl("void print(int i)");
REQUIRE(func != nullptr);
engine->Release();
}
TEST_CASE("Register Type With Behaviour") {
asIScriptEngine* engine = asCreateScriptEngine();
engine->SetMessageCallback(asFUNCTION(MessageCallback), 0, asCALL_CDECL);
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
type fooClass {
behave 4 fooClass@ f(int &in) {repeat int};
}
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto type = engine->GetTypeInfoByName("fooClass");
REQUIRE(type != nullptr);
REQUIRE_EQ(type->GetBehaviourCount(), 1);
asEBehaviours b;
REQUIRE_EQ(std::string(type->GetBehaviourByIndex(0, &b)->GetDeclaration()), "fooClass@ $list(int&in) { repeat int }");
engine->Release();
}
TEST_CASE("Register Type and func") {
asIScriptEngine* engine = asCreateScriptEngine();
engine->SetMessageCallback(asFUNCTION(MessageCallback), 0, asCALL_CDECL);
ASTypeDefParser::TypeDefResult res;
ASTypeDefParser::Parser::ParseAndRegister(res, R"(
type fooClass {
void Foo();
}
func fooClass@ CreateFoo();
)");
res.RegisterTypes(engine);
res.RegisterImplementation(engine);
auto type = engine->GetTypeInfoByName("fooClass");
REQUIRE(type != nullptr);
auto func = engine->GetGlobalFunctionByDecl("fooClass@ CreateFoo()");
REQUIRE(func != nullptr);
engine->Release();
}