From 0033ab2a2bf5d0a78e9f21d712188cfb9d28c07d Mon Sep 17 00:00:00 2001 From: Jan Date: Sun, 14 Nov 2021 12:46:13 +0100 Subject: [PATCH] Add base for menu parsing unit tests --- premake5.lua | 4 + .../CommonEventHandlerCondition.cpp | 2 +- .../CommonEventHandlerCondition.h | 6 +- .../EventHandler/CommonEventHandlerScript.cpp | 2 +- .../EventHandler/CommonEventHandlerScript.h | 2 +- .../CommonEventHandlerSetLocalVar.cpp | 2 +- .../CommonEventHandlerSetLocalVar.h | 2 +- .../EventHandler/ICommonEventHandlerElement.h | 4 +- test/ObjLoadingTests.lua | 53 ++++++ .../EventHandlerSetScopeSequencesTests.cpp | 164 ++++++++++++++++++ test/ObjLoadingTests/main.cpp | 2 + test/ParserTestUtils.lua | 52 ++++++ .../Parsing/Mock/MockLexer.h | 0 .../Parsing/Mock/MockPackValueSupplier.cpp | 0 .../Parsing/Mock/MockPackValueSupplier.h | 0 .../Parsing/Mock/MockParserLineStream.cpp | 0 .../Parsing/Mock/MockParserLineStream.h | 0 .../Parsing/Mock/MockSequence.h | 0 test/ZoneCodeGeneratorLibTests.lua | 2 + 19 files changed, 288 insertions(+), 9 deletions(-) create mode 100644 test/ObjLoadingTests.lua create mode 100644 test/ObjLoadingTests/Parsing/Menu/Sequence/EventHandlerSetScopeSequencesTests.cpp create mode 100644 test/ObjLoadingTests/main.cpp create mode 100644 test/ParserTestUtils.lua rename test/{ZoneCodeGeneratorLibTests => ParserTestUtils}/Parsing/Mock/MockLexer.h (100%) rename test/{ZoneCodeGeneratorLibTests => ParserTestUtils}/Parsing/Mock/MockPackValueSupplier.cpp (100%) rename test/{ZoneCodeGeneratorLibTests => ParserTestUtils}/Parsing/Mock/MockPackValueSupplier.h (100%) rename test/{ZoneCodeGeneratorLibTests => ParserTestUtils}/Parsing/Mock/MockParserLineStream.cpp (100%) rename test/{ZoneCodeGeneratorLibTests => ParserTestUtils}/Parsing/Mock/MockParserLineStream.h (100%) rename test/{ZoneCodeGeneratorLibTests => ParserTestUtils}/Parsing/Mock/MockSequence.h (100%) diff --git a/premake5.lua b/premake5.lua index 733f7ec4..3ba48f78 100644 --- a/premake5.lua +++ b/premake5.lua @@ -127,12 +127,16 @@ group "" -- Tests -- ======================== include "test/ObjCommonTests.lua" +include "test/ObjLoadingTests.lua" +include "test/ParserTestUtils.lua" include "test/ZoneCodeGeneratorLibTests.lua" include "test/ZoneCommonTests.lua" -- Tests group: Unit test and other tests projects group "Tests" ObjCommonTests:project() + ObjLoadingTests:project() + ParserTestUtils:project() ZoneCodeGeneratorLibTests:project() ZoneCommonTests:project() group "" \ No newline at end of file diff --git a/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerCondition.cpp b/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerCondition.cpp index a24210e6..a213d94d 100644 --- a/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerCondition.cpp +++ b/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerCondition.cpp @@ -13,7 +13,7 @@ CommonEventHandlerCondition::CommonEventHandlerCondition(std::unique_ptr m_else_elements; CommonEventHandlerCondition(); - explicit CommonEventHandlerCondition(std::unique_ptr condition, std::unique_ptr conditionElements, - std::unique_ptr elseElements); + CommonEventHandlerCondition(std::unique_ptr condition, std::unique_ptr conditionElements, + std::unique_ptr elseElements); - CommonEventHandlerElementType GetType() override; + _NODISCARD CommonEventHandlerElementType GetType() const override; }; } diff --git a/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerScript.cpp b/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerScript.cpp index 75062478..7ce35e88 100644 --- a/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerScript.cpp +++ b/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerScript.cpp @@ -10,7 +10,7 @@ CommonEventHandlerScript::CommonEventHandlerScript(std::string script) { } -CommonEventHandlerElementType CommonEventHandlerScript::GetType() +CommonEventHandlerElementType CommonEventHandlerScript::GetType() const { return CommonEventHandlerElementType::SCRIPT; } diff --git a/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerScript.h b/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerScript.h index 76ac6fd4..c6ec72d0 100644 --- a/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerScript.h +++ b/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerScript.h @@ -14,6 +14,6 @@ namespace menu CommonEventHandlerScript(); explicit CommonEventHandlerScript(std::string script); - CommonEventHandlerElementType GetType() override; + _NODISCARD CommonEventHandlerElementType GetType() const override; }; } diff --git a/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerSetLocalVar.cpp b/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerSetLocalVar.cpp index a21253f7..e50a2606 100644 --- a/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerSetLocalVar.cpp +++ b/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerSetLocalVar.cpp @@ -14,7 +14,7 @@ CommonEventHandlerSetLocalVar::CommonEventHandlerSetLocalVar(SetLocalVarType typ { } -CommonEventHandlerElementType CommonEventHandlerSetLocalVar::GetType() +CommonEventHandlerElementType CommonEventHandlerSetLocalVar::GetType() const { return CommonEventHandlerElementType::SET_LOCAL_VAR; } diff --git a/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerSetLocalVar.h b/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerSetLocalVar.h index af0fc768..5164d83e 100644 --- a/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerSetLocalVar.h +++ b/src/ObjLoading/Parsing/Menu/Domain/EventHandler/CommonEventHandlerSetLocalVar.h @@ -26,6 +26,6 @@ namespace menu CommonEventHandlerSetLocalVar(); CommonEventHandlerSetLocalVar(SetLocalVarType type, std::string varName, std::unique_ptr value); - CommonEventHandlerElementType GetType() override; + _NODISCARD CommonEventHandlerElementType GetType() const override; }; } diff --git a/src/ObjLoading/Parsing/Menu/Domain/EventHandler/ICommonEventHandlerElement.h b/src/ObjLoading/Parsing/Menu/Domain/EventHandler/ICommonEventHandlerElement.h index c7d8f972..18e9bb34 100644 --- a/src/ObjLoading/Parsing/Menu/Domain/EventHandler/ICommonEventHandlerElement.h +++ b/src/ObjLoading/Parsing/Menu/Domain/EventHandler/ICommonEventHandlerElement.h @@ -1,5 +1,7 @@ #pragma once +#include "Utils/ClassUtils.h" + namespace menu { enum class CommonEventHandlerElementType @@ -21,6 +23,6 @@ namespace menu ICommonEventHandlerElement& operator=(const ICommonEventHandlerElement& other) = default; ICommonEventHandlerElement& operator=(ICommonEventHandlerElement&& other) noexcept = default; - virtual CommonEventHandlerElementType GetType() = 0; + _NODISCARD virtual CommonEventHandlerElementType GetType() const = 0; }; } \ No newline at end of file diff --git a/test/ObjLoadingTests.lua b/test/ObjLoadingTests.lua new file mode 100644 index 00000000..94158af9 --- /dev/null +++ b/test/ObjLoadingTests.lua @@ -0,0 +1,53 @@ +ObjLoadingTests = {} + +function ObjLoadingTests:include(includes) + if includes:handle(self:name()) then + includedirs { + path.join(TestFolder(), "ObjLoadingTests") + } + end +end + +function ObjLoadingTests:link(links) + +end + +function ObjLoadingTests:use() + +end + +function ObjLoadingTests:name() + return "ObjLoadingTests" +end + +function ObjLoadingTests:project() + local folder = TestFolder() + local includes = Includes:create() + local links = Links:create() + + project(self:name()) + targetdir(TargetDirectoryTest) + location "%{wks.location}/test/%{prj.name}" + kind "ConsoleApp" + language "C++" + + files { + path.join(folder, "ObjLoadingTests/**.h"), + path.join(folder, "ObjLoadingTests/**.cpp") + } + + vpaths { + ["*"] = { + path.join(folder, "ObjLoadingTests") + } + } + + self:include(includes) + ParserTestUtils:include(includes) + ObjLoading:include(includes) + catch2:include(includes) + + links:linkto(ParserTestUtils) + links:linkto(ObjLoading) + links:linkall() +end diff --git a/test/ObjLoadingTests/Parsing/Menu/Sequence/EventHandlerSetScopeSequencesTests.cpp b/test/ObjLoadingTests/Parsing/Menu/Sequence/EventHandlerSetScopeSequencesTests.cpp new file mode 100644 index 00000000..5f8febd0 --- /dev/null +++ b/test/ObjLoadingTests/Parsing/Menu/Sequence/EventHandlerSetScopeSequencesTests.cpp @@ -0,0 +1,164 @@ +#include + +#include "Parsing/Menu/Domain/EventHandler/CommonEventHandlerScript.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) + : m_state(std::make_unique(featureLevel)), + 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); + + 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())); + } + + 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) + return couldMatch; + } + + return false; + } + }; + + TEST_CASE("EventHandlerSetScopeSequences: Ensure can use fadeIn", "[parsing][sequence][menu]") + { + EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4); + 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: Keyword casing doesnt matter", "[parsing][sequence][menu]") + { + EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4); + 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); + 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: Closing block terminates EventHandlerSet", "[parsing][sequence][menu]") + { + EventHandlerSetSequenceTestsHelper helper(FeatureLevel::IW4); + 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); + 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" ; )"); + } +} diff --git a/test/ObjLoadingTests/main.cpp b/test/ObjLoadingTests/main.cpp new file mode 100644 index 00000000..2380d6bf --- /dev/null +++ b/test/ObjLoadingTests/main.cpp @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include \ No newline at end of file diff --git a/test/ParserTestUtils.lua b/test/ParserTestUtils.lua new file mode 100644 index 00000000..8585bf8b --- /dev/null +++ b/test/ParserTestUtils.lua @@ -0,0 +1,52 @@ +ParserTestUtils = {} + +function ParserTestUtils:include(includes) + if includes:handle(self:name()) then + includedirs { + path.join(TestFolder(), "ParserTestUtils") + } + end +end + +function ParserTestUtils:link(links) + links:add(self:name()) + links:linkto(Parser) +end + +function ParserTestUtils:use() + +end + +function ParserTestUtils:name() + return "ParserTestUtils" +end + +function ParserTestUtils:project() + local folder = TestFolder() + local includes = Includes:create() + local links = Links:create() + + project(self:name()) + targetdir(TargetDirectoryTest) + location "%{wks.location}/test/%{prj.name}" + kind "StaticLib" + language "C++" + + files { + path.join(folder, "ParserTestUtils/**.h"), + path.join(folder, "ParserTestUtils/**.cpp") + } + + vpaths { + ["*"] = { + path.join(folder, "ParserTestUtils") + } + } + + self:include(includes) + Parser:include(includes) + catch2:include(includes) + + links:linkto(Parser) + links:linkall() +end diff --git a/test/ZoneCodeGeneratorLibTests/Parsing/Mock/MockLexer.h b/test/ParserTestUtils/Parsing/Mock/MockLexer.h similarity index 100% rename from test/ZoneCodeGeneratorLibTests/Parsing/Mock/MockLexer.h rename to test/ParserTestUtils/Parsing/Mock/MockLexer.h diff --git a/test/ZoneCodeGeneratorLibTests/Parsing/Mock/MockPackValueSupplier.cpp b/test/ParserTestUtils/Parsing/Mock/MockPackValueSupplier.cpp similarity index 100% rename from test/ZoneCodeGeneratorLibTests/Parsing/Mock/MockPackValueSupplier.cpp rename to test/ParserTestUtils/Parsing/Mock/MockPackValueSupplier.cpp diff --git a/test/ZoneCodeGeneratorLibTests/Parsing/Mock/MockPackValueSupplier.h b/test/ParserTestUtils/Parsing/Mock/MockPackValueSupplier.h similarity index 100% rename from test/ZoneCodeGeneratorLibTests/Parsing/Mock/MockPackValueSupplier.h rename to test/ParserTestUtils/Parsing/Mock/MockPackValueSupplier.h diff --git a/test/ZoneCodeGeneratorLibTests/Parsing/Mock/MockParserLineStream.cpp b/test/ParserTestUtils/Parsing/Mock/MockParserLineStream.cpp similarity index 100% rename from test/ZoneCodeGeneratorLibTests/Parsing/Mock/MockParserLineStream.cpp rename to test/ParserTestUtils/Parsing/Mock/MockParserLineStream.cpp diff --git a/test/ZoneCodeGeneratorLibTests/Parsing/Mock/MockParserLineStream.h b/test/ParserTestUtils/Parsing/Mock/MockParserLineStream.h similarity index 100% rename from test/ZoneCodeGeneratorLibTests/Parsing/Mock/MockParserLineStream.h rename to test/ParserTestUtils/Parsing/Mock/MockParserLineStream.h diff --git a/test/ZoneCodeGeneratorLibTests/Parsing/Mock/MockSequence.h b/test/ParserTestUtils/Parsing/Mock/MockSequence.h similarity index 100% rename from test/ZoneCodeGeneratorLibTests/Parsing/Mock/MockSequence.h rename to test/ParserTestUtils/Parsing/Mock/MockSequence.h diff --git a/test/ZoneCodeGeneratorLibTests.lua b/test/ZoneCodeGeneratorLibTests.lua index f9a3a548..54b64c01 100644 --- a/test/ZoneCodeGeneratorLibTests.lua +++ b/test/ZoneCodeGeneratorLibTests.lua @@ -44,8 +44,10 @@ function ZoneCodeGeneratorLibTests:project() self:include(includes) ZoneCodeGeneratorLib:include(includes) + ParserTestUtils:include(includes) catch2:include(includes) links:linkto(ZoneCodeGeneratorLib) + links:linkto(ParserTestUtils) links:linkall() end