summaryrefslogtreecommitdiff
path: root/src/unittests/utils
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2017-07-07 17:05:13 +0300
committerAndrei Karas <akaras@inbox.ru>2017-07-07 17:53:24 +0300
commit130f07fd84bfdf781eb42903b3fcbabc26199a3a (patch)
treee4e560c32177e0a64867c5d1584d9bf64b57bbce /src/unittests/utils
parent9bbd191307c97c7589f93a64a4eb9abf3f11c46b (diff)
downloadmv-130f07fd84bfdf781eb42903b3fcbabc26199a3a.tar.gz
mv-130f07fd84bfdf781eb42903b3fcbabc26199a3a.tar.bz2
mv-130f07fd84bfdf781eb42903b3fcbabc26199a3a.tar.xz
mv-130f07fd84bfdf781eb42903b3fcbabc26199a3a.zip
Move unit tests into unittests directory.
Diffstat (limited to 'src/unittests/utils')
-rw-r--r--src/unittests/utils/chatutils_unittest.cc287
-rw-r--r--src/unittests/utils/checkutils_unittest.cc179
-rw-r--r--src/unittests/utils/dumplibs_unittest.cc145
-rw-r--r--src/unittests/utils/langs_unittest.cc115
-rw-r--r--src/unittests/utils/mathutils_unittest.cc102
-rw-r--r--src/unittests/utils/parameters_unittest.cc327
-rw-r--r--src/unittests/utils/stringutils_unittest.cc1724
-rw-r--r--src/unittests/utils/timer_unittest.cc88
-rw-r--r--src/unittests/utils/translation/poparser_unittest.cc158
-rw-r--r--src/unittests/utils/xml_unittest.cc400
-rw-r--r--src/unittests/utils/xmlutils_unittest.cc203
11 files changed, 3728 insertions, 0 deletions
diff --git a/src/unittests/utils/chatutils_unittest.cc b/src/unittests/utils/chatutils_unittest.cc
new file mode 100644
index 000000000..681d91d3e
--- /dev/null
+++ b/src/unittests/utils/chatutils_unittest.cc
@@ -0,0 +1,287 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2012-2017 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "unittests/unittests.h"
+
+#include "client.h"
+#include "configuration.h"
+#include "configmanager.h"
+#include "dirs.h"
+
+#include "actormanager.h"
+#include "graphicsmanager.h"
+#include "party.h"
+
+#include "being/localplayer.h"
+
+#include "fs/virtfs/fs.h"
+
+#include "gui/gui.h"
+#include "gui/theme.h"
+
+#include "utils/chatutils.h"
+#include "utils/delete2.h"
+#include "utils/env.h"
+
+#include "render/sdlgraphics.h"
+
+#include "resources/sdlimagehelper.h"
+
+#include "resources/resourcemanager/resourcemanager.h"
+
+PRAGMA48(GCC diagnostic push)
+PRAGMA48(GCC diagnostic ignored "-Wshadow")
+#ifndef USE_SDL2
+#include <SDL.h>
+#endif // USE_SDL2
+PRAGMA48(GCC diagnostic pop)
+
+#include "debug.h"
+
+TEST_CASE("chatutils leak test1", "")
+{
+ logger = new Logger();
+ REQUIRE(gui == nullptr);
+ ResourceManager::cleanOrphans(true);
+ ResourceManager::deleteInstance();
+ delete2(logger);
+}
+
+TEST_CASE("chatutils replaceVars", "")
+{
+ setEnv("SDL_VIDEODRIVER", "dummy");
+
+ client = new Client;
+ XML::initXML();
+ SDL_Init(SDL_INIT_VIDEO);
+ logger = new Logger();
+ VirtFs::mountDirSilent("data", Append_false);
+ VirtFs::mountDirSilent("../data", Append_false);
+ theme = new Theme;
+ Theme::selectSkin();
+ imageHelper = new SDLImageHelper();
+ mainGraphics = new SDLGraphics;
+
+#ifdef USE_SDL2
+ SDLImageHelper::setRenderer(graphicsManager.createRenderer(
+ graphicsManager.createWindow(640, 480, 0,
+ SDL_WINDOW_SHOWN | SDL_SWSURFACE), SDL_RENDERER_SOFTWARE));
+#else // USE_SDL2
+
+ graphicsManager.createWindow(640, 480, 0, SDL_ANYFORMAT | SDL_SWSURFACE);
+#endif // USE_SDL2
+
+ Dirs::initRootDir();
+ Dirs::initHomeDir();
+
+ ConfigManager::initConfiguration();
+ getConfigDefaults2(config.getDefaultValues());
+ branding.setDefaultValues(getBrandingDefaults());
+
+ gui = new Gui();
+ gui->postInit(mainGraphics);
+
+ ActorSprite::load();
+ localPlayer = new LocalPlayer(static_cast<BeingId>(1),
+ BeingTypeId_zero);
+ actorManager = new ActorManager;
+ std::string str;
+
+ SECTION("empty")
+ {
+ replaceVars(str);
+ REQUIRE(str.empty());
+
+ str = "test line";
+ replaceVars(str);
+ REQUIRE(str == "test line");
+
+ str = "test <PLAYER>";
+ replaceVars(str);
+ REQUIRE(str == "test ");
+
+ str = "test <MONSTER>";
+ replaceVars(str);
+ REQUIRE(str == "test ");
+
+ str = "test <PEOPLE>";
+ replaceVars(str);
+ REQUIRE(str == "test ");
+
+ str = "test <PARTY>";
+ replaceVars(str);
+ REQUIRE(str == "test ");
+
+ str = "test <SOMETHING>";
+ replaceVars(str);
+ REQUIRE(str == "test <SOMETHING>");
+ }
+
+ SECTION("player")
+ {
+ Being *player1 = Being::createBeing(static_cast<BeingId>(2),
+ ActorType::Player,
+ BeingTypeId_zero,
+ nullptr);
+ player1->setName("player1");
+ actorManager->mActors.insert(player1);
+
+ localPlayer->setTarget(player1);
+ str = "test <PLAYER>";
+ replaceVars(str);
+ REQUIRE(str == "test player1");
+ }
+
+ SECTION("monster")
+ {
+ Being *const monster = Being::createBeing(static_cast<BeingId>(3),
+ ActorType::Monster,
+ BeingTypeId_zero,
+ nullptr);
+ monster->setName("monster1");
+ actorManager->mActors.insert(monster);
+
+ localPlayer->setTarget(monster);
+ str = "test <MONSTER>";
+ replaceVars(str);
+ REQUIRE(str == "test monster1");
+ }
+
+ SECTION("people")
+ {
+ actorManager->mActors.insert(localPlayer);
+ str = "test <PEOPLE>";
+ replaceVars(str);
+ REQUIRE(str == "test ");
+
+ Being *const player1 = Being::createBeing(static_cast<BeingId>(2),
+ ActorType::Player,
+ BeingTypeId_zero,
+ nullptr);
+ player1->setName("player1");
+ actorManager->mActors.insert(player1);
+
+ str = "test <PEOPLE>";
+ replaceVars(str);
+ REQUIRE(str == "test player1");
+
+ Being *const player2 = Being::createBeing(static_cast<BeingId>(4),
+ ActorType::Player,
+ BeingTypeId_zero,
+ nullptr);
+ player2->setName("player2");
+ actorManager->mActors.insert(player2);
+
+ str = "test <PEOPLE>";
+ replaceVars(str);
+ const bool correct = str == "test player1,player2" ||
+ str == "test player2,player1";
+ REQUIRE(correct == true);
+ }
+
+ SECTION("party")
+ {
+ actorManager->mActors.insert(localPlayer);
+
+ Party *const party1 = Party::getParty(1);
+ localPlayer->setParty(party1);
+
+ str = "test <PARTY>";
+ replaceVars(str);
+ REQUIRE(str == "test ");
+
+ Being *const player1 = Being::createBeing(static_cast<BeingId>(2),
+ ActorType::Player,
+ BeingTypeId_zero,
+ nullptr);
+ player1->setName("player1");
+ actorManager->mActors.insert(player1);
+ player1->setParty(party1);
+
+ str = "test <PARTY>";
+ replaceVars(str);
+ REQUIRE(str == "test player1");
+
+ Being *const player2 = Being::createBeing(static_cast<BeingId>(4),
+ ActorType::Player,
+ BeingTypeId_zero,
+ nullptr);
+ player2->setName("player2");
+ actorManager->mActors.insert(player2);
+ player2->setParty(party1);
+
+ str = "test <PARTY>";
+ replaceVars(str);
+ REQUIRE(str == "test player1,player2");
+
+ Party *const party2 = Party::getParty(2);
+
+ Being *const player3 = Being::createBeing(static_cast<BeingId>(5),
+ ActorType::Player,
+ BeingTypeId_zero,
+ nullptr);
+ player3->setName("player3");
+ actorManager->mActors.insert(player3);
+ player3->setParty(party2);
+
+ str = "test <PARTY>";
+ replaceVars(str);
+ REQUIRE(str == "test player1,player2");
+
+ player3->setParty(party1);
+
+ str = "test <PARTY>";
+ replaceVars(str);
+ REQUIRE(str == "test player1,player2,player3");
+
+ player2->setParty(party2);
+
+ str = "test <PARTY>";
+ replaceVars(str);
+ REQUIRE(str == "test player1,player3");
+
+ Party::clearParties();
+ }
+
+ delete2(actorManager);
+ delete2(localPlayer);
+ delete2(client);
+ VirtFs::unmountDirSilent("data");
+ VirtFs::unmountDirSilent("../data");
+ delete2(logger);
+// VirtFs::deinit();
+}
+
+TEST_CASE("chatutils textToMe", "")
+{
+ REQUIRE(textToMe("") == "**");
+ REQUIRE(textToMe("123") == "*123*");
+ REQUIRE(textToMe("*") == "***");
+ REQUIRE(textToMe("test line") == "*test line*");
+}
+
+TEST_CASE("chatutils leak test2", "")
+{
+ logger = new Logger();
+ REQUIRE(gui == nullptr);
+ ResourceManager::cleanOrphans(true);
+ ResourceManager::deleteInstance();
+ delete2(logger);
+}
diff --git a/src/unittests/utils/checkutils_unittest.cc b/src/unittests/utils/checkutils_unittest.cc
new file mode 100644
index 000000000..c54dcf9fc
--- /dev/null
+++ b/src/unittests/utils/checkutils_unittest.cc
@@ -0,0 +1,179 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2016-2017 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "unittests/unittests.h"
+
+#include "utils/checkutils.h"
+#include "utils/delete2.h"
+
+#include "debug.h"
+
+namespace
+{
+ bool flag = false;
+} // namespace
+
+static void testReturnFalseV(const bool val)
+{
+ flag = false;
+ returnFalseVReal(val);
+ flag = true;
+}
+
+static void testReturnTrueV(const bool val)
+{
+ flag = false;
+ returnTrueVReal(val);
+ flag = true;
+}
+
+static int testReturnFalse(const bool val)
+{
+ returnFalseReal(0, val);
+ return 1;
+}
+
+static int testReturnTrue(const bool val)
+{
+ returnTrueReal(0, val);
+ return 1;
+}
+
+static int testReturnNullptr(void *val)
+{
+ returnNullptrReal(0, val);
+ return 1;
+}
+
+static void testReturnNullptrV(void *val)
+{
+ flag = false;
+ returnNullptrVReal(val);
+ flag = true;
+}
+
+static bool testFailAlways1()
+{
+ failAlways("test fail");
+ return false;
+}
+
+static bool testFailAlways2()
+{
+ reportAlways("test fail");
+ return false;
+}
+
+TEST_CASE("CheckUtils", "")
+{
+ logger = new Logger;
+
+ SECTION("reportFalse")
+ {
+ REQUIRE(reportFalseReal(false) == false);
+ REQUIRE(reportFalseReal(true) == true);
+ }
+
+ SECTION("reportTrue")
+ {
+ REQUIRE(reportTrueReal(false) == false);
+ REQUIRE(reportTrueReal(true) == true);
+ }
+
+ SECTION("reportAlways")
+ {
+ reportAlwaysReal("test report");
+ }
+
+ SECTION("failFalse")
+ {
+PRAGMA4(GCC diagnostic push)
+PRAGMA4(GCC diagnostic ignored "-Wunused-value")
+ REQUIRE_THROWS(failFalse(false));
+ REQUIRE(failFalse(true) == true);
+ REQUIRE_THROWS(reportFalse(false));
+ REQUIRE(reportFalse(true) == true);
+PRAGMA4(GCC diagnostic pop)
+ }
+
+ SECTION("failTrue")
+ {
+PRAGMA4(GCC diagnostic push)
+PRAGMA4(GCC diagnostic ignored "-Wunused-value")
+ REQUIRE(failTrue(false) == false);
+ REQUIRE_THROWS(failTrue(true));
+ REQUIRE(reportTrue(false) == false);
+ REQUIRE_THROWS(reportTrue(true));
+PRAGMA4(GCC diagnostic pop)
+ }
+
+ SECTION("failAlways")
+ {
+PRAGMA4(GCC diagnostic push)
+PRAGMA4(GCC diagnostic ignored "-Wunused-value")
+ REQUIRE_THROWS(testFailAlways1());
+ REQUIRE_THROWS(testFailAlways2());
+PRAGMA4(GCC diagnostic pop)
+ }
+
+ SECTION("returnFalseV")
+ {
+ testReturnFalseV(false);
+ REQUIRE(flag == false);
+ testReturnFalseV(true);
+ REQUIRE(flag == true);
+ }
+
+ SECTION("returnTrueV")
+ {
+ testReturnTrueV(false);
+ REQUIRE(flag == true);
+ testReturnTrueV(true);
+ REQUIRE(flag == false);
+ }
+
+ SECTION("returnFalse")
+ {
+ REQUIRE(testReturnFalse(false) == 0);
+ REQUIRE(testReturnFalse(true) == 1);
+ }
+
+ SECTION("returnTrue")
+ {
+ REQUIRE(testReturnTrue(false) == 1);
+ REQUIRE(testReturnTrue(true) == 0);
+ }
+
+ SECTION("returnNullptr")
+ {
+ REQUIRE(testReturnNullptr(nullptr) == 0);
+ REQUIRE(testReturnNullptr(reinterpret_cast<void*>(1)) == 1);
+ }
+
+ SECTION("returnNullptrV")
+ {
+ testReturnNullptrV(nullptr);
+ REQUIRE(flag == false);
+ testReturnNullptrV(reinterpret_cast<void*>(1));
+ REQUIRE(flag == true);
+ }
+
+ delete2(logger);
+}
diff --git a/src/unittests/utils/dumplibs_unittest.cc b/src/unittests/utils/dumplibs_unittest.cc
new file mode 100644
index 000000000..35b80c710
--- /dev/null
+++ b/src/unittests/utils/dumplibs_unittest.cc
@@ -0,0 +1,145 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2017 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "unittests/unittests.h"
+
+#include "logger.h"
+
+#include "utils/delete2.h"
+#include "utils/stringutils.h"
+
+PRAGMA48(GCC diagnostic push)
+PRAGMA48(GCC diagnostic ignored "-Wshadow")
+#include <SDL_image.h>
+#include <SDL_mixer.h>
+PRAGMACLANG6GCC(GCC diagnostic push)
+PRAGMACLANG6GCC(GCC diagnostic ignored "-Wold-style-cast")
+#include <SDL_net.h>
+PRAGMACLANG6GCC(GCC diagnostic pop)
+#include <SDL_ttf.h>
+PRAGMA48(GCC diagnostic pop)
+
+#include <zlib.h>
+
+#include "debug.h"
+
+TEST_CASE("dumplibs tests", "")
+{
+ logger = new Logger();
+
+ SECTION("zlib")
+ {
+ const std::string build = ZLIB_VERSION;
+ const std::string link = zlibVersion();
+ REQUIRE(build == link);
+ }
+
+ SECTION("sdl")
+ {
+ const SDL_version *linkVersion = nullptr;
+#ifdef USE_SDL2
+ SDL_version sdlVersion;
+ sdlVersion.major = 0;
+ sdlVersion.minor = 0;
+ sdlVersion.patch = 0;
+ SDL_GetVersion(&sdlVersion);
+ linkVersion = &sdlVersion;
+#else // USE_SDL2
+ linkVersion = SDL_Linked_Version();
+#endif // USE_SDL2
+
+ const std::string build = strprintf("%d.%d.%d",
+ SDL_MAJOR_VERSION,
+ SDL_MINOR_VERSION,
+ SDL_PATCHLEVEL);
+ const std::string link = strprintf("%d.%d.%d",
+ linkVersion->major,
+ linkVersion->minor,
+ linkVersion->patch);
+
+ REQUIRE(build == link);
+ }
+
+ SECTION("sdl_net")
+ {
+ const SDL_version *const linkVersion = SDLNet_Linked_Version();
+
+ const std::string build = strprintf("%d.%d.%d",
+ SDL_NET_MAJOR_VERSION,
+ SDL_NET_MINOR_VERSION,
+ SDL_NET_PATCHLEVEL);
+ const std::string link = strprintf("%d.%d.%d",
+ linkVersion->major,
+ linkVersion->minor,
+ linkVersion->patch);
+
+ REQUIRE(build == link);
+ }
+
+ SECTION("sdl_image")
+ {
+ const SDL_version *const linkVersion = IMG_Linked_Version();
+
+ const std::string build = strprintf("%d.%d.%d",
+ SDL_IMAGE_MAJOR_VERSION,
+ SDL_IMAGE_MINOR_VERSION,
+ SDL_IMAGE_PATCHLEVEL);
+ const std::string link = strprintf("%d.%d.%d",
+ linkVersion->major,
+ linkVersion->minor,
+ linkVersion->patch);
+
+ REQUIRE(build == link);
+ }
+
+ SECTION("sdl_mixer")
+ {
+ const SDL_version *const linkVersion = Mix_Linked_Version();
+
+ const std::string build = strprintf("%d.%d.%d",
+ SDL_MIXER_MAJOR_VERSION,
+ SDL_MIXER_MINOR_VERSION,
+ SDL_MIXER_PATCHLEVEL);
+ const std::string link = strprintf("%d.%d.%d",
+ linkVersion->major,
+ linkVersion->minor,
+ linkVersion->patch);
+
+ REQUIRE(build == link);
+ }
+
+ SECTION("sdl_ttf")
+ {
+ const SDL_version *const linkVersion = TTF_Linked_Version();
+
+ const std::string build = strprintf("%d.%d.%d",
+ SDL_TTF_MAJOR_VERSION,
+ SDL_TTF_MINOR_VERSION,
+ SDL_TTF_PATCHLEVEL);
+ const std::string link = strprintf("%d.%d.%d",
+ linkVersion->major,
+ linkVersion->minor,
+ linkVersion->patch);
+
+ REQUIRE(build == link);
+ }
+
+ delete2(logger);
+}
diff --git a/src/unittests/utils/langs_unittest.cc b/src/unittests/utils/langs_unittest.cc
new file mode 100644
index 000000000..d9ff6eded
--- /dev/null
+++ b/src/unittests/utils/langs_unittest.cc
@@ -0,0 +1,115 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2013-2017 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "unittests/unittests.h"
+
+#include "configuration.h"
+
+#include "utils/env.h"
+#include "utils/langs.h"
+
+#include "debug.h"
+
+TEST_CASE("Langs getLang", "")
+{
+ LangVect langs;
+
+ config.setValue("lang", "C");
+ langs = getLang();
+ REQUIRE(langs.size() == 1);
+ REQUIRE(langs[0] == "C");
+
+ config.setValue("lang", "ru_RU");
+ langs = getLang();
+ REQUIRE(langs.size() == 2);
+ REQUIRE(langs[0] == "ru_RU");
+ REQUIRE(langs[1] == "ru");
+
+ config.setValue("lang", "ru_RU.UTF-8");
+ langs = getLang();
+ REQUIRE(langs.size() == 2);
+ REQUIRE(langs[0] == "ru_RU");
+ REQUIRE(langs[1] == "ru");
+
+ config.setValue("lang", "");
+
+ setEnv("LANG", "C");
+ langs = getLang();
+ REQUIRE(langs.size() == 1);
+ REQUIRE(langs[0] == "C");
+
+ setEnv("LANG", "ru_RU");
+ langs = getLang();
+ REQUIRE(langs.size() == 2);
+ REQUIRE(langs[0] == "ru_RU");
+ REQUIRE(langs[1] == "ru");
+
+ setEnv("LANG", "ru_RU.UTF-8");
+ langs = getLang();
+ REQUIRE(langs.size() == 2);
+ REQUIRE(langs[0] == "ru_RU");
+ REQUIRE(langs[1] == "ru");
+}
+
+TEST_CASE("Langs getLangSimple", "")
+{
+ config.setValue("lang", "C");
+ REQUIRE(getLangSimple() == "C");
+
+ config.setValue("lang", "ru_RU");
+ REQUIRE(getLangSimple() == "ru_RU");
+
+ config.setValue("lang", "ru_RU.UTF-8");
+ REQUIRE(getLangSimple() == "ru_RU.UTF-8");
+
+ config.setValue("lang", "");
+
+ setEnv("LANG", "C");
+ REQUIRE(getLangSimple() == "C");
+
+ setEnv("LANG", "ru_RU");
+ REQUIRE(getLangSimple() == "ru_RU");
+
+ setEnv("LANG", "ru_RU.UTF-8");
+ REQUIRE(getLangSimple() == "ru_RU.UTF-8");
+}
+
+TEST_CASE("Langs getLangShort", "")
+{
+ config.setValue("lang", "C");
+ REQUIRE(getLangShort() == "C");
+
+ config.setValue("lang", "ru_RU");
+ REQUIRE(getLangShort() == "ru");
+
+ config.setValue("lang", "ru_RU.UTF-8");
+ REQUIRE(getLangShort() == "ru");
+
+ config.setValue("lang", "");
+
+ setEnv("LANG", "C");
+ REQUIRE(getLangShort() == "C");
+
+ setEnv("LANG", "ru_RU");
+ REQUIRE(getLangShort() == "ru");
+
+ setEnv("LANG", "ru_RU.UTF-8");
+ REQUIRE(getLangShort() == "ru");
+}
diff --git a/src/unittests/utils/mathutils_unittest.cc b/src/unittests/utils/mathutils_unittest.cc
new file mode 100644
index 000000000..3eb0214ef
--- /dev/null
+++ b/src/unittests/utils/mathutils_unittest.cc
@@ -0,0 +1,102 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2013-2017 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "unittests/unittests.h"
+
+#include "utils/mathutils.h"
+
+#include "debug.h"
+
+TEST_CASE("MathUtils powerOfTwo", "")
+{
+ REQUIRE(powerOfTwo(0) == 1);
+ REQUIRE(powerOfTwo(1) == 1);
+ REQUIRE(powerOfTwo(2) == 2);
+ REQUIRE(powerOfTwo(3) == 4);
+ REQUIRE(powerOfTwo(4) == 4);
+ REQUIRE(powerOfTwo(5) == 8);
+ REQUIRE(powerOfTwo(6) == 8);
+ REQUIRE(powerOfTwo(7) == 8);
+ REQUIRE(powerOfTwo(8) == 8);
+ REQUIRE(powerOfTwo(9) == 16);
+ REQUIRE(powerOfTwo(10) == 16);
+ REQUIRE(powerOfTwo(11) == 16);
+ REQUIRE(powerOfTwo(12) == 16);
+ REQUIRE(powerOfTwo(13) == 16);
+ REQUIRE(powerOfTwo(14) == 16);
+ REQUIRE(powerOfTwo(15) == 16);
+ REQUIRE(powerOfTwo(16) == 16);
+ REQUIRE(powerOfTwo(17) == 32);
+ REQUIRE(powerOfTwo(18) == 32);
+ REQUIRE(powerOfTwo(19) == 32);
+ REQUIRE(powerOfTwo(20) == 32);
+ REQUIRE(powerOfTwo(21) == 32);
+ REQUIRE(powerOfTwo(22) == 32);
+ REQUIRE(powerOfTwo(23) == 32);
+ REQUIRE(powerOfTwo(24) == 32);
+ REQUIRE(powerOfTwo(25) == 32);
+ REQUIRE(powerOfTwo(26) == 32);
+ REQUIRE(powerOfTwo(27) == 32);
+ REQUIRE(powerOfTwo(28) == 32);
+ REQUIRE(powerOfTwo(29) == 32);
+ REQUIRE(powerOfTwo(30) == 32);
+ REQUIRE(powerOfTwo(31) == 32);
+ REQUIRE(powerOfTwo(32) == 32);
+ REQUIRE(powerOfTwo(33) == 64);
+ REQUIRE(powerOfTwo(34) == 64);
+ REQUIRE(powerOfTwo(35) == 64);
+ REQUIRE(powerOfTwo(36) == 64);
+ REQUIRE(powerOfTwo(37) == 64);
+ REQUIRE(powerOfTwo(38) == 64);
+ REQUIRE(powerOfTwo(39) == 64);
+ REQUIRE(powerOfTwo(41) == 64);
+ REQUIRE(powerOfTwo(42) == 64);
+ REQUIRE(powerOfTwo(43) == 64);
+ REQUIRE(powerOfTwo(44) == 64);
+ REQUIRE(powerOfTwo(45) == 64);
+ REQUIRE(powerOfTwo(46) == 64);
+ REQUIRE(powerOfTwo(47) == 64);
+ REQUIRE(powerOfTwo(48) == 64);
+ REQUIRE(powerOfTwo(49) == 64);
+ REQUIRE(powerOfTwo(50) == 64);
+ REQUIRE(powerOfTwo(51) == 64);
+ REQUIRE(powerOfTwo(52) == 64);
+ REQUIRE(powerOfTwo(53) == 64);
+ REQUIRE(powerOfTwo(54) == 64);
+ REQUIRE(powerOfTwo(55) == 64);
+ REQUIRE(powerOfTwo(56) == 64);
+ REQUIRE(powerOfTwo(57) == 64);
+ REQUIRE(powerOfTwo(58) == 64);
+ REQUIRE(powerOfTwo(59) == 64);
+ REQUIRE(powerOfTwo(60) == 64);
+ REQUIRE(powerOfTwo(61) == 64);
+ REQUIRE(powerOfTwo(62) == 64);
+ REQUIRE(powerOfTwo(63) == 64);
+ REQUIRE(powerOfTwo(64) == 64);
+ REQUIRE(powerOfTwo(65) == 128);
+
+ REQUIRE(powerOfTwo(1000000) == 1048576);
+}
+
+TEST_CASE("MathUtils tests fastSqrtInt", "")
+{
+ for (int f = 0; f < 1005; f ++)
+ REQUIRE(fastSqrtInt(f) == CAST_S32(sqrt(f)));
+}
diff --git a/src/unittests/utils/parameters_unittest.cc b/src/unittests/utils/parameters_unittest.cc
new file mode 100644
index 000000000..90d872d5a
--- /dev/null
+++ b/src/unittests/utils/parameters_unittest.cc
@@ -0,0 +1,327 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2012-2017 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "unittests/unittests.h"
+
+#include "utils/parameters.h"
+
+#include "debug.h"
+
+TEST_CASE("parameters basic 1", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "", ",", '\"') == true);
+ REQUIRE(pars.empty());
+}
+
+TEST_CASE("parameters basic 2", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "one,two, tree", ",", '\"') == true);
+ REQUIRE(pars.size() == 3);
+ REQUIRE(pars[0] == "one");
+ REQUIRE(pars[1] == "two");
+ REQUIRE(pars[2] == "tree");
+}
+
+TEST_CASE("parameters basic 3", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, ", ,,,", ",", '\"') == true);
+ REQUIRE(pars.empty());
+}
+
+TEST_CASE("parameters basic 4", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "one,,two, tree", ",", '\"') == true);
+ REQUIRE(pars.size() == 3);
+ REQUIRE(pars[0] == "one");
+ REQUIRE(pars[1] == "two");
+ REQUIRE(pars[2] == "tree");
+}
+
+TEST_CASE("parameters escape 1", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\\\"", ",", '\"') == true);
+ REQUIRE(pars.size() == 1);
+ REQUIRE(pars[0] == "\"");
+}
+
+TEST_CASE("parameters escape 2", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\\\", test", ",", '\"') == true);
+ REQUIRE(pars.size() == 2);
+ REQUIRE(pars[0] == "\"");
+ REQUIRE(pars[1] == "test");
+}
+
+TEST_CASE("parameters escape 3", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "test,\\\"", ",", '\"') == true);
+ REQUIRE(pars.size() == 2);
+ REQUIRE(pars[0] == "test");
+ REQUIRE(pars[1] == "\"");
+}
+
+TEST_CASE("parameters quote 1", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"one\",,two, tree", ",", '\"') == true);
+ REQUIRE(pars.size() == 3);
+ REQUIRE(pars[0] == "one");
+ REQUIRE(pars[1] == "two");
+ REQUIRE(pars[2] == "tree");
+}
+
+TEST_CASE("parameters quote 2", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"\",,two, tree", ",", '\"') == true);
+ REQUIRE(pars.size() == 3);
+ REQUIRE(pars[0].empty());
+ REQUIRE(pars[1] == "two");
+ REQUIRE(pars[2] == "tree");
+}
+
+TEST_CASE("parameters quote 3", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"one test\",,two, tree", ",", '\"') ==
+ true);
+ REQUIRE(pars.size() == 3);
+ REQUIRE(pars[0] == "one test");
+ REQUIRE(pars[1] == "two");
+ REQUIRE(pars[2] == "tree");
+}
+
+TEST_CASE("parameters quote 4", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"\\\"one test\\\"\",,two, tree", ",", '\"')
+ == true);
+ REQUIRE(pars.size() == 3);
+ REQUIRE(pars[0] == "\"one test\"");
+ REQUIRE(pars[1] == "two");
+ REQUIRE(pars[2] == "tree");
+}
+
+TEST_CASE("parameters quote 5", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"\\\"one \\\"test\\\"\",,two, tree",
+ ",", '\"') == true);
+ REQUIRE(pars.size() == 3);
+ REQUIRE(pars[0] == "\"one \"test\"");
+ REQUIRE(pars[1] == "two");
+ REQUIRE(pars[2] == "tree");
+}
+
+TEST_CASE("parameters quote 6", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"one, test\",,two, tree", ",", '\"')
+ == true);
+ REQUIRE(pars.size() == 3);
+ REQUIRE(pars[0] == "one, test");
+ REQUIRE(pars[1] == "two");
+ REQUIRE(pars[2] == "tree");
+}
+
+TEST_CASE("parameters quote 7", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"\\\"one, test\\\"\",,two, tree",
+ ",", '\"') == true);
+ REQUIRE(pars.size() == 3);
+ REQUIRE(pars[0] == "\"one, test\"");
+ REQUIRE(pars[1] == "two");
+ REQUIRE(pars[2] == "tree");
+}
+
+TEST_CASE("parameters quote 8", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"\\\"\",,two, tree", ",", '\"')
+ == true);
+ REQUIRE(pars.size() == 3);
+ REQUIRE(pars[0] == "\"");
+ REQUIRE(pars[1] == "two");
+ REQUIRE(pars[2] == "tree");
+}
+
+TEST_CASE("parameters quote 9", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"\\\",,two, tree", ",", '\"')
+ == true);
+ REQUIRE(pars.size() == 1);
+ REQUIRE(pars[0] == "\"\",,two, tree");
+}
+
+TEST_CASE("parameters quote 10", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"", ",", '\"')
+ == true);
+ REQUIRE(pars.size() == 1);
+ REQUIRE(pars[0] == "\"");
+}
+
+TEST_CASE("parameters quote 11", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\\\"", ",", '\"')
+ == true);
+ REQUIRE(pars.size() == 1);
+ REQUIRE(pars[0] == "\"");
+}
+
+TEST_CASE("parameters quote 12", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, ",\"", ",", '\"')
+ == true);
+ REQUIRE(pars.size() == 1);
+ REQUIRE(pars[0] == "\"");
+}
+
+TEST_CASE("parameters quote 13", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\",", ",", '\"')
+ == true);
+ REQUIRE(pars.size() == 1);
+ REQUIRE(pars[0] == "\",");
+}
+
+TEST_CASE("parameters quote 14", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\\\",", ",", '\"')
+ == true);
+ REQUIRE(pars.size() == 1);
+ REQUIRE(pars[0] == "\"");
+}
+
+TEST_CASE("parameters quote 15", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, ",\\\"", ",", '\"')
+ == true);
+ REQUIRE(pars.size() == 1);
+ REQUIRE(pars[0] == "\"");
+}
+
+TEST_CASE("parameters quote 16", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"one test\"", ",", '\"') ==
+ true);
+ REQUIRE(pars.size() == 1);
+ REQUIRE(pars[0] == "one test");
+}
+
+TEST_CASE("parameters quote 17", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"one, test\"", ",", '\"') ==
+ true);
+ REQUIRE(pars.size() == 1);
+ REQUIRE(pars[0] == "one, test");
+}
+
+TEST_CASE("parameters quote 18", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"one\\\" test\"", ",", '\"') ==
+ true);
+ REQUIRE(pars.size() == 1);
+ REQUIRE(pars[0] == "one\" test");
+}
+
+TEST_CASE("parameters quote 19", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"one\\\" ,test\"", ",", '\"') ==
+ true);
+ REQUIRE(pars.size() == 1);
+ REQUIRE(pars[0] == "one\" ,test");
+}
+
+TEST_CASE("parameters quote 20", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"one\\\" test,\"", ",", '\"') ==
+ true);
+ REQUIRE(pars.size() == 1);
+ REQUIRE(pars[0] == "one\" test,");
+}
+
+TEST_CASE("parameters complex 1", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"test\" \"line\"", ",", '\"') == true);
+ REQUIRE(pars.size() == 1);
+ REQUIRE(pars[0] == "test\" \"line");
+}
+
+TEST_CASE("parameters complex 2", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"test\", \"line\"", ",", '\"') == true);
+ REQUIRE(pars.size() == 2);
+ REQUIRE(pars[0] == "test");
+ REQUIRE(pars[1] == "line");
+}
+
+TEST_CASE("parameters complex 3", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"test,\" \"line\"", ",", '\"') == true);
+ REQUIRE(pars.size() == 1);
+ REQUIRE(pars[0] == "test,\" \"line");
+}
+
+TEST_CASE("parameters broken 1", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, "\"", ",", '\"') == true);
+ REQUIRE(pars.size() == 1);
+ REQUIRE(pars[0] == "\"");
+}
+
+TEST_CASE("parameters broken 2", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars, ",", ",", '\"') == true);
+ REQUIRE(pars.empty());
+}
+
+TEST_CASE("parameters broken 3", "")
+{
+ StringVect pars;
+ REQUIRE(splitParameters(pars,
+ ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", ",", '\"') == true);
+ REQUIRE(pars.empty());
+}
diff --git a/src/unittests/utils/stringutils_unittest.cc b/src/unittests/utils/stringutils_unittest.cc
new file mode 100644
index 000000000..b137ef30d
--- /dev/null
+++ b/src/unittests/utils/stringutils_unittest.cc
@@ -0,0 +1,1724 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2012-2017 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "unittests/unittests.h"
+
+#include "configuration.h"
+#include "logger.h"
+
+#include "const/utils/utf8.h"
+
+#include "fs/virtfs/fs.h"
+
+#include "utils/delete2.h"
+#include "utils/dtor.h"
+
+#include "resources/iteminfo.h"
+
+#include "resources/db/itemdb.h"
+
+#include "resources/resourcemanager/resourcemanager.h"
+
+#include "debug.h"
+
+TEST_CASE("stringuntils trim 1", "")
+{
+ std::string str = "str";
+ REQUIRE("str" == trim(str));
+
+ str = " str";
+ REQUIRE("str" == trim(str));
+ REQUIRE("str" == trim(str));
+
+ str = " str this IS Long Стринг "
+ "~!@#$%^&*()_+`-=[]\\{}|;':\",./<>? ";
+ REQUIRE("str this IS Long Стринг ~!@#$%^&*()_+`-=[]\\{}|;':\",./<>?" ==
+ trim(str));
+
+ str = "";
+ REQUIRE(trim(str).empty());
+}
+
+TEST_CASE("stringuntils toLower 1", "")
+{
+ std::string str = "str";
+ REQUIRE("str" == toLower(str));
+
+ str = " StR";
+ REQUIRE(" str" == toLower(str));
+
+ str = " str this IS Long "
+ "~!@#$%^&*()_+`-=[]\\{}|;':\",./<>? ";
+
+ REQUIRE(" str this is long ~!@#$%^&*()_+`-=[]\\{}|;':\",./<>? " ==
+ toLower(str));
+
+ str = "";
+ REQUIRE(toLower(str).empty());
+}
+
+TEST_CASE("stringuntils toUpper 1", "")
+{
+ std::string str = "str";
+ REQUIRE("STR" == toUpper(str));
+
+ str = " StR";
+ REQUIRE(" STR" == toUpper(str));
+
+ str = " str this IS Long "
+ "~!@#$%^&*()_+`-=[]\\{}|;':,./<>? ";
+
+ REQUIRE(" STR THIS IS LONG ~!@#$%^&*()_+`-=[]\\{}|;':,./<>? " ==
+ toUpper(str));
+
+ str = "";
+ REQUIRE(toUpper(str).empty());
+}
+
+TEST_CASE("stringuntils atox 1", "")
+{
+ std::string str = "0x10";
+ REQUIRE(16 == atox(str));
+
+ str = "0x0";
+ REQUIRE(0 == atox(str));
+
+ str = "0x1";
+ REQUIRE(1 == atox(str));
+
+ str = "0x0x0x0x0x0x0x0";
+ REQUIRE(0 == atox(str));
+
+ str = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ const int k = atox(str);
+ printf("%d\n", k); // for avoid warning
+
+ str = "";
+ REQUIRE(0 == atox(str));
+
+ str = "0";
+ REQUIRE(0 == atox(str));
+
+ str = "0x";
+ REQUIRE(0 == atox(str));
+
+ str = "zzz";
+ REQUIRE(0 == atox(str));
+}
+
+TEST_CASE("stringuntils ipToString 1", "")
+{
+ REQUIRE("0.0.0.0" == std::string(ipToString(0)));
+ REQUIRE("219.255.210.73" == std::string(ipToString(1238564827)));
+}
+
+TEST_CASE("stringuntils toString 1", "")
+{
+ REQUIRE(strprintf("%d", 0) == toString(0));
+ REQUIRE(strprintf("%d", -1) == toString(-1));
+ REQUIRE(strprintf("%d", 30000000) == toString(30000000));
+ REQUIRE(strprintf("%d", -10000000) == toString(-10000000));
+ REQUIRE(strprintf("%d", 30000000) == toString(
+ static_cast<signed int>(30000000)));
+ REQUIRE(strprintf("%d", 3000) == toString(CAST_U16(3000)));
+ REQUIRE(strprintf("%d", 123) == toString(CAST_U8(123)));
+ REQUIRE(strprintf("%u", static_cast<uint32_t>(30000000)) == toString(
+ static_cast<uint32_t>(30000000)));
+ REQUIRE(strprintf("%f", 3.1f) == toString(3.1f));
+ REQUIRE(strprintf("%f", 3.1) == toString(3.1));
+}
+
+TEST_CASE("stringuntils toStringPrint 1", "")
+{
+ REQUIRE(toStringPrint(0) == "0 0x0");
+ REQUIRE(toStringPrint(10) == "10 0xa");
+ REQUIRE(toStringPrint(255) == "255 0xff");
+}
+
+TEST_CASE("stringuntils parse2Int 1", "")
+{
+ int a = -1;
+ int b = -1;
+
+ REQUIRE(parse2Int("", a, b) == false);
+ REQUIRE(a == -1);
+ REQUIRE(b == -1);
+
+ a = -1;
+ b = -1;
+ REQUIRE(parse2Int(",", a, b) == false);
+ REQUIRE(a == -1);
+ REQUIRE(b == -1);
+
+ a = -1;
+ b = -1;
+ REQUIRE(parse2Int("10,20", a, b) == true);
+ REQUIRE(a == 10);
+ REQUIRE(b == 20);
+
+ a = -1;
+ b = -1;
+ REQUIRE(parse2Int("10 20", a, b) == true);
+ REQUIRE(a == 10);
+ REQUIRE(b == 20);
+
+ a = -1;
+ b = -1;
+ REQUIRE(parse2Int("10 z20", a, b) == true);
+ REQUIRE(a == 10);
+ REQUIRE(b == 0);
+}
+
+TEST_CASE("stringuntils parse2Str 1", "")
+{
+ std::string str1 = "-";
+ std::string str2 = "-";
+
+ REQUIRE(parse2Str("", str1, str2) == false);
+ REQUIRE(str1 == "-");
+ REQUIRE(str2 == "-");
+
+ REQUIRE(parse2Str(",", str1, str2) == false);
+ REQUIRE(str1 == "-");
+ REQUIRE(str2 == "-");
+
+ str1 = "-";
+ str2 = "-";
+ REQUIRE(parse2Str("test line", str1, str2) == true);
+ REQUIRE(str1 == "test");
+ REQUIRE(str2 == "line");
+
+ str1 = "-";
+ str2 = "-";
+ REQUIRE(parse2Str("test,line", str1, str2) == true);
+ REQUIRE(str1 == "test");
+ REQUIRE(str2 == "line");
+}
+
+TEST_CASE("stringuntils parseNumber 1", "")
+{
+ REQUIRE(parseNumber("") == 0);
+ REQUIRE(parseNumber("0x") == 0);
+ REQUIRE(parseNumber("10") == 10);
+ REQUIRE(parseNumber("h10") == 16);
+ REQUIRE(parseNumber("x100") == 256);
+ REQUIRE(parseNumber("0x20") == 32);
+}
+
+TEST_CASE("stringuntils removeToken 1", "")
+{
+ std::string str;
+
+ REQUIRE(removeToken(str, " ").empty());
+ REQUIRE(str.empty());
+
+ str = "test";
+ REQUIRE(removeToken(str, " ").empty());
+ REQUIRE(str.empty());
+
+ str = "test line";
+ REQUIRE(removeToken(str, " ") == "line");
+ REQUIRE(str == "line");
+
+ str = "test,line";
+ REQUIRE(removeToken(str, ",") == "line");
+ REQUIRE(str == "line");
+
+ str = "test line";
+ REQUIRE(removeToken(str, ",").empty());
+ REQUIRE(str.empty());
+
+ str = ",line";
+ REQUIRE(removeToken(str, ",").empty());
+ REQUIRE(str.empty());
+}
+
+TEST_CASE("stringuntils strprintf 1", "")
+{
+ REQUIRE(strprintf("%s very long string. 123456789012345678901234567890"
+ "+++++++++++++++++++++++++++++++++++++++"
+ "________________________________"
+ "***********************************"
+ "----------------------------------------"
+ "|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| %s",
+ "test", "end of test") ==
+ "test very long string. 123456789012345678901234567890"
+ "+++++++++++++++++++++++++++++++++++++++"
+ "________________________________"
+ "***********************************"
+ "----------------------------------------"
+ "|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| "
+ "end of test");
+}
+
+TEST_CASE("stringuntils toString 2", "")
+{
+ for (int f = 0; f < 10000000; f += 123)
+ {
+ REQUIRE(strprintf("%d", f) == toString(f));
+ }
+}
+
+TEST_CASE("stringuntils removeColors 1", "")
+{
+ REQUIRE(removeColors("").empty());
+ REQUIRE("#" == removeColors("#"));
+ REQUIRE("##" == removeColors("##"));
+ REQUIRE(removeColors("##1").empty());
+ REQUIRE("2" == removeColors("##12"));
+ REQUIRE("1##" == removeColors("1##"));
+ REQUIRE("1" == removeColors("1##2"));
+ REQUIRE("13" == removeColors("1##23"));
+ REQUIRE("#1#2" == removeColors("#1#2"));
+ REQUIRE("#1" == removeColors("#1##2"));
+}
+
+TEST_CASE("stringuntils compareStrI 1", "")
+{
+ std::string str1;
+ std::string str2;
+ REQUIRE(0 == compareStrI(str1, str2));
+
+ str1 = "test";
+ str2 = "test";
+ REQUIRE(0 == compareStrI(str1, str2));
+
+ str1 = "test";
+ str2 = "test1";
+ REQUIRE(0 > compareStrI(str1, str2));
+
+ str1 = "test";
+ str2 = "aest1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ REQUIRE(0 < compareStrI(str1, str2));
+
+ str1 = "testaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ str2 = "testaa";
+ REQUIRE(0 < compareStrI(str1, str2));
+}
+
+TEST_CASE("stringuntils isWordSeparator 1", "")
+{
+ REQUIRE(isWordSeparator(' '));
+ REQUIRE(isWordSeparator(','));
+ REQUIRE(isWordSeparator('.'));
+ REQUIRE(isWordSeparator('\"'));
+ REQUIRE(!isWordSeparator(0));
+ REQUIRE(!isWordSeparator('a'));
+ REQUIRE(!isWordSeparator('-'));
+}
+
+TEST_CASE("stringuntils findSameSubstring", "")
+{
+ std::string str1;
+ std::string str2;
+
+ REQUIRE(findSameSubstring("", "").empty());
+
+ str1 = "test line";
+ str2 = "test line";
+ REQUIRE("test line" == findSameSubstring(str1, str2));
+
+ str1 = "test li";
+ str2 = "test line";
+ REQUIRE("test li" == findSameSubstring(str1, str2));
+
+ str1 = "test li";
+ str2 = "est li";
+ REQUIRE(findSameSubstring(str1, str2).empty());
+}
+
+TEST_CASE("stringuntils findSameSubstringI", "")
+{
+ std::string str1;
+ std::string str2;
+
+ REQUIRE(findSameSubstringI("", "").empty());
+
+ str1 = "tEst line";
+ str2 = "tesT line";
+ REQUIRE("tEst line" == findSameSubstringI(str1, str2));
+
+ str1 = "test Li";
+ str2 = "test lINe";
+ REQUIRE("test Li" == findSameSubstringI(str1, str2));
+
+ str1 = "test lINe";
+ str2 = "test Li";
+ REQUIRE("test lI" == findSameSubstringI(str1, str2));
+
+ str1 = "teSt li";
+ str2 = "est li";
+ REQUIRE(findSameSubstringI(str1, str2).empty());
+}
+
+TEST_CASE("stringuntils findI 1", "")
+{
+ REQUIRE(0 == findI("", ""));
+ REQUIRE(std::string::npos == findI("test", "line"));
+ REQUIRE(0 == findI("test line", "t"));
+ REQUIRE(0 == findI("test line", "te"));
+ REQUIRE(3 == findI("test line", "t l"));
+}
+
+TEST_CASE("stringuntils findI 2", "")
+{
+ std::vector <std::string> vect1;
+ vect1.push_back("test");
+ vect1.push_back("line");
+ vect1.push_back("qwe");
+
+ REQUIRE(std::string::npos == findI("", vect1));
+ REQUIRE(0 == findI("test", vect1));
+ REQUIRE(0 == findI("tesT lIne", vect1));
+ REQUIRE(5 == findI("teoT line", vect1));
+ REQUIRE(std::string::npos == findI("zzz", vect1));
+}
+
+TEST_CASE("stringuntils encodeStr 1", "")
+{
+ std::string str = encodeStr(10, 1);
+ REQUIRE(10 == decodeStr(str));
+
+ str.clear();
+ REQUIRE(0 == decodeStr(str));
+
+ str = encodeStr(10, 2);
+ REQUIRE(10 == decodeStr(str));
+
+ str = encodeStr(100, 3);
+ REQUIRE(100 == decodeStr(str));
+
+ str = encodeStr(1000, 4);
+ REQUIRE(1000 == decodeStr(str));
+}
+
+TEST_CASE("stringuntils extractNameFromSprite 1", "")
+{
+ REQUIRE(extractNameFromSprite("").empty());
+ REQUIRE("test" == extractNameFromSprite("test"));
+ REQUIRE("test" == extractNameFromSprite("test.qwe"));
+ REQUIRE("line" == extractNameFromSprite("test/line.zzz"));
+ REQUIRE("line" == extractNameFromSprite("test\\line.zzz"));
+ REQUIRE("line" == extractNameFromSprite("test/test2\\line.zzz"));
+ REQUIRE("line" == extractNameFromSprite("test\\test2/line.zzz"));
+}
+
+TEST_CASE("stringuntils removeSpriteIndex 1", "")
+{
+ REQUIRE(removeSpriteIndex("").empty());
+ REQUIRE("test" == removeSpriteIndex("test"));
+ REQUIRE("test" == removeSpriteIndex("test[1]"));
+ REQUIRE("line" == removeSpriteIndex("test/line[12]"));
+ REQUIRE("line" == removeSpriteIndex("test\\line[12]"));
+ REQUIRE("line" == removeSpriteIndex("test/test2\\line[12]"));
+ REQUIRE("line" == removeSpriteIndex("test\\test2/line[1]"));
+}
+
+TEST_CASE("stringutils getSafeUtf8String 1", "")
+{
+ const char *str;
+ str = getSafeUtf8String("");
+ REQUIRE(str != nullptr);
+ REQUIRE(strcmp("", str) == 0);
+ REQUIRE(str[0] == '\0');
+ REQUIRE(str[UTF8_MAX_SIZE - 1] == '\0');
+ delete [] str;
+
+ str = getSafeUtf8String("test line");
+ REQUIRE(str != nullptr);
+ REQUIRE(strcmp("test line", str) == 0);
+ REQUIRE(str[strlen("test line")] == '\0');
+ REQUIRE(str[UTF8_MAX_SIZE - 1] == '\0');
+ delete [] str;
+
+ str = getSafeUtf8String("1");
+ REQUIRE(str != nullptr);
+ REQUIRE(strcmp("1", str) == 0);
+ REQUIRE(str[1] == '\0');
+ REQUIRE(str[UTF8_MAX_SIZE - 1] == '\0');
+ delete [] str;
+}
+
+TEST_CASE("stringutils getSafeUtf8String 2", "")
+{
+ char *str;
+
+ getSafeUtf8String("test", nullptr);
+
+ str = new char[65535];
+ getSafeUtf8String("", str);
+ REQUIRE(str != nullptr);
+ REQUIRE(strcmp("", str) == 0);
+ REQUIRE(str[0] == '\0');
+ REQUIRE(str[UTF8_MAX_SIZE - 1] == '\0');
+ delete [] str;
+
+ str = new char[65535];
+ getSafeUtf8String("test line", str);
+ REQUIRE(str != nullptr);
+ REQUIRE(strcmp("test line", str) == 0);
+ REQUIRE(str[strlen("test line")] == '\0');
+ REQUIRE(str[UTF8_MAX_SIZE - 1] == '\0');
+ delete [] str;
+
+ str = new char[65535];
+ getSafeUtf8String("1", str);
+ REQUIRE(str != nullptr);
+ REQUIRE(strcmp("1", str) == 0);
+ REQUIRE(str[1] == '\0');
+ REQUIRE(str[UTF8_MAX_SIZE - 1] == '\0');
+ delete [] str;
+
+ str = new char[65535];
+ char *data1 = new char[65510];
+ memset(data1, 'a', 65510);
+ data1[65509] = '\0';
+ char *data2 = new char[65510];
+ memset(data2, 'a', 65500);
+ data2[65500] = '\0';
+ getSafeUtf8String(data1, str);
+ REQUIRE(str != nullptr);
+ REQUIRE(strcmp(data2, str) == 0);
+ REQUIRE(str[65500] == '\0');
+ delete [] data1;
+ delete [] data2;
+ delete [] str;
+}
+
+TEST_CASE("stringuntils getFileName 1", "")
+{
+ REQUIRE(getFileName("").empty());
+ REQUIRE("file" == getFileName("file"));
+ REQUIRE("file" == getFileName("test/file1\\file"));
+ REQUIRE("file" == getFileName("test\\file1/file"));
+ REQUIRE(getFileName("file/").empty());
+ REQUIRE("file" == getFileName("/file"));
+}
+
+TEST_CASE("stringuntils getFileDir 1", "")
+{
+ REQUIRE(getFileDir("").empty());
+ REQUIRE("file" == getFileDir("file"));
+ REQUIRE("test/file1" == getFileDir("test/file1\\file"));
+ REQUIRE("test\\file1" == getFileDir("test\\file1/file"));
+ REQUIRE("file" == getFileDir("file/"));
+ REQUIRE(getFileDir("/file").empty());
+}
+
+TEST_CASE("stringuntils replaceAll 1", "")
+{
+ std::string str1;
+ std::string str2;
+ std::string str3;
+
+ REQUIRE(replaceAll(str1, str2, str3).empty());
+
+ str1 = "this is test line";
+ str2 = "";
+ str3 = "";
+ REQUIRE("this is test line" == replaceAll(str1, str2, str3));
+
+ str1 = "this is test line";
+ str2 = "is ";
+ str3 = "";
+ REQUIRE("thtest line" == replaceAll(str1, str2, str3));
+
+ str1 = "this is test line";
+ str2 = "";
+ str3 = "1";
+ REQUIRE("this is test line" == replaceAll(str1, str2, str3));
+}
+
+TEST_CASE("stringuntils replaceRecursiveAll 1", "")
+{
+ std::string str;
+ str = "";
+ replaceRecursiveAll(str, "line", '.');
+ REQUIRE(str.empty());
+ str = "test line";
+ replaceRecursiveAll(str, "line", '.');
+ REQUIRE(str == "test .");
+ str = "11112222";
+ replaceRecursiveAll(str, "11", '1');
+ REQUIRE(str == "12222");
+ str = "122221";
+ replaceRecursiveAll(str, "11", '1');
+ REQUIRE(str == "122221");
+ str = "1222211";
+ replaceRecursiveAll(str, "11", '1');
+ REQUIRE(str == "122221");
+ str = "11112222";
+ replaceRecursiveAll(str, "112", '1');
+ REQUIRE(str == "111222");
+ str = "111122224";
+ replaceRecursiveAll(str, "112", '1');
+ REQUIRE(str == "1112224");
+ str = "3111122224";
+ replaceRecursiveAll(str, "112", '1');
+ REQUIRE(str == "31112224");
+ str = "121212";
+ replaceRecursiveAll(str, "12", '1');
+ REQUIRE(str == "111");
+ str = "1121212";
+ replaceRecursiveAll(str, "12", '1');
+ REQUIRE(str == "1111");
+ str = "11212122";
+ replaceRecursiveAll(str, "12", '1');
+ REQUIRE(str == "1111");
+ str = "112121222";
+ replaceRecursiveAll(str, "12", '1');
+ REQUIRE(str == "1111");
+ str = "112211221122";
+ replaceRecursiveAll(str, "12", '1');
+ REQUIRE(str == "111111");
+}
+
+TEST_CASE("stringuntils getBoolFromString 1", "")
+{
+ REQUIRE(getBoolFromString("true"));
+ REQUIRE(getBoolFromString("yes"));
+ REQUIRE(getBoolFromString("on"));
+ REQUIRE(!getBoolFromString("false"));
+ REQUIRE(!getBoolFromString("no"));
+ REQUIRE(!getBoolFromString("off"));
+ REQUIRE(getBoolFromString("1"));
+ REQUIRE(!getBoolFromString("0"));
+ REQUIRE(getBoolFromString("2"));
+
+ REQUIRE(getBoolFromString(" true"));
+ REQUIRE(getBoolFromString("yes "));
+ REQUIRE(getBoolFromString(" on"));
+ REQUIRE(!getBoolFromString("false "));
+ REQUIRE(!getBoolFromString(" no"));
+ REQUIRE(!getBoolFromString("off "));
+ REQUIRE(getBoolFromString(" 1"));
+ REQUIRE(!getBoolFromString("0 "));
+ REQUIRE(getBoolFromString(" 2"));
+
+ REQUIRE(getBoolFromString("tRue "));
+ REQUIRE(getBoolFromString(" Yes"));
+ REQUIRE(getBoolFromString("ON "));
+ REQUIRE(!getBoolFromString(" fALse"));
+ REQUIRE(!getBoolFromString("nO "));
+ REQUIRE(!getBoolFromString(" oFF"));
+}
+
+TEST_CASE("stringuntils parseBoolean 1", "")
+{
+ REQUIRE(parseBoolean("true") == 1);
+ REQUIRE(parseBoolean("yes") == 1);
+ REQUIRE(parseBoolean("on") == 1);
+ REQUIRE(parseBoolean("false") == 0);
+ REQUIRE(parseBoolean("no") == 0);
+ REQUIRE(parseBoolean("off") == 0);
+ REQUIRE(parseBoolean("1") == 1);
+ REQUIRE(parseBoolean("0") == 0);
+ REQUIRE(parseBoolean("2") == -1);
+ REQUIRE(parseBoolean("test") == -1);
+ REQUIRE(parseBoolean("") == -1);
+
+ REQUIRE(parseBoolean("true ") == 1);
+ REQUIRE(parseBoolean(" yes") == 1);
+ REQUIRE(parseBoolean("on ") == 1);
+ REQUIRE(parseBoolean(" false") == 0);
+ REQUIRE(parseBoolean("no ") == 0);
+ REQUIRE(parseBoolean(" off") == 0);
+ REQUIRE(parseBoolean("1 ") == 1);
+ REQUIRE(parseBoolean(" 0") == 0);
+ REQUIRE(parseBoolean("2 ") == -1);
+ REQUIRE(parseBoolean(" test") == -1);
+ REQUIRE(parseBoolean(" ") == -1);
+
+ REQUIRE(parseBoolean(" tRue") == 1);
+ REQUIRE(parseBoolean("Yes ") == 1);
+ REQUIRE(parseBoolean(" ON") == 1);
+ REQUIRE(parseBoolean("FaLse ") == 0);
+ REQUIRE(parseBoolean(" nO") == 0);
+ REQUIRE(parseBoolean("oFf ") == 0);
+ REQUIRE(parseBoolean(" tEst") == -1);
+}
+
+TEST_CASE("stringuntils splitToIntSet 1", "")
+{
+ std::set<int> tokens;
+ splitToIntSet(tokens, "", ',');
+ REQUIRE(tokens.empty() == true);
+
+ tokens.clear();
+ splitToIntSet(tokens, "10z,aa,-1", ',');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens.find(10) != tokens.end());
+ REQUIRE(tokens.find(0) != tokens.end());
+ REQUIRE(tokens.find(-1) != tokens.end());
+
+ tokens.clear();
+ splitToIntSet(tokens, "10,2,30", ',');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens.find(10) != tokens.end());
+ REQUIRE(tokens.find(2) != tokens.end());
+ REQUIRE(tokens.find(30) != tokens.end());
+
+ tokens.clear();
+ splitToIntSet(tokens, "10,2,30,", ',');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens.find(10) != tokens.end());
+ REQUIRE(tokens.find(2) != tokens.end());
+ REQUIRE(tokens.find(30) != tokens.end());
+
+ tokens.clear();
+ splitToIntSet(tokens, "10,2;30", ',');
+ REQUIRE(tokens.size() == 2);
+ REQUIRE(tokens.find(10) != tokens.end());
+ REQUIRE(tokens.find(2) != tokens.end());
+
+ tokens.clear();
+ splitToIntSet(tokens, "10;20;30", ';');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens.find(10) != tokens.end());
+ REQUIRE(tokens.find(20) != tokens.end());
+ REQUIRE(tokens.find(30) != tokens.end());
+}
+
+TEST_CASE("stringuntils splitToIntList 1", "")
+{
+ std::list<int> tokens;
+ tokens = splitToIntList("", ',');
+ REQUIRE(tokens.empty() == true);
+
+ tokens.clear();
+ tokens = splitToIntList("10z,a,-1", ',');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens.front() == 10);
+ tokens.pop_front();
+ REQUIRE(tokens.front() == 0);
+ tokens.pop_front();
+ REQUIRE(tokens.front() == -1);
+ tokens.pop_front();
+
+ tokens.clear();
+ tokens = splitToIntList("10,2,30", ',');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens.front() == 10);
+ tokens.pop_front();
+ REQUIRE(tokens.front() == 2);
+ tokens.pop_front();
+ REQUIRE(tokens.front() == 30);
+ tokens.pop_front();
+
+ tokens.clear();
+ tokens = splitToIntList("10,2,30,", ',');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens.front() == 10);
+ tokens.pop_front();
+ REQUIRE(tokens.front() == 2);
+ tokens.pop_front();
+ REQUIRE(tokens.front() == 30);
+ tokens.pop_front();
+
+ tokens.clear();
+ tokens = splitToIntList("10,2;30", ',');
+ REQUIRE(tokens.size() == 2);
+ REQUIRE(tokens.front() == 10);
+ tokens.pop_front();
+ REQUIRE(tokens.front() == 2);
+ tokens.pop_front();
+
+ tokens.clear();
+ tokens = splitToIntList("10;20;30", ';');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens.front() == 10);
+ tokens.pop_front();
+ REQUIRE(tokens.front() == 20);
+ tokens.pop_front();
+ REQUIRE(tokens.front() == 30);
+ tokens.pop_front();
+}
+
+TEST_CASE("stringuntils splitToStringSet 1", "")
+{
+ std::set<std::string> tokens;
+ splitToStringSet(tokens, "", ',');
+ REQUIRE(tokens.empty() == true);
+
+ tokens.clear();
+ splitToStringSet(tokens, "10q,2w,30e", ',');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens.find("10q") != tokens.end());
+ REQUIRE(tokens.find("2w") != tokens.end());
+ REQUIRE(tokens.find("30e") != tokens.end());
+
+ tokens.clear();
+ splitToStringSet(tokens, "10q,2w,30e,", ',');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens.find("10q") != tokens.end());
+ REQUIRE(tokens.find("2w") != tokens.end());
+ REQUIRE(tokens.find("30e") != tokens.end());
+
+ tokens.clear();
+ splitToStringSet(tokens, "10q,,30e", ',');
+ REQUIRE(tokens.size() == 2);
+ REQUIRE(tokens.find("10q") != tokens.end());
+ REQUIRE(tokens.find("30e") != tokens.end());
+
+ tokens.clear();
+ splitToStringSet(tokens, "10q,2w,30e,", ',');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens.find("10q") != tokens.end());
+ REQUIRE(tokens.find("2w") != tokens.end());
+ REQUIRE(tokens.find("30e") != tokens.end());
+
+ tokens.clear();
+ splitToStringSet(tokens, "10w,2w;30e", ',');
+ REQUIRE(tokens.size() == 2);
+ REQUIRE(tokens.find("10w") != tokens.end());
+ REQUIRE(tokens.find("2w;30e") != tokens.end());
+
+ tokens.clear();
+ splitToStringSet(tokens, "10q;20w;30e", ';');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens.find("10q") != tokens.end());
+ REQUIRE(tokens.find("20w") != tokens.end());
+ REQUIRE(tokens.find("30e") != tokens.end());
+}
+
+TEST_CASE("stringuntils splitToIntVector 1", "")
+{
+ std::vector<int> tokens;
+ splitToIntVector(tokens, "", ',');
+ REQUIRE(tokens.empty() == true);
+
+ tokens.clear();
+ splitToIntVector(tokens, "10,2,30", ',');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens[0] == 10);
+ REQUIRE(tokens[1] == 2);
+ REQUIRE(tokens[2] == 30);
+
+ tokens.clear();
+ splitToIntVector(tokens, "10,2a,z30", ',');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens[0] == 10);
+ REQUIRE(tokens[1] == 2);
+ REQUIRE(tokens[2] == 0);
+
+ tokens.clear();
+ splitToIntVector(tokens, "10,2,30,", ',');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens[0] == 10);
+ REQUIRE(tokens[1] == 2);
+ REQUIRE(tokens[2] == 30);
+
+ tokens.clear();
+ splitToIntVector(tokens, "10,,30", ',');
+ REQUIRE(tokens.size() == 2);
+ REQUIRE(tokens[0] == 10);
+ REQUIRE(tokens[1] == 30);
+
+ tokens.clear();
+ splitToIntVector(tokens, "10,2;30", ',');
+ REQUIRE(tokens.size() == 2);
+ REQUIRE(tokens[0] == 10);
+ REQUIRE(tokens[1] == 2);
+
+ tokens.clear();
+ splitToIntVector(tokens, "10;20;30", ';');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens[0] == 10);
+ REQUIRE(tokens[1] == 20);
+ REQUIRE(tokens[2] == 30);
+}
+
+TEST_CASE("stringuntils splitToStringVector 1", "")
+{
+ std::vector<std::string> tokens;
+ splitToStringVector(tokens, "", ',');
+ REQUIRE(tokens.empty() == true);
+
+ tokens.clear();
+ splitToStringVector(tokens, "t,line,zz", ',');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens[0] == "t");
+ REQUIRE(tokens[1] == "line");
+ REQUIRE(tokens[2] == "zz");
+
+ tokens.clear();
+ splitToStringVector(tokens, "t,line,zz,", ',');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens[0] == "t");
+ REQUIRE(tokens[1] == "line");
+ REQUIRE(tokens[2] == "zz");
+
+ tokens.clear();
+ splitToStringVector(tokens, "t,,zz", ',');
+ REQUIRE(tokens.size() == 2);
+ REQUIRE(tokens[0] == "t");
+ REQUIRE(tokens[1] == "zz");
+
+ tokens.clear();
+ splitToStringVector(tokens, "10,a2;30", ',');
+ REQUIRE(tokens.size() == 2);
+ REQUIRE(tokens[0] == "10");
+ REQUIRE(tokens[1] == "a2;30");
+
+ tokens.clear();
+ splitToStringVector(tokens, "a10;b;3line", ';');
+ REQUIRE(tokens.size() == 3);
+ REQUIRE(tokens[0] == "a10");
+ REQUIRE(tokens[1] == "b");
+ REQUIRE(tokens[2] == "3line");
+}
+
+TEST_CASE("stringuntils replaceSpecialChars 1", "")
+{
+ std::string str;
+
+ str = "";
+ replaceSpecialChars(str);
+ REQUIRE(str.empty());
+
+ str = "test";
+ replaceSpecialChars(str);
+ REQUIRE("test" == str);
+
+ str = "&";
+ replaceSpecialChars(str);
+ REQUIRE("&" == str);
+
+ str = "&1";
+ replaceSpecialChars(str);
+ REQUIRE("&1" == str);
+
+ str = "&33";
+ replaceSpecialChars(str);
+ REQUIRE("&33" == str);
+
+ str = "&33;";
+ replaceSpecialChars(str);
+ REQUIRE("!" == str);
+
+ str = "&33z;";
+ replaceSpecialChars(str);
+ REQUIRE("&33z;" == str);
+
+ str = "1&33;";
+ replaceSpecialChars(str);
+ REQUIRE("1!" == str);
+
+ str = "&33;2";
+ replaceSpecialChars(str);
+ REQUIRE("!2" == str);
+
+ str = "&33;&";
+ replaceSpecialChars(str);
+ REQUIRE("!&" == str);
+
+ str = "test line&33;";
+ replaceSpecialChars(str);
+ REQUIRE("test line!" == str);
+}
+
+TEST_CASE("stringuntils normalize 1", "")
+{
+ REQUIRE(normalize("").empty());
+ REQUIRE(normalize("test") == "test");
+ REQUIRE(normalize("Test") == "test");
+ REQUIRE(normalize(" test line") == "test line");
+ REQUIRE(normalize("test line ") == "test line");
+ REQUIRE(normalize(" tEst line") == "test line");
+ REQUIRE(normalize("test lIne ") == "test line");
+}
+
+TEST_CASE("stringuntils combineDye 1", "")
+{
+ REQUIRE(combineDye("", "").empty());
+ REQUIRE("test" == combineDye("test", ""));
+ REQUIRE("|line" == combineDye("", "line"));
+ REQUIRE("test|line" == combineDye("test", "line"));
+ REQUIRE("|line" == combineDye("|w", "line"));
+ REQUIRE("aaa|line" == combineDye("aaa|w", "line"));
+ REQUIRE("test|line" == combineDye("test|w", "line"));
+}
+
+TEST_CASE("stringuntils combineDye 2", "")
+{
+ REQUIRE(combineDye2("", "").empty());
+ REQUIRE("test" == combineDye2("test", ""));
+ REQUIRE("test" == combineDye2("test", "W"));
+ REQUIRE(combineDye2("", "line").empty());
+ REQUIRE("test.xml" == combineDye2("test.xml", "123"));
+ REQUIRE("test.xml|#43413d,59544f,7a706c" ==
+ combineDye2("test.xml|#43413d,59544f,7a706c", ""));
+ REQUIRE("test.xml|#43413d,59544f,7a706c:W;" ==
+ combineDye2("test.xml|#43413d,59544f,7a706c", "W"));
+ REQUIRE("test.xml|#43413d,59544f,7a706c:W;#123456:B;" ==
+ combineDye2("test.xml|#43413d,59544f,7a706c;#123456", "W;B"));
+}
+
+TEST_CASE("stringuntils combineDye 3", "")
+{
+ REQUIRE(combineDye3("", "").empty());
+ REQUIRE("test" == combineDye3("test", ""));
+ REQUIRE(combineDye3("", "line").empty());
+ REQUIRE("test.xml|123" == combineDye3("test.xml", "123"));
+ REQUIRE("test.xml|#43413d,59544f,7a706c" ==
+ combineDye3("test.xml|#43413d,59544f,7a706c", ""));
+ REQUIRE("test.xml|#43413d,59544f,7a706c:W;" ==
+ combineDye3("test.xml|#43413d,59544f,7a706c", "W"));
+ REQUIRE("test.xml|#43413d,59544f,7a706c:W;#123456:B;" ==
+ combineDye3("test.xml|#43413d,59544f,7a706c;#123456", "W;B"));
+}
+
+TEST_CASE("stringuntils packList 1", "")
+{
+ std::list <std::string> list;
+ REQUIRE(packList(list).empty());
+
+ list.push_back(std::string());
+ REQUIRE("|" == packList(list));
+
+ list.clear();
+ list.push_back("test");
+ REQUIRE("test" == packList(list));
+
+ list.push_back("line");
+ REQUIRE("test|line" == packList(list));
+
+ list.push_back("2");
+ REQUIRE("test|line|2" == packList(list));
+
+ list.clear();
+ list.push_back("|test");
+ list.push_back("line");
+ REQUIRE("|test|line" == packList(list));
+}
+
+TEST_CASE("stringuntils stringToHexPath 1", "")
+{
+ std::string str;
+
+ str = "";
+ REQUIRE(stringToHexPath(str).empty());
+
+ str = "a";
+ REQUIRE("%61/" == stringToHexPath(str));
+
+ str = "ab";
+ REQUIRE("%61/%62" == stringToHexPath(str));
+
+ str = "abc";
+ REQUIRE("%61/%62%63" == stringToHexPath(str));
+
+ str = "abcd";
+ REQUIRE("%61/%62%63%64" == stringToHexPath(str));
+}
+
+TEST_CASE("stringuntils deleteCharLeft 1", "")
+{
+ std::string str;
+ unsigned int pos = 0;
+
+ str = "";
+ deleteCharLeft(str, nullptr);
+ REQUIRE(str.empty());
+
+ str = "test line";
+ pos = 4;
+ deleteCharLeft(str, &pos);
+ REQUIRE("tes line" == str);
+
+ str = "тест line";
+ pos = 8;
+ deleteCharLeft(str, &pos);
+ REQUIRE("тес line" == str);
+
+ str = "test line\x0";
+ pos = 4;
+ deleteCharLeft(str, &pos);
+ REQUIRE("tes line\x0" == str);
+}
+
+TEST_CASE("stringuntils findLast 1", "")
+{
+ std::string str;
+
+ str = "";
+ REQUIRE(findLast(str, ""));
+
+ str = "test line";
+ REQUIRE(findLast(str, "line"));
+
+ str = "test line";
+ REQUIRE(!findLast(str, "lin"));
+}
+
+TEST_CASE("stringuntils findFirst 1", "")
+{
+ std::string str;
+
+ str = "";
+ REQUIRE(findFirst(str, ""));
+
+ str = "test line";
+ REQUIRE(findFirst(str, "test"));
+
+ str = "test";
+ REQUIRE(findFirst(str, "test line") == false);
+
+ str = "test line";
+ REQUIRE(findFirst(str, "est") == false);
+}
+
+TEST_CASE("stringuntils findCutLast 1", "")
+{
+ std::string str;
+
+ str = "";
+ REQUIRE(findCutLast(str, ""));
+ REQUIRE(str.empty());
+
+ str = "test line";
+ REQUIRE(findCutLast(str, "line"));
+ REQUIRE("test " == str);
+
+ str = "test line";
+ REQUIRE(findCutLast(str, "lin") == false);
+ REQUIRE("test line" == str);
+
+ str = "test";
+ REQUIRE(findCutLast(str, "test line") == false);
+ REQUIRE("test" == str);
+}
+
+TEST_CASE("stringuntils CutLast 1", "")
+{
+ std::string str;
+
+ str = "";
+ cutLast(str, "");
+ REQUIRE(str.empty());
+
+ str = "test line";
+ cutLast(str, "line");
+ REQUIRE("test " == str);
+
+ str = "test line";
+ cutLast(str, "lin");
+ REQUIRE("test line" == str);
+
+ str = "test";
+ cutLast(str, "test line");
+ REQUIRE("test" == str);
+}
+
+TEST_CASE("stringuntils findCutFirst 1", "")
+{
+ std::string str;
+
+ str = "";
+ REQUIRE(findCutFirst(str, ""));
+ REQUIRE(str.empty());
+
+ str = "test line";
+ REQUIRE(findCutFirst(str, "test"));
+ REQUIRE(" line" == str);
+
+ str = "test line";
+ REQUIRE(findCutFirst(str, "est") == false);
+ REQUIRE("test line" == str);
+
+ str = "test";
+ REQUIRE(findCutFirst(str, "test line") == false);
+ REQUIRE("test" == str);
+}
+
+TEST_CASE("stringuntils cutFirst 1", "")
+{
+ std::string str;
+
+ str = "";
+ cutFirst(str, "");
+ REQUIRE(str.empty());
+
+ str = "test line";
+ cutFirst(str, "test");
+ REQUIRE(" line" == str);
+
+ str = "test line";
+ cutFirst(str, "est");
+ REQUIRE("test line" == str);
+
+ str = "test";
+ cutFirst(str, "test line");
+ REQUIRE("test" == str);
+}
+
+TEST_CASE("stringuntils removeProtocol 1", "")
+{
+ std::string str;
+
+ str = "";
+ REQUIRE(removeProtocol(str).empty());
+
+ str = "http://";
+ REQUIRE(removeProtocol(str).empty());
+
+ str = "http://test";
+ REQUIRE("test" == removeProtocol(str));
+}
+
+TEST_CASE("stringuntils strStartWith 1", "")
+{
+ REQUIRE(strStartWith("", ""));
+ REQUIRE(!strStartWith("", "1"));
+ REQUIRE(strStartWith("test line", "test"));
+ REQUIRE(strStartWith("test line", "test line"));
+ REQUIRE(!strStartWith("test line", "est"));
+}
+
+TEST_CASE("stringuntils encodeLinkText", "")
+{
+ std::string str;
+
+ str = encodeLinkText("test line");
+ REQUIRE(str == "test line");
+ str = encodeLinkText("test|line");
+ REQUIRE(str == "test\342\235\230line");
+ str = encodeLinkText("test||line");
+ REQUIRE(str == "test\342\235\230\342\235\230line");
+}
+
+TEST_CASE("stringuntils decodeLinkText", "")
+{
+ std::string str;
+
+ str = encodeLinkText("test|line");
+ REQUIRE(str == "test\342\235\230line");
+ str = decodeLinkText(str);
+ REQUIRE(str == "test|line");
+}
+
+TEST_CASE("stringuntils isDigit", "")
+{
+ std::string str;
+
+ REQUIRE_FALSE(isDigit(""));
+ REQUIRE(isDigit("1"));
+ REQUIRE(isDigit("123"));
+ REQUIRE_FALSE(isDigit("+123"));
+ REQUIRE_FALSE(isDigit("-123"));
+ REQUIRE_FALSE(isDigit("1.23"));
+ REQUIRE_FALSE(isDigit("12-34"));
+}
+
+TEST_CASE("stringuntils findAny", "")
+{
+ std::string str;
+
+ REQUIRE(findAny("test line", ",", 0) == std::string::npos);
+ REQUIRE(findAny("test line", " ", 0) == 4U);
+ REQUIRE(findAny("test, line", ", ", 0) == 4U);
+ REQUIRE(findAny("test ,line", ", ", 0) == 4U);
+ REQUIRE(findAny("test, line", " ,", 2) == 4U);
+ REQUIRE(findAny("test ,line", " ,", 3) == 4U);
+ REQUIRE(findAny("\"one\",,two, tree", ",", 5) == 5U);
+}
+
+TEST_CASE("stringuntils escapeString", "")
+{
+ REQUIRE(escapeString("") == "\"\"");
+ REQUIRE(escapeString("1") == "\"1\"");
+ REQUIRE(escapeString(" ") == "\" \"");
+ REQUIRE(escapeString("\"") == "\"\\\"\"");
+ REQUIRE(escapeString("123") == "\"123\"");
+ REQUIRE(escapeString("12\"3") == "\"12\\\"3\"");
+ REQUIRE(escapeString("12\"\"3") == "\"12\\\"\\\"3\"");
+ REQUIRE(escapeString("\"123\"") == "\"\\\"123\\\"\"");
+ REQUIRE(escapeString("\\") == "\"\\\"");
+ REQUIRE(escapeString("12\\3") == "\"12\\3\"");
+}
+
+TEST_CASE("stringuntils sanitizePath", "")
+{
+ std::string path;
+ const std::string sep = dirSeparator;
+ path = "";
+ sanitizePath(path);
+ REQUIRE(path.empty());
+ path = "/";
+ sanitizePath(path);
+ REQUIRE(path == dirSeparator);
+ path = "/\\";
+ sanitizePath(path);
+ REQUIRE(path == dirSeparator);
+ path = "\\/";
+ sanitizePath(path);
+ REQUIRE(path == dirSeparator);
+ path = "//";
+ sanitizePath(path);
+ REQUIRE(path == dirSeparator);
+ path = "///";
+ sanitizePath(path);
+ REQUIRE(path == dirSeparator);
+ path = "//\\/";
+ sanitizePath(path);
+ REQUIRE(path == dirSeparator);
+ path = "///\\";
+ sanitizePath(path);
+ REQUIRE(path == dirSeparator);
+ path = "\\";
+ sanitizePath(path);
+ REQUIRE(path == dirSeparator);
+ path = "\\\\";
+ sanitizePath(path);
+ REQUIRE(path == dirSeparator);
+ path = "\\/\\";
+ sanitizePath(path);
+ REQUIRE(path == dirSeparator);
+ path = "\\\\/";
+ sanitizePath(path);
+ REQUIRE(path == dirSeparator);
+ path = "test";
+ sanitizePath(path);
+ REQUIRE(path == "test");
+ path = "./test";
+ sanitizePath(path);
+ REQUIRE(path == "." + sep + "test");
+ path = "test line";
+ sanitizePath(path);
+ REQUIRE(path == "test line");
+ path = "dir/test";
+ sanitizePath(path);
+ REQUIRE(path == "dir" + sep + "test");
+ path = "/dir/test";
+ sanitizePath(path);
+ REQUIRE(path == sep + "dir" + sep + "test");
+ path = "dir//test";
+ sanitizePath(path);
+ REQUIRE(path == "dir" + sep + "test");
+ path = "dir///test";
+ sanitizePath(path);
+ REQUIRE(path == "dir" + sep + "test");
+ path = "dir///\\test";
+ sanitizePath(path);
+ REQUIRE(path == "dir" + sep + "test");
+ path = "dir/\\//test";
+ sanitizePath(path);
+ REQUIRE(path == "dir" + sep + "test");
+ path = "dir\\test";
+ sanitizePath(path);
+ REQUIRE(path == "dir" + sep + "test");
+ path = "dir/test/";
+ sanitizePath(path);
+ REQUIRE(path == "dir" + sep + "test" + sep);
+ path = "dir/test\\";
+ sanitizePath(path);
+ REQUIRE(path == "dir" + sep + "test" + sep);
+ path = "/very\\long/dir\\with\\sepa/ra/tors";
+ sanitizePath(path);
+ REQUIRE(path == sep + "very" + sep + "long" + sep + \
+ "dir" + sep + "with" + sep + "sepa" + sep + "ra" + sep + "tors");
+ path = "/very\\long/dir\\\\with\\sepa//ra/tors";
+ sanitizePath(path);
+ REQUIRE(path == sep + "very" + sep + "long" + sep + \
+ "dir" + sep + "with" + sep + "sepa" + sep + "ra" + sep + "tors");
+}
+
+TEST_CASE("stringuntils pathJoin1", "")
+{
+ const std::string sep = dirSeparator;
+
+ REQUIRE(pathJoin("", "") == sep);
+ REQUIRE(pathJoin(sep, "") == sep);
+ REQUIRE(pathJoin("", sep) == sep);
+ REQUIRE(pathJoin(sep, sep) == sep);
+ REQUIRE(pathJoin("dir1", "dir2") == "dir1" + sep + "dir2");
+ REQUIRE(pathJoin("dir1" + sep, "dir2") == "dir1" + sep + "dir2");
+ REQUIRE(pathJoin("dir1", sep + "dir2") == "dir1" + sep + "dir2");
+ REQUIRE(pathJoin("dir1" + sep, sep + "dir2") == "dir1" + sep + "dir2");
+ REQUIRE(pathJoin("dir1" + sep + "dir2" + sep + "dir3", "dir4") ==
+ "dir1" + sep + "dir2" + sep + "dir3" + sep + "dir4");
+ REQUIRE(pathJoin("dir1" + sep + "dir2" + sep, "dir3" + sep + "dir4") ==
+ "dir1" + sep + "dir2" + sep + "dir3" + sep + "dir4");
+ REQUIRE(pathJoin("dir1" + sep + "dir2", "dir3" + sep + "dir4") ==
+ "dir1" + sep + "dir2" + sep + "dir3" + sep + "dir4");
+ REQUIRE(pathJoin("dir1" + sep + "dir2", sep + "dir3" + sep + "dir4") ==
+ "dir1" + sep + "dir2" + sep + "dir3" + sep + "dir4");
+}
+
+TEST_CASE("stringuntils pathJoin2", "")
+{
+ const std::string sep = dirSeparator;
+
+ REQUIRE(pathJoin("", "", "") == sep);
+ REQUIRE(pathJoin(sep, "", "") == sep);
+ REQUIRE(pathJoin("", sep, "") == sep);
+ REQUIRE(pathJoin("", "", sep) == sep);
+ REQUIRE(pathJoin(sep, sep, "") == sep);
+ REQUIRE(pathJoin(sep, "", sep) == sep);
+ REQUIRE(pathJoin("", sep, sep) == sep);
+ REQUIRE(pathJoin(sep, sep, sep) == sep);
+
+ REQUIRE(pathJoin("dir1", "dir2", "dir3") ==
+ "dir1" + sep + "dir2" + sep + "dir3");
+ REQUIRE(pathJoin("dir1" + sep, "dir2", "dir3") ==
+ "dir1" + sep + "dir2" + sep + "dir3");
+ REQUIRE(pathJoin("dir1", sep + "dir2", "dir3") ==
+ "dir1" + sep + "dir2" + sep + "dir3");
+ REQUIRE(pathJoin("dir1", "dir2" + sep, "dir3") ==
+ "dir1" + sep + "dir2" + sep + "dir3");
+ REQUIRE(pathJoin("dir1", "dir2", sep + "dir3") ==
+ "dir1" + sep + "dir2" + sep + "dir3");
+ REQUIRE(pathJoin("dir1", "dir2", "dir3" + sep) ==
+ "dir1" + sep + "dir2" + sep + "dir3" + sep);
+ REQUIRE(pathJoin("dir1" + sep, sep + "dir2", "dir3") ==
+ "dir1" + sep + "dir2" + sep + "dir3");
+ REQUIRE(pathJoin("dir1" + sep, "dir2" + sep, "dir3") ==
+ "dir1" + sep + "dir2" + sep + "dir3");
+ REQUIRE(pathJoin("dir1" + sep, "dir2", sep + "dir3") ==
+ "dir1" + sep + "dir2" + sep + "dir3");
+ REQUIRE(pathJoin("dir1" + sep, sep + "dir2" + sep, "dir3") ==
+ "dir1" + sep + "dir2" + sep + "dir3");
+ REQUIRE(pathJoin("dir1" + sep, sep + "dir2", sep + "dir3") ==
+ "dir1" + sep + "dir2" + sep + "dir3");
+ REQUIRE(pathJoin("dir1" + sep, sep + "dir2" + sep, "dir3") ==
+ "dir1" + sep + "dir2" + sep + "dir3");
+ REQUIRE(pathJoin("dir1" + sep, sep + "dir2" + sep, sep + "dir3") ==
+ "dir1" + sep + "dir2" + sep + "dir3");
+ REQUIRE(pathJoin("dir1" + sep + "dir2" + sep + "dir3", "dir4", "dir5") ==
+ "dir1" + sep + "dir2" + sep + "dir3" + sep + "dir4" + sep + "dir5");
+ REQUIRE(pathJoin("dir1" + sep + "dir2" + sep,
+ "dir3" + sep + "dir4",
+ "dir5") ==
+ "dir1" + sep + "dir2" + sep + "dir3" + sep + "dir4" + sep + "dir5");
+ REQUIRE(pathJoin("dir1" + sep + "dir2",
+ "dir3",
+ sep + "dir4" + sep + "dir5") ==
+ "dir1" + sep + "dir2" + sep + "dir3" + sep + "dir4" + sep + "dir5");
+ REQUIRE(pathJoin("dir1" + sep + "dir2",
+ sep + "dir3" + sep + "dir4",
+ sep + "dir5") ==
+ "dir1" + sep + "dir2" + sep + "dir3" + sep + "dir4" + sep + "dir5");
+}
+
+TEST_CASE("stringuntils urlJoin", "")
+{
+ REQUIRE(urlJoin("", "") == "/");
+ REQUIRE(urlJoin("/", "") == "/");
+ REQUIRE(urlJoin("", "/") == "/");
+ REQUIRE(urlJoin("/", "/") == "/");
+ REQUIRE(urlJoin("dir1", "dir2") == "dir1/dir2");
+ REQUIRE(urlJoin("dir1/", "dir2") == "dir1/dir2");
+ REQUIRE(urlJoin("dir1", "/dir2") == "dir1/dir2");
+ REQUIRE(urlJoin("dir1/", "/dir2") == "dir1/dir2");
+ REQUIRE(urlJoin("dir1/dir2/dir3", "dir4") == "dir1/dir2/dir3/dir4");
+ REQUIRE(urlJoin("dir1/dir2/", "dir3/dir4") == "dir1/dir2/dir3/dir4");
+ REQUIRE(urlJoin("dir1/dir2", "dir3/dir4") == "dir1/dir2/dir3/dir4");
+ REQUIRE(urlJoin("dir1/dir2", "/dir3/dir4") == "dir1/dir2/dir3/dir4");
+}
+
+TEST_CASE("stringuntils secureChatCommand", "")
+{
+ std::string str;
+ secureChatCommand(str);
+ REQUIRE(str.empty());
+ str = "test";
+ secureChatCommand(str);
+ REQUIRE(str == "test");
+ str = "test line";
+ secureChatCommand(str);
+ REQUIRE(str == "test line");
+ str = "/test";
+ secureChatCommand(str);
+ REQUIRE(str == "_/test");
+ str = "@test";
+ secureChatCommand(str);
+ REQUIRE(str == "_@test");
+ str = "#test";
+ secureChatCommand(str);
+ REQUIRE(str == "_#test");
+}
+
+#ifdef ENABLE_NLS
+TEST_CASE("stringuntils timeDiffToString", "")
+{
+ REQUIRE(timeDiffToString(60 * 60 * 24 * 7) == "1 week");
+ REQUIRE(timeDiffToString(60 * 60 * 24 * 7 * 2 +
+ 60 * 60 * 24 * 3
+ ) == "2 weeks, 3 days");
+ REQUIRE(timeDiffToString(60 * 60 * 24 * 7 * 2 +
+ 60 * 60 * 24 * 3 +
+ 60 * 60 * 4
+ ) == "2 weeks, 3 days, 4 hours");
+ REQUIRE(timeDiffToString(60 * 60 * 24 * 7 * 2 +
+ 60 * 60 * 24 * 3 +
+ 60 * 60 * 4 +
+ 60 * 7
+ ) == "2 weeks, 3 days, 4 hours, 7 minutes");
+ REQUIRE(timeDiffToString(60 * 60 * 24 * 7 * 2 +
+ 60 * 60 * 24 * 3 +
+ 60 * 60 * 4 +
+ 60 * 7 +
+ 10
+ ) == "2 weeks, 3 days, 4 hours, 7 minutes, 10 seconds");
+ REQUIRE(timeDiffToString(5) == "5 seconds");
+ REQUIRE(timeDiffToString(0) == "0 seconds");
+ REQUIRE(timeDiffToString(60 * 60 * 24 * 3
+ ) == "3 days");
+ REQUIRE(timeDiffToString(60 * 60 * 4
+ ) == "4 hours");
+ REQUIRE(timeDiffToString(60 * 7
+ ) == "7 minutes");
+}
+#endif // ENABLE_NLS
+
+TEST_CASE("stringuntils replaceItemLinks", "")
+{
+ logger = new Logger();
+ VirtFs::mountDirSilent("data", Append_false);
+ VirtFs::mountDirSilent("../data", Append_false);
+ VirtFs::mountDirSilent("data/test", Append_false);
+ VirtFs::mountDirSilent("../data/test", Append_false);
+
+ ItemDB::NamedItemInfos &namedInfos = ItemDB::getNamedItemInfosTest();
+ ItemDB::ItemInfos &infos = ItemDB::getItemInfosTest();
+ paths.setDefaultValues(getPathsDefaults());
+ ItemInfo *info = new ItemInfo;
+ info->setId(123456);
+ info->setName("test name 1");
+ namedInfos["test name 1"] = info;
+ infos[123456] = info;
+
+ info = new ItemInfo;
+ info->setId(123);
+ info->setName("test name 2");
+ namedInfos["test name 2"] = info;
+ namedInfos["qqq"] = info;
+ infos[123] = info;
+
+ std::string str;
+
+ SECTION("empty")
+ {
+ str = "test line";
+ replaceItemLinks(str);
+ REQUIRE(str == "test line");
+
+ str = "";
+ replaceItemLinks(str);
+ REQUIRE(str.empty());
+
+ str = "[]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[]");
+
+ str = "[qqq]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[@@123|qqq@@]");
+
+ str = "[,]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[,]");
+
+ str = "[, ]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[, ]");
+ }
+
+ SECTION("simple")
+ {
+ str = "[test name 1]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[@@123456|test name 1@@]");
+
+ str = "text1 [test name 1] text2";
+ replaceItemLinks(str);
+ REQUIRE(str == "text1 [@@123456|test name 1@@] text2");
+
+ str = "[test name 1][test name 1]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[@@123456|test name 1@@][@@123456|test name 1@@]");
+
+ str = "[test name 1] [test name 1]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[@@123456|test name 1@@] [@@123456|test name 1@@]");
+
+ str = "test1 [test name 1]test2[test name 1] test3";
+ replaceItemLinks(str);
+ REQUIRE(str == "test1 [@@123456|test name 1@@]test2"
+ "[@@123456|test name 1@@] test3");
+
+// failing because assert
+// str = "[test name 1] [no link]";
+// replaceItemLinks(str);
+// REQUIRE(str == "[@@123456|test name 1@@] [no link]");
+
+ str = "[test name 1,test name 2]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[@@123456,123|@@]");
+
+ str = "[test name 1, test name 2 ]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[@@123456,123|@@]");
+ }
+
+ SECTION("broken")
+ {
+ str = "[";
+ replaceItemLinks(str);
+ REQUIRE(str == "[");
+
+ str = "]";
+ replaceItemLinks(str);
+ REQUIRE(str == "]");
+
+ str = "][";
+ replaceItemLinks(str);
+ REQUIRE(str == "][");
+
+ str = "]]";
+ replaceItemLinks(str);
+ REQUIRE(str == "]]");
+
+ str = "]t";
+ replaceItemLinks(str);
+ REQUIRE(str == "]t");
+
+ str = "t[";
+ replaceItemLinks(str);
+ REQUIRE(str == "t[");
+
+ str = "t]";
+ replaceItemLinks(str);
+ REQUIRE(str == "t]");
+
+ str = "[[[";
+ replaceItemLinks(str);
+ REQUIRE(str == "[[[");
+
+ str = "[[]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[[]");
+
+ str = "[[t";
+ replaceItemLinks(str);
+ REQUIRE(str == "[[t");
+
+ str = "[][";
+ replaceItemLinks(str);
+ REQUIRE(str == "[][");
+
+ str = "[]]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[]]");
+
+ str = "[]t";
+ replaceItemLinks(str);
+ REQUIRE(str == "[]t");
+
+ str = "[t[";
+ replaceItemLinks(str);
+ REQUIRE(str == "[t[");
+
+// failing because assert
+// str = "[t]";
+// replaceItemLinks(str);
+// REQUIRE(str == "[t]");
+
+ str = "t[[";
+ replaceItemLinks(str);
+ REQUIRE(str == "t[[");
+
+ str = "t[]";
+ replaceItemLinks(str);
+ REQUIRE(str == "t[]");
+
+ str = "t[[";
+ replaceItemLinks(str);
+ REQUIRE(str == "t[[");
+
+ str = "]]]";
+ replaceItemLinks(str);
+ REQUIRE(str == "]]]");
+ }
+
+ SECTION("broken2")
+ {
+ str = "[][]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[][]");
+
+ str = "[[]]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[[]]");
+
+ str = "][[]";
+ replaceItemLinks(str);
+ REQUIRE(str == "][[]");
+ }
+
+ SECTION("broken3")
+ {
+ str = "[[test name 1]]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[[@@123456|test name 1@@]]");
+
+ str = "[[test name 1]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[[@@123456|test name 1@@]");
+
+ str = "[[qqq] name 1]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[[@@123|qqq@@] name 1]");
+
+ str = "[[test name 1]test name 1]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[[@@123456|test name 1@@]test name 1]");
+
+ str = "[[test name 1[]test name 1]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[[test name 1[]test name 1]");
+
+ str = "[[test name 1],test name2,test name 1]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[[@@123456|test name 1@@],test name2,test name 1]");
+
+ str = "[[ test name 1], test name2,test name 1 ]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[[@@123456|test name 1@@], test name2,test name 1 ]");
+
+ str = "[[test name 1,test name2[]test name 1]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[[test name 1,test name2[]test name 1]");
+
+ str = "[[test name 1 ,test name2[] test name 1]";
+ replaceItemLinks(str);
+ REQUIRE(str == "[[test name 1 ,test name2[] test name 1]");
+ }
+ ResourceManager::deleteInstance();
+ delete_all(infos);
+ infos.clear();
+ namedInfos.clear();
+ VirtFs::unmountDirSilent("data");
+ VirtFs::unmountDirSilent("../data");
+ VirtFs::unmountDirSilent("data/test");
+ VirtFs::unmountDirSilent("../data/test");
+ delete2(logger);
+// VirtFs::deinit();
+}
diff --git a/src/unittests/utils/timer_unittest.cc b/src/unittests/utils/timer_unittest.cc
new file mode 100644
index 000000000..b5cfc692e
--- /dev/null
+++ b/src/unittests/utils/timer_unittest.cc
@@ -0,0 +1,88 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2012-2017 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "unittests/unittests.h"
+
+#include "const/utils/timer.h"
+
+#include "utils/timer.h"
+
+#include <climits>
+
+#include "debug.h"
+
+static const int MAX_TICK_VALUE = INT_MAX / 2;
+
+TEST_CASE("timer const", "")
+{
+ REQUIRE(MILLISECONDS_IN_A_TICK != 0);
+}
+
+TEST_CASE("timer get_elapsed_time", "")
+{
+ tick_time = 0;
+ REQUIRE(get_elapsed_time(0) == 0);
+ REQUIRE(get_elapsed_time(MAX_TICK_VALUE - 1) == 1 * MILLISECONDS_IN_A_TICK);
+ REQUIRE(get_elapsed_time(MAX_TICK_VALUE - 2) == 2 * MILLISECONDS_IN_A_TICK);
+
+ tick_time = 1;
+ REQUIRE(get_elapsed_time(0) == 1 * MILLISECONDS_IN_A_TICK);
+ REQUIRE(get_elapsed_time(1) == 0 * MILLISECONDS_IN_A_TICK);
+ REQUIRE(get_elapsed_time(MAX_TICK_VALUE - 1) == 2 * MILLISECONDS_IN_A_TICK);
+ REQUIRE(get_elapsed_time(MAX_TICK_VALUE - 2) == 3 * MILLISECONDS_IN_A_TICK);
+
+ tick_time = 10;
+ REQUIRE(get_elapsed_time(0) == 10 * MILLISECONDS_IN_A_TICK);
+ REQUIRE(get_elapsed_time(10) == 0 * MILLISECONDS_IN_A_TICK);
+ REQUIRE(get_elapsed_time(MAX_TICK_VALUE - 1) ==
+ 11 * MILLISECONDS_IN_A_TICK);
+
+ tick_time = 10000;
+ REQUIRE(get_elapsed_time(0) == 10000 * MILLISECONDS_IN_A_TICK);
+ REQUIRE(get_elapsed_time(10) == 9990 * MILLISECONDS_IN_A_TICK);
+ REQUIRE(get_elapsed_time(10000) == 0 * MILLISECONDS_IN_A_TICK);
+ REQUIRE(get_elapsed_time(MAX_TICK_VALUE - 1) ==
+ 10001 * MILLISECONDS_IN_A_TICK);
+}
+
+TEST_CASE("timer get_elapsed_time1", "")
+{
+ tick_time = 0;
+ REQUIRE(get_elapsed_time1(0) == 0);
+ REQUIRE(get_elapsed_time1(MAX_TICK_VALUE - 1) == 1);
+ REQUIRE(get_elapsed_time1(MAX_TICK_VALUE - 2) == 2);
+
+ tick_time = 1;
+ REQUIRE(get_elapsed_time1(0) == 1);
+ REQUIRE(get_elapsed_time1(1) == 0);
+ REQUIRE(get_elapsed_time1(MAX_TICK_VALUE - 1) == 2);
+ REQUIRE(get_elapsed_time1(MAX_TICK_VALUE - 2) == 3);
+
+ tick_time = 10;
+ REQUIRE(get_elapsed_time1(0) == 10);
+ REQUIRE(get_elapsed_time1(10) == 0);
+ REQUIRE(get_elapsed_time1(MAX_TICK_VALUE - 1) == 11);
+
+ tick_time = 10000;
+ REQUIRE(get_elapsed_time1(0) == 10000);
+ REQUIRE(get_elapsed_time1(10) == 9990);
+ REQUIRE(get_elapsed_time1(10000) == 0);
+ REQUIRE(get_elapsed_time1(MAX_TICK_VALUE - 1) == 10001);
+}
diff --git a/src/unittests/utils/translation/poparser_unittest.cc b/src/unittests/utils/translation/poparser_unittest.cc
new file mode 100644
index 000000000..f724e66fb
--- /dev/null
+++ b/src/unittests/utils/translation/poparser_unittest.cc
@@ -0,0 +1,158 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2016-2017 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "unittests/unittests.h"
+
+#include "client.h"
+#include "configuration.h"
+#include "configmanager.h"
+#include "dirs.h"
+#include "graphicsmanager.h"
+
+#include "being/actorsprite.h"
+
+#include "fs/virtfs/fs.h"
+
+#include "gui/gui.h"
+#include "gui/theme.h"
+
+#include "utils/delete2.h"
+#include "utils/env.h"
+
+#include "utils/translation/podict.h"
+#include "utils/translation/poparser.h"
+
+#include "render/sdlgraphics.h"
+
+#include "resources/sdlimagehelper.h"
+
+#include "resources/resourcemanager/resourcemanager.h"
+
+#include "debug.h"
+
+TEST_CASE("PoParser leak test1", "")
+{
+ logger = new Logger();
+ REQUIRE(gui == nullptr);
+ ResourceManager::cleanOrphans(true);
+ ResourceManager::deleteInstance();
+ delete2(logger);
+}
+
+TEST_CASE("PoParser tests", "PoParser")
+{
+ setEnv("SDL_VIDEODRIVER", "dummy");
+
+ client = new Client;
+ logger = new Logger();
+ VirtFs::mountDirSilent("data", Append_false);
+ VirtFs::mountDirSilent("../data", Append_false);
+
+ mainGraphics = new SDLGraphics;
+ imageHelper = new SDLImageHelper();
+#ifdef USE_SDL2
+ SDLImageHelper::setRenderer(graphicsManager.createRenderer(
+ graphicsManager.createWindow(640, 480, 0,
+ SDL_WINDOW_SHOWN | SDL_SWSURFACE), SDL_RENDERER_SOFTWARE));
+#else // USE_SDL2
+
+ graphicsManager.createWindow(640, 480, 0, SDL_ANYFORMAT | SDL_SWSURFACE);
+#endif // USE_SDL2
+
+ theme = new Theme;
+ Theme::selectSkin();
+
+ Dirs::initRootDir();
+ Dirs::initHomeDir();
+
+ ConfigManager::initConfiguration();
+ getConfigDefaults2(config.getDefaultValues());
+ branding.setDefaultValues(getBrandingDefaults());
+
+ ActorSprite::load();
+ gui = new Gui();
+ gui->postInit(mainGraphics);
+
+ SECTION("PoParser empty")
+ {
+ PoParser *parser = new PoParser;
+ PoDict *dict = parser->load("ru",
+ "unknownfilename.po",
+ nullptr);
+
+ REQUIRE(dict != nullptr);
+ REQUIRE(dict->getMap() != nullptr);
+ REQUIRE(dict->getMap()->empty());
+
+ delete parser;
+ delete dict;
+ }
+
+ SECTION("PoParser normal")
+ {
+ PoParser *parser = new PoParser;
+ PoDict *dict = parser->load("ru",
+ "test/test1",
+ nullptr);
+
+ REQUIRE(dict != nullptr);
+ REQUIRE(dict->getMap() != nullptr);
+ REQUIRE(dict->getMap()->size() == 1786);
+ REQUIRE(dict->getStr("Unknown skill message.") ==
+ "Неизвестная ошибка скилов.");
+ REQUIRE(dict->getStr("Full strip failed because of coating.") ==
+ "Full strip failed because of coating.");
+ REQUIRE(dict->getStr("You picked up %d [@@%d|%s@@].") ==
+ "Вы подняли %d [@@%d|%s@@].");
+
+ delete parser;
+ delete dict;
+ }
+
+ SECTION("PoParser fuzzy")
+ {
+ PoParser *parser = new PoParser;
+ PoDict *dict = parser->load("ru",
+ "test/test1",
+ nullptr);
+
+ REQUIRE(dict != nullptr);
+ REQUIRE(dict->getMap() != nullptr);
+ REQUIRE(dict->getMap()->size() == 1786);
+ REQUIRE(dict->getStr("Atk +100%.") == "Atk +100%.");
+
+ delete parser;
+ delete dict;
+ }
+ delete2(client);
+ VirtFs::unmountDirSilent("data");
+ VirtFs::unmountDirSilent("../data");
+ delete2(logger);
+// VirtFs::deinit();
+}
+
+TEST_CASE("PoParser leak test2", "")
+{
+ logger = new Logger();
+ REQUIRE(gui == nullptr);
+ ResourceManager::cleanOrphans(true);
+ ResourceManager::deleteInstance();
+ delete2(logger);
+}
diff --git a/src/unittests/utils/xml_unittest.cc b/src/unittests/utils/xml_unittest.cc
new file mode 100644
index 000000000..f9f7990f8
--- /dev/null
+++ b/src/unittests/utils/xml_unittest.cc
@@ -0,0 +1,400 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2014-2017 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "unittests/unittests.h"
+
+#include "client.h"
+#include "configuration.h"
+#include "configmanager.h"
+#include "dirs.h"
+#include "graphicsmanager.h"
+
+#include "being/actorsprite.h"
+
+#include "fs/virtfs/fs.h"
+
+#include "gui/gui.h"
+#include "gui/theme.h"
+
+#include "utils/delete2.h"
+#include "utils/env.h"
+#ifdef ENABLE_PUGIXML
+#include "utils/xmlwriter.h"
+#endif // ENABLE_PUGIXML
+
+#include "render/sdlgraphics.h"
+
+#include "resources/sdlimagehelper.h"
+
+#include "resources/resourcemanager/resourcemanager.h"
+
+#include "debug.h"
+
+TEST_CASE("xml test1", "")
+{
+ logger = new Logger();
+ REQUIRE(client == nullptr);
+ REQUIRE(gui == nullptr);
+ ResourceManager::cleanOrphans(true);
+ ResourceManager::deleteInstance();
+ delete2(logger);
+}
+
+TEST_CASE("xml doc", "")
+{
+ setEnv("SDL_VIDEODRIVER", "dummy");
+
+ logger = new Logger();
+ client = new Client;
+ XML::initXML();
+ VirtFs::mountDirSilent("data", Append_false);
+ VirtFs::mountDirSilent("../data", Append_false);
+ mainGraphics = new SDLGraphics;
+ imageHelper = new SDLImageHelper();
+#ifdef USE_SDL2
+ SDLImageHelper::setRenderer(graphicsManager.createRenderer(
+ graphicsManager.createWindow(640, 480, 0,
+ SDL_WINDOW_SHOWN | SDL_SWSURFACE), SDL_RENDERER_SOFTWARE));
+#else // USE_SDL2
+
+ graphicsManager.createWindow(640, 480, 0, SDL_ANYFORMAT | SDL_SWSURFACE);
+#endif // USE_SDL2
+
+ Dirs::initRootDir();
+ Dirs::initHomeDir();
+
+ ConfigManager::initConfiguration();
+ getConfigDefaults2(config.getDefaultValues());
+ branding.setDefaultValues(getBrandingDefaults());
+
+ theme = new Theme;
+ Theme::selectSkin();
+
+ const char *const tempXmlName = "tempxml.xml";
+ ActorSprite::load();
+ gui = new Gui();
+ gui->postInit(mainGraphics);
+
+ SECTION("load1")
+ {
+ XML::Document doc("graphics/gui/browserbox.xml",
+ UseVirtFs_true,
+ SkipError_false);
+ REQUIRE(doc.isLoaded() == true);
+ REQUIRE(doc.isValid() == true);
+ REQUIRE(doc.rootNode() != nullptr);
+ REQUIRE(xmlNameEqual(doc.rootNode(), "skinset") == true);
+ REQUIRE(xmlNameEqual(doc.rootNode(), "skinset123") == false);
+ REQUIRE(xmlTypeEqual(doc.rootNode(), XML_ELEMENT_NODE) == true);
+// REQUIRE(XmlHaveChildContent(doc.rootNode()) == true);
+ }
+
+ SECTION("load2")
+ {
+ const char *const xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<root><data option1=\"false\" option2=\"true\"/>"
+ "<cont>this is test</cont></root>";
+ XML::Document doc(xml, strlen(xml));
+ REQUIRE(doc.isLoaded() == true);
+ REQUIRE(doc.isValid() == true);
+ REQUIRE(doc.rootNode() != nullptr);
+ REQUIRE(xmlNameEqual(doc.rootNode(), "root") == true);
+ REQUIRE(xmlNameEqual(doc.rootNode(), "root123") == false);
+ REQUIRE(xmlTypeEqual(doc.rootNode(), XML_ELEMENT_NODE) == true);
+ REQUIRE(XmlHasProp(doc.rootNode(), "option1") == false);
+ REQUIRE(XmlHasProp(doc.rootNode(), "option123") == false);
+ REQUIRE(XmlHaveChildContent(doc.rootNode()) == false);
+ }
+
+ SECTION("load3")
+ {
+ const std::string xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<!-- comment here\nand here -->"
+ "<root><data option1=\"false\" option2=\"true\"/></root>";
+ XML::Document doc(xml.c_str(), xml.size());
+ REQUIRE(doc.isLoaded() == true);
+ REQUIRE(doc.isValid() == true);
+ REQUIRE(doc.rootNode() != nullptr);
+ REQUIRE(xmlNameEqual(doc.rootNode(), "root") == true);
+ REQUIRE(xmlNameEqual(doc.rootNode(), "root123") == false);
+ REQUIRE(xmlTypeEqual(doc.rootNode(), XML_ELEMENT_NODE) == true);
+ REQUIRE(XmlHasProp(doc.rootNode(), "option1") == false);
+ REQUIRE(XmlHasProp(doc.rootNode(), "option123") == false);
+ REQUIRE(XmlHaveChildContent(doc.rootNode()) == false);
+ }
+
+ SECTION("load4")
+ {
+ const char *const xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<root>this is test</root>";
+ XML::Document doc(xml, strlen(xml));
+ REQUIRE(doc.isLoaded() == true);
+ REQUIRE(doc.isValid() == true);
+ REQUIRE(doc.rootNode() != nullptr);
+ REQUIRE(xmlNameEqual(doc.rootNode(), "root") == true);
+ REQUIRE(xmlNameEqual(doc.rootNode(), "root123") == false);
+ REQUIRE(xmlTypeEqual(doc.rootNode(), XML_ELEMENT_NODE) == true);
+ REQUIRE(XmlHasProp(doc.rootNode(), "option1") == false);
+ REQUIRE(XmlHasProp(doc.rootNode(), "option123") == false);
+ REQUIRE(XmlHaveChildContent(doc.rootNode()) == true);
+ REQUIRE(!strcmp(XmlChildContent(doc.rootNode()), "this is test"));
+ }
+
+ SECTION("properties")
+ {
+ XML::Document doc("graphics/gui/browserbox.xml",
+ UseVirtFs_true,
+ SkipError_false);
+
+ XmlNodeConstPtr rootNode = doc.rootNode();
+ REQUIRE(XML::getProperty(rootNode, "image", "") == "window.png");
+ }
+
+ SECTION("for each")
+ {
+ XML::Document doc("graphics/gui/browserbox.xml",
+ UseVirtFs_true,
+ SkipError_false);
+
+ XmlNodeConstPtr rootNode = doc.rootNode();
+// REQUIRE(XmlHaveChildContent(rootNode) == true);
+ XmlNodePtr node = XmlNodeDefault;
+ for_each_xml_child_node(widgetNode, rootNode)
+ {
+ node = widgetNode;
+ if (xmlNameEqual(node, "widget"))
+ break;
+ }
+ REQUIRE(node != nullptr);
+ REQUIRE(xmlTypeEqual(node, XML_ELEMENT_NODE) == true);
+ REQUIRE(xmlNameEqual(node, "widget") == true);
+// REQUIRE(XmlHaveChildContent(node) == true);
+ for_each_xml_child_node(optionNode, node)
+ {
+ node = optionNode;
+ if (xmlNameEqual(node, "option"))
+ break;
+ }
+ REQUIRE(node != nullptr);
+ REQUIRE(xmlTypeEqual(node, XML_ELEMENT_NODE) == true);
+ REQUIRE(xmlNameEqual(node, "option") == true);
+ REQUIRE(XmlHaveChildContent(node) == false);
+ REQUIRE(XmlHasProp(node, "name") == true);
+ REQUIRE(XmlHasProp(node, "value") == true);
+ REQUIRE(XmlHasProp(node, "option123") == false);
+ REQUIRE(XML::getProperty(node, "name", "") == "padding");
+ REQUIRE(XML::langProperty(node, "name", "") == "padding");
+ REQUIRE(XML::getProperty(node, "value", 0) == 1);
+ REQUIRE(XML::getBoolProperty(node, "value", true) == true);
+ REQUIRE(XML::getBoolProperty(node, "value", false) == false);
+ REQUIRE(XML::getIntProperty(node, "value", -1, -10, 100) == 1);
+ }
+
+ SECTION("child1")
+ {
+ XML::Document doc("graphics/gui/browserbox.xml",
+ UseVirtFs_true,
+ SkipError_false);
+
+ XmlNodeConstPtr rootNode = doc.rootNode();
+ XmlNodePtr node = XML::findFirstChildByName(rootNode, "widget");
+ REQUIRE(node != nullptr);
+ REQUIRE(xmlTypeEqual(node, XML_ELEMENT_NODE) == true);
+ REQUIRE(xmlNameEqual(node, "widget") == true);
+// REQUIRE(XmlHaveChildContent(node) == true);
+ node = XML::findFirstChildByName(node, "option");
+ REQUIRE(node != nullptr);
+ REQUIRE(xmlTypeEqual(node, XML_ELEMENT_NODE) == true);
+ REQUIRE(xmlNameEqual(node, "option") == true);
+ REQUIRE(XmlHaveChildContent(node) == false);
+ REQUIRE(XmlHasProp(node, "name") == true);
+ REQUIRE(XmlHasProp(node, "value") == true);
+ REQUIRE(XmlHasProp(node, "option123") == false);
+ REQUIRE(XML::getProperty(node, "name", "") == "padding");
+ REQUIRE(XML::langProperty(node, "name", "") == "padding");
+ REQUIRE(XML::langProperty(node, "name123", "").empty());
+ REQUIRE(XML::getProperty(node, "value", 0) == 1);
+ REQUIRE(XML::getProperty(node, "value123", -1) == -1);
+ REQUIRE(XML::getBoolProperty(node, "value", true) == true);
+ REQUIRE(XML::getBoolProperty(node, "value", false) == false);
+ REQUIRE(XML::getBoolProperty(node, "value123", true) == true);
+ REQUIRE(XML::getIntProperty(node, "value", -1, -10, 100) == 1);
+ REQUIRE(XML::getIntProperty(node, "value123", -1, -10, 100) == -1);
+ }
+
+ SECTION("child2")
+ {
+ const char *const xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<root><data option1=\"false\" option2=\"true\" "
+ "option3=\"10.5\"/></root>";
+ XML::Document doc(xml, strlen(xml));
+ XmlNodeConstPtr rootNode = doc.rootNode();
+ REQUIRE(XmlHaveChildContent(rootNode) == false);
+ XmlNodePtr node = XML::findFirstChildByName(rootNode, "data");
+ REQUIRE(node != nullptr);
+ REQUIRE(xmlTypeEqual(node, XML_ELEMENT_NODE) == true);
+ REQUIRE(xmlNameEqual(node, "data") == true);
+ REQUIRE(XmlHaveChildContent(node) == false);
+ REQUIRE(XmlHasProp(node, "option1") == true);
+ REQUIRE(XmlHasProp(node, "option123") == false);
+ REQUIRE(XML::getBoolProperty(node, "option1", true) == false);
+ REQUIRE(XML::getBoolProperty(node, "option2", false) == true);
+ const float opt3 = XML::getFloatProperty(node, "option3", 0.0);
+ REQUIRE(opt3 > 10);
+ REQUIRE(opt3 < 11);
+ }
+
+ SECTION("child3")
+ {
+ const std::string xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<!-- comment --><root><!-- comment -->"
+ "<data option1=\"false\" option2=\"true\" "
+ "option3=\"10.5\"/><!-- comment --></root>";
+ XML::Document doc(xml.c_str(), xml.size());
+ XmlNodeConstPtr rootNode = doc.rootNode();
+// REQUIRE(XmlHaveChildContent(rootNode) == true);
+ XmlNodePtr node = XML::findFirstChildByName(rootNode, "data");
+ REQUIRE(node != nullptr);
+ REQUIRE(xmlTypeEqual(node, XML_ELEMENT_NODE) == true);
+ REQUIRE(xmlNameEqual(node, "data") == true);
+ REQUIRE(XmlHaveChildContent(node) == false);
+ REQUIRE(XmlHasProp(node, "option1") == true);
+ REQUIRE(XmlHasProp(node, "option123") == false);
+ REQUIRE(XML::getBoolProperty(node, "option1", true) == false);
+ REQUIRE(XML::getBoolProperty(node, "option2", false) == true);
+ const float opt3 = XML::getFloatProperty(node, "option3", 0.0);
+ REQUIRE(opt3 > 10);
+ REQUIRE(opt3 < 11);
+ }
+
+ SECTION("validate")
+ {
+// REQUIRE(XML::Document::validateXml(
+// "graphics/gui/browserbox.xml") == true);
+ REQUIRE(XML::Document::validateXml(
+ "graphics/gui/bubble.png") == false);
+ REQUIRE(XML::Document::validateXml(
+ "graphics/gui/testfile123.xml") == false);
+ }
+
+ SECTION("save1")
+ {
+ // clean
+ ::remove(tempXmlName);
+
+ // save
+ FILE *const testFile = fopen(tempXmlName, "w");
+ REQUIRE(testFile);
+ fclose(testFile);
+ XmlTextWriterPtr writer = XmlNewTextWriterFilename(
+ tempXmlName,
+ 0);
+ XmlTextWriterSetIndent(writer, 1);
+ XmlTextWriterStartDocument(writer, nullptr, nullptr, nullptr);
+ XmlTextWriterStartRootElement(writer, "root");
+ XmlTextWriterEndDocument(writer);
+ XmlSaveTextWriterFilename(writer, tempXmlName);
+ XmlFreeTextWriter(writer);
+
+ // load
+ XML::Document doc(tempXmlName,
+ UseVirtFs_false,
+ SkipError_false);
+ REQUIRE(doc.isLoaded() == true);
+ REQUIRE(doc.isValid() == true);
+ REQUIRE(doc.rootNode() != nullptr);
+ REQUIRE(xmlNameEqual(doc.rootNode(), "root") == true);
+ REQUIRE(xmlNameEqual(doc.rootNode(), "skinset123") == false);
+ REQUIRE(xmlTypeEqual(doc.rootNode(), XML_ELEMENT_NODE) == true);
+// REQUIRE(XmlHaveChildContent(doc.rootNode()) == true);
+
+ // clean again
+ ::remove(tempXmlName);
+ }
+
+ SECTION("save2")
+ {
+ // clean
+ ::remove(tempXmlName);
+
+ // save
+ FILE *const testFile = fopen(tempXmlName, "w");
+ REQUIRE(testFile);
+ fclose(testFile);
+ XmlTextWriterPtr writer = XmlNewTextWriterFilename(
+ tempXmlName,
+ 0);
+ XmlTextWriterSetIndent(writer, 1);
+ XmlTextWriterStartDocument(writer, nullptr, nullptr, nullptr);
+ XmlTextWriterStartRootElement(writer, "root");
+
+ XmlTextWriterStartElement(writer, "option");
+ XmlTextWriterWriteAttribute(writer, "name", "the name");
+ XmlTextWriterWriteAttribute(writer, "value", "the value");
+ XmlTextWriterEndElement(writer);
+
+ XmlTextWriterEndDocument(writer);
+ XmlSaveTextWriterFilename(writer, tempXmlName);
+ XmlFreeTextWriter(writer);
+
+ // load
+ XML::Document doc(tempXmlName,
+ UseVirtFs_false,
+ SkipError_false);
+ REQUIRE(doc.isLoaded() == true);
+ REQUIRE(doc.isValid() == true);
+ REQUIRE(doc.rootNode() != nullptr);
+ REQUIRE(xmlNameEqual(doc.rootNode(), "root") == true);
+ REQUIRE(xmlNameEqual(doc.rootNode(), "skinset123") == false);
+ REQUIRE(xmlTypeEqual(doc.rootNode(), XML_ELEMENT_NODE) == true);
+// REQUIRE(XmlHaveChildContent(doc.rootNode()) == true);
+ XmlNodePtr node = XML::findFirstChildByName(doc.rootNode(), "option");
+ REQUIRE(node != nullptr);
+ REQUIRE(xmlTypeEqual(node, XML_ELEMENT_NODE) == true);
+ REQUIRE(xmlNameEqual(node, "option") == true);
+ REQUIRE(XmlHaveChildContent(node) == false);
+ REQUIRE(XmlHasProp(node, "name") == true);
+ REQUIRE(XmlHasProp(node, "value") == true);
+ REQUIRE(XmlHasProp(node, "option123") == false);
+ REQUIRE(XML::getProperty(node, "name", "") == "the name");
+ REQUIRE(XML::getProperty(node, "value", "") == "the value");
+
+ // clean again
+ ::remove(tempXmlName);
+ }
+
+ delete2(theme);
+ delete2(client);
+ ResourceManager::deleteInstance();
+ VirtFs::unmountDirSilent("data");
+ VirtFs::unmountDirSilent("../data");
+
+ delete2(logger);
+// VirtFs::deinit();
+}
+
+TEST_CASE("xml test2", "")
+{
+ logger = new Logger();
+ REQUIRE(gui == nullptr);
+ ResourceManager::cleanOrphans(true);
+ ResourceManager::deleteInstance();
+ delete2(logger);
+}
diff --git a/src/unittests/utils/xmlutils_unittest.cc b/src/unittests/utils/xmlutils_unittest.cc
new file mode 100644
index 000000000..014730e95
--- /dev/null
+++ b/src/unittests/utils/xmlutils_unittest.cc
@@ -0,0 +1,203 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2014-2017 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "unittests/unittests.h"
+
+#include "client.h"
+#include "graphicsmanager.h"
+
+#include "being/actorsprite.h"
+
+#include "fs/virtfs/fs.h"
+
+#include "gui/gui.h"
+
+#include "utils/delete2.h"
+#include "utils/env.h"
+#include "utils/xmlutils.h"
+
+#include "render/sdlgraphics.h"
+
+#include "resources/resourcemanager/resourcemanager.h"
+
+#include "resources/sdlimagehelper.h"
+
+#include "debug.h"
+
+TEST_CASE("xmlutils leak test1", "")
+{
+ logger = new Logger();
+ REQUIRE(gui == nullptr);
+ ResourceManager::cleanOrphans(true);
+ ResourceManager::deleteInstance();
+ delete2(logger);
+}
+
+TEST_CASE("xmlutils readXmlIntVector 1", "")
+{
+ setEnv("SDL_VIDEODRIVER", "dummy");
+
+ client = new Client;
+ XML::initXML();
+ logger = new Logger();
+ VirtFs::mountDirSilent("data", Append_false);
+ VirtFs::mountDirSilent("../data", Append_false);
+
+ mainGraphics = new SDLGraphics;
+ imageHelper = new SDLImageHelper();
+#ifdef USE_SDL2
+ SDLImageHelper::setRenderer(graphicsManager.createRenderer(
+ graphicsManager.createWindow(640, 480, 0,
+ SDL_WINDOW_SHOWN | SDL_SWSURFACE), SDL_RENDERER_SOFTWARE));
+#else // USE_SDL2
+
+ graphicsManager.createWindow(640, 480, 0, SDL_ANYFORMAT | SDL_SWSURFACE);
+#endif // USE_SDL2
+
+ ActorSprite::load();
+
+ std::vector<int> arr;
+
+ readXmlIntVector("graphics/gui/browserbox.xml",
+ "skinset",
+ "widget",
+ "option",
+ "value",
+ arr,
+ SkipError_false);
+
+ REQUIRE(5 == arr.size());
+ REQUIRE(1 == arr[0]);
+ REQUIRE(15 == arr[1]);
+ REQUIRE(0 == arr[2]);
+ REQUIRE(1 == arr[3]);
+ REQUIRE(1 == arr[4]);
+ delete2(client);
+ ResourceManager::deleteInstance();
+ VirtFs::unmountDirSilent("data");
+ VirtFs::unmountDirSilent("../data");
+ delete2(logger);
+// VirtFs::deinit();
+}
+
+TEST_CASE("xmlutils readXmlStringMap 1", "")
+{
+ setEnv("SDL_VIDEODRIVER", "dummy");
+
+ client = new Client;
+ XML::initXML();
+ logger = new Logger();
+ VirtFs::mountDirSilent("data", Append_false);
+ VirtFs::mountDirSilent("../data", Append_false);
+
+ mainGraphics = new SDLGraphics;
+ imageHelper = new SDLImageHelper();
+#ifdef USE_SDL2
+ SDLImageHelper::setRenderer(graphicsManager.createRenderer(
+ graphicsManager.createWindow(640, 480, 0,
+ SDL_WINDOW_SHOWN | SDL_SWSURFACE), SDL_RENDERER_SOFTWARE));
+#else // USE_SDL2
+
+ graphicsManager.createWindow(640, 480, 0, SDL_ANYFORMAT | SDL_SWSURFACE);
+#endif // USE_SDL2
+
+ ActorSprite::load();
+
+ std::map<std::string, std::string> arr;
+
+ readXmlStringMap("graphics/sprites/manaplus_emotes.xml",
+ "emotes",
+ "emote",
+ "sprite",
+ "name",
+ "variant",
+ arr,
+ SkipError_false);
+
+ REQUIRE(arr.size() == 27);
+ REQUIRE(arr["Kitty"] == "0");
+ REQUIRE(arr["xD"] == "1");
+ REQUIRE(arr["Metal"] == "26");
+ delete2(client);
+ ResourceManager::deleteInstance();
+ VirtFs::unmountDirSilent("data");
+ VirtFs::unmountDirSilent("../data");
+ delete2(logger);
+// VirtFs::deinit();
+}
+
+TEST_CASE("xmlutils readXmlIntMap 1", "")
+{
+ setEnv("SDL_VIDEODRIVER", "dummy");
+
+ client = new Client;
+ XML::initXML();
+ logger = new Logger();
+ VirtFs::mountDirSilent("data", Append_false);
+ VirtFs::mountDirSilent("../data", Append_false);
+ VirtFs::mountDirSilent("data/test", Append_false);
+ VirtFs::mountDirSilent("../data/test", Append_false);
+
+ mainGraphics = new SDLGraphics;
+ imageHelper = new SDLImageHelper();
+#ifdef USE_SDL2
+ SDLImageHelper::setRenderer(graphicsManager.createRenderer(
+ graphicsManager.createWindow(640, 480, 0,
+ SDL_WINDOW_SHOWN | SDL_SWSURFACE), SDL_RENDERER_SOFTWARE));
+#else // USE_SDL2
+
+ graphicsManager.createWindow(640, 480, 0, SDL_ANYFORMAT | SDL_SWSURFACE);
+#endif // USE_SDL2
+
+ ActorSprite::load();
+
+ std::map<int32_t, int32_t> arr;
+
+ readXmlIntMap("testintmap.xml",
+ "tests",
+ "sub",
+ "item",
+ "id",
+ "val",
+ arr,
+ SkipError_false);
+
+ REQUIRE(arr.size() == 3);
+ REQUIRE(arr[1] == 2);
+ REQUIRE(arr[10] == 20);
+ REQUIRE(arr[3] == 0);
+ delete2(client);
+ ResourceManager::deleteInstance();
+ VirtFs::unmountDirSilent("data/test");
+ VirtFs::unmountDirSilent("../data/test");
+ VirtFs::unmountDirSilent("data");
+ VirtFs::unmountDirSilent("../data");
+ delete2(logger);
+// VirtFs::deinit();
+}
+
+TEST_CASE("xmlutils leak test2", "")
+{
+ logger = new Logger();
+ REQUIRE(gui == nullptr);
+ ResourceManager::cleanOrphans(true);
+ ResourceManager::deleteInstance();
+ delete2(logger);
+}