diff --git a/Code/components/console/ConsoleRegistry.cpp b/Code/components/console/ConsoleRegistry.cpp index 74d7bbef0..bf0f2317b 100644 --- a/Code/components/console/ConsoleRegistry.cpp +++ b/Code/components/console/ConsoleRegistry.cpp @@ -41,17 +41,24 @@ ConsoleRegistry::ConsoleRegistry(const char* acLoggerName) m_out = spdlog::get(acLoggerName); BASE_ASSERT(m_out.get(), "Output logger not found"); - // Register global stuff. - for (auto* i = CommandBase::ROOT(); i;) + auto* i = CommandBase::ROOT(); + CommandBase::ROOT() = nullptr; + while (i) { m_commands.push_back(i); - i = i->next; + auto* j = i->next; + i->next = nullptr; + i = j; } - for (auto* i = SettingBase::ROOT(); i;) + auto* k = SettingBase::ROOT(); + SettingBase::ROOT() = nullptr; + while (k) { - m_settings.push_back(i); - i = i->next; + m_settings.push_back(k); + auto* j = k->next; + k->next = nullptr; + k = j; } RegisterNatives(); @@ -61,11 +68,12 @@ ConsoleRegistry::~ConsoleRegistry() { for (CommandBase* c : m_ownedCommands) delete c; + for (SettingBase* s : m_ownedSettings) + delete s; } void ConsoleRegistry::RegisterNatives() { - // TODO: put this strictly on console out. RegisterCommand<>("help", "Show a list of commands", [&](const ArgStack&) { m_out->info("<------Commands-({})--->", m_commands.size()); for (CommandBase* c : m_commands) @@ -97,6 +105,7 @@ void ConsoleRegistry::AddSetting(SettingBase* apSetting) (void)guard; m_settings.push_back(apSetting); + m_ownedSettings.push_back(apSetting); } CommandBase* ConsoleRegistry::FindCommand(const char* acName) @@ -109,6 +118,16 @@ CommandBase* ConsoleRegistry::FindCommand(const char* acName) return *it; } +SettingBase* ConsoleRegistry::FindSetting(const char* acName) +{ + // TODO: Maybe lookup by some hash... + auto it = std::find_if(m_settings.begin(), m_settings.end(), + [&](SettingBase* apSetting) { return std::strcmp(apSetting->name, acName) == 0; }); + if (it == m_settings.end()) + return nullptr; + return *it; +} + void ConsoleRegistry::TryExecuteCommand(const std::string& acLine) { if (acLine.length() <= 2 || acLine[0] != kCommandPrefix) @@ -141,7 +160,7 @@ void ConsoleRegistry::TryExecuteCommand(const std::string& acLine) return; } - ArgStack stack; + ArgStack stack(pCommand->m_argCount); auto result = CreateArgStack(pCommand, &tokens[1], stack); if (!result.val) { @@ -174,7 +193,7 @@ ResultAnd ConsoleRegistry::CreateArgStack(const CommandBase* apCommand, continue; } - return ResultAnd("Expected boolean argument, got y", false); + return ResultAnd("Expected boolean argument", false); } case CommandBase::Type::kNumeric: { if (!IsNumber(stringArg)) diff --git a/Code/components/console/ConsoleRegistry.h b/Code/components/console/ConsoleRegistry.h index 84057ab6d..553549dce 100644 --- a/Code/components/console/ConsoleRegistry.h +++ b/Code/components/console/ConsoleRegistry.h @@ -58,6 +58,7 @@ class ConsoleRegistry void TryExecuteCommand(const std::string& acLine); CommandBase* FindCommand(const char* acName); + SettingBase* FindSetting(const char* acName); // Call this from your main thread, this will drain the work item queue. bool Update(); @@ -73,6 +74,7 @@ class ConsoleRegistry std::vector m_commands; std::vector m_ownedCommands; std::vector m_settings; + std::vector m_ownedSettings; CommandQueue m_queue; std::shared_ptr m_out; diff --git a/Code/components/console/ConsoleRegistryTest.cpp b/Code/components/console/ConsoleRegistryTest.cpp new file mode 100644 index 000000000..a327eff77 --- /dev/null +++ b/Code/components/console/ConsoleRegistryTest.cpp @@ -0,0 +1,72 @@ +// Copyright (C) 2022 TiltedPhoques SRL. +// For licensing information see LICENSE at the root of this distribution. + +#include +#include +#include +#include + +namespace console +{ +namespace +{ +class ConsoleRegistryTest : public ::testing::Test +{ + public: + void SetUp() override; + void TearDown() override; + + private: +}; + +void ConsoleRegistryTest::SetUp() +{ + spdlog::stdout_color_mt("Test"); +} + +void ConsoleRegistryTest::TearDown() +{ + spdlog::drop("Test"); +} + +TEST_F(ConsoleRegistryTest, RegisterCommand) +{ + // "static" command + Command sc{"test0", "desc", [&](ArgStack& stack) { + EXPECT_EQ(stack.Pop(), 7); + }}; + + // "static" setting + Setting ss{"test0", "", true, SettingBase::Flags::kLocked}; + + ConsoleRegistry r("Test"); + r.RegisterCommand("name", "description", [&](ArgStack& stack) { + EXPECT_TRUE(stack.Pop()); + EXPECT_FALSE(stack.Pop()); + }); + + ASSERT_TRUE(r.FindCommand("name")); + + r.TryExecuteCommand("/name true false"); + r.TryExecuteCommand("/test0 7"); + r.TryExecuteCommand("/test0 10 10 10"); + r.TryExecuteCommand("/test0 true"); + + r.RegisterSetting("name", "desc", false); + ASSERT_TRUE(r.FindSetting("name")); + ASSERT_TRUE(r.FindSetting("test0")); + + // FAIL + r.TryExecuteCommand("test0 7"); + r.TryExecuteCommand("/test \xe2\x28\xa1"); +} + +TEST_F(ConsoleRegistryTest, RegisterSetting) +{ + // ConsoleRegistry r("Test"); + // r.RegisterSetting("name", "desc", false); + + //ASSERT_TRUE(r.FindSetting("name")); +} +} // namespace +} // namespace console diff --git a/Code/components/console/ConsoleUtilsTest.cpp b/Code/components/console/ConsoleUtilsTest.cpp new file mode 100644 index 000000000..17382c49d --- /dev/null +++ b/Code/components/console/ConsoleUtilsTest.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2022 TiltedPhoques SRL. +// For licensing information see LICENSE at the root of this distribution. + +#include +#include + +namespace console +{ +namespace +{ +TEST(ConsoleUtils, TestUTF8) +{ + EXPECT_TRUE(CheckIsValidUTF8("A Quick brown fox jumps over the fence")); + EXPECT_FALSE(CheckIsValidUTF8("\xe2\x28\xa1")); +} + +TEST(ConsoleUtils, TestNumeric) +{ + EXPECT_TRUE(IsNumber("10")); + EXPECT_TRUE(IsNumber("10.00")); + + // German way is not supported yet. + //EXPECT_TRUE(IsNumber("10,00")); + + EXPECT_FALSE(IsNumber("ten")); + EXPECT_FALSE(IsNumber("ten100")); + EXPECT_FALSE(IsNumber("ten10,0")); + EXPECT_FALSE(IsNumber("ten10.0")); + EXPECT_FALSE(IsNumber("ten 10.0 10")); +} +} // namespace +} // namespace console diff --git a/Code/components/console/StringTokenizerTest.cpp b/Code/components/console/StringTokenizerTest.cpp new file mode 100644 index 000000000..975537113 --- /dev/null +++ b/Code/components/console/StringTokenizerTest.cpp @@ -0,0 +1,62 @@ +// Copyright (C) 2022 TiltedPhoques SRL. +// For licensing information see LICENSE at the root of this distribution. + +#include +#include + +namespace console +{ +namespace +{ +TEST(StringTokenizer, Count) +{ + { + StringTokenizer t("A Quick brown fox jumps over the fence"); + EXPECT_EQ(t.CountTokens(), 8); + } + + { + StringTokenizer t("A_Quick brown fox_jumps over the fence"); + EXPECT_EQ(t.CountTokens(), 6); + } + + { + StringTokenizer t("A Quick brown\nfox jumps\rover the fence"); + EXPECT_EQ(t.CountTokens(), 8); + } +} + +TEST(StringTokenizer, Tokinize) +{ + { + StringTokenizer t("A Quick brown fox jumps over the fence"); + + std::vector vec; + while (t.HasMore()) + t.GetNext(vec.emplace_back()); + + EXPECT_EQ(vec.size(), 8); + } + + { + StringTokenizer t("A_Quick brown fox_jumps over the fence"); + + std::vector vec; + while (t.HasMore()) + t.GetNext(vec.emplace_back()); + + EXPECT_EQ(vec.size(), 6); + } + + { + StringTokenizer t("A Quick brown\nfox jumps\rover the fence"); + + std::vector vec; + while (t.HasMore()) + t.GetNext(vec.emplace_back()); + + EXPECT_EQ(vec.size(), 8); + } +} +} // namespace +} diff --git a/Code/components/console/xmake.lua b/Code/components/console/xmake.lua index fad912131..c620c6090 100644 --- a/Code/components/console/xmake.lua +++ b/Code/components/console/xmake.lua @@ -1,17 +1,2 @@ -target("Console") - set_kind("static") - set_group("Components") - add_configfiles("BuildInfo.h.in") - add_includedirs( - ".", - "../", - "../../", - "../../../build", - {public = true}) - add_headerfiles("**.h") - add_files("**.cpp") - add_packages( - "tiltedcore", - "hopscotch-map", - "gtest", - "spdlog") +component("Console") +unittest("Console") \ No newline at end of file diff --git a/Code/components/xmake.lua b/Code/components/xmake.lua index 76f484d2a..a1ba491fa 100644 --- a/Code/components/xmake.lua +++ b/Code/components/xmake.lua @@ -1,2 +1,47 @@ --- List all components required here. +-- This function defines the core component idoms +function component(name) + target(name) + set_kind("static") + set_group("Components") + add_configfiles("BuildInfo.h.in") + add_includedirs( + ".", + "../", + "../../", + "../../../build", + {public = true}) + add_headerfiles("**.h") + add_files("**.cpp") + add_packages( + "tiltedcore", + "hopscotch-map", + "gtest", + "spdlog") +end + +-- this isnt fully specified yet. +function unittest(name) + target(name .. "-Test") + set_kind("binary") + set_group("Components") + add_configfiles("BuildInfo.h.in") + add_includedirs( + ".", + "../", + "../../", + "../../../build", + {public = true}) + add_headerfiles( + "**.h") + add_files( + "**.cpp", + "../../../build/TestMain.cpp") + add_packages( + "tiltedcore", + "hopscotch-map", + "gtest", + "spdlog") + end + +-- List all components required below: includes("console") \ No newline at end of file diff --git a/Code/server/xmake.lua b/Code/server/xmake.lua index e6c336ce5..3209bf42a 100644 --- a/Code/server/xmake.lua +++ b/Code/server/xmake.lua @@ -4,7 +4,6 @@ target(name) set_kind("binary") set_group("Server") --set_basename(name .. "RebornServer") - set_languages("cxx17") add_defines(def) add_includedirs( ".", diff --git a/xmake.lua b/xmake.lua index 814808b7b..9311e4b64 100644 --- a/xmake.lua +++ b/xmake.lua @@ -13,7 +13,6 @@ add_rules("plugin.vsxmake.autoupdate") add_requires("entt", "recastnavigation") --- fuck the xmake ecosystem. before_build(function (target) import("modules.version") local branch, commitHash = version() @@ -28,6 +27,14 @@ before_build(function (target) bool_to_number[branch == "bluedove"], bool_to_number[branch == "prerel"]) io.writefile("build/BranchInfo.h", contents) + + local testContents = [[ + #include + int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); + }]] + io.writefile("build/TestMain.cpp", testContents) end) if is_mode("debug") then