Merge pull request #93 from badgerman/master

E3 Lua Tests & memory leaks removed
This commit is contained in:
Enno Rehling 2014-12-31 21:26:48 +01:00
commit 64ac0ae5e4
48 changed files with 2221 additions and 2118 deletions

View File

@ -19,4 +19,5 @@ $ROOT/$BIN_DIR/eressea/test_eressea
cd $ROOT cd $ROOT
[ -e eressea.ini ] || ln -sf conf/eressea.ini [ -e eressea.ini ] || ln -sf conf/eressea.ini
$ROOT/$BIN_DIR/eressea/eressea -v0 scripts/run-tests.lua $ROOT/$BIN_DIR/eressea/eressea -v0 scripts/run-tests.lua
$ROOT/$BIN_DIR/eressea/eressea -v0 scripts/run-tests-e3.lua
cd $OLDWPD cd $OLDWPD

19
scripts/run-tests-e3.lua Normal file
View File

@ -0,0 +1,19 @@
-- new tests 2014-06-11
path = 'scripts'
if config.source_dir ~= nil then
path = config.source_dir .. '/' .. path
end
package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua'
config.rules = 'e3'
require 'eressea'
require 'eressea.path'
require 'eressea.xmlconf'
require 'tests.e3'
require 'lunit'
eressea.settings.set("rules.alliances", "0")
rules = require('eressea.' .. config.rules)
lunit.main()

View File

@ -3,7 +3,7 @@ require "lunit"
module("tests.e3.castles", package.seeall, lunit.testcase ) module("tests.e3.castles", package.seeall, lunit.testcase )
function setup() function setup()
eressea.free_game() eressea.game.reset()
end end
function test_small_castles() function test_small_castles()

View File

@ -0,0 +1,3 @@
require 'tests.e3.castles'
require 'tests.e3.stealth'
require 'tests.e3.spells'

View File

@ -3,7 +3,7 @@ require "lunit"
module("tests.e3.spells", package.seeall, lunit.testcase) module("tests.e3.spells", package.seeall, lunit.testcase)
function setup() function setup()
eressea.free_game() eressea.game.reset()
eressea.settings.set("magic.fumble.enable", "0") eressea.settings.set("magic.fumble.enable", "0")
eressea.settings.set("nmr.removenewbie", "0") eressea.settings.set("nmr.removenewbie", "0")
eressea.settings.set("nmr.timeout", "0") eressea.settings.set("nmr.timeout", "0")
@ -11,7 +11,6 @@ function setup()
end end
function test_blessedharvest_lasts_n_turn() function test_blessedharvest_lasts_n_turn()
eressea.free_game()
local r = region.create(0, 0, "plain") local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "halfling", "de") local f = faction.create("noreply@eressea.de", "halfling", "de")
local u = unit.create(f, r) local u = unit.create(f, r)

View File

@ -6,18 +6,18 @@ local f
local u local u
function setup() function setup()
eressea.free_game() eressea.game.reset()
eressea.settings.set("rules.economy.food", "4") eressea.settings.set("rules.economy.food", "4")
local r = region.create(0,0, "plain") local r = region.create(0,0, "plain")
f = faction.create("stealthy@eressea.de", "human", "de") f = faction.create("stealth1@eressea.de", "human", "de")
u = unit.create(f, r, 1) u = unit.create(f, r, 1)
f = faction.create("stealth@eressea.de", "human", "de") f = faction.create("stealth2@eressea.de", "human", "de")
end end
function test_stealth_faction_on() function test_stealth_faction_on()
u:clear_orders() u:clear_orders()
u:add_order("TARNEN PARTEI") u:add_order("TARNE PARTEI")
eressea.settings.set("rules.stealth.faction", 1) eressea.settings.set("rules.stealth.faction", 1)
process_orders() process_orders()
@ -27,7 +27,7 @@ end
function test_stealth_faction_off() function test_stealth_faction_off()
u:clear_orders() u:clear_orders()
u:add_order("TARNEN PARTEI") u:add_order("TARNE PARTEI")
eressea.settings.set("rules.stealth.faction", 0) eressea.settings.set("rules.stealth.faction", 0)
process_orders() process_orders()

View File

@ -7,4 +7,3 @@ require 'tests.locale'
require 'tests.regions' require 'tests.regions'
require 'tests.study' require 'tests.study'
require 'tests.movement' require 'tests.movement'

View File

@ -4,7 +4,7 @@ module("tests.eressea.pool", package.seeall, lunit.testcase )
function setup() function setup()
eressea.game.reset() eressea.game.reset()
eressea.config.reset(); eressea.config.reset()
eressea.settings.set("rules.economy.food", "0") eressea.settings.set("rules.economy.food", "0")
eressea.settings.set("nmr.removenewbie", "0") eressea.settings.set("nmr.removenewbie", "0")
eressea.settings.set("nmr.timeout", "0") eressea.settings.set("nmr.timeout", "0")

View File

@ -5,6 +5,7 @@
#include "json.h" #include "json.h"
#include <kernel/faction.h> #include <kernel/faction.h>
#include <kernel/item.h>
#include <kernel/config.h> #include <kernel/config.h>
#include <kernel/save.h> #include <kernel/save.h>
@ -14,6 +15,7 @@
void eressea_free_game(void) { void eressea_free_game(void) {
free_gamedata(); free_gamedata();
init_resources();
} }
int eressea_read_game(const char * filename) { int eressea_read_game(const char * filename) {

View File

@ -514,6 +514,7 @@ static void reset_game(void)
for (f = factions; f; f = f->next) { for (f = factions; f; f = f->next) {
f->flags &= FFL_SAVEMASK; f->flags &= FFL_SAVEMASK;
} }
init_locales();
} }
static int tolua_process_orders(lua_State * L) static int tolua_process_orders(lua_State * L)

View File

@ -45,6 +45,7 @@ static void test_export_no_regions(CuTest * tc) {
buf[len] = '\0'; buf[len] = '\0';
CuAssertStrEquals(tc, "{}", strip(buf)); CuAssertStrEquals(tc, "{}", strip(buf));
mstream_done(&out); mstream_done(&out);
test_cleanup();
} }
static cJSON *export_a_region(CuTest * tc, const struct terrain_type *terrain, region **_r) { static cJSON *export_a_region(CuTest * tc, const struct terrain_type *terrain, region **_r) {
@ -93,6 +94,7 @@ static void test_export_land_region(CuTest * tc) {
CuAssertPtrNotNull(tc, attr = cJSON_GetObjectItem(json, "name")); CuAssertPtrNotNull(tc, attr = cJSON_GetObjectItem(json, "name"));
CuAssertStrEquals(tc, r->land->name, attr->valuestring); CuAssertStrEquals(tc, r->land->name, attr->valuestring);
cJSON_Delete(json); cJSON_Delete(json);
test_cleanup();
} }
static void test_export_ocean_region(CuTest * tc) { static void test_export_ocean_region(CuTest * tc) {
@ -103,6 +105,7 @@ static void test_export_ocean_region(CuTest * tc) {
json = export_a_region(tc, terrain, 0); json = export_a_region(tc, terrain, 0);
CuAssertPtrEquals(tc, 0, cJSON_GetObjectItem(json, "name")); CuAssertPtrEquals(tc, 0, cJSON_GetObjectItem(json, "name"));
cJSON_Delete(json); cJSON_Delete(json);
test_cleanup();
} }
static void test_export_no_factions(CuTest * tc) { static void test_export_no_factions(CuTest * tc) {
@ -119,6 +122,7 @@ static void test_export_no_factions(CuTest * tc) {
buf[len]=0; buf[len]=0;
CuAssertStrEquals(tc, "{}", strip(buf)); CuAssertStrEquals(tc, "{}", strip(buf));
mstream_done(&out); mstream_done(&out);
test_cleanup();
} }
CuSuite *get_json_suite(void) { CuSuite *get_json_suite(void) {

View File

@ -57,6 +57,7 @@ static void test_build_requires_materials(CuTest *tc) {
i_change(&u->items, itype, 2); i_change(&u->items, itype, 2);
CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 1)); CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 1));
CuAssertIntEquals(tc, 1, i_get(u->items, itype)); CuAssertIntEquals(tc, 1, i_get(u->items, itype));
test_cleanup();
} }
static void test_build_requires_building(CuTest *tc) { static void test_build_requires_building(CuTest *tc) {
@ -78,6 +79,7 @@ static void test_build_requires_building(CuTest *tc) {
CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 1)); CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 1));
btype->maxcapacity = 0; btype->maxcapacity = 0;
CuAssertIntEquals_Msg(tc, "cannot build when production building capacity exceeded", EBUILDINGREQ, build(u, &bf.cons, 0, 1)); CuAssertIntEquals_Msg(tc, "cannot build when production building capacity exceeded", EBUILDINGREQ, build(u, &bf.cons, 0, 1));
test_cleanup();
} }
static void test_build_failure_missing_skill(CuTest *tc) { static void test_build_failure_missing_skill(CuTest *tc) {
@ -89,6 +91,7 @@ static void test_build_failure_missing_skill(CuTest *tc) {
rtype = bf.cons.materials[0].rtype; rtype = bf.cons.materials[0].rtype;
i_change(&u->items, rtype->itype, 1); i_change(&u->items, rtype->itype, 1);
CuAssertIntEquals(tc, ENEEDSKILL, build(u, &bf.cons, 1, 1)); CuAssertIntEquals(tc, ENEEDSKILL, build(u, &bf.cons, 1, 1));
test_cleanup();
} }
static void test_build_failure_low_skill(CuTest *tc) { static void test_build_failure_low_skill(CuTest *tc) {
@ -101,6 +104,7 @@ static void test_build_failure_low_skill(CuTest *tc) {
i_change(&u->items, rtype->itype, 1); i_change(&u->items, rtype->itype, 1);
set_level(u, SK_ARMORER, bf.cons.minskill-1); set_level(u, SK_ARMORER, bf.cons.minskill-1);
CuAssertIntEquals(tc, ELOWSKILL, build(u, &bf.cons, 0, 10)); CuAssertIntEquals(tc, ELOWSKILL, build(u, &bf.cons, 0, 10));
test_cleanup();
} }
static void test_build_failure_completed(CuTest *tc) { static void test_build_failure_completed(CuTest *tc) {
@ -115,6 +119,7 @@ static void test_build_failure_completed(CuTest *tc) {
bf.cons.maxsize = 1; bf.cons.maxsize = 1;
CuAssertIntEquals(tc, ECOMPLETE, build(u, &bf.cons, bf.cons.maxsize, 10)); CuAssertIntEquals(tc, ECOMPLETE, build(u, &bf.cons, bf.cons.maxsize, 10));
CuAssertIntEquals(tc, 1, i_get(u->items, rtype->itype)); CuAssertIntEquals(tc, 1, i_get(u->items, rtype->itype));
test_cleanup();
} }
static void test_build_limits(CuTest *tc) { static void test_build_limits(CuTest *tc) {
@ -202,6 +207,7 @@ static void test_build_building_no_materials(CuTest *tc) {
CuAssertIntEquals(tc, ENOMATERIALS, build_building(u, btype, 0, 4, 0)); CuAssertIntEquals(tc, ENOMATERIALS, build_building(u, btype, 0, 4, 0));
CuAssertPtrEquals(tc, 0, u->region->buildings); CuAssertPtrEquals(tc, 0, u->region->buildings);
CuAssertPtrEquals(tc, 0, u->building); CuAssertPtrEquals(tc, 0, u->building);
test_cleanup();
} }
static void test_build_building_with_golem(CuTest *tc) { static void test_build_building_with_golem(CuTest *tc) {
@ -220,6 +226,7 @@ static void test_build_building_with_golem(CuTest *tc) {
CuAssertPtrNotNull(tc, u->region->buildings); CuAssertPtrNotNull(tc, u->region->buildings);
CuAssertIntEquals(tc, 1, u->region->buildings->size); CuAssertIntEquals(tc, 1, u->region->buildings->size);
CuAssertIntEquals(tc, 0, u->number); CuAssertIntEquals(tc, 0, u->number);
test_cleanup();
} }
static void test_build_building_success(CuTest *tc) { static void test_build_building_success(CuTest *tc) {
@ -243,6 +250,7 @@ static void test_build_building_success(CuTest *tc) {
CuAssertPtrEquals(tc, u->region->buildings, u->building); CuAssertPtrEquals(tc, u->region->buildings, u->building);
CuAssertIntEquals(tc, 1, u->building->size); CuAssertIntEquals(tc, 1, u->building->size);
CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype)); CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype));
test_cleanup();
} }
CuSuite *get_build_suite(void) CuSuite *get_build_suite(void)

View File

@ -92,8 +92,14 @@ void bt_register(building_type * type)
ql_push(&buildingtypes, (void *)type); ql_push(&buildingtypes, (void *)type);
} }
void free_buildingtype(void *ptr) {
building_type *btype =(building_type *)ptr;
free(btype->_name);
free(btype);
}
void free_buildingtypes(void) { void free_buildingtypes(void) {
ql_foreach(buildingtypes, free); ql_foreach(buildingtypes, free_buildingtype);
ql_free(buildingtypes); ql_free(buildingtypes);
buildingtypes = 0; buildingtypes = 0;
} }

