Skip to content

Commit 37a05ec

Browse files
SmallJokersfan5
authored andcommittedJan 29, 2021
Settings: Proper priority hierarchy
Remove old defaults system Introduce priority-based fallback list Use new functions for map_meta special functions Change groups to use end tags Unittest changes: * Adapt unittest to the new code * Compare Settings objects
1 parent 5e9dd16 commit 37a05ec

21 files changed

+359
-299
lines changed
 

Diff for: ‎src/content/subgames.cpp

+13-11
Original file line numberDiff line numberDiff line change
@@ -329,18 +329,16 @@ void loadGameConfAndInitWorld(const std::string &path, const std::string &name,
329329
}
330330
}
331331

332-
// Override defaults with those provided by the game.
333-
// We clear and reload the defaults because the defaults
334-
// might have been overridden by other subgame config
335-
// files that were loaded before.
336-
g_settings->clearDefaults();
337-
set_default_settings(g_settings);
338-
339-
Settings game_defaults;
340-
getGameMinetestConfig(gamespec.path, game_defaults);
341-
game_defaults.removeSecureSettings();
332+
Settings *game_settings = Settings::getLayer(SL_GAME);
333+
const bool new_game_settings = (game_settings == nullptr);
334+
if (new_game_settings) {
335+
// Called by main-menu without a Server instance running
336+
// -> create and free manually
337+
game_settings = Settings::createLayer(SL_GAME);
338+
}
342339

343-
g_settings->overrideDefaults(&game_defaults);
340+
getGameMinetestConfig(gamespec.path, *game_settings);
341+
game_settings->removeSecureSettings();
344342

345343
infostream << "Initializing world at " << final_path << std::endl;
346344

@@ -381,4 +379,8 @@ void loadGameConfAndInitWorld(const std::string &path, const std::string &name,
381379

382380
fs::safeWriteToFile(map_meta_path, oss.str());
383381
}
382+
383+
// The Settings object is no longer needed for created worlds
384+
if (new_game_settings)
385+
delete game_settings;
384386
}

Diff for: ‎src/database/database-files.cpp

+7-8
Original file line numberDiff line numberDiff line change
@@ -122,18 +122,17 @@ void PlayerDatabaseFiles::serialize(RemotePlayer *p, std::ostream &os)
122122
args.set("name", p->m_name);
123123

124124
// This should not happen
125-
assert(m_sao);
126-
args.setU16("hp", p->m_sao->getHP());
127-
args.setV3F("position", p->m_sao->getBasePosition());
128-
args.setFloat("pitch", p->m_sao->getLookPitch());
129-
args.setFloat("yaw", p->m_sao->getRotation().Y);
130-
args.setU16("breath", p->m_sao->getBreath());
125+
PlayerSAO *sao = p->getPlayerSAO();
126+
assert(sao);
127+
args.setU16("hp", sao->getHP());
128+
args.setV3F("position", sao->getBasePosition());
129+
args.setFloat("pitch", sao->getLookPitch());
130+
args.setFloat("yaw", sao->getRotation().Y);
131+
args.setU16("breath", sao->getBreath());
131132

