From 9afe9b2b32b7818551ef898aba6a9667854e179a Mon Sep 17 00:00:00 2001 From: Jan Date: Sun, 14 Nov 2021 14:03:56 +0100 Subject: [PATCH] Add unit tests for menu EventHandlerSetScope If Statements --- .../EventHandlerSetScopeSequencesTests.cpp | 465 ++++++++++++++++++ 1 file changed, 465 insertions(+) diff --git a/test/ObjLoadingTests/Parsing/Menu/Sequence/EventHandlerSetScopeSequencesTests.cpp b/test/ObjLoadingTests/Parsing/Menu/Sequence/EventHandlerSetScopeSequencesTests.cpp index 5f8febd0..0bcffe66 100644 --- a/test/ObjLoadingTests/Parsing/Menu/Sequence/EventHandlerSetScopeSequencesTests.cpp +++ b/test/ObjLoadingTests/Parsing/Menu/Sequence/EventHandlerSetScopeSequencesTests.cpp @@ -161,4 +161,469 @@ namespace test::parsing::menu::sequence::event_handler_set 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); + 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->Evaluate(); + REQUIRE(staticValue.m_type == CommonExpressionValue::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); + 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); + 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->Evaluate(); + REQUIRE(staticValue.m_type == CommonExpressionValue::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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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()); + } }