View File

@ -49,7 +49,7 @@ extern "C" {
#define BTF_NAMECHANGE 0x100 /* name and description can be changed more than once */ #define BTF_NAMECHANGE 0x100 /* name and description can be changed more than once */
typedef struct building_type { typedef struct building_type {
const char *_name; char *_name;
int flags; /* flags */ int flags; /* flags */
int capacity; /* Kapazität pro Größenpunkt */ int capacity; /* Kapazität pro Größenpunkt */

View File

@ -22,6 +22,9 @@ static void test_register_building(CuTest * tc)
bt_register(btype); bt_register(btype);
CuAssertPtrNotNull(tc, bt_find("herp")); CuAssertPtrNotNull(tc, bt_find("herp"));
// free(btype->_name);
// free(btype);
test_cleanup();
} }
static void test_building_set_owner(CuTest * tc) static void test_building_set_owner(CuTest * tc)
@ -51,6 +54,7 @@ static void test_building_set_owner(CuTest * tc)
CuAssertPtrEquals(tc, u1, building_owner(bld)); CuAssertPtrEquals(tc, u1, building_owner(bld));
building_set_owner(u2); building_set_owner(u2);
CuAssertPtrEquals(tc, u2, building_owner(bld)); CuAssertPtrEquals(tc, u2, building_owner(bld));
test_cleanup();
} }
static void test_buildingowner_goes_to_next_when_empty(CuTest * tc) static void test_buildingowner_goes_to_next_when_empty(CuTest * tc)
@ -85,6 +89,7 @@ static void test_buildingowner_goes_to_next_when_empty(CuTest * tc)
CuAssertPtrEquals(tc, u, building_owner(bld)); CuAssertPtrEquals(tc, u, building_owner(bld));
u->number = 0; u->number = 0;
CuAssertPtrEquals(tc, u2, building_owner(bld)); CuAssertPtrEquals(tc, u2, building_owner(bld));
test_cleanup();
} }
static void test_buildingowner_goes_to_other_when_empty(CuTest * tc) static void test_buildingowner_goes_to_other_when_empty(CuTest * tc)
@ -120,6 +125,7 @@ static void test_buildingowner_goes_to_other_when_empty(CuTest * tc)
CuAssertPtrEquals(tc, u, building_owner(bld)); CuAssertPtrEquals(tc, u, building_owner(bld));
u->number = 0; u->number = 0;
CuAssertPtrEquals(tc, u2, building_owner(bld)); CuAssertPtrEquals(tc, u2, building_owner(bld));
test_cleanup();
} }
static void test_buildingowner_goes_to_same_faction_when_empty(CuTest * tc) static void test_buildingowner_goes_to_same_faction_when_empty(CuTest * tc)
@ -159,6 +165,7 @@ static void test_buildingowner_goes_to_same_faction_when_empty(CuTest * tc)
CuAssertPtrEquals(tc, u3, building_owner(bld)); CuAssertPtrEquals(tc, u3, building_owner(bld));
u3->number = 0; u3->number = 0;
CuAssertPtrEquals(tc, u2, building_owner(bld)); CuAssertPtrEquals(tc, u2, building_owner(bld));
test_cleanup();
} }
static void test_buildingowner_goes_to_next_after_leave(CuTest * tc) static void test_buildingowner_goes_to_next_after_leave(CuTest * tc)
@ -193,6 +200,7 @@ static void test_buildingowner_goes_to_next_after_leave(CuTest * tc)
CuAssertPtrEquals(tc, u, building_owner(bld)); CuAssertPtrEquals(tc, u, building_owner(bld));
leave_building(u); leave_building(u);
CuAssertPtrEquals(tc, u2, building_owner(bld)); CuAssertPtrEquals(tc, u2, building_owner(bld));
test_cleanup();
} }
static void test_buildingowner_goes_to_other_after_leave(CuTest * tc) static void test_buildingowner_goes_to_other_after_leave(CuTest * tc)
@ -227,6 +235,7 @@ static void test_buildingowner_goes_to_other_after_leave(CuTest * tc)
CuAssertPtrEquals(tc, u, building_owner(bld)); CuAssertPtrEquals(tc, u, building_owner(bld));
leave_building(u); leave_building(u);
CuAssertPtrEquals(tc, u2, building_owner(bld)); CuAssertPtrEquals(tc, u2, building_owner(bld));
test_cleanup();
} }
static void test_buildingowner_goes_to_same_faction_after_leave(CuTest * tc) static void test_buildingowner_goes_to_same_faction_after_leave(CuTest * tc)
@ -268,6 +277,7 @@ static void test_buildingowner_goes_to_same_faction_after_leave(CuTest * tc)
CuAssertPtrEquals(tc, u2, building_owner(bld)); CuAssertPtrEquals(tc, u2, building_owner(bld));
leave_building(u2); leave_building(u2);
CuAssertPtrEquals(tc, 0, building_owner(bld)); CuAssertPtrEquals(tc, 0, building_owner(bld));
test_cleanup();
} }
static void test_buildingowner_resets_when_empty(CuTest * tc) static void test_buildingowner_resets_when_empty(CuTest * tc)
@ -302,6 +312,7 @@ static void test_buildingowner_resets_when_empty(CuTest * tc)
CuAssertPtrEquals(tc, 0, building_owner(bld)); CuAssertPtrEquals(tc, 0, building_owner(bld));
u->number = 1; u->number = 1;
CuAssertPtrEquals(tc, u, building_owner(bld)); CuAssertPtrEquals(tc, u, building_owner(bld));
test_cleanup();
} }
void test_buildingowner_goes_to_empty_unit_after_leave(CuTest * tc) void test_buildingowner_goes_to_empty_unit_after_leave(CuTest * tc)
@ -343,6 +354,7 @@ void test_buildingowner_goes_to_empty_unit_after_leave(CuTest * tc)
CuAssertPtrEquals(tc, 0, building_owner(bld)); CuAssertPtrEquals(tc, 0, building_owner(bld));
u2->number = 1; u2->number = 1;
CuAssertPtrEquals(tc, u2, building_owner(bld)); CuAssertPtrEquals(tc, u2, building_owner(bld));
test_cleanup();
} }
CuSuite *get_building_suite(void) CuSuite *get_building_suite(void)

View File

