#ifdef TESTS_BUILD #include #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