#include #include #include "Parsing/Menu/Domain/EventHandler/CommonEventHandlerScript.h" #include "Parsing/Menu/Domain/EventHandler/CommonEventHandlerSetLocalVar.h" #include "Utils/ClassUtils.h" #include "Parsing/Menu/Sequence/EventHandlerSetScopeSequences.h" #include "Parsing/Mock/MockLexer.h" using namespace menu; namespace test::parsing::menu::sequence::event_handler_set { class EventHandlerSetSequenceTestsHelper { public: std::vector> m_all_sequences; std::vector m_scope_sequences; std::unique_ptr m_state; std::unique_ptr> m_lexer; std::unique_ptr m_event_handler_set; unsigned m_consumed_token_count; explicit EventHandlerSetSequenceTestsHelper(FeatureLevel featureLevel, bool permissive) : m_state(std::make_unique(featureLevel, false)), m_event_handler_set(std::make_unique()), m_consumed_token_count(0u) { EventHandlerSetScopeSequences scopeSequences(m_all_sequences, m_scope_sequences); scopeSequences.AddSequences(m_state->m_feature_level, permissive); m_state->m_current_menu = m_state->m_menus.emplace_back(std::make_unique()).get(); m_state->m_current_event_handler_set = m_event_handler_set.get(); m_state->m_current_nested_event_handler_set = m_event_handler_set.get(); } void Tokens(std::initializer_list> tokens) { m_lexer = std::make_unique>(tokens, SimpleParserValue::EndOfFile(TokenPos())); } void Tokens(std::vector tokens) { m_lexer = std::make_unique>(std::move(tokens), SimpleParserValue::EndOfFile(TokenPos())); } bool PerformTest() { REQUIRE(m_lexer); m_consumed_token_count = 0; for (const auto* sequence : m_scope_sequences) { const auto couldMatch = sequence->MatchSequence(m_lexer.get(), m_state.get(), m_consumed_token_count); if (couldMatch) { m_lexer->PopTokens(static_cast(m_consumed_token_count)); return couldMatch; } } return false; } }; #pragma region General TEST_CASE("EventHandlerSetScopeSequences: Keyword casing doesnt matter", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Identifier(pos, new std::string("fadein")), SimpleParserValue::String(pos, new std::string("some_element")), SimpleParserValue::Character(pos, ';'), SimpleParserValue::EndOfFile(pos) }); const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 3); const auto script = helper.m_state->m_current_script.str(); REQUIRE(script == R"("fadein" "some_element" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Invalid keywords are not recognized", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Identifier(pos, new std::string("noScriptCommand")), SimpleParserValue::String(pos, new std::string("some_element")), SimpleParserValue::Character(pos, ';'), SimpleParserValue::EndOfFile(pos) }); const auto result = helper.PerformTest(); REQUIRE(!result); REQUIRE(helper.m_consumed_token_count == 0); } TEST_CASE("EventHandlerSetScopeSequences: Permissive mode ignores unknown script tokens and adds them to script", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, true); const TokenPos pos; helper.Tokens({ SimpleParserValue::Identifier(pos, new std::string("uiScript")), SimpleParserValue::Identifier(pos, new std::string("somethingUnknown")), SimpleParserValue::String(pos, new std::string("anArgumentForTheUnknownScript")), SimpleParserValue::Character(pos, ';'), SimpleParserValue::EndOfFile(pos) }); auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 1); auto script = helper.m_state->m_current_script.str(); REQUIRE(script == R"("uiScript" )"); result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 1); script = helper.m_state->m_current_script.str(); REQUIRE(script == R"("uiScript" "somethingUnknown" )"); result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 1); script = helper.m_state->m_current_script.str(); REQUIRE(script == R"("uiScript" "somethingUnknown" "anArgumentForTheUnknownScript" )"); result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 1); script = helper.m_state->m_current_script.str(); REQUIRE(script == R"("uiScript" "somethingUnknown" "anArgumentForTheUnknownScript" ; )"); } #pragma endregion void TestGenericScriptStatement(const std::initializer_list> tokens, const std::string& expectedScript) { std::vector tokenList(std::make_move_iterator(tokens.begin()), std::make_move_iterator(tokens.end())); const auto initialValueCount = tokenList.size(); tokenList.emplace_back(SimpleParserValue::Character(TokenPos(), ';')); tokenList.emplace_back(SimpleParserValue::EndOfFile(TokenPos())); EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); helper.Tokens(std::move(tokenList)); const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == initialValueCount + 1); const auto script = helper.m_state->m_current_script.str(); REQUIRE(script == expectedScript); } #pragma region Command Tests TEST_CASE("EventHandlerSetScopeSequences: Ensure can use fadeIn", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("fadeIn")), SimpleParserValue::String(TokenPos(), new std::string("some_element")) }, R"("fadeIn" "some_element" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use fadeOut", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("fadeOut")), SimpleParserValue::String(TokenPos(), new std::string("some_element")) }, R"("fadeOut" "some_element" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use show", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("show")), SimpleParserValue::String(TokenPos(), new std::string("some_element")) }, R"("show" "some_element" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use hide", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("hide")), SimpleParserValue::String(TokenPos(), new std::string("some_element")) }, R"("hide" "some_element" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use showMenu", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("showMenu")), SimpleParserValue::String(TokenPos(), new std::string("some_element")) }, R"("showMenu" "some_element" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use hideMenu", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("hideMenu")), SimpleParserValue::String(TokenPos(), new std::string("some_element")) }, R"("hideMenu" "some_element" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use setColor", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("setColor")), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Integer(TokenPos(), 1), }, R"("setColor" "1" "1" "1" "1" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use setColor with 3 colors", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("setColor")), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Integer(TokenPos(), 1), }, R"("setColor" "1" "1" "1" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use setColor with 2 colors", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("setColor")), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Integer(TokenPos(), 1), }, R"("setColor" "1" "1" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use setColor with 1 color", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("setColor")), SimpleParserValue::Integer(TokenPos(), 1), }, R"("setColor" "1" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure cannot use setColor with no color", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Identifier(pos, new std::string("setColor")), SimpleParserValue::Character(pos, ';'), SimpleParserValue::EndOfFile(pos) }); const auto result = helper.PerformTest(); REQUIRE(result == false); REQUIRE(helper.m_consumed_token_count == 0); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use open", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("open")), SimpleParserValue::String(TokenPos(), new std::string("some_element")) }, R"("open" "some_element" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use close", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("close")), SimpleParserValue::String(TokenPos(), new std::string("some_element")) }, R"("close" "some_element" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use escape", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("escape")), SimpleParserValue::String(TokenPos(), new std::string("some_element")) }, R"("escape" "some_element" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use closeForAllPlayers", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("closeForAllPlayers")), SimpleParserValue::String(TokenPos(), new std::string("some_element")) }, R"("closeForAllPlayers" "some_element" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use ingameOpen", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("ingameOpen")), SimpleParserValue::String(TokenPos(), new std::string("some_element")) }, R"("ingameOpen" "some_element" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use ingameClose", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("ingameClose")), SimpleParserValue::String(TokenPos(), new std::string("some_element")) }, R"("ingameClose" "some_element" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use setBackground", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("setBackground")), SimpleParserValue::String(TokenPos(), new std::string("some_element")) }, R"("setBackground" "some_element" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use setItemColor with forecolor", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("setItemColor")), SimpleParserValue::String(TokenPos(), new std::string("some_element")), SimpleParserValue::String(TokenPos(), new std::string("forecolor")), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Integer(TokenPos(), 1), }, R"("setItemColor" "some_element" "forecolor" "1" "1" "1" "1" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use setItemColor with backcolor", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("setItemColor")), SimpleParserValue::String(TokenPos(), new std::string("some_element")), SimpleParserValue::String(TokenPos(), new std::string("backcolor")), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Integer(TokenPos(), 1), }, R"("setItemColor" "some_element" "backcolor" "1" "1" "1" "1" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use setItemColor with bordercolor", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("setItemColor")), SimpleParserValue::String(TokenPos(), new std::string("some_element")), SimpleParserValue::String(TokenPos(), new std::string("bordercolor")), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Integer(TokenPos(), 1), }, R"("setItemColor" "some_element" "bordercolor" "1" "1" "1" "1" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use focusFirst", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("focusFirst")), }, R"("focusFirst" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use setFocus", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("setFocus")), SimpleParserValue::String(TokenPos(), new std::string("some_element")) }, R"("setFocus" "some_element" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use setFocusByDvar", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("setFocusByDvar")), SimpleParserValue::String(TokenPos(), new std::string("some_dvar")) }, R"("setFocusByDvar" "some_dvar" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use setDvar", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("setDvar")), SimpleParserValue::String(TokenPos(), new std::string("some_dvar")), SimpleParserValue::String(TokenPos(), new std::string("some_value")), }, R"("setDvar" "some_dvar" "some_value" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use exec", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("exec")), SimpleParserValue::String(TokenPos(), new std::string("some_command")) }, R"("exec" "some_command" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use execNow", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("execNow")), SimpleParserValue::String(TokenPos(), new std::string("some_command")) }, R"("execNow" "some_command" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use execOnDvarStringValue", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("execOnDvarStringValue")), SimpleParserValue::String(TokenPos(), new std::string("some_dvar")), SimpleParserValue::String(TokenPos(), new std::string("some_value")), SimpleParserValue::String(TokenPos(), new std::string("some_command")) }, R"("execOnDvarStringValue" "some_dvar" "some_value" "some_command" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use execOnDvarIntValue", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("execOnDvarIntValue")), SimpleParserValue::String(TokenPos(), new std::string("some_dvar")), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::String(TokenPos(), new std::string("some_command")) }, R"("execOnDvarIntValue" "some_dvar" "1" "some_command" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use execOnDvarFloatValue", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("execOnDvarFloatValue")), SimpleParserValue::String(TokenPos(), new std::string("some_dvar")), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::String(TokenPos(), new std::string("some_command")) }, R"("execOnDvarFloatValue" "some_dvar" "1" "some_command" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use execNowOnDvarStringValue", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("execNowOnDvarStringValue")), SimpleParserValue::String(TokenPos(), new std::string("some_dvar")), SimpleParserValue::String(TokenPos(), new std::string("some_value")), SimpleParserValue::String(TokenPos(), new std::string("some_command")) }, R"("execNowOnDvarStringValue" "some_dvar" "some_value" "some_command" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use execNowOnDvarIntValue", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("execNowOnDvarIntValue")), SimpleParserValue::String(TokenPos(), new std::string("some_dvar")), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::String(TokenPos(), new std::string("some_command")) }, R"("execNowOnDvarIntValue" "some_dvar" "1" "some_command" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use execNowOnDvarFloatValue", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("execNowOnDvarFloatValue")), SimpleParserValue::String(TokenPos(), new std::string("some_dvar")), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::String(TokenPos(), new std::string("some_command")) }, R"("execNowOnDvarFloatValue" "some_dvar" "1" "some_command" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use play", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("play")), SimpleParserValue::String(TokenPos(), new std::string("some_sound")) }, R"("play" "some_sound" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use scriptMenuResponse", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("scriptMenuResponse")), SimpleParserValue::String(TokenPos(), new std::string("some_response")) }, R"("scriptMenuResponse" "some_response" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use respondOnDvarStringValue", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("respondOnDvarStringValue")), SimpleParserValue::String(TokenPos(), new std::string("some_dvar")), SimpleParserValue::String(TokenPos(), new std::string("some_value")), SimpleParserValue::String(TokenPos(), new std::string("some_response")) }, R"("respondOnDvarStringValue" "some_dvar" "some_value" "some_response" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use respondOnDvarIntValue", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("respondOnDvarIntValue")), SimpleParserValue::String(TokenPos(), new std::string("some_dvar")), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::String(TokenPos(), new std::string("some_response")) }, R"("respondOnDvarIntValue" "some_dvar" "1" "some_response" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use respondOnDvarFloatValue", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("respondOnDvarFloatValue")), SimpleParserValue::String(TokenPos(), new std::string("some_dvar")), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::String(TokenPos(), new std::string("some_response")) }, R"("respondOnDvarFloatValue" "some_dvar" "1" "some_response" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use setPlayerDataSp", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("setPlayerDataSp")) }, R"("setPlayerDataSp" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use updateMail", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("updateMail")) }, R"("updateMail" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use openMail", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("openMail")) }, R"("openMail" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use deleteMail", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("deleteMail")) }, R"("deleteMail" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use doMailLottery", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("doMailLottery")) }, R"("doMailLottery" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use resetStatsConfirm", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("resetStatsConfirm")) }, R"("resetStatsConfirm" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use resetStatsCancel", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("resetStatsCancel")) }, R"("resetStatsCancel" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use setGameMode", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("setGameMode")), SimpleParserValue::String(TokenPos(), new std::string("some_game_mode")) }, R"("setGameMode" "some_game_mode" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use feederTop", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("feederTop")) }, R"("feederTop" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use feederBottom", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("feederBottom")) }, R"("feederBottom" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use showGamerCard", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("showGamerCard")) }, R"("showGamerCard" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use openForGameType", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("openForGameType")), SimpleParserValue::String(TokenPos(), new std::string("some_game_type")) }, R"("openForGameType" "some_game_type" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use closeForGameType", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("closeForGameType")), SimpleParserValue::String(TokenPos(), new std::string("some_game_type")) }, R"("closeForGameType" "some_game_type" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use kickPlayer", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("kickPlayer")) }, R"("kickPlayer" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use getKickPlayerQuestion", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("getKickPlayerQuestion")) }, R"("getKickPlayerQuestion" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use partyUpdateMissingMapPackDvar", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("partyUpdateMissingMapPackDvar")) }, R"("partyUpdateMissingMapPackDvar" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use togglePlayerMute", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("togglePlayerMute")) }, R"("togglePlayerMute" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use resolveError", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("resolveError")) }, R"("resolveError" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use lerp scale", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("lerp")), SimpleParserValue::Identifier(TokenPos(), new std::string("scale")), SimpleParserValue::Identifier(TokenPos(), new std::string("from")), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Identifier(TokenPos(), new std::string("to")), SimpleParserValue::Integer(TokenPos(), 2), SimpleParserValue::Identifier(TokenPos(), new std::string("over")), SimpleParserValue::Integer(TokenPos(), 3), }, R"("lerp" "scale" "from" "1" "to" "2" "over" "3" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use lerp alpha", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("lerp")), SimpleParserValue::Identifier(TokenPos(), new std::string("alpha")), SimpleParserValue::Identifier(TokenPos(), new std::string("from")), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Identifier(TokenPos(), new std::string("to")), SimpleParserValue::Integer(TokenPos(), 2), SimpleParserValue::Identifier(TokenPos(), new std::string("over")), SimpleParserValue::Integer(TokenPos(), 3), }, R"("lerp" "alpha" "from" "1" "to" "2" "over" "3" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use lerp x", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("lerp")), SimpleParserValue::Identifier(TokenPos(), new std::string("x")), SimpleParserValue::Identifier(TokenPos(), new std::string("from")), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Identifier(TokenPos(), new std::string("to")), SimpleParserValue::Integer(TokenPos(), 2), SimpleParserValue::Identifier(TokenPos(), new std::string("over")), SimpleParserValue::Integer(TokenPos(), 3), }, R"("lerp" "x" "from" "1" "to" "2" "over" "3" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use lerp y", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("lerp")), SimpleParserValue::Identifier(TokenPos(), new std::string("y")), SimpleParserValue::Identifier(TokenPos(), new std::string("from")), SimpleParserValue::Integer(TokenPos(), 1), SimpleParserValue::Identifier(TokenPos(), new std::string("to")), SimpleParserValue::Integer(TokenPos(), 2), SimpleParserValue::Identifier(TokenPos(), new std::string("over")), SimpleParserValue::Integer(TokenPos(), 3), }, R"("lerp" "y" "from" "1" "to" "2" "over" "3" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure can use setPlayerData", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("setPlayerData")), SimpleParserValue::Character(TokenPos(), '('), SimpleParserValue::Identifier(TokenPos(), new std::string("customClasses")), SimpleParserValue::Character(TokenPos(), ','), SimpleParserValue::Identifier(TokenPos(), new std::string("localVarInt")), SimpleParserValue::Character(TokenPos(), '('), SimpleParserValue::Identifier(TokenPos(), new std::string("classIndex")), SimpleParserValue::Character(TokenPos(), ')'), SimpleParserValue::Character(TokenPos(), ','), SimpleParserValue::String(TokenPos(), new std::string("perks")), SimpleParserValue::Character(TokenPos(), ','), SimpleParserValue::Integer(TokenPos(), 0), SimpleParserValue::Character(TokenPos(), ','), SimpleParserValue::Identifier(TokenPos(), new std::string("speciality_null")), SimpleParserValue::Character(TokenPos(), ')'), }, R"("setPlayerData" ( "customClasses" , "localVarInt" ( "classIndex" ) , "perks" , "0" , "speciality_null" ) ; )"); } #pragma endregion #pragma region Unit Tests for setLocalVar TEST_CASE("EventHandlerSetScopeSequences: Ensure setLocalVarBool is script on static value", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("setLocalVarBool")), SimpleParserValue::Identifier(TokenPos(), new std::string("sample_var")), SimpleParserValue::Integer(TokenPos(), 1339), SimpleParserValue::Character(TokenPos(), '-'), SimpleParserValue::Integer(TokenPos(), 2), }, R"("setLocalVarBool" "sample_var" "1337" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure setLocalVarInt is script on static value", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("setLocalVarInt")), SimpleParserValue::Identifier(TokenPos(), new std::string("sample_var")), SimpleParserValue::Integer(TokenPos(), 1339), SimpleParserValue::Character(TokenPos(), '-'), SimpleParserValue::Integer(TokenPos(), 2), }, R"("setLocalVarInt" "sample_var" "1337" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure setLocalVarString is script on static value", "[parsing][sequence][menu]") { TestGenericScriptStatement( { SimpleParserValue::Identifier(TokenPos(), new std::string("setLocalVarString")), SimpleParserValue::Identifier(TokenPos(), new std::string("sample_var")), SimpleParserValue::String(TokenPos(), new std::string("Hello")), SimpleParserValue::Character(TokenPos(), '+'), SimpleParserValue::String(TokenPos(), new std::string(" ")), SimpleParserValue::Character(TokenPos(), '+'), SimpleParserValue::String(TokenPos(), new std::string("World")), }, R"("setLocalVarString" "sample_var" "Hello World" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: Ensure setLocalVarBool is setLocalVar handler on non-static value", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Identifier(TokenPos(), new std::string("setLocalVarBool")), SimpleParserValue::Identifier(TokenPos(), new std::string("sample_var")), SimpleParserValue::Identifier(TokenPos(), new std::string("milliseconds")), SimpleParserValue::Character(TokenPos(), '('), SimpleParserValue::Character(TokenPos(), ')'), SimpleParserValue::Character(TokenPos(), '%'), SimpleParserValue::Integer(TokenPos(), 2), SimpleParserValue::Character(TokenPos(), ';'), SimpleParserValue::EndOfFile(pos) }); const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 8); REQUIRE(helper.m_event_handler_set->m_elements.size() == 1); const auto* firstElement = helper.m_event_handler_set->m_elements[0].get(); REQUIRE(firstElement->GetType() == CommonEventHandlerElementType::SET_LOCAL_VAR); const auto* setLocalVarElement = dynamic_cast(firstElement); REQUIRE(setLocalVarElement != nullptr); REQUIRE(setLocalVarElement->m_type == SetLocalVarType::BOOL); REQUIRE(setLocalVarElement->m_var_name == "sample_var"); REQUIRE(setLocalVarElement->m_value); REQUIRE(setLocalVarElement->m_value->IsStatic() == false); } TEST_CASE("EventHandlerSetScopeSequences: Ensure setLocalVarInt is setLocalVar handler on non-static value", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Identifier(TokenPos(), new std::string("setLocalVarInt")), SimpleParserValue::Identifier(TokenPos(), new std::string("sample_var")), SimpleParserValue::Identifier(TokenPos(), new std::string("milliseconds")), SimpleParserValue::Character(TokenPos(), '('), SimpleParserValue::Character(TokenPos(), ')'), SimpleParserValue::Character(TokenPos(), '*'), SimpleParserValue::Integer(TokenPos(), 2), SimpleParserValue::Character(TokenPos(), ';'), SimpleParserValue::EndOfFile(pos) }); const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 8); REQUIRE(helper.m_event_handler_set->m_elements.size() == 1); const auto* firstElement = helper.m_event_handler_set->m_elements[0].get(); REQUIRE(firstElement->GetType() == CommonEventHandlerElementType::SET_LOCAL_VAR); const auto* setLocalVarElement = dynamic_cast(firstElement); REQUIRE(setLocalVarElement != nullptr); REQUIRE(setLocalVarElement->m_type == SetLocalVarType::INT); REQUIRE(setLocalVarElement->m_var_name == "sample_var"); REQUIRE(setLocalVarElement->m_value); REQUIRE(setLocalVarElement->m_value->IsStatic() == false); } TEST_CASE("EventHandlerSetScopeSequences: Ensure setLocalVarFloat is setLocalVar handler on non-static value", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Identifier(TokenPos(), new std::string("setLocalVarFloat")), SimpleParserValue::Identifier(TokenPos(), new std::string("sample_var")), SimpleParserValue::Identifier(TokenPos(), new std::string("milliseconds")), SimpleParserValue::Character(TokenPos(), '('), SimpleParserValue::Character(TokenPos(), ')'), SimpleParserValue::Character(TokenPos(), '/'), SimpleParserValue::Integer(TokenPos(), 2), SimpleParserValue::Character(TokenPos(), ';'), SimpleParserValue::EndOfFile(pos) }); const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 8); REQUIRE(helper.m_event_handler_set->m_elements.size() == 1); const auto* firstElement = helper.m_event_handler_set->m_elements[0].get(); REQUIRE(firstElement->GetType() == CommonEventHandlerElementType::SET_LOCAL_VAR); const auto* setLocalVarElement = dynamic_cast(firstElement); REQUIRE(setLocalVarElement != nullptr); REQUIRE(setLocalVarElement->m_type == SetLocalVarType::FLOAT); REQUIRE(setLocalVarElement->m_var_name == "sample_var"); REQUIRE(setLocalVarElement->m_value); REQUIRE(setLocalVarElement->m_value->IsStatic() == false); } TEST_CASE("EventHandlerSetScopeSequences: Ensure setLocalVarString is setLocalVar handler on non-static value", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Identifier(TokenPos(), new std::string("setLocalVarString")), SimpleParserValue::Identifier(TokenPos(), new std::string("sample_var")), SimpleParserValue::Identifier(TokenPos(), new std::string("milliseconds")), SimpleParserValue::Character(TokenPos(), '('), SimpleParserValue::Character(TokenPos(), ')'), SimpleParserValue::Character(TokenPos(), '+'), SimpleParserValue::String(TokenPos(), new std::string(" Hello")), SimpleParserValue::Character(TokenPos(), ';'), SimpleParserValue::EndOfFile(pos) }); const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 8); REQUIRE(helper.m_event_handler_set->m_elements.size() == 1); const auto* firstElement = helper.m_event_handler_set->m_elements[0].get(); REQUIRE(firstElement->GetType() == CommonEventHandlerElementType::SET_LOCAL_VAR); const auto* setLocalVarElement = dynamic_cast(firstElement); REQUIRE(setLocalVarElement != nullptr); REQUIRE(setLocalVarElement->m_type == SetLocalVarType::STRING); REQUIRE(setLocalVarElement->m_var_name == "sample_var"); REQUIRE(setLocalVarElement->m_value); REQUIRE(setLocalVarElement->m_value->IsStatic() == false); } #pragma endregion #pragma region Unit Tests for If/ElseIf/Else/CloseBracket TEST_CASE("EventHandlerSetScopeSequences: Closing block terminates EventHandlerSet", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Character(pos, '}'), SimpleParserValue::EndOfFile(pos) }); const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 1); const auto script = helper.m_state->m_current_script.str(); REQUIRE(helper.m_state->m_current_event_handler_set == nullptr); REQUIRE(helper.m_state->m_current_nested_event_handler_set == nullptr); REQUIRE(helper.m_event_handler_set); REQUIRE(helper.m_event_handler_set->m_elements.empty()); } TEST_CASE("EventHandlerSetScopeSequences: Closing block finishes current script", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Character(pos, '}'), SimpleParserValue::EndOfFile(pos) }); helper.m_state->m_current_script << R"("fadeIn" "some_element" ; )"; const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 1); REQUIRE(helper.m_state->m_current_event_handler_set == nullptr); REQUIRE(helper.m_state->m_current_nested_event_handler_set == nullptr); REQUIRE(helper.m_event_handler_set); REQUIRE(helper.m_event_handler_set->m_elements.size() == 1); const auto* firstElement = helper.m_event_handler_set->m_elements[0].get(); REQUIRE(firstElement->GetType() == CommonEventHandlerElementType::SCRIPT); const auto* scriptElement = dynamic_cast(firstElement); REQUIRE(scriptElement != nullptr); REQUIRE(scriptElement->m_script == R"("fadeIn" "some_element" ; )"); } TEST_CASE("EventHandlerSetScopeSequences: If opens new condition", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Identifier(pos, new std::string("if")), SimpleParserValue::Character(pos, '('), SimpleParserValue::Integer(pos, 1336), SimpleParserValue::Character(pos, '+'), SimpleParserValue::Integer(pos, 1), SimpleParserValue::Character(pos, ')'), SimpleParserValue::Character(pos, '{'), SimpleParserValue::EndOfFile(pos) }); const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 7); REQUIRE(helper.m_state->m_current_event_handler_set == helper.m_event_handler_set.get()); REQUIRE(helper.m_event_handler_set); REQUIRE(helper.m_event_handler_set->m_elements.size() == 1); const auto* firstElement = helper.m_event_handler_set->m_elements[0].get(); REQUIRE(firstElement->GetType() == CommonEventHandlerElementType::CONDITION); const auto* conditionElement = dynamic_cast(firstElement); REQUIRE(conditionElement != nullptr); REQUIRE(conditionElement->m_condition != nullptr); REQUIRE(conditionElement->m_condition->IsStatic()); const auto staticValue = conditionElement->m_condition->EvaluateStatic(); REQUIRE(staticValue.m_type == SimpleExpressionValue::Type::INT); REQUIRE(staticValue.m_int_value == 1337); REQUIRE(conditionElement->m_condition_elements); REQUIRE(helper.m_state->m_current_nested_event_handler_set == conditionElement->m_condition_elements.get()); REQUIRE(!conditionElement->m_else_elements); REQUIRE(helper.m_state->m_condition_stack.size() == 1); REQUIRE(helper.m_state->m_condition_stack.top().m_condition == conditionElement); REQUIRE(helper.m_state->m_condition_stack.top().m_auto_skip == false); REQUIRE(helper.m_state->m_condition_stack.top().m_in_condition_elements == true); } TEST_CASE("EventHandlerSetScopeSequences: If applies current script", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Identifier(pos, new std::string("if")), SimpleParserValue::Character(pos, '('), SimpleParserValue::Integer(pos, 420), SimpleParserValue::Character(pos, ')'), SimpleParserValue::Character(pos, '{'), SimpleParserValue::EndOfFile(pos) }); helper.m_state->m_current_script << R"("fadeIn" "some_element" ; )"; const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 5); REQUIRE(helper.m_state->m_current_event_handler_set == helper.m_event_handler_set.get()); REQUIRE(helper.m_event_handler_set); REQUIRE(helper.m_event_handler_set->m_elements.size() == 2); const auto* firstElement = helper.m_event_handler_set->m_elements[0].get(); REQUIRE(firstElement->GetType() == CommonEventHandlerElementType::SCRIPT); const auto* scriptElement = dynamic_cast(firstElement); REQUIRE(scriptElement != nullptr); REQUIRE(scriptElement->m_script == R"("fadeIn" "some_element" ; )"); const auto* secondElement = helper.m_event_handler_set->m_elements[1].get(); REQUIRE(secondElement->GetType() == CommonEventHandlerElementType::CONDITION); const auto* conditionElement = dynamic_cast(secondElement); REQUIRE(conditionElement != nullptr); } TEST_CASE("EventHandlerSetScopeSequences: ElseIf opens new condition", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Character(pos, '}'), SimpleParserValue::Identifier(pos, new std::string("elseif")), SimpleParserValue::Character(pos, '('), SimpleParserValue::Integer(pos, 1336), SimpleParserValue::Character(pos, '+'), SimpleParserValue::Integer(pos, 1), SimpleParserValue::Character(pos, ')'), SimpleParserValue::Character(pos, '{'), SimpleParserValue::EndOfFile(pos) }); const auto currentIfCondition = std::make_unique(nullptr, std::make_unique(), nullptr); helper.m_state->m_current_nested_event_handler_set = currentIfCondition->m_condition_elements.get(); helper.m_state->m_condition_stack.emplace(currentIfCondition.get()); const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 8); REQUIRE(helper.m_state->m_current_event_handler_set == helper.m_event_handler_set.get()); REQUIRE(helper.m_event_handler_set); REQUIRE(helper.m_event_handler_set->m_elements.empty()); // Doesnt add new element REQUIRE(currentIfCondition->m_else_elements); REQUIRE(currentIfCondition->m_else_elements->m_elements.size() == 1); const auto* firstElement = currentIfCondition->m_else_elements->m_elements[0].get(); REQUIRE(firstElement->GetType() == CommonEventHandlerElementType::CONDITION); const auto* conditionElement = dynamic_cast(firstElement); REQUIRE(conditionElement != nullptr); REQUIRE(conditionElement->m_condition != nullptr); REQUIRE(conditionElement->m_condition->IsStatic()); const auto staticValue = conditionElement->m_condition->EvaluateStatic(); REQUIRE(staticValue.m_type == SimpleExpressionValue::Type::INT); REQUIRE(staticValue.m_int_value == 1337); REQUIRE(conditionElement->m_condition_elements); REQUIRE(helper.m_state->m_current_nested_event_handler_set == conditionElement->m_condition_elements.get()); REQUIRE(!conditionElement->m_else_elements); REQUIRE(helper.m_state->m_condition_stack.size() == 2); REQUIRE(helper.m_state->m_condition_stack.top().m_condition == conditionElement); REQUIRE(helper.m_state->m_condition_stack.top().m_auto_skip == true); REQUIRE(helper.m_state->m_condition_stack.top().m_in_condition_elements == true); } TEST_CASE("EventHandlerSetScopeSequences: ElseIf applies current script", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Character(pos, '}'), SimpleParserValue::Identifier(pos, new std::string("elseif")), SimpleParserValue::Character(pos, '('), SimpleParserValue::Integer(pos, 420), SimpleParserValue::Character(pos, ')'), SimpleParserValue::Character(pos, '{'), SimpleParserValue::EndOfFile(pos) }); const auto currentIfCondition = std::make_unique(nullptr, std::make_unique(), nullptr); helper.m_state->m_current_nested_event_handler_set = currentIfCondition->m_condition_elements.get(); helper.m_state->m_condition_stack.emplace(currentIfCondition.get()); helper.m_state->m_current_script << R"("fadeIn" "some_element" ; )"; const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 6); REQUIRE(currentIfCondition->m_condition_elements); REQUIRE(currentIfCondition->m_condition_elements->m_elements.size() == 1); const auto* firstConditionElement = currentIfCondition->m_condition_elements->m_elements[0].get(); REQUIRE(firstConditionElement->GetType() == CommonEventHandlerElementType::SCRIPT); const auto* scriptElement = dynamic_cast(firstConditionElement); REQUIRE(scriptElement != nullptr); REQUIRE(scriptElement->m_script == R"("fadeIn" "some_element" ; )"); REQUIRE(currentIfCondition->m_else_elements); REQUIRE(currentIfCondition->m_else_elements->m_elements.size() == 1); const auto* firstElseElement = currentIfCondition->m_else_elements->m_elements[0].get(); REQUIRE(firstElseElement->GetType() == CommonEventHandlerElementType::CONDITION); } TEST_CASE("EventHandlerSetScopeSequences: ElseIf cannot be specified when not in if", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Character(pos, '}'), SimpleParserValue::Identifier(pos, new std::string("elseif")), SimpleParserValue::Character(pos, '('), SimpleParserValue::Integer(pos, 420), SimpleParserValue::Character(pos, ')'), SimpleParserValue::Character(pos, '{'), SimpleParserValue::EndOfFile(pos) }); REQUIRE_THROWS_AS(helper.PerformTest(), ParsingException); } TEST_CASE("EventHandlerSetScopeSequences: ElseIf cannot be specified when else was already used", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Character(pos, '}'), SimpleParserValue::Identifier(pos, new std::string("elseif")), SimpleParserValue::Character(pos, '('), SimpleParserValue::Integer(pos, 420), SimpleParserValue::Character(pos, ')'), SimpleParserValue::Character(pos, '{'), SimpleParserValue::EndOfFile(pos) }); const auto currentIfCondition = std::make_unique(nullptr, std::make_unique(), std::make_unique()); helper.m_state->m_current_nested_event_handler_set = currentIfCondition->m_condition_elements.get(); helper.m_state->m_condition_stack.emplace(currentIfCondition.get()); helper.m_state->m_condition_stack.top().m_in_condition_elements = false; REQUIRE_THROWS_AS(helper.PerformTest(), ParsingException); } TEST_CASE("EventHandlerSetScopeSequences: Else switches to else element", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Character(pos, '}'), SimpleParserValue::Identifier(pos, new std::string("else")), SimpleParserValue::Character(pos, '{'), SimpleParserValue::EndOfFile(pos) }); const auto currentIfCondition = std::make_unique(nullptr, std::make_unique(), nullptr); helper.m_state->m_current_nested_event_handler_set = currentIfCondition->m_condition_elements.get(); helper.m_state->m_condition_stack.emplace(currentIfCondition.get()); const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 3); REQUIRE(helper.m_state->m_current_event_handler_set == helper.m_event_handler_set.get()); REQUIRE(helper.m_event_handler_set); REQUIRE(helper.m_event_handler_set->m_elements.empty()); // Doesn't add new element REQUIRE(currentIfCondition->m_else_elements); REQUIRE(currentIfCondition->m_else_elements->m_elements.empty()); REQUIRE(helper.m_state->m_condition_stack.size() == 1); REQUIRE(helper.m_state->m_condition_stack.top().m_condition == currentIfCondition.get()); REQUIRE(helper.m_state->m_condition_stack.top().m_auto_skip == false); REQUIRE(helper.m_state->m_condition_stack.top().m_in_condition_elements == false); } TEST_CASE("EventHandlerSetScopeSequences: Else keeps auto_skip value", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Character(pos, '}'), SimpleParserValue::Identifier(pos, new std::string("else")), SimpleParserValue::Character(pos, '{'), SimpleParserValue::EndOfFile(pos) }); const auto currentIfCondition = std::make_unique(nullptr, std::make_unique(), nullptr); helper.m_state->m_current_nested_event_handler_set = currentIfCondition->m_condition_elements.get(); helper.m_state->m_condition_stack.emplace(currentIfCondition.get(), true); const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 3); REQUIRE(helper.m_state->m_current_event_handler_set == helper.m_event_handler_set.get()); REQUIRE(helper.m_event_handler_set); REQUIRE(helper.m_event_handler_set->m_elements.empty()); // Doesn't add new element REQUIRE(currentIfCondition->m_else_elements); REQUIRE(currentIfCondition->m_else_elements->m_elements.empty()); REQUIRE(helper.m_state->m_condition_stack.size() == 1); REQUIRE(helper.m_state->m_condition_stack.top().m_condition == currentIfCondition.get()); REQUIRE(helper.m_state->m_condition_stack.top().m_auto_skip == true); REQUIRE(helper.m_state->m_condition_stack.top().m_in_condition_elements == false); } TEST_CASE("EventHandlerSetScopeSequences: Else cannot be specified when not in if", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Character(pos, '}'), SimpleParserValue::Identifier(pos, new std::string("else")), SimpleParserValue::Character(pos, '{'), SimpleParserValue::EndOfFile(pos) }); REQUIRE_THROWS_AS(helper.PerformTest(), ParsingException); } TEST_CASE("EventHandlerSetScopeSequences: Else cannot be specified when else was already used", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Character(pos, '}'), SimpleParserValue::Identifier(pos, new std::string("else")), SimpleParserValue::Character(pos, '{'), SimpleParserValue::EndOfFile(pos) }); const auto currentIfCondition = std::make_unique(nullptr, std::make_unique(), std::make_unique()); helper.m_state->m_current_nested_event_handler_set = currentIfCondition->m_condition_elements.get(); helper.m_state->m_condition_stack.emplace(currentIfCondition.get()); helper.m_state->m_condition_stack.top().m_in_condition_elements = false; REQUIRE_THROWS_AS(helper.PerformTest(), ParsingException); } TEST_CASE("EventHandlerSetScopeSequences: CloseBlock closes if statements", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Character(pos, '}'), SimpleParserValue::EndOfFile(pos) }); const auto currentIfCondition = std::make_unique(nullptr, std::make_unique(), nullptr); helper.m_state->m_current_nested_event_handler_set = currentIfCondition->m_condition_elements.get(); helper.m_state->m_condition_stack.emplace(currentIfCondition.get()); const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 1); REQUIRE(helper.m_state->m_current_event_handler_set == helper.m_event_handler_set.get()); REQUIRE(helper.m_event_handler_set); REQUIRE(helper.m_event_handler_set->m_elements.empty()); // Doesn't add new element REQUIRE(helper.m_state->m_current_nested_event_handler_set == helper.m_event_handler_set.get()); REQUIRE(helper.m_state->m_condition_stack.empty()); } TEST_CASE("EventHandlerSetScopeSequences: CloseBlock closes nested if statements to parent if statement", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Character(pos, '}'), SimpleParserValue::EndOfFile(pos) }); const auto baseIfCondition = std::make_unique(nullptr, std::make_unique(), nullptr); helper.m_state->m_current_nested_event_handler_set = baseIfCondition->m_condition_elements.get(); helper.m_state->m_condition_stack.emplace(baseIfCondition.get()); const auto nestedIfCondition = std::make_unique(nullptr, std::make_unique(), nullptr); helper.m_state->m_current_nested_event_handler_set = nestedIfCondition->m_condition_elements.get(); helper.m_state->m_condition_stack.emplace(nestedIfCondition.get()); const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 1); REQUIRE(helper.m_state->m_current_event_handler_set == helper.m_event_handler_set.get()); REQUIRE(helper.m_event_handler_set); REQUIRE(helper.m_state->m_current_nested_event_handler_set->m_elements.empty()); // Doesn't add new element REQUIRE(helper.m_state->m_current_nested_event_handler_set == baseIfCondition->m_condition_elements.get()); REQUIRE(helper.m_state->m_condition_stack.size() == 1); } TEST_CASE("EventHandlerSetScopeSequences: CloseBlock closes nested if statements to parent else statement", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Character(pos, '}'), SimpleParserValue::EndOfFile(pos) }); const auto baseIfCondition = std::make_unique(nullptr, std::make_unique(), std::make_unique()); helper.m_state->m_current_nested_event_handler_set = baseIfCondition->m_condition_elements.get(); helper.m_state->m_condition_stack.emplace(baseIfCondition.get()); helper.m_state->m_condition_stack.top().m_in_condition_elements = false; const auto nestedIfCondition = std::make_unique(nullptr, std::make_unique(), nullptr); helper.m_state->m_current_nested_event_handler_set = nestedIfCondition->m_condition_elements.get(); helper.m_state->m_condition_stack.emplace(nestedIfCondition.get()); const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 1); REQUIRE(helper.m_state->m_current_event_handler_set == helper.m_event_handler_set.get()); REQUIRE(helper.m_event_handler_set); REQUIRE(helper.m_state->m_current_nested_event_handler_set->m_elements.empty()); // Doesn't add new element REQUIRE(helper.m_state->m_current_nested_event_handler_set == baseIfCondition->m_else_elements.get()); REQUIRE(helper.m_state->m_condition_stack.size() == 1); } TEST_CASE("EventHandlerSetScopeSequences: CloseBlock closes all autoskip conditions to parent if statement", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Character(pos, '}'), SimpleParserValue::EndOfFile(pos) }); const auto baseIfCondition = std::make_unique(nullptr, std::make_unique(), nullptr); helper.m_state->m_current_nested_event_handler_set = baseIfCondition->m_condition_elements.get(); helper.m_state->m_condition_stack.emplace(baseIfCondition.get()); const auto nestedIfCondition = std::make_unique(nullptr, std::make_unique(), nullptr); helper.m_state->m_current_nested_event_handler_set = nestedIfCondition->m_condition_elements.get(); helper.m_state->m_condition_stack.emplace(nestedIfCondition.get()); const auto moreNestedIfCondition = std::make_unique(nullptr, std::make_unique(), nullptr); helper.m_state->m_current_nested_event_handler_set = moreNestedIfCondition->m_condition_elements.get(); helper.m_state->m_condition_stack.emplace(moreNestedIfCondition.get(), true); const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 1); REQUIRE(helper.m_state->m_current_event_handler_set == helper.m_event_handler_set.get()); REQUIRE(helper.m_event_handler_set); REQUIRE(helper.m_state->m_current_nested_event_handler_set->m_elements.empty()); // Doesn't add new element REQUIRE(helper.m_state->m_current_nested_event_handler_set == baseIfCondition->m_condition_elements.get()); REQUIRE(helper.m_state->m_condition_stack.size() == 1); } TEST_CASE("EventHandlerSetScopeSequences: CloseBlock closes all autoskip conditions to base", "[parsing][sequence][menu]") { EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4, false); const TokenPos pos; helper.Tokens({ SimpleParserValue::Character(pos, '}'), SimpleParserValue::EndOfFile(pos) }); const auto baseIfCondition = std::make_unique(nullptr, std::make_unique(), nullptr); helper.m_state->m_current_nested_event_handler_set = baseIfCondition->m_condition_elements.get(); helper.m_state->m_condition_stack.emplace(baseIfCondition.get()); const auto nestedIfCondition = std::make_unique(nullptr, std::make_unique(), nullptr); helper.m_state->m_current_nested_event_handler_set = nestedIfCondition->m_condition_elements.get(); helper.m_state->m_condition_stack.emplace(nestedIfCondition.get(), true); const auto result = helper.PerformTest(); REQUIRE(result); REQUIRE(helper.m_consumed_token_count == 1); REQUIRE(helper.m_state->m_current_event_handler_set == helper.m_event_handler_set.get()); REQUIRE(helper.m_event_handler_set); REQUIRE(helper.m_state->m_current_nested_event_handler_set->m_elements.empty()); // Doesn't add new element REQUIRE(helper.m_state->m_current_nested_event_handler_set == helper.m_event_handler_set.get()); REQUIRE(helper.m_state->m_condition_stack.empty()); } #pragma endregion }