132133
std::string extended_attrs;
133134
{
134135
// serializeExtraAttributes
135-
PlayerSAO *sao = p->getPlayerSAO();
136-
assert(sao);
137136
Json::Value json_root;
138137

139138
const StringMap &attrs = sao->getMeta().getStrings();

Diff for: ‎src/database/database-files.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ class PlayerDatabaseFiles : public PlayerDatabase
3838
void listPlayers(std::vector<std::string> &res);
3939

4040
private:
41-
void deSerialize(RemotePlayer *p, std::istream &is,
42-
const std::string &playername, PlayerSAO *sao);
41+
void deSerialize(RemotePlayer *p, std::istream &is, const std::string &playername,
42+
PlayerSAO *sao);
4343
/*
4444
serialize() writes a bunch of text that can contain
4545
any characters except a '\0', and such an ending that

Diff for: ‎src/defaultsettings.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2727
#include "mapgen/mapgen.h" // Mapgen::setDefaultSettings
2828
#include "util/string.h"
2929

30-
void set_default_settings(Settings *settings)
30+
void set_default_settings()
3131
{
32+
Settings *settings = Settings::createLayer(SL_DEFAULTS);
33+
3234
// Client and server
3335
settings->setDefault("language", "");
3436
settings->setDefault("name", "");

Diff for: ‎src/defaultsettings.h

+1-8
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,4 @@ class Settings;
2525
* initialize basic default settings
2626
* @param settings pointer to settings
2727
*/
28-
void set_default_settings(Settings *settings);
29-
30-
/**
31-
* override a default settings by settings from another settings element
32-
* @param settings target settings pointer
33-
* @param from source settings pointer
34-
*/
35-
void override_default_settings(Settings *settings, Settings *from);
28+
void set_default_settings();

Diff for: ‎src/gui/guiKeyChangeMenu.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ bool GUIKeyChangeMenu::acceptInput()
248248
{
249249
for (key_setting *k : key_settings) {
250250
std::string default_key;
251-
g_settings->getDefaultNoEx(k->setting_name, default_key);
251+
Settings::getLayer(SL_DEFAULTS)->getNoEx(k->setting_name, default_key);
252252

253253
if (k->key.sym() != default_key)
254254
g_settings->set(k->setting_name, k->key.sym());

Diff for: ‎src/main.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -487,12 +487,15 @@ static bool create_userdata_path()
487487
static bool init_common(const Settings &cmd_args, int argc, char *argv[])
488488
{
489489
startup_message();
490-
set_default_settings(g_settings);
490+
set_default_settings();
491491

492492
// Initialize sockets
493493
sockets_init();
494494
atexit(sockets_cleanup);
495495

496+
// Initialize g_settings
497+
Settings::createLayer(SL_GLOBAL);
498+
496499
if (!read_config_file(cmd_args))
497500
return false;
498501

@@ -524,6 +527,7 @@ static bool read_config_file(const Settings &cmd_args)
524527
// Path of configuration file in use
525528
sanity_check(g_settings_path == ""); // Sanity check
526529

530+
527531
if (cmd_args.exists("config")) {
528532
bool r = g_settings->readConfigFile(cmd_args.get("config").c_str());
529533
if (!r) {

Diff for: ‎src/map.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1184,7 +1184,7 @@ bool Map::isBlockOccluded(MapBlock *block, v3s16 cam_pos_nodes)
11841184
ServerMap::ServerMap(const std::string &savedir, IGameDef *gamedef,
11851185
EmergeManager *emerge, MetricsBackend *mb):
11861186
Map(gamedef),
1187-
settings_mgr(g_settings, savedir + DIR_DELIM + "map_meta.txt"),
1187+
settings_mgr(savedir + DIR_DELIM + "map_meta.txt"),
11881188
m_emerge(emerge)
11891189
{
11901190
verbosestream<<FUNCTION_NAME<<std::endl;

Diff for: ‎src/map_settings_manager.cpp

+29-38
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2525

2626
#include "map_settings_manager.h"
2727

28-
MapSettingsManager::MapSettingsManager(Settings *user_settings,
29-
const std::string &map_meta_path):
30-
m_map_meta_path(map_meta_path),
31-
m_map_settings(new Settings()),
32-
m_user_settings(user_settings)
28+
MapSettingsManager::MapSettingsManager(const std::string &map_meta_path):
29+
m_map_meta_path(map_meta_path)
3330
{
34-
assert(m_user_settings != NULL);
35-
36-
Mapgen::setDefaultSettings(m_map_settings);
37-
// This inherits the combined defaults provided by loadGameConfAndInitWorld.
38-
m_map_settings->overrideDefaults(user_settings);
31+
m_map_settings = Settings::createLayer(SL_MAP, "[end_of_params]");
32+
Mapgen::setDefaultSettings(Settings::getLayer(SL_DEFAULTS));
3933
}
4034

4135

@@ -49,22 +43,23 @@ MapSettingsManager::~MapSettingsManager()
4943
bool MapSettingsManager::getMapSetting(
5044
const std::string &name, std::string *value_out)
5145
{
46+
// Get from map_meta.txt, then try from all other sources
5247
if (m_map_settings->getNoEx(name, *value_out))
5348
return true;
5449

5550
// Compatibility kludge
56-
if (m_user_settings == g_settings && name == "seed")
57-
return m_user_settings->getNoEx("fixed_map_seed", *value_out);
51+
if (name == "seed")
52+
return Settings::getLayer(SL_GLOBAL)->getNoEx("fixed_map_seed", *value_out);
5853

59-
return m_user_settings->getNoEx(name, *value_out);
54+
return false;
6055
}
6156

6257

6358
bool MapSettingsManager::getMapSettingNoiseParams(
6459
const std::string &name, NoiseParams *value_out)
6560
{
66-
return m_map_settings->getNoiseParams(name, *value_out) ||
67-
m_user_settings->getNoiseParams(name, *value_out);
61+
// TODO: Rename to "getNoiseParams"
62+
return m_map_settings->getNoiseParams(name, *value_out);
6863
}
6964

7065

@@ -77,7 +72,7 @@ bool MapSettingsManager::setMapSetting(
7772
if (override_meta)
7873
m_map_settings->set(name, value);
7974
else
80-
m_map_settings->setDefault(name, value);
75+
Settings::getLayer(SL_GLOBAL)->set(name, value);
8176

8277
return true;
8378
}
@@ -89,7 +84,11 @@ bool MapSettingsManager::setMapSettingNoiseParams(
8984
if (mapgen_params)
9085
return false;
9186

92-
m_map_settings->setNoiseParams(name, *value, !override_meta);
87+
if (override_meta)
88+
m_map_settings->setNoiseParams(name, *value);
89+
else
90+
Settings::getLayer(SL_GLOBAL)->setNoiseParams(name, *value);
91+
9392
return true;
9493
}
9594

@@ -104,8 +103,8 @@ bool MapSettingsManager::loadMapMeta()
104103
return false;
105104
}
106105

107-
if (!m_map_settings->parseConfigLines(is, "[end_of_params]")) {
108-
errorstream << "loadMapMeta: [end_of_params] not found!" << std::endl;
106+
if (!m_map_settings->parseConfigLines(is)) {
107+
errorstream << "loadMapMeta: Format error. '[end_of_params]' missing?" << std::endl;
109108
return false;
110109
}
111110

@@ -116,28 +115,22 @@ bool MapSettingsManager::loadMapMeta()
116115
bool MapSettingsManager::saveMapMeta()
117116
{
118117
// If mapgen params haven't been created yet; abort
119-
if (!mapgen_params)
118+
if (!mapgen_params) {
119+
errorstream << "saveMapMeta: mapgen_params not present!" << std::endl;
120120
return false;
121+
}
121122

123+
// Paths set up by subgames.cpp, but not in unittests
122124
if (!fs::CreateAllDirs(fs::RemoveLastPathComponent(m_map_meta_path))) {
123125
errorstream << "saveMapMeta: could not create dirs to "
124126
<< m_map_meta_path;
125127
return false;
126128
}
127129

128-
std::ostringstream oss(std::ios_base::binary);
129-
Settings conf;
130+
mapgen_params->MapgenParams::writeParams(m_map_settings);
131+
mapgen_params->writeParams(m_map_settings);
130132

131-
mapgen_params->MapgenParams::writeParams(&conf);
132-
mapgen_params->writeParams(&conf);
133-
conf.writeLines(oss);
134-
135-
// NOTE: If there are ever types of map settings other than
136-
// those relating to map generation, save them here
137-
138-
oss << "[end_of_params]\n";
139-
140-
if (!fs::safeWriteToFile(m_map_meta_path, oss.str())) {
133+
if (!m_map_settings->updateConfigFile(m_map_meta_path.c_str())) {
141134
errorstream << "saveMapMeta: could not write "
142135
<< m_map_meta_path << std::endl;
143136
return false;
@@ -152,23 +145,21 @@ MapgenParams *MapSettingsManager::makeMapgenParams()
152145
if (mapgen_params)
153146
return mapgen_params;
154147

155-
assert(m_user_settings != NULL);
156148
assert(m_map_settings != NULL);
157149

158150
// At this point, we have (in order of precedence):
159-
// 1). m_mapgen_settings->m_settings containing map_meta.txt settings or
151+
// 1). SL_MAP containing map_meta.txt settings or
160152
// explicit overrides from scripts
161-
// 2). m_mapgen_settings->m_defaults containing script-set mgparams without
162-
// overrides
163-
// 3). g_settings->m_settings containing all user-specified config file
153+
// 2). SL_GLOBAL containing all user-specified config file
164154
// settings
165-
// 4). g_settings->m_defaults containing any low-priority settings from
155+
// 3). SL_DEFAULTS containing any low-priority settings from
166156
// scripts, e.g. mods using Lua as an enhanced config file)
167157

168158
// Now, get the mapgen type so we can create the appropriate MapgenParams
169159
std::string mg_name;
170160
MapgenType mgtype = getMapSetting("mg_name", &mg_name) ?
171161
Mapgen::getMapgenType(mg_name) : MAPGEN_DEFAULT;
162+
172163
if (mgtype == MAPGEN_INVALID) {
173164
errorstream << "EmergeManager: mapgen '" << mg_name <<
174165
"' not valid; falling back to " <<

Diff for: ‎src/map_settings_manager.h

+2-3
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,7 @@ struct MapgenParams;
4444
*/
4545
class MapSettingsManager {
4646
public:
47-
MapSettingsManager(Settings *user_settings,
48-
const std::string &map_meta_path);
47+
MapSettingsManager(const std::string &map_meta_path);
4948
~MapSettingsManager();
5049

5150
// Finalized map generation parameters
@@ -71,6 +70,6 @@ class MapSettingsManager {
7170

7271
private:
7372
std::string m_map_meta_path;
73+
// TODO: Rename to "m_settings"
7474
Settings *m_map_settings;
75-
Settings *m_user_settings;
7675
};

Diff for: ‎src/remoteplayer.h

-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,6 @@ class RemotePlayer : public Player
140140
void onSuccessfulSave();
141141

142142
private:
143-
144143
PlayerSAO *m_sao = nullptr;
145144
bool m_dirty = false;
146145

Diff for: ‎src/script/lua_api/l_mapgen.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,7 @@ int ModApiMapgen::l_set_noiseparams(lua_State *L)
982982

983983
bool set_default = !lua_isboolean(L, 3) || readParam<bool>(L, 3);
984984

985-
g_settings->setNoiseParams(name, np, set_default);
985+
Settings::getLayer(set_default ? SL_DEFAULTS : SL_GLOBAL)->setNoiseParams(name, np);
986986

987987
return 0;
988988
}

Diff for: ‎src/script/lua_api/l_settings.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ int LuaSettings::l_set_np_group(lua_State *L)
197197

198198
SET_SECURITY_CHECK(L, key);
199199

200-
o->m_settings->setNoiseParams(key, value, false);
200+
o->m_settings->setNoiseParams(key, value);
201201

202202
return 0;
203203
}

Diff for: ‎src/script/scripting_mainmenu.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
3131
extern "C" {
3232
#include "lualib.h"
3333
}
34-
34+
#include "settings.h"
3535
#define MAINMENU_NUM_ASYNC_THREADS 4
3636

3737

Diff for: ‎src/server.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ Server::~Server()
351351
// Deinitialize scripting
352352
infostream << "Server: Deinitializing scripting" << std::endl;
353353
delete m_script;
354+
delete m_game_settings;
354355

355356
while (!m_unsent_map_edit_queue.empty()) {
356357
delete m_unsent_map_edit_queue.front();
@@ -368,6 +369,8 @@ void Server::init()
368369
infostream << "- world: " << m_path_world << std::endl;
369370
infostream << "- game: " << m_gamespec.path << std::endl;
370371

372+
m_game_settings = Settings::createLayer(SL_GAME);
373+
371374
// Create world if it doesn't exist
372375
try {
373376
loadGameConfAndInitWorld(m_path_world,

Diff for: ‎src/server.h

+1
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
524524
u16 m_max_chatmessage_length;
525525
// For "dedicated" server list flag
526526
bool m_dedicated;
527+
Settings *m_game_settings = nullptr;
527528

528529
// Thread can set; step() will throw as ServerError
529530
MutexedVariable<std::string> m_async_fatal_error;

Diff for: ‎src/serverenvironment.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ void ServerEnvironment::saveMeta()
632632
// Open file and serialize
633633
std::ostringstream ss(std::ios_base::binary);
634634

635-
Settings args;
635+
Settings args("EnvArgsEnd");
636636
args.setU64("game_time", m_game_time);
637637
args.setU64("time_of_day", getTimeOfDay());
638638
args.setU64("last_clear_objects_time", m_last_clear_objects_time);
@@ -641,7 +641,6 @@ void ServerEnvironment::saveMeta()
641641
m_lbm_mgr.createIntroductionTimesString());
642642
args.setU64("day_count", m_day_count);
643643
args.writeLines(ss);
644-
ss<<"EnvArgsEnd\n";
645644

646645
if(!fs::safeWriteToFile(path, ss.str()))
647646
{
@@ -676,9 +675,9 @@ void ServerEnvironment::loadMeta()
676675
throw SerializationError("Couldn't load env meta");
677676
}
678677

679-
Settings args;
678+
Settings args("EnvArgsEnd");
680679

681-
if (!args.parseConfigLines(is, "EnvArgsEnd")) {
680+
if (!args.parseConfigLines(is)) {
682681
throw SerializationError("ServerEnvironment::loadMeta(): "
683682
"EnvArgsEnd not found!");
684683
}

Diff for: ‎src/settings.cpp

+143-157
Large diffs are not rendered by default.

Diff for: ‎src/settings.h

+25-18
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class Settings;
3030
struct NoiseParams;
3131

3232
// Global objects
33-
extern Settings *g_settings;
33+
extern Settings *g_settings; // Same as Settings::getLayer(SL_GLOBAL);
3434
extern std::string g_settings_path;
3535

3636
// Type for a settings changed callback function
@@ -60,6 +60,14 @@ enum SettingsParseEvent {
6060
SPE_MULTILINE,
6161
};
6262

63+
enum SettingsLayer {
64+
SL_DEFAULTS,
65+
SL_GAME,
66+
SL_GLOBAL,
67+
SL_MAP,
68+
SL_TOTAL_COUNT
69+
};
70+
6371
struct ValueSpec {
6472
ValueSpec(ValueType a_type, const char *a_help=NULL)
6573
{
@@ -92,8 +100,13 @@ typedef std::unordered_map<std::string, SettingsEntry> SettingEntries;
92100

93101
class Settings {
94102
public:
95-
Settings() = default;
103+
static Settings *createLayer(SettingsLayer sl, const std::string &end_tag = "");
104+
static Settings *getLayer(SettingsLayer sl);
105+
SettingsLayer getLayerType() const { return m_settingslayer; }
96106

107+
Settings(const std::string &end_tag = "") :
108+
m_end_tag(end_tag)
109+
{}
97110
~Settings();
98111

99112
Settings & operator += (const Settings &other);
@@ -110,7 +123,7 @@ class Settings {
110123
// NOTE: Types of allowed_options are ignored. Returns success.
111124
bool parseCommandLine(int argc, char *argv[],
112125
std::map<std::string, ValueSpec> &allowed_options);
113-
bool parseConfigLines(std::istream &is, const std::string &end = "");
126+
bool parseConfigLines(std::istream &is);
114127
void writeLines(std::ostream &os, u32 tab_depth=0) const;
115128

116129
/***********
@@ -146,7 +159,6 @@ class Settings {
146159

147160
bool getGroupNoEx(const std::string &name, Settings *&val) const;
148161
bool getNoEx(const std::string &name, std::string &val) const;
149-
bool getDefaultNoEx(const std::string &name, std::string &val) const;
150162
bool getFlag(const std::string &name) const;
151163
bool getU16NoEx(const std::string &name, u16 &val) const;
152164
bool getS16NoEx(const std::string &name, s16 &val) const;
@@ -170,11 +182,10 @@ class Settings {
170182
// N.B. Groups not allocated with new must be set to NULL in the settings
171183
// tree before object destruction.
172184
bool setEntry(const std::string &name, const void *entry,
173-
bool set_group, bool set_default);
185+
bool set_group);
174186
bool set(const std::string &name, const std::string &value);
175187
bool setDefault(const std::string &name, const std::string &value);
176188
bool setGroup(const std::string &name, const Settings &group);
177-
bool setGroupDefault(const std::string &name, const Settings &group);
178189
bool setBool(const std::string &name, bool value);
179190
bool setS16(const std::string &name, s16 value);
180191
bool setU16(const std::string &name, u16 value);
@@ -185,21 +196,16 @@ class Settings {
185196
bool setV3F(const std::string &name, v3f value);
186197
bool setFlagStr(const std::string &name, u32 flags,
187198
const FlagDesc *flagdesc = nullptr, u32 flagmask = U32_MAX);
188-
bool setNoiseParams(const std::string &name, const NoiseParams &np,
189-
bool set_default=false);
199+
bool setNoiseParams(const std::string &name, const NoiseParams &np);
190200

191201
// remove a setting
192202
bool remove(const std::string &name);
193-
void clear();
194-
void clearDefaults();
195203

196204
/**************
197205
* Miscellany *
198206
**************/
199207

200208
void setDefault(const std::string &name, const FlagDesc *flagdesc, u32 flags);
201-
// Takes the provided setting values and uses them as new defaults
202-
void overrideDefaults(Settings *other);
203209
const FlagDesc *getFlagDescFallback(const std::string &name) const;
204210

205211
void registerChangedCallback(const std::string &name,
@@ -215,9 +221,9 @@ class Settings {
215221
***********************/
216222

217223
SettingsParseEvent parseConfigObject(const std::string &line,
218-
const std::string &end, std::string &name, std::string &value);
224+
std::string &name, std::string &value);
219225
bool updateConfigObject(std::istream &is, std::ostream &os,
220-
const std::string &end, u32 tab_depth=0);
226+
u32 tab_depth=0);
221227

222228
static bool checkNameValid(const std::string &name);
223229
static bool checkValueValid(const std::string &value);
@@ -228,9 +234,9 @@ class Settings {
228234
/***********
229235
* Getters *
230236
***********/
237+
Settings *getParent() const;
231238

232239
const SettingsEntry &getEntry(const std::string &name) const;
233-
const SettingsEntry &getEntryDefault(const std::string &name) const;
234240

235241
// Allow TestSettings to run sanity checks using private functions.
236242
friend class TestSettings;
@@ -242,14 +248,15 @@ class Settings {
242248
void doCallbacks(const std::string &name) const;
243249

244250
SettingEntries m_settings;
245-
SettingEntries m_defaults;
246-
std::unordered_map<std::string, const FlagDesc *> m_flags;
247-
248251
SettingsCallbackMap m_callbacks;
252+
std::string m_end_tag;
249253

250254
mutable std::mutex m_callback_mutex;
251255

252256
// All methods that access m_settings/m_defaults directly should lock this.
253257
mutable std::mutex m_mutex;
254258

259+
static Settings *s_layers[SL_TOTAL_COUNT];
260+
SettingsLayer m_settingslayer = SL_TOTAL_COUNT;
261+
static std::unordered_map<std::string, const FlagDesc *> s_flags;
255262
};

Diff for: ‎src/unittest/test_map_settings_manager.cpp

+55-31
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class TestMapSettingsManager : public TestBase {
3030
TestMapSettingsManager() { TestManager::registerTestModule(this); }
3131
const char *getName() { return "TestMapSettingsManager"; }
3232

33-
void makeUserConfig(Settings *conf);
33+
void makeUserConfig();
3434
std::string makeMetaFile(bool make_corrupt);
3535

3636
void runTests(IGameDef *gamedef);
@@ -65,8 +65,11 @@ void check_noise_params(const NoiseParams *np1, const NoiseParams *np2)
6565
}
6666

6767

68-
void TestMapSettingsManager::makeUserConfig(Settings *conf)
68+
void TestMapSettingsManager::makeUserConfig()
6969
{
70+
delete Settings::getLayer(SL_GLOBAL);
71+
Settings *conf = Settings::createLayer(SL_GLOBAL);
72+
7073
conf->set("mg_name", "v7");
7174
conf->set("seed", "5678");
7275
conf->set("water_level", "20");
@@ -103,12 +106,11 @@ std::string TestMapSettingsManager::makeMetaFile(bool make_corrupt)
103106

104107
void TestMapSettingsManager::testMapSettingsManager()
105108
{
106-
Settings user_settings;
107-
makeUserConfig(&user_settings);
109+
makeUserConfig();
108110

109111
std::string test_mapmeta_path = makeMetaFile(false);
110112

111-
MapSettingsManager mgr(&user_settings, test_mapmeta_path);
113+
MapSettingsManager mgr(test_mapmeta_path);
112114
std::string value;
113115

114116
UASSERT(mgr.getMapSetting("mg_name", &value));
@@ -140,6 +142,12 @@ void TestMapSettingsManager::testMapSettingsManager()
140142
mgr.setMapSettingNoiseParams("mgv5_np_height", &script_np_height);
141143
mgr.setMapSettingNoiseParams("mgv5_np_factor", &script_np_factor);
142144

145+
{
146+
NoiseParams dummy;
147+
mgr.getMapSettingNoiseParams("mgv5_np_factor", &dummy);
148+
check_noise_params(&dummy, &script_np_factor);
149+
}
150+
143151
// Now make our Params and see if the values are correctly sourced
144152
MapgenParams *params = mgr.makeMapgenParams();
145153
UASSERT(params->mgtype == MAPGEN_V5);
@@ -188,50 +196,66 @@ void TestMapSettingsManager::testMapSettingsManager()
188196

189197
void TestMapSettingsManager::testMapMetaSaveLoad()
190198
{
191-
Settings conf;
192199
std::string path = getTestTempDirectory()
193200
+ DIR_DELIM + "foobar" + DIR_DELIM + "map_meta.txt";
194201

202+
makeUserConfig();
203+
Settings &conf = *Settings::getLayer(SL_GLOBAL);
204+
205+
// There cannot be two MapSettingsManager
206+
// copy the mapgen params to compare them
207+
MapgenParams params1, params2;
195208
// Create a set of mapgen params and save them to map meta
196-
conf.set("seed", "12345");
197-
conf.set("water_level", "5");
198-
MapSettingsManager mgr1(&conf, path);
199-
MapgenParams *params1 = mgr1.makeMapgenParams();
200-
UASSERT(params1);
201-
UASSERT(mgr1.saveMapMeta());
209+
{
210+
conf.set("seed", "12345");
211+
conf.set("water_level", "5");
212+
MapSettingsManager mgr(path);
213+
MapgenParams *params = mgr.makeMapgenParams();
214+
UASSERT(params);
215+
params1 = *params;
216+
params1.bparams = nullptr; // No double-free
217+
UASSERT(mgr.saveMapMeta());
218+
}
202219

203220
// Now try loading the map meta to mapgen params
204-
conf.set("seed", "67890");
205-
conf.set("water_level", "32");
206-
MapSettingsManager mgr2(&conf, path);
207-
UASSERT(mgr2.loadMapMeta());
208-
MapgenParams *params2 = mgr2.makeMapgenParams();
209-
UASSERT(params2);
221+
{
222+
conf.set("seed", "67890");
223+
conf.set("water_level", "32");
224+
MapSettingsManager mgr(path);
225+
UASSERT(mgr.loadMapMeta());
226+
MapgenParams *params = mgr.makeMapgenParams();
227+
UASSERT(params);
228+
params2 = *params;
229+
params2.bparams = nullptr; // No double-free
230+
}
210231

211232
// Check that both results are correct
212-
UASSERTEQ(u64, params1->seed, 12345);
213-
UASSERTEQ(s16, params1->water_level, 5);
214-
UASSERTEQ(u64, params2->seed, 12345);
215-
UASSERTEQ(s16, params2->water_level, 5);
233+
UASSERTEQ(u64, params1.seed, 12345);
234+
UASSERTEQ(s16, params1.water_level, 5);
235+
UASSERTEQ(u64, params2.seed, 12345);
236+
UASSERTEQ(s16, params2.water_level, 5);
216237
}
217238

218239

219240
void TestMapSettingsManager::testMapMetaFailures()
220241
{
221242
std::string test_mapmeta_path;
222-
Settings conf;
223243

224244
// Check to see if it'll fail on a non-existent map meta file
225-
test_mapmeta_path = "woobawooba/fgdfg/map_meta.txt";
226-
UASSERT(!fs::PathExists(test_mapmeta_path));
245+
{
246+
test_mapmeta_path = "woobawooba/fgdfg/map_meta.txt";
247+
UASSERT(!fs::PathExists(test_mapmeta_path));
227248

228-
MapSettingsManager mgr1(&conf, test_mapmeta_path);
229-
UASSERT(!mgr1.loadMapMeta());
249+
MapSettingsManager mgr1(test_mapmeta_path);
250+
UASSERT(!mgr1.loadMapMeta());
251+
}
230252

231253
// Check to see if it'll fail on a corrupt map meta file
232-
test_mapmeta_path = makeMetaFile(true);
233-
UASSERT(fs::PathExists(test_mapmeta_path));
254+
{
255+
test_mapmeta_path = makeMetaFile(true);
256+
UASSERT(fs::PathExists(test_mapmeta_path));
234257

235-
MapSettingsManager mgr2(&conf, test_mapmeta_path);
236-
UASSERT(!mgr2.loadMapMeta());
258+
MapSettingsManager mgr2(test_mapmeta_path);
259+
UASSERT(!mgr2.loadMapMeta());
260+
}
237261
}

Diff for: ‎src/unittest/test_settings.cpp

+62-11
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2121

2222
#include <cmath>
2323
#include "settings.h"
24+
#include "defaultsettings.h"
2425
#include "noise.h"
2526

2627
class TestSettings : public TestBase {
@@ -31,6 +32,7 @@ class TestSettings : public TestBase {
3132
void runTests(IGameDef *gamedef);
3233

3334
void testAllSettings();
35+
void testDefaults();
3436
void testFlagDesc();
3537

3638
static const char *config_text_before;
@@ -42,6 +44,7 @@ static TestSettings g_test_instance;
4244
void TestSettings::runTests(IGameDef *gamedef)
4345
{
4446
TEST(testAllSettings);
47+
TEST(testDefaults);
4548
TEST(testFlagDesc);
4649
}
4750

@@ -70,7 +73,8 @@ const char *TestSettings::config_text_before =
7073
" with leading whitespace!\n"
7174
"\"\"\"\n"
7275
"np_terrain = 5, 40, (250, 250, 250), 12341, 5, 0.7, 2.4\n"
73-
"zoop = true";
76+
"zoop = true\n"
77+
"[dummy_eof_end_tag]\n";
7478

7579
const std::string TestSettings::config_text_after =
7680
"leet = 1337\n"
@@ -111,12 +115,34 @@ const std::string TestSettings::config_text_after =
111115
" animals = cute\n"
112116
" num_apples = 4\n"
113117
" num_oranges = 53\n"
114-
"}\n";
118+
"}\n"
119+
"[dummy_eof_end_tag]";
120+
121+
void compare_settings(const std::string &name, Settings *a, Settings *b)
122+
{
123+
auto keys = a->getNames();
124+
Settings *group1, *group2;
125+
std::string value1, value2;
126+
for (auto &key : keys) {
127+
if (a->getGroupNoEx(key, group1)) {
128+
UASSERT(b->getGroupNoEx(key, group2));
129+
130+
compare_settings(name + "->" + key, group1, group2);
131+
continue;
132+
}
133+
134+
UASSERT(b->getNoEx(key, value1));
135+
// For identification
136+
value1 = name + "->" + key + "=" + value1;
137+
value2 = name + "->" + key + "=" + a->get(key);
138+
UASSERTCMP(std::string, ==, value2, value1);
139+
}
140+
}
115141

116142
void TestSettings::testAllSettings()
117143
{
118144
try {
119-
Settings s;
145+
Settings s("[dummy_eof_end_tag]");
120146

121147
// Test reading of settings
122148
std::istringstream is(config_text_before);
@@ -197,21 +223,44 @@ void TestSettings::testAllSettings()
197223
is.clear();
198224
is.seekg(0);
199225

200-
UASSERT(s.updateConfigObject(is, os, "", 0) == true);
201-
//printf(">>>> expected config:\n%s\n", TEST_CONFIG_TEXT_AFTER);
202-
//printf(">>>> actual config:\n%s\n", os.str().c_str());
203-
#if __cplusplus < 201103L
204-
// This test only works in older C++ versions than C++11 because we use unordered_map
205-
UASSERT(os.str() == config_text_after);
206-
#endif
226+
UASSERT(s.updateConfigObject(is, os, 0) == true);
227+
228+
{
229+
// Confirm settings
230+
Settings s2("[dummy_eof_end_tag]");
231+
std::istringstream is(config_text_after, std::ios_base::binary);
232+
s2.parseConfigLines(is);
233+
234+
compare_settings("(main)", &s, &s2);
235+
}
236+
207237
} catch (SettingNotFoundException &e) {
208238
UASSERT(!"Setting not found!");
209239
}
210240
}
211241

242+
void TestSettings::testDefaults()
243+
{
244+
Settings *game = Settings::createLayer(SL_GAME);
245+
Settings *def = Settings::getLayer(SL_DEFAULTS);
246+
247+
def->set("name", "FooBar");
248+
UASSERT(def->get("name") == "FooBar");
249+
UASSERT(game->get("name") == "FooBar");
250+
251+
game->set("name", "Baz");
252+
UASSERT(game->get("name") == "Baz");
253+
254+
delete game;
255+
256+
// Restore default settings
257+
delete Settings::getLayer(SL_DEFAULTS);
258+
set_default_settings();
259+
}
260+
212261
void TestSettings::testFlagDesc()
213262
{
214-
Settings s;
263+
Settings &s = *Settings::createLayer(SL_GAME);
215264
FlagDesc flagdesc[] = {
216265
{ "biomes", 0x01 },
217266
{ "trees", 0x02 },
@@ -242,4 +291,6 @@ void TestSettings::testFlagDesc()
242291
// Enabled: tables
243292
s.set("test_flags", "16");
244293
UASSERT(s.getFlagStr("test_flags", flagdesc, nullptr) == 0x10);
294+
295+
delete &s;
245296
}

0 commit comments

Comments
 (0)
Please sign in to comment.