Skip to content

Commit 6c18494

Browse files
authoredMar 16, 2018
Server: delegate mod management & config to ServerModConfiguration (#7131)
* Server: delegate mod management & config to ServerModConfiguration (rename it to ServerModManager) * Use c++11 range based loops * Add unittests + experimental/default mod as a test case to permit testing mod loading in future tests
1 parent 5e61f64 commit 6c18494

13 files changed

+359
-74
lines changed
 

Diff for: ‎src/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -379,10 +379,12 @@ add_subdirectory(script)
379379
add_subdirectory(unittest)
380380
add_subdirectory(util)
381381
add_subdirectory(irrlicht_changes)
382+
add_subdirectory(server)
382383

383384
set(common_SRCS
384385
${database_SRCS}
385386
${mapgen_SRCS}
387+
${server_SRCS}
386388
ban.cpp
387389
chat.cpp
388390
clientiface.cpp

Diff for: ‎src/gui/guiConfirmRegistration.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ void GUIConfirmRegistration::regenerateGui(v2u32 screensize)
113113
core::rect<s32> rect2(0, 0, 540, 30);
114114
rect2 += topleft_client + v2s32(30, ypos);
115115
gui::IGUIEditBox *e = Environment->addEditBox(m_pass_confirm.c_str(),
116-
rect2, true, this, ID_confirmPassword);
116+
rect2, true, this, ID_confirmPassword);
117117
e->setPasswordBox(true);
118118
}
119119

Diff for: ‎src/mods.cpp

-14
Original file line numberDiff line numberDiff line change
@@ -322,20 +322,6 @@ void ModConfiguration::resolveDependencies()
322322
m_unsatisfied_mods.assign(unsatisfied.begin(), unsatisfied.end());
323323
}
324324

325-
ServerModConfiguration::ServerModConfiguration(const std::string &worldpath):
326-
ModConfiguration(worldpath)
327-
{
328-
SubgameSpec gamespec = findWorldSubgame(worldpath);
329-
330-
// Add all game mods and all world mods
331-
addModsInPath(gamespec.gamemods_path);
332-
addModsInPath(worldpath + DIR_DELIM + "worldmods");
333-
334-
// Load normal mods
335-
std::string worldmt = worldpath + DIR_DELIM + "world.mt";
336-
addModsFromConfig(worldmt, gamespec.addon_mods_paths);
337-
}
338-
339325
#ifndef SERVER
340326
ClientModConfiguration::ClientModConfiguration(const std::string &path):
341327
ModConfiguration(path)

Diff for: ‎src/mods.h

+8-14
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class ModConfiguration
7878
return m_unsatisfied_mods.empty();
7979
}
8080

81-
std::vector<ModSpec> getMods()
81+
const std::vector<ModSpec> &getMods() const
8282
{
8383
return m_sorted_mods;
8484
}
@@ -102,6 +102,13 @@ class ModConfiguration
102102
void addModsFromConfig(const std::string &settings_path, const std::set<std::string> &mods);
103103

104104
void checkConflictsAndDeps();
105+
protected:
106+
// list of mods sorted such that they can be loaded in the
107+
// given order with all dependencies being fullfilled. I.e.,
108+
// every mod in this list has only dependencies on mods which
109+
// appear earlier in the vector.
110+
std::vector<ModSpec> m_sorted_mods;
111+
105112
private:
106113
// move mods from m_unsatisfied_mods to m_sorted_mods
107114
// in an order that satisfies dependencies
@@ -112,12 +119,6 @@ class ModConfiguration
112119
// only the ones with really unsatisfied dependencies.
113120
std::vector<ModSpec> m_unsatisfied_mods;
114121

115-
// list of mods sorted such that they can be loaded in the
116-
// given order with all dependencies being fullfilled. I.e.,
117-
// every mod in this list has only dependencies on mods which
118-
// appear earlier in the vector.
119-
std::vector<ModSpec> m_sorted_mods;
120-
121122
// set of mod names for which an unresolved name conflict
122123
// exists. A name conflict happens when two or more mods
123124
// at the same level have the same name but different paths.
@@ -132,13 +133,6 @@ class ModConfiguration
132133