@ -1047,23 +1047,24 @@ int get_param_int(const struct param *p, const char *key, int def)
int check_param(const struct param *p, const char *key, const char *searchvalue) int check_param(const struct param *p, const char *key, const char *searchvalue)
{ {
int result = 0;
const char *value = get_param(p, key); const char *value = get_param(p, key);
if (!value) { if (!value) {
return 0; return 0;
} }
char *p_value = malloc(sizeof(char)* (strlen(value) + 1)); char *p_value = _strdup(value);
strcpy(p_value, value);
const char *delimiter = " ,;"; const char *delimiter = " ,;";
char *v = strtok(p_value, delimiter); char *v = strtok(p_value, delimiter);
while (v != NULL) { while (v != NULL) {
if (strcmp(v, searchvalue) == 0) if (strcmp(v, searchvalue) == 0) {
{ result = 1;
return 1; break;
} }
v = strtok(NULL, delimiter); v = strtok(NULL, delimiter);
} }
return 0; free(p_value);
return result;
} }
static const char *g_datadir; static const char *g_datadir;
@ -1143,6 +1144,7 @@ void kernel_done(void)
* calling it is optional, e.g. a release server will most likely not do it. * calling it is optional, e.g. a release server will most likely not do it.
*/ */
translation_done(); translation_done();
free_attribs();
} }
attrib_type at_germs = { attrib_type at_germs = {
@ -1759,8 +1761,6 @@ void free_gamedata(void)
a_remove(&global.attribs, global.attribs); a_remove(&global.attribs, global.attribs);
} }
++global.cookie; /* readgame() already does this, but sjust in case */ ++global.cookie; /* readgame() already does this, but sjust in case */
init_resources();
} }
const char * game_name(void) { const char * game_name(void) {

View File

@ -1167,10 +1167,7 @@ static item *default_spoil(const struct race *rc, int size)
return itm; return itm;
} }
#ifndef DISABLE_TESTS int free_itype(item_type *itype) {
int free_itype_cb(const void * match, const void * key, size_t keylen, void *cbdata) {
item_type *itype;
cb_get_kv(match, &itype, sizeof(itype));
free(itype->construction); free(itype->construction);
free(itype->_appearance[0]); free(itype->_appearance[0]);
free(itype->_appearance[1]); free(itype->_appearance[1]);
@ -1182,16 +1179,23 @@ int free_rtype_cb(const void * match, const void * key, size_t keylen, void *cbd
resource_type *rtype; resource_type *rtype;
cb_get_kv(match, &rtype, sizeof(rtype)); cb_get_kv(match, &rtype, sizeof(rtype));
free(rtype->_name); free(rtype->_name);
if (rtype->itype) {
free_itype(rtype->itype);
}
free(rtype); free(rtype);
return 0; return 0;
} }
void test_clear_resources(void) void free_resources(void)
{ {
int i; int i;
memset((void *)oldpotiontype, 0, sizeof(oldpotiontype)); memset((void *)oldpotiontype, 0, sizeof(oldpotiontype));
while (luxurytypes) {
luxury_type * next = luxurytypes->next;
free(luxurytypes);
luxurytypes = next;
}
cb_foreach(&cb_resources, "", 0, free_rtype_cb, 0); cb_foreach(&cb_resources, "", 0, free_rtype_cb, 0);
cb_clear(&cb_resources); cb_clear(&cb_resources);
++num_resources; ++num_resources;
@ -1201,7 +1205,6 @@ void test_clear_resources(void)
cb_clear(rnames + i); cb_clear(rnames + i);
} }
} }
#endif
void register_resources(void) void register_resources(void)
{ {

View File

@ -313,9 +313,9 @@ extern "C" {
extern struct attrib_type at_showitem; /* show this potion's description */ extern struct attrib_type at_showitem; /* show this potion's description */
extern void register_resources(void); void register_resources(void);
extern void init_resources(void); void init_resources(void);
extern void init_itemtypes(void); void init_itemtypes(void);
extern void register_item_give(int (*foo) (struct unit *, struct unit *, extern void register_item_give(int (*foo) (struct unit *, struct unit *,
const struct item_type *, int, struct order *), const char *name); const struct item_type *, int, struct order *), const char *name);
@ -324,9 +324,7 @@ extern "C" {
extern void register_item_useonother(int (*foo) (struct unit *, int, extern void register_item_useonother(int (*foo) (struct unit *, int,
const struct item_type *, int, struct order *), const char *name); const struct item_type *, int, struct order *), const char *name);
#ifndef DISABLE_TESTS void free_resources(void);
void test_clear_resources(void);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -2,6 +2,8 @@
#include <kernel/item.h> #include <kernel/item.h>
#include <kernel/pool.h> #include <kernel/pool.h>
#include <kernel/region.h>
#include <kernel/terrain.h>
#include <kernel/unit.h> #include <kernel/unit.h>
#include <util/language.h> #include <util/language.h>
#include <util/functions.h> #include <util/functions.h>
@ -116,6 +118,31 @@ void test_findresourcetype(CuTest * tc)
CuAssertPtrNotNull(tc, findresourcetype("Bauer", lang)); CuAssertPtrNotNull(tc, findresourcetype("Bauer", lang));
} }
#include <modules/autoseed.h>
static void test_fix_demand(CuTest *tc) {
region *r;
terrain_type *tplain;
item_type *ltype;
test_cleanup();
ltype = test_create_itemtype("balm");
ltype->rtype->flags |= (RTF_ITEM | RTF_POOLED);
new_luxurytype(ltype, 0);
ltype = test_create_itemtype("oint");
ltype->rtype->flags |= (RTF_ITEM | RTF_POOLED);
new_luxurytype(ltype, 0);
tplain = test_create_terrain("plain", LAND_REGION);
r = new_region(0, 0, NULL, 0);
CuAssertPtrNotNull(tc, r);
terraform_region(r, tplain);
CuAssertPtrNotNull(tc, r->land);
CuAssertIntEquals(tc, 0, fix_demand(r));
CuAssertPtrNotNull(tc, r->land->demands);
CuAssertPtrNotNull(tc, r->land->demands->next);
CuAssertPtrNotNull(tc, r_luxury(r));
test_cleanup();
}
CuSuite *get_item_suite(void) CuSuite *get_item_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); CuSuite *suite = CuSuiteNew();
@ -125,5 +152,6 @@ CuSuite *get_item_suite(void)
SUITE_ADD_TEST(suite, test_resource_type); SUITE_ADD_TEST(suite, test_resource_type);
SUITE_ADD_TEST(suite, test_finditemtype); SUITE_ADD_TEST(suite, test_finditemtype);
SUITE_ADD_TEST(suite, test_findresourcetype); SUITE_ADD_TEST(suite, test_findresourcetype);
SUITE_ADD_TEST(suite, test_fix_demand);
return suite; return suite;
} }

View File

