PorygonLang/tests/integration/FunctionsTests.cpp

203 lines
5.6 KiB
C++

#ifdef TESTS_BUILD
#include <catch.hpp>
#include "../src/Script.hpp"
using namespace Porygon;
TEST_CASE( "Define script function", "[integration]" ) {
Script* script = Script::Create("function add(number a, number b) a + b end");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto variable = script->GetVariable(u"add");
REQUIRE(variable != nullptr);
REQUIRE(variable->GetTypeClass() == TypeClass::Function);
delete script;
delete variable;
}
TEST_CASE( "Define script function and call", "[integration]" ) {
Script* script = Script::Create("function add(number a, number b) result = a + b end add(1, 2)");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto variable = script->GetVariable(u"add");
REQUIRE(variable != nullptr);
REQUIRE(variable->GetTypeClass() == TypeClass::Function);
auto result = script->GetVariable(u"result");
REQUIRE(result->GetTypeClass() == TypeClass::Number);
REQUIRE(result->EvaluateInteger() == 3);
delete script;
delete variable;
delete result;
}
TEST_CASE( "Define script function and call multiple times", "[integration]" ) {
Script* script = Script::Create("result = 0 function add(number a) result = result + a end add(1) add(4)");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto variable = script->GetVariable(u"add");
REQUIRE(variable != nullptr);
REQUIRE(variable->GetTypeClass() == TypeClass::Function);
auto result = script->GetVariable(u"result");
REQUIRE(result->GetTypeClass() == TypeClass::Number);
REQUIRE(result->EvaluateInteger() == 5);
delete script;
delete variable;
delete result;
}
TEST_CASE( "Define script function and call from extern", "[integration]" ) {
Script* script = Script::Create("result = 0 function add(number a) result = result + a end");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
REQUIRE(script->HasFunction(u"add"));
auto toAddVal = new NumericEvalValue(5);
script->CallFunction(u"add", {toAddVal});
delete toAddVal;
toAddVal = new NumericEvalValue(6);
script->CallFunction(u"add", {toAddVal});
delete toAddVal;
auto result = script->GetVariable(u"result");
REQUIRE(result->GetTypeClass() == TypeClass::Number);
REQUIRE(result->EvaluateInteger() == 11);
delete script;
delete result;
}
TEST_CASE( "Define script function and return", "[integration]" ) {
Script* script = Script::Create(
"val = 0\n"
"function add(number a, number b) \n"
"return a + b \n"
"val = val + 1\n"
"end");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
REQUIRE(script->HasFunction(u"add"));
auto toAddVal = new NumericEvalValue(5);
auto toAddVal2 = new NumericEvalValue(6);
auto result = script->CallFunction(u"add", {toAddVal, toAddVal2});
delete toAddVal;
delete toAddVal2;
REQUIRE(result->GetTypeClass() == TypeClass::Number);
REQUIRE(result->EvaluateInteger() == 11);
auto variable = script->GetVariable(u"val");
REQUIRE(variable->GetTypeClass() == TypeClass::Number);
REQUIRE(variable->EvaluateInteger() == 0);
delete script;
delete variable;
delete result;
}
TEST_CASE( "Functions can call themselves", "[integration]" ) {
Script* script = Script::Create(
R"(
val = 0
function add()
if val < 5 then
val = val + 1
add()
end
end
)");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
script->CallFunction(u"add", {});
auto variable = script->GetVariable(u"val");
REQUIRE(variable->GetTypeClass() == TypeClass::Number);
REQUIRE(variable->EvaluateInteger() == 5);
delete script;
delete variable;
}
TEST_CASE( "Functions respect scope", "[integration]" ) {
Script* script = Script::Create(
R"(
function test()
function foo()
local a = 10
end
if true then
if true then
local a = 50
foo()
result = a
end
end
end
test()
)"
);
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto variable = script->GetVariable(u"result");
REQUIRE(variable->GetTypeClass() == TypeClass::Number);
REQUIRE(variable->EvaluateInteger() == 50);
delete script;
delete variable;
}
TEST_CASE( "Return doesn't parse next line expression", "[integration]" ) {
Script* script = Script::Create(
R"(
return
1 + 1
)"
);
REQUIRE(!script->Diagnostics -> HasErrors());
auto result = script->Evaluate();
REQUIRE(result == nullptr);
delete script;
}
TEST_CASE( "Allow declaration of multiple functions with different signatures", "[integration]" ) {
Script* script = Script::Create(
R"(
function add(number a, number b)
return a + b
end
function add(string a, string b)
return a + b
end
intResult = add(5, 500)
stringResult = add('foo', 'bar')
)"
);
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto intVar = script -> GetVariable(u"intResult");
REQUIRE(intVar != nullptr);
CHECK(intVar->EvaluateInteger() == 505);
auto stringVar = script -> GetVariable(u"stringResult");
REQUIRE(stringVar != nullptr);
CHECK(stringVar->EvaluateString() == u"foobar");
delete script;
delete intVar;
delete stringVar;
}
TEST_CASE( "Malformed parameter logs error", "[integration]" ) {
Script* script = Script::Create(uR"(
function blockOwnCritical( move, target, hitNumber )
return true
end
)");
REQUIRE(script->Diagnostics -> HasErrors());
delete script;
}
#endif