133134
};
134135

135-
class ServerModConfiguration: public ModConfiguration
136-
{
137-
public:
138-
ServerModConfiguration(const std::string &worldpath);
139-
140-
};
141-
142136
#ifndef SERVER
143137
class ClientModConfiguration: public ModConfiguration
144138
{

Diff for: ‎src/server.cpp

+18-44
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
5858
#include "util/serialize.h"
5959
#include "util/thread.h"
6060
#include "defaultsettings.h"
61+
#include "server/mods.h"
6162
#include "util/base64.h"
6263
#include "util/sha1.h"
6364
#include "util/hex.h"
@@ -203,12 +204,12 @@ Server::Server(
203204
std::string ban_path = m_path_world + DIR_DELIM "ipban.txt";
204205
m_banmanager = new BanManager(ban_path);
205206

206-
ServerModConfiguration modconf(m_path_world);
207-
m_mods = modconf.getMods();
208-
std::vector<ModSpec> unsatisfied_mods = modconf.getUnsatisfiedMods();
207+
m_modmgr = std::unique_ptr<ServerModManager>(new ServerModManager(
208+
m_path_world));
209+
std::vector<ModSpec> unsatisfied_mods = m_modmgr->getUnsatisfiedMods();
209210
// complain about mods with unsatisfied dependencies
210-
if (!modconf.isConsistent()) {
211-
modconf.printUnsatisfiedModsError();
211+
if (!m_modmgr->isConsistent()) {
212+
m_modmgr->printUnsatisfiedModsError();
212213
}
213214

214215
//lock environment
@@ -224,27 +225,9 @@ Server::Server(
224225

225226
m_script->loadMod(getBuiltinLuaPath() + DIR_DELIM "init.lua", BUILTIN_MOD_NAME);
226227

227-
// Print mods
228-
infostream << "Server: Loading mods: ";
229-
for (std::vector<ModSpec>::const_iterator i = m_mods.begin();
230-
i != m_mods.end(); ++i) {
231-
infostream << (*i).name << " ";
232-
}
233-
infostream << std::endl;
234-
// Load and run "mod" scripts
235-
for (std::vector<ModSpec>::const_iterator it = m_mods.begin();
236-
it != m_mods.end(); ++it) {
237-
const ModSpec &mod = *it;
238-
if (!string_allowed(mod.name, MODNAME_ALLOWED_CHARS)) {
239-
throw ModError("Error loading mod \"" + mod.name +
240-
"\": Mod name does not follow naming conventions: "
241-
"Only characters [a-z0-9_] are allowed.");
242-
}
243-
std::string script_path = mod.path + DIR_DELIM + "init.lua";
244-
infostream << " [" << padStringRight(mod.name, 12) << "] [\""
245-
<< script_path << "\"]" << std::endl;
246-
m_script->loadMod(script_path, mod.name);
247-
}
228+
m_mods = m_modmgr->getMods();
229+
230+
m_modmgr->loadMods(m_script);
248231

249232
// Read Textures and calculate sha1 sums
250233
fillMediaCache();
@@ -580,7 +563,7 @@ void Server::AsyncRunStep(bool initial_step)
580563
m_lag,
581564
m_gamespec.id,
582565
Mapgen::getMapgenName(m_emerge->mgparams->mgtype),
583-
m_mods,
566+
m_modmgr->getMods(),
584567
m_dedicated);
585568
counter = 0.01;
586569
}
@@ -2237,13 +2220,7 @@ void Server::fillMediaCache()
22372220

22382221
// Collect all media file paths
22392222
std::vector<std::string> paths;
2240-
for (const ModSpec &mod : m_mods) {
2241-
paths.push_back(mod.path + DIR_DELIM + "textures");
2242-
paths.push_back(mod.path + DIR_DELIM + "sounds");
2243-
paths.push_back(mod.path + DIR_DELIM + "media");
2244-
paths.push_back(mod.path + DIR_DELIM + "models");
2245-
paths.push_back(mod.path + DIR_DELIM + "locale");
2246-
}
2223+
m_modmgr->getModsMediaPaths(paths);
22472224
fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
22482225
fs::GetRecursiveDirs(paths, porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
22492226

@@ -3326,22 +3303,19 @@ IWritableCraftDefManager *Server::getWritableCraftDefManager()
33263303
return m_craftdef;
33273304
}
33283305

3306+
const std::vector<ModSpec> & Server::getMods() const
3307+
{
3308+
return m_modmgr->getMods();
3309+
}
3310+
33293311
const ModSpec *Server::getModSpec(const std::string &modname) const
33303312
{
3331-
std::vector<ModSpec>::const_iterator it;
3332-
for (it = m_mods.begin(); it != m_mods.end(); ++it) {
3333-
const ModSpec &mod = *it;
3334-
if (mod.name == modname)
3335-
return &mod;
3336-
}
3337-
return NULL;
3313+
return m_modmgr->getModSpec(modname);
33383314
}
33393315

33403316
void Server::getModNames(std::vector<std::string> &modlist)
33413317
{
3342-
std::vector<ModSpec>::iterator it;
3343-
for (it = m_mods.begin(); it != m_mods.end(); ++it)
3344-
modlist.push_back(it->name);
3318+
m_modmgr->getModNames(modlist);
33453319
}
33463320

33473321
std::string Server::getBuiltinLuaPath()

Diff for: ‎src/server.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class ServerEnvironment;
6161
struct SimpleSoundSpec;
6262
struct CloudParams;
6363
class ServerThread;
64+
class ServerModManager;
6465

6566
enum ClientDeletionReason {
6667
CDR_LEAVE,
@@ -268,7 +269,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
268269
NodeDefManager* getWritableNodeDefManager();
269270
IWritableCraftDefManager* getWritableCraftDefManager();
270271

271-
virtual const std::vector<ModSpec> &getMods() const { return m_mods; }
272+
virtual const std::vector<ModSpec> &getMods() const;
272273
virtual const ModSpec* getModSpec(const std::string &modname) const;
273274
void getModNames(std::vector<std::string> &modlist);
274275
std::string getBuiltinLuaPath();
@@ -541,6 +542,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
541542
EventManager *m_event;
542543

543544
// Mods
545+
std::unique_ptr<ServerModManager> m_modmgr;
544546
std::vector<ModSpec> m_mods;
545547

546548
/*

Diff for: ‎src/server/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
set(server_SRCS
2+
${CMAKE_CURRENT_SOURCE_DIR}/mods.cpp
3+
PARENT_SCOPE)

Diff for: ‎src/server/mods.cpp

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
Minetest
3+
Copyright (C) 2018 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
4+
5+
This program is free software; you can redistribute it and/or modify
6+
it under the terms of the GNU Lesser General Public License as published by
7+
the Free Software Foundation; either version 2.1 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public License along
16+
with this program; if not, write to the Free Software Foundation, Inc.,
17+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*/
19+
20+
#include "mods.h"
21+
#include "filesys.h"
22+
#include "log.h"
23+
#include "scripting_server.h"
24+
#include "subgame.h"
25+
26+
/**
27+
* Manage server mods
28+
*
29+
* All new calls to this class must be tested in test_servermodmanager.cpp
30+
*/
31+
32+
/**
33+
* Creates a ServerModManager which targets worldpath
34+
* @param worldpath
35+
*/
36+
ServerModManager::ServerModManager(const std::string &worldpath) :
37+
ModConfiguration(worldpath)
38+
{
39+
SubgameSpec gamespec = findWorldSubgame(worldpath);
40+
41+
// Add all game mods and all world mods
42+
addModsInPath(gamespec.gamemods_path);
43+
addModsInPath(worldpath + DIR_DELIM + "worldmods");
44+
45+
// Load normal mods
46+
std::string worldmt = worldpath + DIR_DELIM + "world.mt";
47+
addModsFromConfig(worldmt, gamespec.addon_mods_paths);
48+
}
49+
50+
// This function cannot be currenctly easily tested but it should be ASAP
51+
void ServerModManager::loadMods(ServerScripting *script)
52+
{
53+
// Print mods
54+
infostream << "Server: Loading mods: ";
55+
for (const ModSpec &mod : m_sorted_mods) {
56+
infostream << mod.name << " ";
57+
}
58+
infostream << std::endl;
59+
// Load and run "mod" scripts
60+
for (const ModSpec &mod : m_sorted_mods) {
61+
if (!string_allowed(mod.name, MODNAME_ALLOWED_CHARS)) {
62+
throw ModError("Error loading mod \"" + mod.name +
63+
"\": Mod name does not follow naming "
64+
"conventions: "
65+
"Only characters [a-z0-9_] are allowed.");
66+
}
67+
std::string script_path = mod.path + DIR_DELIM + "init.lua";
68+
infostream << " [" << padStringRight(mod.name, 12) << "] [\""
69+
<< script_path << "\"]" << std::endl;
70+
script->loadMod(script_path, mod.name);
71+
}
72+
}
73+
74+
const ModSpec *ServerModManager::getModSpec(const std::string &modname) const
75+
{
76+
std::vector<ModSpec>::const_iterator it;
77+
for (it = m_sorted_mods.begin(); it != m_sorted_mods.end(); ++it) {
78+
const ModSpec &mod = *it;
79+
if (mod.name == modname)
80+
return &mod;
81+
}
82+
return NULL;
83+
}
84+
85+
void ServerModManager::getModNames(std::vector<std::string> &modlist) const
86+
{
87+
for (const ModSpec &spec : m_sorted_mods)
88+
modlist.push_back(spec.name);
89+
}
90+
91+
void ServerModManager::getModsMediaPaths(std::vector<std::string> &paths) const
92+
{
93+
for (const ModSpec &spec : m_sorted_mods) {
94+
paths.push_back(spec.path + DIR_DELIM + "textures");
95+
paths.push_back(spec.path + DIR_DELIM + "sounds");
96+
paths.push_back(spec.path + DIR_DELIM + "media");
97+
paths.push_back(spec.path + DIR_DELIM + "models");
98+
paths.push_back(spec.path + DIR_DELIM + "locale");
99+
}
100+
}

Diff for: ‎src/server/mods.h

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
Minetest
3+
Copyright (C) 2018 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
4+
5+
This program is free software; you can redistribute it and/or modify
6+
it under the terms of the GNU Lesser General Public License as published by
7+
the Free Software Foundation; either version 2.1 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public License along
16+
with this program; if not, write to the Free Software Foundation, Inc.,
17+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*/
19+
20+
#pragma once
21+
22+
#include "../mods.h"
23+
24+
class ServerScripting;
25+
26+
/**
27+
* Manage server mods
28+
*
29+
* All new calls to this class must be tested in test_servermodmanager.cpp
30+
*/
31+
class ServerModManager : public ModConfiguration
32+
{
33+
public:
34+
/**
35+
* Creates a ServerModManager which targets worldpath
36+
* @param worldpath
37+
*/
38+
ServerModManager(const std::string &worldpath);
39+
void loadMods(ServerScripting *script);
40+
const ModSpec *getModSpec(const std::string &modname) const;
41+
void getModNames(std::vector<std::string> &modlist) const;
42+
void getModsMediaPaths(std::vector<std::string> &paths) const;
43+
};

Diff for: ‎src/unittest/CMakeLists.txt

+9
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ set (UNITTEST_SRCS
2222
${CMAKE_CURRENT_SOURCE_DIR}/test_serialization.cpp
2323
${CMAKE_CURRENT_SOURCE_DIR}/test_settings.cpp
2424
${CMAKE_CURRENT_SOURCE_DIR}/test_socket.cpp
25+
${CMAKE_CURRENT_SOURCE_DIR}/test_servermodmanager.cpp
2526
${CMAKE_CURRENT_SOURCE_DIR}/test_threading.cpp
2627
${CMAKE_CURRENT_SOURCE_DIR}/test_utilities.cpp
2728
${CMAKE_CURRENT_SOURCE_DIR}/test_voxelarea.cpp
@@ -33,3 +34,11 @@ set (UNITTEST_CLIENT_SRCS
3334
${CMAKE_CURRENT_SOURCE_DIR}/test_gameui.cpp
3435
${CMAKE_CURRENT_SOURCE_DIR}/test_keycode.cpp
3536
PARENT_SCOPE)
37+
38+
set (TEST_WORLDDIR ${CMAKE_CURRENT_SOURCE_DIR}/test_world)
39+
set (TEST_SUBGAME_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../games/minimal)
40+
41+
configure_file(
42+
"${CMAKE_CURRENT_SOURCE_DIR}/test_config.h.in"
43+
"${PROJECT_BINARY_DIR}/test_config.h"
Has conversations. Original line has conversations.
44+
)

Diff for: ‎src/unittest/test_config.h.in

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Filled in by the build system
2+
3+
#pragma once
4+
5+
#define TEST_WORLDDIR "@TEST_WORLDDIR@"
6+
#define TEST_SUBGAME_PATH "@TEST_SUBGAME_PATH@"

Diff for: ‎src/unittest/test_servermodmanager.cpp

+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
2+
Minetest
3+
Copyright (C) 2018 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
4+
5+
This program is free software; you can redistribute it and/or modify
6+
it under the terms of the GNU Lesser General Public License as published by
7+
the Free Software Foundation; either version 2.1 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public License along
16+
with this program; if not, write to the Free Software Foundation, Inc.,
17+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*/
19+
20+
#include "test.h"
21+
#include <algorithm>
22+
#include "server/mods.h"
23+
#include "test_config.h"
24+
25+
class TestServerModManager : public TestBase
26+
{
27+
public:
28+
TestServerModManager() { TestManager::registerTestModule(this); }
29+
const char *getName() { return "TestServerModManager"; }
30+
31+
void runTests(IGameDef *gamedef);
32+
33+
void testCreation();
34+
void testIsConsistent();
35+
void testUnsatisfiedMods();
36+
void testGetMods();
37+
void testGetModsWrongDir();
38+
void testGetModspec();
39+
void testGetModNamesWrongDir();
40+
void testGetModNames();
41+
void testGetModMediaPathsWrongDir();
42+
void testGetModMediaPaths();
43+
};
44+
45+
static TestServerModManager g_test_instance;
46+
47+
void TestServerModManager::runTests(IGameDef *gamedef)
48+
{
49+
const char *saved_env_mt_subgame_path = getenv("MINETEST_SUBGAME_PATH");
50+
#ifdef WIN32
51+
{
52+
std::string subgame_path("MINETEST_SUBGAME_PATH=");
53+
subgame_path.append(TEST_SUBGAME_PATH);
54+
_putenv(subgame_path.c_str());
55+
}
56+
#else
57+
setenv("MINETEST_SUBGAME_PATH", TEST_SUBGAME_PATH, 1);
58+
#endif
59+
60+
TEST(testCreation);
61+
TEST(testIsConsistent);
62+
TEST(testGetModsWrongDir);
63+
TEST(testUnsatisfiedMods);
64+
TEST(testGetMods);
65+
TEST(testGetModspec);
66+
TEST(testGetModNamesWrongDir);
67+
TEST(testGetModNames);
68+
TEST(testGetModMediaPathsWrongDir);
69+
TEST(testGetModMediaPaths);
70+
71+
#ifdef WIN32
72+
{
73+
std::string subgame_path("MINETEST_SUBGAME_PATH=");
74+
subgame_path.append(saved_env_mt_subgame_path);
75+
_putenv(subgame_path.c_str());
76+
}
77+
#else
78+
setenv("MINETEST_SUBGAME_PATH", saved_env_mt_subgame_path, 1);
79+
#endif
80+
}
81+
82+
void TestServerModManager::testCreation()
83+
{
84+
ServerModManager sm(TEST_WORLDDIR);
85+
}
86+
87+
void TestServerModManager::testGetModsWrongDir()
88+
{
89+
// Test in non worlddir to ensure no mods are found
90+
ServerModManager sm(std::string(TEST_WORLDDIR) + DIR_DELIM + "..");
91+
UASSERTEQ(bool, sm.getMods().empty(), true);
92+
}
93+
94+
void TestServerModManager::testUnsatisfiedMods()
95+
{
96+
ServerModManager sm(std::string(TEST_WORLDDIR));
97+
UASSERTEQ(bool, sm.getUnsatisfiedMods().empty(), true);
98+
}
99+
100+
void TestServerModManager::testIsConsistent()
101+
{
102+
ServerModManager sm(std::string(TEST_WORLDDIR));
103+
UASSERTEQ(bool, sm.isConsistent(), true);
104+
}
105+
106+
void TestServerModManager::testGetMods()
107+
{
108+
ServerModManager sm(std::string(TEST_WORLDDIR));
109+
const auto &mods = sm.getMods();
110+
UASSERTEQ(bool, mods.empty(), false);
111+
112+
// Ensure we found default mod inside the test folder
113+
bool default_found = false;
114+
for (const auto &m : mods) {
115+
if (m.name == "default")
116+
default_found = true;
117+
118+
// Verify if paths are not empty
119+
UASSERTEQ(bool, m.path.empty(), false);
120+
}
121+
122+
UASSERTEQ(bool, default_found, true);
123+
}
124+
125+
void TestServerModManager::testGetModspec()
126+
{
127+
ServerModManager sm(std::string(TEST_WORLDDIR));
128+
UASSERTEQ(const ModSpec *, sm.getModSpec("wrongmod"), NULL);
129+
UASSERT(sm.getModSpec("default") != NULL);
130+
}
131+
132+
void TestServerModManager::testGetModNamesWrongDir()
133+
{
134+
ServerModManager sm(std::string(TEST_WORLDDIR) + DIR_DELIM + "..");
135+
std::vector<std::string> result;
136+
sm.getModNames(result);
137+
UASSERTEQ(bool, result.empty(), true);
138+
}
139+
140+
void TestServerModManager::testGetModNames()
141+
{
142+
ServerModManager sm(std::string(TEST_WORLDDIR));
143+
std::vector<std::string> result;
144+
sm.getModNames(result);
145+
UASSERTEQ(bool, result.empty(), false);
146+
UASSERT(std::find(result.begin(), result.end(), "default") != result.end());
147+
}
148+
149+
void TestServerModManager::testGetModMediaPathsWrongDir()
150+
{
151+
ServerModManager sm(std::string(TEST_WORLDDIR) + DIR_DELIM + "..");
152+
std::vector<std::string> result;
153+
sm.getModsMediaPaths(result);
154+
UASSERTEQ(bool, result.empty(), true);
155+
}
156+
157+
void TestServerModManager::testGetModMediaPaths()
158+
{
159+
ServerModManager sm(std::string(TEST_WORLDDIR));
160+
std::vector<std::string> result;
161+
sm.getModsMediaPaths(result);
162+
UASSERTEQ(bool, result.empty(), false);
163+
// We should have 5 folders for each mod (textures, media, locale, model, sounds)
164+
UASSERTEQ(unsigned long, result.size() % 5, 0);
165+
}

Diff for: ‎src/unittest/test_world/world.mt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
gameid = minimal

0 commit comments

Comments
 (0)
Please sign in to comment.