@ -155,7 +155,7 @@ static void json_construction(cJSON *json, construction **consp) {
return; return;
} }
if (json->type != cJSON_Object) { if (json->type != cJSON_Object) {
log_error("building %s is not a json object: %d", json->string, json->type); log_error("construction %s is not a json object: %d", json->string, json->type);
return; return;
} }
construction * cons = (construction *)calloc(sizeof(construction), 1); construction * cons = (construction *)calloc(sizeof(construction), 1);
@ -178,7 +178,7 @@ static void json_construction(cJSON *json, construction **consp) {
} }
break; break;
default: default:
log_error("building %s contains unknown attribute %s", json->string, child->string); log_error("construction %s contains unknown attribute %s", json->string, child->string);
} }
} }
*consp = cons; *consp = cons;
@ -304,7 +304,7 @@ static void json_ship(cJSON *json, ship_type *st) {
} }
break; break;
case cJSON_Array: case cJSON_Array:
st->coasts = (const terrain_type **) st->coasts = (terrain_type **)
malloc(sizeof(terrain_type *) * (1+cJSON_GetArraySize(child))); malloc(sizeof(terrain_type *) * (1+cJSON_GetArraySize(child)));
for (i=0,iter=child->child;iter;iter=iter->next) { for (i=0,iter=child->child;iter;iter=iter->next) {
if (iter->type==cJSON_String) { if (iter->type==cJSON_String) {

View File

@ -40,8 +40,7 @@ typedef struct locale_data {
const struct locale *lang; const struct locale *lang;
} locale_data; } locale_data;
static struct locale_data *locale_array[16]; static struct locale_data *locale_array[MAXLOCALES];
static int nlocales = 0;
typedef struct order_data { typedef struct order_data {
const char *_str; const char *_str;
@ -272,15 +271,10 @@ static order *create_order_i(keyword_t kwd, const char *sptr, int persistent,
} }
} }
for (lindex = 0; lindex != nlocales; ++lindex) { lindex = locale_index(lang);
if (locale_array[lindex]->lang == lang) assert(lindex < MAXLOCALES);
break; locale_array[lindex] = (locale_data *)calloc(1, sizeof(locale_data));
} locale_array[lindex]->lang = lang;
if (lindex == nlocales) {
locale_array[nlocales] = (locale_data *)calloc(1, sizeof(locale_data));
locale_array[nlocales]->lang = lang;
++nlocales;
}
ord = (order *)malloc(sizeof(order)); ord = (order *)malloc(sizeof(order));
ord->_persistent = persistent; ord->_persistent = persistent;
@ -569,10 +563,7 @@ void push_order(order ** ordp, order * ord)
keyword_t init_order(const struct order *ord) keyword_t init_order(const struct order *ord)
{ {
char *cmd = 0;
assert(ord && ord->data); assert(ord && ord->data);
if (ord->data->_str) cmd = _strdup(ord->data->_str); init_tokens_str(ord->data->_str);
init_tokens_str(cmd);
return ord->data->_keyword; return ord->data->_keyword;
} }

View File

@ -9,7 +9,6 @@
#include <tests.h> #include <tests.h>
#include <CuTest.h> #include <CuTest.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
static void test_create_order(CuTest *tc) { static void test_create_order(CuTest *tc) {
char cmd[32]; char cmd[32];
@ -127,8 +126,7 @@ static void test_init_order(CuTest *tc) {
} }
static void test_getstrtoken(CuTest *tc) { static void test_getstrtoken(CuTest *tc) {
char *cmd = _strdup("hurr \"durr\" \"\" \'\'"); init_tokens_str("hurr \"durr\" \"\" \'\'");
init_tokens_str(cmd);
CuAssertStrEquals(tc, "hurr", getstrtoken()); CuAssertStrEquals(tc, "hurr", getstrtoken());
CuAssertStrEquals(tc, "durr", getstrtoken()); CuAssertStrEquals(tc, "durr", getstrtoken());
CuAssertStrEquals(tc, "", getstrtoken()); CuAssertStrEquals(tc, "", getstrtoken());
@ -139,8 +137,7 @@ static void test_getstrtoken(CuTest *tc) {
} }
static void test_skip_token(CuTest *tc) { static void test_skip_token(CuTest *tc) {
char *cmd = _strdup("hurr \"durr\""); init_tokens_str("hurr \"durr\"");
init_tokens_str(cmd);
skip_token(); skip_token();
CuAssertStrEquals(tc, "durr", getstrtoken()); CuAssertStrEquals(tc, "durr", getstrtoken());
CuAssertStrEquals(tc, 0, getstrtoken()); CuAssertStrEquals(tc, 0, getstrtoken());

View File

@ -141,6 +141,8 @@ void racelist_insert(struct race_list **rl, const struct race *r)
void free_races(void) { void free_races(void) {
while (races) { while (races) {
race * rc = races->next; race * rc = races->next;
free(races->_name);
free(races->def_damage);
free(races); free(races);
races = rc; races = rc;
} }

View File

@ -119,7 +119,7 @@ extern "C" {
typedef struct race { typedef struct race {
struct param *parameters; struct param *parameters;
const char *_name; char *_name;
float magres; float magres;
float maxaura; /* Faktor auf Maximale Aura */ float maxaura; /* Faktor auf Maximale Aura */
float regaura; /* Faktor auf Regeneration */ float regaura; /* Faktor auf Regeneration */
@ -133,7 +133,7 @@ extern "C" {
float speed; float speed;
float aggression; /* chance that a monster will attack */ float aggression; /* chance that a monster will attack */
int hitpoints; int hitpoints;
const char *def_damage; char *def_damage;
int armor; int armor;
int at_default; /* Angriffsskill Unbewaffnet (default: -2) */ int at_default; /* Angriffsskill Unbewaffnet (default: -2) */
int df_default; /* Verteidigungsskill Unbewaffnet (default: -2) */ int df_default; /* Verteidigungsskill Unbewaffnet (default: -2) */

View File

@ -69,11 +69,9 @@ region *regions;
int get_maxluxuries(void) int get_maxluxuries(void)
{ {
static int maxluxuries = -1;
if (maxluxuries == -1) {
const luxury_type *ltype; const luxury_type *ltype;
maxluxuries = 0; int maxluxuries = 0;
for (ltype = luxurytypes; ltype; ltype = ltype->next) for (ltype = luxurytypes; ltype; ltype = ltype->next) {
++maxluxuries; ++maxluxuries;
} }
return maxluxuries; return maxluxuries;

View File

@ -238,8 +238,15 @@ void free_ship(ship * s)
free(s); free(s);
} }
static void free_shiptype(void *ptr) {
ship_type *stype = (ship_type *)ptr;
free(stype->_name);
free(stype->coasts);
free(stype);
}
void free_shiptypes(void) { void free_shiptypes(void) {
ql_foreach(shiptypes, free); ql_foreach(shiptypes, free_shiptype);
ql_free(shiptypes); ql_free(shiptypes);
shiptypes = 0; shiptypes = 0;
} }

View File

@ -33,7 +33,7 @@ extern "C" {
#define SFL_NOCOAST 0x04 #define SFL_NOCOAST 0x04
typedef struct ship_type { typedef struct ship_type {
const char *_name; char *_name;
int range; /* range in regions */ int range; /* range in regions */
int flags; /* flags */ int flags; /* flags */
@ -55,7 +55,7 @@ extern "C" {
int df_bonus; /* Verändert den Verteidigungskill (default: 0) */ int df_bonus; /* Verändert den Verteidigungskill (default: 0) */
float tac_bonus; float tac_bonus;
const struct terrain_type **coasts; /* coast that this ship can land on */ struct terrain_type ** coasts; /* coast that this ship can land on */
struct construction *construction; /* how to build a ship */ struct construction *construction; /* how to build a ship */
} ship_type; } ship_type;

View File

@ -45,6 +45,7 @@ void spellbook_clear(spellbook *sb)
free(sbe); free(sbe);
} }
ql_free(sb->spells); ql_free(sb->spells);
free(sb->name);
} }
int spellbook_foreach(spellbook *sb, int (*callback)(spellbook_entry *, void *), void * data) int spellbook_foreach(spellbook *sb, int (*callback)(spellbook_entry *, void *), void * data)

View File

@ -27,6 +27,8 @@ void test_named_spellbooks(CuTest * tc)
sb = create_spellbook(0); sb = create_spellbook(0);
CuAssertPtrNotNull(tc, sb); CuAssertPtrNotNull(tc, sb);
CuAssertPtrEquals(tc, 0, sb->name); CuAssertPtrEquals(tc, 0, sb->name);
spellbook_clear(sb);
free(sb);
sb = create_spellbook("spells"); sb = create_spellbook("spells");
CuAssertPtrNotNull(tc, sb); CuAssertPtrNotNull(tc, sb);

View File

@ -63,8 +63,7 @@ const char *terraindata[MAXTERRAINS] = {
static terrain_type *registered_terrains; static terrain_type *registered_terrains;
#ifndef DISABLE_TESTS void free_terrains(void)
void test_clear_terrains(void)
{ {
while (registered_terrains) { while (registered_terrains) {
terrain_type * t = registered_terrains; terrain_type * t = registered_terrains;
@ -74,7 +73,6 @@ void test_clear_terrains(void)
free(t); free(t);
} }
} }
#endif
const terrain_type *terrains(void) const terrain_type *terrains(void)
{ {

View File

@ -75,10 +75,7 @@ extern "C" {
extern const char *terrain_name(const struct region *r); extern const char *terrain_name(const struct region *r);
extern void init_terrains(void); extern void init_terrains(void);
void free_terrains(void);
#ifndef DISABLE_TESTS
void test_clear_terrains(void);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -289,17 +289,23 @@ static int parse_buildings(xmlDocPtr doc)
btype->name = btype->name =
(const char *(*)(const struct building_type *, (const char *(*)(const struct building_type *,
const struct building *, int))fun; const struct building *, int))fun;
} else if (strcmp((const char *)propValue, "init") == 0) { }
else if (strcmp((const char *)propValue, "init") == 0) {
btype->init = (void(*)(struct building_type *))fun; btype->init = (void(*)(struct building_type *))fun;
} else if (strcmp((const char *)propValue, "age") == 0) { }
else if (strcmp((const char *)propValue, "age") == 0) {
btype->age = (void(*)(struct building *))fun; btype->age = (void(*)(struct building *))fun;
} else if (strcmp((const char *)propValue, "protection") == 0) { }
else if (strcmp((const char *)propValue, "protection") == 0) {
btype->protection = (int(*)(struct building *, struct unit *))fun; btype->protection = (int(*)(struct building *, struct unit *))fun;
} else if (strcmp((const char *)propValue, "taxes") == 0) { }
else if (strcmp((const char *)propValue, "taxes") == 0) {
btype->taxes = (double(*)(const struct building *, int))fun; btype->taxes = (double(*)(const struct building *, int))fun;
} else if (strcmp((const char *)propValue, "age") == 0) { }
else if (strcmp((const char *)propValue, "age") == 0) {
btype->age = (void(*)(struct building *))fun; btype->age = (void(*)(struct building *))fun;
} else { }
else {
log_error("unknown function type '%s' for building %s\n", (const char *)propValue, btype->_name); log_error("unknown function type '%s' for building %s\n", (const char *)propValue, btype->_name);
} }
xmlFree(propValue); xmlFree(propValue);
@ -357,7 +363,8 @@ static int parse_calendar(xmlDocPtr doc)
months_per_year = 0; months_per_year = 0;
if (nsetCalendars == NULL || nsetCalendars->nodeNr == 0) { if (nsetCalendars == NULL || nsetCalendars->nodeNr == 0) {
rv = -1; rv = -1;
} else }
else
for (c = 0; c != nsetCalendars->nodeNr; ++c) { for (c = 0; c != nsetCalendars->nodeNr; ++c) {
xmlNodePtr calendar = nsetCalendars->nodeTab[c]; xmlNodePtr calendar = nsetCalendars->nodeTab[c];
xmlXPathObjectPtr xpathWeeks, xpathMonths, xpathSeasons; xmlXPathObjectPtr xpathWeeks, xpathMonths, xpathSeasons;
@ -528,14 +535,14 @@ static int parse_ships(xmlDocPtr doc)
if (k == 0) { if (k == 0) {
assert(st->coasts == NULL); assert(st->coasts == NULL);
st->coasts = st->coasts =
(const terrain_type **)malloc(sizeof(const terrain_type *) * (terrain_type **)malloc(sizeof(terrain_type *) *
(result->nodesetval->nodeNr + 1)); (result->nodesetval->nodeNr + 1));
st->coasts[result->nodesetval->nodeNr] = NULL; st->coasts[result->nodesetval->nodeNr] = NULL;
} }
propValue = xmlGetProp(node, BAD_CAST "terrain"); propValue = xmlGetProp(node, BAD_CAST "terrain");
assert(propValue != NULL); assert(propValue != NULL);
st->coasts[c] = get_terrain((const char *)propValue); st->coasts[c] = get_or_create_terrain((const char *)propValue);
if (st->coasts[c] != NULL) if (st->coasts[c] != NULL)
++c; ++c;
else { else {
@ -723,7 +730,8 @@ static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype)
wtype->attack = wtype->attack =
(bool(*)(const struct troop *, const struct weapon_type *, (bool(*)(const struct troop *, const struct weapon_type *,
int *))fun; int *))fun;
} else { }
else {
log_error("unknown function type '%s' for item '%s'\n", (const char *)propValue, itype->rtype->_name); log_error("unknown function type '%s' for item '%s'\n", (const char *)propValue, itype->rtype->_name);
} }
xmlFree(propValue); xmlFree(propValue);
@ -827,18 +835,22 @@ static item_type *xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype)
itype->give = itype->give =
(int(*)(struct unit *, struct unit *, const struct item_type *, int, (int(*)(struct unit *, struct unit *, const struct item_type *, int,
struct order *))fun; struct order *))fun;
} else if (strcmp((const char *)propValue, "use") == 0) { }
else if (strcmp((const char *)propValue, "use") == 0) {
itype->use = itype->use =
(int(*)(struct unit *, const struct item_type *, int, (int(*)(struct unit *, const struct item_type *, int,
struct order *))fun; struct order *))fun;
} else if (strcmp((const char *)propValue, "canuse") == 0) { }
else if (strcmp((const char *)propValue, "canuse") == 0) {
itype->canuse = itype->canuse =
(bool(*)(const struct unit *, const struct item_type *))fun; (bool(*)(const struct unit *, const struct item_type *))fun;
} else if (strcmp((const char *)propValue, "useonother") == 0) { }
else if (strcmp((const char *)propValue, "useonother") == 0) {
itype->useonother = itype->useonother =
(int(*)(struct unit *, int, const struct item_type *, int, (int(*)(struct unit *, int, const struct item_type *, int,
struct order *))fun; struct order *))fun;
} else { }
else {
log_error("unknown function type '%s' for item '%s'\n", (const char *)propValue, rtype->_name); log_error("unknown function type '%s' for item '%s'\n", (const char *)propValue, rtype->_name);
} }
xmlFree(propValue); xmlFree(propValue);
@ -875,9 +887,11 @@ static int parse_rules(xmlDocPtr doc)
global.functions.wage = global.functions.wage =
(int(*)(const struct region *, const struct faction *, (int(*)(const struct region *, const struct faction *,
const struct race *, int))fun; const struct race *, int))fun;
} else if (strcmp((const char *)propValue, "maintenance") == 0) { }
else if (strcmp((const char *)propValue, "maintenance") == 0) {
global.functions.maintenance = (int(*)(const struct unit *))fun; global.functions.maintenance = (int(*)(const struct unit *))fun;
} else { }
else {
log_error("unknown function for rule '%s'\n", (const char *)propValue); log_error("unknown function for rule '%s'\n", (const char *)propValue);
} }
xmlFree(propValue); xmlFree(propValue);
@ -943,11 +957,14 @@ static int parse_resources(xmlDocPtr doc)
assert(propValue != NULL); assert(propValue != NULL);
if (strcmp((const char *)propValue, "change") == 0) { if (strcmp((const char *)propValue, "change") == 0) {
rtype->uchange = (rtype_uchange)fun; rtype->uchange = (rtype_uchange)fun;
} else if (strcmp((const char *)propValue, "get") == 0) { }
else if (strcmp((const char *)propValue, "get") == 0) {
rtype->uget = (rtype_uget)fun; rtype->uget = (rtype_uget)fun;
} else if (strcmp((const char *)propValue, "name") == 0) { }
else if (strcmp((const char *)propValue, "name") == 0) {
rtype->name = (rtype_name)fun; rtype->name = (rtype_name)fun;
} else { }
else {
log_error("unknown function type '%s' for resource %s\n", (const char *)propValue, rtype->_name); log_error("unknown function type '%s' for resource %s\n", (const char *)propValue, rtype->_name);
} }
xmlFree(propValue); xmlFree(propValue);
@ -1000,13 +1017,16 @@ static int parse_resources(xmlDocPtr doc)
if (strcmp((const char *)propValue, "skill") == 0) { if (strcmp((const char *)propValue, "skill") == 0) {
rdata->modifiers[k].value.i = xml_ivalue(node, "value", 0); rdata->modifiers[k].value.i = xml_ivalue(node, "value", 0);
rdata->modifiers[k].flags = RMF_SKILL; rdata->modifiers[k].flags = RMF_SKILL;
} else if (strcmp((const char *)propValue, "material") == 0) { }
else if (strcmp((const char *)propValue, "material") == 0) {
rdata->modifiers[k].value.f = (float)xml_fvalue(node, "value", 0); rdata->modifiers[k].value.f = (float)xml_fvalue(node, "value", 0);
rdata->modifiers[k].flags = RMF_SAVEMATERIAL; rdata->modifiers[k].flags = RMF_SAVEMATERIAL;
} else if (strcmp((const char *)propValue, "resource") == 0) { }
else if (strcmp((const char *)propValue, "resource") == 0) {
rdata->modifiers[k].value.f = (float)xml_fvalue(node, "value", 0); rdata->modifiers[k].value.f = (float)xml_fvalue(node, "value", 0);
rdata->modifiers[k].flags = RMF_SAVERESOURCE; rdata->modifiers[k].flags = RMF_SAVERESOURCE;
} else if (strcmp((const char *)propValue, "require") == 0) { }
else if (strcmp((const char *)propValue, "require") == 0) {
xmlChar *propBldg = xmlGetProp(node, BAD_CAST "building"); xmlChar *propBldg = xmlGetProp(node, BAD_CAST "building");
if (propBldg != NULL) { if (propBldg != NULL) {
btype = bt_get_or_create((const char *)propBldg); btype = bt_get_or_create((const char *)propBldg);
@ -1014,7 +1034,8 @@ static int parse_resources(xmlDocPtr doc)
rdata->modifiers[k].flags = RMF_REQUIREDBUILDING; rdata->modifiers[k].flags = RMF_REQUIREDBUILDING;
xmlFree(propBldg); xmlFree(propBldg);
} }
} else { }
else {
log_error("unknown type '%s' for resourcelimit-modifier '%s'\n", (const char *)propValue, rtype->_name); log_error("unknown type '%s' for resourcelimit-modifier '%s'\n", (const char *)propValue, rtype->_name);
} }
xmlFree(propValue); xmlFree(propValue);
@ -1031,7 +1052,8 @@ static int parse_resources(xmlDocPtr doc)
if (propFlag != NULL) { if (propFlag != NULL) {
if (strcmp((const char *)propFlag, "logging") == 0) { if (strcmp((const char *)propFlag, "logging") == 0) {
rdata->guard |= GUARD_TREES; rdata->guard |= GUARD_TREES;
} else if (strcmp((const char *)propFlag, "mining") == 0) { }
else if (strcmp((const char *)propFlag, "mining") == 0) {
rdata->guard |= GUARD_MINING; rdata->guard |= GUARD_MINING;
} }
xmlFree(propFlag); xmlFree(propFlag);
@ -1060,9 +1082,11 @@ static int parse_resources(xmlDocPtr doc)
assert(propValue != NULL); assert(propValue != NULL);
if (strcmp((const char *)propValue, "produce") == 0) { if (strcmp((const char *)propValue, "produce") == 0) {
rdata->produce = (rlimit_produce)fun; rdata->produce = (rlimit_produce)fun;
} else if (strcmp((const char *)propValue, "limit") == 0) { }
else if (strcmp((const char *)propValue, "limit") == 0) {
rdata->limit = (rlimit_limit)fun; rdata->limit = (rlimit_limit)fun;
} else { }
else {
log_error("unknown limit '%s' for resource %s\n", (const char *)propValue, rtype->_name); log_error("unknown limit '%s' for resource %s\n", (const char *)propValue, rtype->_name);
} }
xmlFree(propValue); xmlFree(propValue);
@ -1162,11 +1186,13 @@ static void add_spells(equipment * eq, xmlNodeSetPtr nsetItems)
sp = find_spell((const char *)propValue); sp = find_spell((const char *)propValue);
if (!sp) { if (!sp) {
log_error("no spell '%s' for equipment-set '%s'\n", (const char *)propValue, eq->name); log_error("no spell '%s' for equipment-set '%s'\n", (const char *)propValue, eq->name);
} else { }
else {
int level = xml_ivalue(node, "level", 0); int level = xml_ivalue(node, "level", 0);
if (level > 0) { if (level > 0) {
equipment_addspell(eq, sp, level); equipment_addspell(eq, sp, level);
} else { }
else {
log_error("spell '%s' for equipment-set '%s' has no level\n", sp->sname, eq->name); log_error("spell '%s' for equipment-set '%s' has no level\n", sp->sname, eq->name);
} }
} }
@ -1190,7 +1216,8 @@ static void add_skills(equipment * eq, xmlNodeSetPtr nsetSkills)
if (sk == NOSKILL) { if (sk == NOSKILL) {
log_error("unknown skill '%s' in equipment-set %s\n", (const char *)propValue, eq->name); log_error("unknown skill '%s' in equipment-set %s\n", (const char *)propValue, eq->name);
xmlFree(propValue); xmlFree(propValue);
} else { }
else {
xmlFree(propValue); xmlFree(propValue);
propValue = xmlGetProp(node, BAD_CAST "level"); propValue = xmlGetProp(node, BAD_CAST "level");
if (propValue != NULL) { if (propValue != NULL) {
@ -1338,7 +1365,8 @@ static int parse_spellbooks(xmlDocPtr doc)
if (propValue) { if (propValue) {
sb = get_spellbook((const char *)propValue); sb = get_spellbook((const char *)propValue);
xmlFree(propValue); xmlFree(propValue);
} else { }
else {
log_error("spellbook at index '%d' has n name\n", i); log_error("spellbook at index '%d' has n name\n", i);
continue; continue;
} }
@ -1359,7 +1387,8 @@ static int parse_spellbooks(xmlDocPtr doc)
} }
if (sp && level > 0) { if (sp && level > 0) {
spellbook_add(sb, sp, level); spellbook_add(sb, sp, level);
} else { }
else {
log_error("invalid entry at index '%d' in spellbook '%s'\n", k, sb->name); log_error("invalid entry at index '%d' in spellbook '%s'\n", k, sb->name);
} }
} }
@ -1459,7 +1488,8 @@ static int parse_spells(xmlDocPtr doc)
} }
strlcpy(zText + 7, sp->sname, sizeof(zText) - 7); strlcpy(zText + 7, sp->sname, sizeof(zText) - 7);
fumble = get_function(zText); fumble = get_function(zText);
} else { }
else {
for (k = 0; k != result->nodesetval->nodeNr; ++k) { for (k = 0; k != result->nodesetval->nodeNr; ++k) {
xmlNodePtr node = result->nodesetval->nodeTab[k]; xmlNodePtr node = result->nodesetval->nodeTab[k];
pf_generic fun; pf_generic fun;
@ -1469,12 +1499,15 @@ static int parse_spells(xmlDocPtr doc)
if (strcmp((const char *)propValue, "cast") == 0) { if (strcmp((const char *)propValue, "cast") == 0) {
if (fun) { if (fun) {
cast = fun; cast = fun;
} else { }
else {
log_error("unknown function name '%s' for spell '%s'\n", (const char *)propValue, sp->sname); log_error("unknown function name '%s' for spell '%s'\n", (const char *)propValue, sp->sname);
} }
} else if (fun && strcmp((const char *)propValue, "fumble") == 0) { }
else if (fun && strcmp((const char *)propValue, "fumble") == 0) {
fumble = fun; fumble = fun;
} else { }
else {
log_error("unknown function type '%s' for spell '%s'\n", (const char *)propValue, sp->sname); log_error("unknown function type '%s' for spell '%s'\n", (const char *)propValue, sp->sname);
} }
xmlFree(propValue); xmlFree(propValue);
@ -1516,7 +1549,8 @@ static int parse_spells(xmlDocPtr doc)
log_error("spell '%s' has linear cost but fixed level\n", sp->sname); log_error("spell '%s' has linear cost but fixed level\n", sp->sname);
} }
component->cost = SPC_LINEAR; component->cost = SPC_LINEAR;
} else if (strcmp((const char *)propValue, "level") == 0) { }
else if (strcmp((const char *)propValue, "level") == 0) {
if ((sp->sptyp&SPELLLEVEL) == 0) { if ((sp->sptyp&SPELLLEVEL) == 0) {
log_error("spell '%s' has levelled cost but fixed level\n", sp->sname); log_error("spell '%s' has levelled cost but fixed level\n", sp->sname);
} }
@ -1692,7 +1726,8 @@ static int parse_races(xmlDocPtr doc)
for (child = node->children; child; child = child->next) { for (child = node->children; child; child = child->next) {
if (strcmp((const char *)child->name, "ai") == 0) { if (strcmp((const char *)child->name, "ai") == 0) {
parse_ai(rc, child); parse_ai(rc, child);
} else if (strcmp((const char *)child->name, "param") == 0) { }
else if (strcmp((const char *)child->name, "param") == 0) {
parse_param(&rc->parameters, child); parse_param(&rc->parameters, child);
} }
} }
@ -1718,7 +1753,8 @@ static int parse_races(xmlDocPtr doc)
rc->study_speed = calloc(1, MAXSKILLS); rc->study_speed = calloc(1, MAXSKILLS);
rc->study_speed[sk] = (char)speed; rc->study_speed[sk] = (char)speed;
} }
} else { }
else {
log_error("unknown skill '%s' in race '%s'\n", (const char *)propValue, rc->_name); log_error("unknown skill '%s' in race '%s'\n", (const char *)propValue, rc->_name);
} }
xmlFree(propValue); xmlFree(propValue);
@ -1741,19 +1777,25 @@ static int parse_races(xmlDocPtr doc)
assert(propValue != NULL); assert(propValue != NULL);
if (strcmp((const char *)propValue, "name") == 0) { if (strcmp((const char *)propValue, "name") == 0) {
rc->generate_name = (const char *(*)(const struct unit *))fun; rc->generate_name = (const char *(*)(const struct unit *))fun;
} else if (strcmp((const char *)propValue, "describe") == 0) { }
else if (strcmp((const char *)propValue, "describe") == 0) {
rc->describe = rc->describe =
(const char *(*)(const struct unit *, const struct locale *))fun; (const char *(*)(const struct unit *, const struct locale *))fun;
} else if (strcmp((const char *)propValue, "age") == 0) { }
else if (strcmp((const char *)propValue, "age") == 0) {
rc->age = (void(*)(struct unit *))fun; rc->age = (void(*)(struct unit *))fun;
} else if (strcmp((const char *)propValue, "move") == 0) { }
else if (strcmp((const char *)propValue, "move") == 0) {
rc->move_allowed = rc->move_allowed =
(bool(*)(const struct region *, const struct region *))fun; (bool(*)(const struct region *, const struct region *))fun;
} else if (strcmp((const char *)propValue, "itemdrop") == 0) { }
else if (strcmp((const char *)propValue, "itemdrop") == 0) {
rc->itemdrop = (struct item * (*)(const struct race *, int))fun; rc->itemdrop = (struct item * (*)(const struct race *, int))fun;
} else if (strcmp((const char *)propValue, "initfamiliar") == 0) { }
else if (strcmp((const char *)propValue, "initfamiliar") == 0) {
rc->init_familiar = (void(*)(struct unit *))fun; rc->init_familiar = (void(*)(struct unit *))fun;
} else { }
else {
log_error("unknown function type '%s' for race %s\n", (const char *)propValue, rc->_name); log_error("unknown function type '%s' for race %s\n", (const char *)propValue, rc->_name);
} }
xmlFree(propValue); xmlFree(propValue);
@ -1773,7 +1815,8 @@ static int parse_races(xmlDocPtr doc)
if (xml_bvalue(node, "default", false)) { if (xml_bvalue(node, "default", false)) {
rc->familiars[k] = rc->familiars[0]; rc->familiars[k] = rc->familiars[0];
rc->familiars[0] = frc; rc->familiars[0] = frc;
} else { }
else {
rc->familiars[k] = frc; rc->familiars[k] = frc;
} }
xmlFree(propValue); xmlFree(propValue);
@ -1804,7 +1847,8 @@ static int parse_races(xmlDocPtr doc)
if (propValue != NULL) { if (propValue != NULL) {
attack->data.dice = _strdup((const char *)propValue); attack->data.dice = _strdup((const char *)propValue);
xmlFree(propValue); xmlFree(propValue);
} else { }
else {
attack->data.sp = xml_spell(node, "spell"); attack->data.sp = xml_spell(node, "spell");
if (attack->data.sp) { if (attack->data.sp) {
attack->level = xml_ivalue(node, "level", 0); attack->level = xml_ivalue(node, "level", 0);
@ -2000,7 +2044,8 @@ static int parse_messages(xmlDocPtr doc)
mtype = mt_find((const char *)propValue); mtype = mt_find((const char *)propValue);
if (mtype == NULL) { if (mtype == NULL) {
mtype = mt_register(mt_new((const char *)propValue, (const char **)argv)); mtype = mt_register(mt_new((const char *)propValue, (const char **)argv));
} else { }
else {
assert(argv != NULL || !"cannot redefine arguments of message now"); assert(argv != NULL || !"cannot redefine arguments of message now");
} }
xmlFree(propValue); xmlFree(propValue);
@ -2087,7 +2132,8 @@ xml_readstrings(xmlXPathContextPtr xpath, xmlNodePtr * nodeTab, int nodeNr,
locale_setstring(lang, zName, (const char *)propText); locale_setstring(lang, zName, (const char *)propText);
} }
xmlFree(propText); xmlFree(propText);
} else { }
else {
log_warning("string %s has no text in locale %s\n", zName, locale_name(lang)); log_warning("string %s has no text in locale %s\n", zName, locale_name(lang));
} }
} }

View File

@ -2979,7 +2979,16 @@ spellbook * get_spellbook(const char * name)
return result; return result;
} }
int free_spellbook_cb(const void *match, const void *key, size_t keylen, void *data) {
spellbook *sb;
cb_get_kv(match, &sb, sizeof(sb));
spellbook_clear(sb);
free(sb);
return 0;
}
void free_spellbooks(void) void free_spellbooks(void)
{ {
cb_foreach(&cb_spellbooks, "", 0, free_spellbook_cb, NULL);
cb_clear(&cb_spellbooks); cb_clear(&cb_spellbooks);
} }

View File

@ -39,6 +39,7 @@ void test_updatespells(CuTest * tc)
CuAssertPtrNotNull(tc, f->spellbook); CuAssertPtrNotNull(tc, f->spellbook);
CuAssertIntEquals(tc, 1, ql_length(f->spellbook->spells)); CuAssertIntEquals(tc, 1, ql_length(f->spellbook->spells));
CuAssertPtrNotNull(tc, spellbook_get(f->spellbook, sp)); CuAssertPtrNotNull(tc, spellbook_get(f->spellbook, sp));
test_cleanup();
} }
void test_spellbooks(CuTest * tc) void test_spellbooks(CuTest * tc)
@ -63,12 +64,11 @@ void test_spellbooks(CuTest * tc)
entry = spellbook_get(herp, sp); entry = spellbook_get(herp, sp);
CuAssertPtrNotNull(tc, entry); CuAssertPtrNotNull(tc, entry);
CuAssertPtrEquals(tc, sp, entry->sp); CuAssertPtrEquals(tc, sp, entry->sp);
/* CuAssertPtrEquals(tc, 0, spellbook_get(derp, sname)); */
test_cleanup(); test_cleanup();
herp = get_spellbook("herp"); herp = get_spellbook("herp");
CuAssertPtrNotNull(tc, herp); CuAssertPtrNotNull(tc, herp);
/* CuAssertPtrEquals(tc, 0, spellbook_get(herp, sname)); */ test_cleanup();
} }
static spell * test_magic_create_spell(void) static spell * test_magic_create_spell(void)
@ -120,6 +120,7 @@ void test_pay_spell(CuTest * tc)
CuAssertIntEquals(tc, 0, get_resource(u, get_resourcetype(R_SILVER))); CuAssertIntEquals(tc, 0, get_resource(u, get_resourcetype(R_SILVER)));
CuAssertIntEquals(tc, 0, get_resource(u, get_resourcetype(R_AURA))); CuAssertIntEquals(tc, 0, get_resource(u, get_resourcetype(R_AURA)));
CuAssertIntEquals(tc, 0, get_resource(u, get_resourcetype(R_HORSE))); CuAssertIntEquals(tc, 0, get_resource(u, get_resourcetype(R_HORSE)));
test_cleanup();
} }
void test_pay_spell_failure(CuTest * tc) void test_pay_spell_failure(CuTest * tc)
@ -157,6 +158,7 @@ void test_pay_spell_failure(CuTest * tc)
CuAssertIntEquals(tc, 0, eff_spelllevel(u, sp, 3, 1)); CuAssertIntEquals(tc, 0, eff_spelllevel(u, sp, 3, 1));
CuAssertIntEquals(tc, 0, change_resource(u, get_resourcetype(R_SILVER), -1)); CuAssertIntEquals(tc, 0, change_resource(u, get_resourcetype(R_SILVER), -1));
CuAssertIntEquals(tc, 0, eff_spelllevel(u, sp, 2, 1)); CuAssertIntEquals(tc, 0, eff_spelllevel(u, sp, 2, 1));
test_cleanup();
} }
void test_getspell_unit(CuTest * tc) void test_getspell_unit(CuTest * tc)
@ -185,6 +187,7 @@ void test_getspell_unit(CuTest * tc)
unit_add_spell(u, 0, sp, 1); unit_add_spell(u, 0, sp, 1);
CuAssertPtrNotNull(tc, unit_getspell(u, "Herp-a-derp", lang)); CuAssertPtrNotNull(tc, unit_getspell(u, "Herp-a-derp", lang));
test_cleanup();
} }
void test_getspell_faction(CuTest * tc) void test_getspell_faction(CuTest * tc)
@ -215,6 +218,7 @@ void test_getspell_faction(CuTest * tc)
f->spellbook = create_spellbook(0); f->spellbook = create_spellbook(0);
spellbook_add(f->spellbook, sp, 1); spellbook_add(f->spellbook, sp, 1);
CuAssertPtrEquals(tc, sp, unit_getspell(u, "Herp-a-derp", lang)); CuAssertPtrEquals(tc, sp, unit_getspell(u, "Herp-a-derp", lang));
test_cleanup();
} }
void test_getspell_school(CuTest * tc) void test_getspell_school(CuTest * tc)
@ -246,6 +250,7 @@ void test_getspell_school(CuTest * tc)
CuAssertPtrNotNull(tc, book); CuAssertPtrNotNull(tc, book);
spellbook_add(book, sp, 1); spellbook_add(book, sp, 1);
CuAssertPtrEquals(tc, sp, unit_getspell(u, "Herp-a-derp", lang)); CuAssertPtrEquals(tc, sp, unit_getspell(u, "Herp-a-derp", lang));
test_cleanup();
} }
void test_set_pre_combatspell(CuTest * tc) void test_set_pre_combatspell(CuTest * tc)
@ -278,6 +283,7 @@ void test_set_pre_combatspell(CuTest * tc)
unset_combatspell(u, sp); unset_combatspell(u, sp);
CuAssertIntEquals(tc, 0, get_combatspelllevel(u, index)); CuAssertIntEquals(tc, 0, get_combatspelllevel(u, index));
CuAssertPtrEquals(tc, 0, (spell *)get_combatspell(u, index)); CuAssertPtrEquals(tc, 0, (spell *)get_combatspell(u, index));
test_cleanup();
} }
void test_set_main_combatspell(CuTest * tc) void test_set_main_combatspell(CuTest * tc)
@ -310,6 +316,7 @@ void test_set_main_combatspell(CuTest * tc)
unset_combatspell(u, sp); unset_combatspell(u, sp);
CuAssertIntEquals(tc, 0, get_combatspelllevel(u, index)); CuAssertIntEquals(tc, 0, get_combatspelllevel(u, index));
CuAssertPtrEquals(tc, 0, (spell *)get_combatspell(u, index)); CuAssertPtrEquals(tc, 0, (spell *)get_combatspell(u, index));
test_cleanup();
} }
void test_set_post_combatspell(CuTest * tc) void test_set_post_combatspell(CuTest * tc)
@ -342,6 +349,7 @@ void test_set_post_combatspell(CuTest * tc)
unset_combatspell(u, sp); unset_combatspell(u, sp);
CuAssertIntEquals(tc, 0, get_combatspelllevel(u, index)); CuAssertIntEquals(tc, 0, get_combatspelllevel(u, index));
CuAssertPtrEquals(tc, 0, (spell *)get_combatspell(u, index)); CuAssertPtrEquals(tc, 0, (spell *)get_combatspell(u, index));
test_cleanup();
} }
void test_hasspell(CuTest * tc) void test_hasspell(CuTest * tc)
@ -371,6 +379,7 @@ void test_hasspell(CuTest * tc)
set_level(u, SK_MAGIC, 1); set_level(u, SK_MAGIC, 1);
CuAssertTrue(tc, !u_hasspell(u, sp)); CuAssertTrue(tc, !u_hasspell(u, sp));
test_cleanup();
} }
CuSuite *get_magic_suite(void) CuSuite *get_magic_suite(void)

View File

@ -17,6 +17,7 @@
#include <tests.h> #include <tests.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
static void test_market_curse(CuTest * tc) static void test_market_curse(CuTest * tc)
{ {
@ -45,7 +46,7 @@ static void test_market_curse(CuTest * tc)
set_param(&global.parameters, "rules.region_owners", "1"); set_param(&global.parameters, "rules.region_owners", "1");
btype = (building_type *)calloc(1, sizeof(building_type)); btype = (building_type *)calloc(1, sizeof(building_type));
btype->_name = "market"; btype->_name = _strdup("market");
bt_register(btype); bt_register(btype);
terrain = get_terrain("plain"); terrain = get_terrain("plain");

View File

@ -127,90 +127,32 @@ bool(*fun) (const region * r))
static bool f_nolux(const region * r) static bool f_nolux(const region * r)
{ {
if (r->land && count_demand(r) != get_maxluxuries()) return (r->land && count_demand(r) != get_maxluxuries());
return true;
return false;
} }
int fix_demand(region * rd) int fix_demand(region * rd) {
{ luxury_type * ltype;
region_list *rl, *rlist = NULL; int maxluxuries = get_maxluxuries();
static const luxury_type *mlux[MAXLUXURIES]; if (maxluxuries > 0) {
const luxury_type *ltypes[MAXLUXURIES]; int sale = rng_int() % maxluxuries;
const luxury_type *sale = NULL; for (ltype = luxurytypes; sale != 0 && ltype; ltype = ltype->next) {
int maxlux = 0; --sale;
static int maxluxuries = -1;
// TODO: this entire function is impossible to understand
recurse_regions(rd, &rlist, f_nolux);
if (maxluxuries < 0) {
int i = 0;
for (sale = luxurytypes; sale; sale = sale->next) {
ltypes[i++] = sale;
} }
maxluxuries = i; setluxuries(rd, ltype);
return 0;
} }
if (maxluxuries == 0) {
return -1; return -1;
} }
else {
int i; int fix_all_demand(region *rd) {
for (i = 0; i != maxluxuries; ++i) { region_list *rl, *rlist = NULL;
mlux[i] = 0; recurse_regions(rd, &rlist, f_nolux);
}
}
for (rl = rlist; rl; rl = rl->next) { for (rl = rlist; rl; rl = rl->next) {
region *r = rl->data; region *r = rl->data;
direction_t d;
for (d = 0; d != MAXDIRECTIONS; ++d) {
region *nr = rconnect(r, d);
if (nr && nr->land && nr->land->demands) {
struct demand *dmd;
for (dmd = nr->land->demands; dmd; dmd = dmd->next) {
if (dmd->value == 0) {
int i;
for (i = 0; i != maxluxuries; ++i) {
if (mlux[i] == NULL) {
maxlux = i;
mlux[i] = dmd->type;
break;
}
else if (mlux[i] == dmd->type) {
break;
}
}
break;
}
}
}
}
freset(r, RF_MARK); /* undo recursive marker */ freset(r, RF_MARK); /* undo recursive marker */
if (!fix_demand(r)) {
return -1;
} }
if (maxlux < 2) {
int i;
for (i = maxlux; i != 2; ++i) {
int j;
do {
int k = rng_int() % maxluxuries;
mlux[i] = ltypes[k];
for (j = 0; j != i; ++j) {
if (mlux[j] == mlux[i])
break;
}
} while (j != i);
}
maxlux = 2;
}
for (rl = rlist; rl; rl = rl->next) {
region *r = rl->data;
sale = mlux[rng_int() % maxlux];
if (sale)
setluxuries(r, sale);
}
while (rlist) {
rl = rlist->next;
free(rlist);
rlist = rl;
} }
return 0; return 0;
} }

View File

@ -28,7 +28,7 @@ static void test_ship_not_allowed_in_coast(CuTest * tc)
ttype = test_create_terrain("glacier", LAND_REGION | ARCTIC_REGION | WALK_INTO | SAIL_INTO); ttype = test_create_terrain("glacier", LAND_REGION | ARCTIC_REGION | WALK_INTO | SAIL_INTO);
otype = test_create_terrain("ocean", SEA_REGION | SAIL_INTO); otype = test_create_terrain("ocean", SEA_REGION | SAIL_INTO);
stype = test_create_shiptype("derp"); stype = test_create_shiptype("derp");
stype->coasts = (const struct terrain_type **)calloc(2, sizeof(const struct terrain_type *)); stype->coasts = (struct terrain_type **)calloc(2, sizeof(struct terrain_type *));
r1 = test_create_region(0, 0, ttype); r1 = test_create_region(0, 0, ttype);
r2 = test_create_region(1, 0, otype); r2 = test_create_region(1, 0, otype);

View File

@ -210,12 +210,13 @@ void set_factionstealth(unit * u, faction * f)
int setstealth_cmd(unit * u, struct order *ord) int setstealth_cmd(unit * u, struct order *ord)
{ {
char token[64];
const char *s; const char *s;
int level, rule; int level, rule;
const race *trace; const race *trace;
init_order(ord); init_order(ord);
s = getstrtoken(); s = gettoken(token, sizeof(token));
/* Tarne ohne Parameter: Setzt maximale Tarnung */ /* Tarne ohne Parameter: Setzt maximale Tarnung */
@ -286,7 +287,7 @@ int setstealth_cmd(unit * u, struct order *ord)
/* TARNE PARTEI is disabled */ /* TARNE PARTEI is disabled */
break; break;
} }
s = getstrtoken(); s = gettoken(token, sizeof(token));
if (rule & 1) { if (rule & 1) {
if (!s || *s == 0) { if (!s || *s == 0) {
fset(u, UFL_ANON_FACTION); fset(u, UFL_ANON_FACTION);
@ -299,13 +300,13 @@ int setstealth_cmd(unit * u, struct order *ord)
} }
if (rule & 2) { if (rule & 2) {
if (get_keyword(s, u->faction->locale) == K_NUMBER) { if (get_keyword(s, u->faction->locale) == K_NUMBER) {
const char *s2 = getstrtoken(); s = gettoken(token, sizeof(token));
int nr = -1; int nr = -1;
if (s2) { if (s) {
nr = atoi36(s2); nr = atoi36(s);
} }
if (!s2 || *s2 == 0 || nr == u->faction->no) { if (!s || *s == 0 || nr == u->faction->no) {
a_removeall(&u->attribs, &at_otherfaction); a_removeall(&u->attribs, &at_otherfaction);
break; break;
} }

View File

@ -86,6 +86,7 @@ int RunAllTests(void)
log_flags = flags; log_flags = flags;
fail_count = suite->failCount; fail_count = suite->failCount;
CuSuiteDelete(suite); CuSuiteDelete(suite);
kernel_done();
return fail_count; return fail_count;
} }

View File

@ -57,8 +57,8 @@ struct unit *test_create_unit(struct faction *f, struct region *r)
void test_cleanup(void) void test_cleanup(void)
{ {
test_clear_terrains(); free_terrains();
test_clear_resources(); free_resources();
global.functions.maintenance = NULL; global.functions.maintenance = NULL;
global.functions.wage = NULL; global.functions.wage = NULL;
default_locale = 0; default_locale = 0;
@ -75,7 +75,6 @@ terrain_type *
test_create_terrain(const char * name, unsigned int flags) test_create_terrain(const char * name, unsigned int flags)
{ {
terrain_type * t = get_or_create_terrain(name); terrain_type * t = get_or_create_terrain(name);
t->_name = _strdup(name);
t->flags = flags; t->flags = flags;
return t; return t;
} }

View File

@ -3,6 +3,7 @@
#include <kernel/types.h> #include <kernel/types.h>
#include <kernel/item.h> #include <kernel/item.h>
#include <kernel/region.h> #include <kernel/region.h>
#include <kernel/terrain.h>
#include <util/language.h> #include <util/language.h>
@ -12,6 +13,7 @@
static void test_resources(CuTest *tc) { static void test_resources(CuTest *tc) {
resource_type *rtype; resource_type *rtype;
test_cleanup(); test_cleanup();
init_resources();
CuAssertPtrNotNull(tc, rt_find("hp")); CuAssertPtrNotNull(tc, rt_find("hp"));
CuAssertPtrEquals(tc, rt_find("hp"), (void *)get_resourcetype(R_LIFE)); CuAssertPtrEquals(tc, rt_find("hp"), (void *)get_resourcetype(R_LIFE));
CuAssertPtrNotNull(tc, rt_find("peasant")); CuAssertPtrNotNull(tc, rt_find("peasant"));
@ -27,6 +29,7 @@ static void test_resources(CuTest *tc) {
CuAssertPtrEquals(tc, (void *)rtype, (void *)get_resourcetype(R_STONE)); CuAssertPtrEquals(tc, (void *)rtype, (void *)get_resourcetype(R_STONE));
test_cleanup(); test_cleanup();
CuAssertPtrEquals(tc, 0, rt_find("stone")); CuAssertPtrEquals(tc, 0, rt_find("stone"));
CuAssertPtrEquals(tc, 0, rt_find("peasant"));
rtype = rt_get_or_create("stone"); rtype = rt_get_or_create("stone");
CuAssertPtrEquals(tc, (void *)rtype, (void *)get_resourcetype(R_STONE)); CuAssertPtrEquals(tc, (void *)rtype, (void *)get_resourcetype(R_STONE));
} }
@ -36,15 +39,13 @@ static void test_recreate_world(CuTest * tc)
test_cleanup(); test_cleanup();
CuAssertPtrEquals(tc, 0, get_locale("de")); CuAssertPtrEquals(tc, 0, get_locale("de"));
CuAssertPtrEquals(tc, 0, (void *)rt_find("horse")); CuAssertPtrEquals(tc, 0, (void *)rt_find("horse"));
CuAssertPtrNotNull(tc, get_resourcetype(R_LIFE));
CuAssertPtrNotNull(tc, get_resourcetype(R_PERMAURA));
CuAssertPtrNotNull(tc, get_resourcetype(R_AURA));
CuAssertPtrNotNull(tc, (void *)rt_find("money"));
test_create_world(); test_create_world();
CuAssertPtrEquals(tc, default_locale, get_locale("de")); CuAssertPtrEquals(tc, default_locale, get_locale("de"));
CuAssertPtrNotNull(tc, default_locale); CuAssertPtrNotNull(tc, default_locale);
CuAssertPtrNotNull(tc, findregion(0, 0)); CuAssertPtrNotNull(tc, findregion(0, 0));
CuAssertPtrNotNull(tc, get_terrain("plain"));
CuAssertPtrNotNull(tc, get_terrain("ocean"));
CuAssertPtrNotNull(tc, (void *)rt_find("horse")); CuAssertPtrNotNull(tc, (void *)rt_find("horse"));
CuAssertPtrNotNull(tc, get_resourcetype(R_HORSE)); CuAssertPtrNotNull(tc, get_resourcetype(R_HORSE));
CuAssertPtrNotNull(tc, (void *)rt_find("money")); CuAssertPtrNotNull(tc, (void *)rt_find("money"));
@ -56,14 +57,16 @@ static void test_recreate_world(CuTest * tc)
test_cleanup(); test_cleanup();
CuAssertPtrEquals(tc, 0, get_locale("de")); CuAssertPtrEquals(tc, 0, get_locale("de"));
CuAssertPtrEquals(tc, 0, (void*)get_terrain("plain"));
CuAssertPtrEquals(tc, 0, (void*)get_terrain("ocean"));
CuAssertPtrEquals(tc, 0, (void*)rt_find("horse")); CuAssertPtrEquals(tc, 0, (void*)rt_find("horse"));
CuAssertPtrEquals(tc, 0, (void*)get_resourcetype(R_HORSE)); CuAssertPtrEquals(tc, 0, (void*)get_resourcetype(R_HORSE));
CuAssertPtrNotNull(tc, (void *)rt_find("money")); CuAssertPtrEquals(tc, 0, (void *)rt_find("money"));
CuAssertPtrNotNull(tc, get_resourcetype(R_LIFE)); CuAssertPtrEquals(tc, 0, (void *)get_resourcetype(R_LIFE));
CuAssertPtrNotNull(tc, get_resourcetype(R_SILVER)); CuAssertPtrEquals(tc, 0, (void *)get_resourcetype(R_SILVER));
CuAssertPtrNotNull(tc, get_resourcetype(R_AURA)); CuAssertPtrEquals(tc, 0, (void *)get_resourcetype(R_AURA));
CuAssertPtrNotNull(tc, get_resourcetype(R_PERMAURA)); CuAssertPtrEquals(tc, 0, (void *)get_resourcetype(R_PERMAURA));
CuAssertPtrNotNull(tc, get_resourcetype(R_PEASANT)); CuAssertPtrEquals(tc, 0, (void *)get_resourcetype(R_PEASANT));
CuAssertPtrEquals(tc, 0, findregion(0, 0)); CuAssertPtrEquals(tc, 0, findregion(0, 0));
} }

View File

@ -355,3 +355,7 @@ void a_write(struct storage *store, const attrib * attribs, const void *owner)
} }
WRITE_TOK(store, "end"); WRITE_TOK(store, "end");
} }
void free_attribs(void) {
cb_clear(&cb_deprecated);
}

View File

@ -79,6 +79,8 @@ extern "C" {
extern void a_write(struct storage *store, const attrib * attribs, extern void a_write(struct storage *store, const attrib * attribs,
const void *owner); const void *owner);
void free_attribs(void);
#define DEFAULT_AGE NULL #define DEFAULT_AGE NULL
#define DEFAULT_INIT NULL #define DEFAULT_INIT NULL
#define DEFAULT_FINALIZE NULL #define DEFAULT_FINALIZE NULL

View File

@ -147,14 +147,13 @@ const char *locale_string(const locale * lang, const char *key)
} }
find = find->nexthash; find = find->nexthash;
} }
if (!find) { if (find) {
log_warning("missing translation for \"%s\" in locale %s\n", key, lang->name); return find->str;
}
log_error("missing translation for \"%s\" in locale %s\n", key, lang->name);
if (lang->fallback) { if (lang->fallback) {
return locale_string(lang->fallback, key); return locale_string(lang->fallback, key);
} }
return 0;
}
return find->str;
} }
return 0; return 0;
} }
@ -242,6 +241,7 @@ void add_translation(struct critbit_tree **cbp, const char *key, int i) {
if (str) { if (str) {
size_t len = strlen(str); size_t len = strlen(str);
if (!cb) { if (!cb) {
// TODO: this will leak, because we do not know how to clean it up */
*cbp = cb = (struct critbit_tree *)calloc(1, sizeof(struct critbit_tree *)); *cbp = cb = (struct critbit_tree *)calloc(1, sizeof(struct critbit_tree *));
} }
len = cb_new_kv(str, len, &i, sizeof(int), buffer); len = cb_new_kv(str, len, &i, sizeof(int), buffer);
@ -319,6 +319,7 @@ void free_locales(void) {
free(strings); free(strings);
} }
} }
free(locales->name);
free(locales); free(locales);
locales = next; locales = next;
} }

View File

@ -14,7 +14,7 @@ typedef struct locale_str {
} locale_str; } locale_str;
typedef struct locale { typedef struct locale {
const char *name; char *name;
unsigned int index; unsigned int index;
struct locale *next; struct locale *next;
unsigned int hashkey; unsigned int hashkey;

View File

@ -211,7 +211,13 @@ void freetokens(void * root)
int i; int i;
for (i = 0; node && i != NODEHASHSIZE; ++i) { for (i = 0; node && i != NODEHASHSIZE; ++i) {
if (node->next[i]) { if (node->next[i]) {
tref ** refs = &node->next[i];
freetokens(node->next[i]->node); freetokens(node->next[i]->node);
while (*refs) {
tref * ref = *refs;
*refs = ref->nexthash;
free(ref);
}
} }
} }
free(node); free(node);

View File

@ -61,7 +61,10 @@ static void a_initdirection(attrib * a)
static void a_freedirection(attrib * a) static void a_freedirection(attrib * a)
{ {
free(a->data.v); spec_direction *d = (spec_direction *)(a->data.v);
free(d->desc);
free(d->keyword);
free(d);
} }
static int a_agedirection(attrib * a) static int a_agedirection(attrib * a)