Merge pull request #493 from ennorehling/tests-without-files

Remove file operations from most tests
This commit is contained in:
Enno Rehling 2016-03-09 14:39:44 +01:00
commit c1786c14ed
9 changed files with 327 additions and 211 deletions

View File

@ -16,6 +16,7 @@ MACHINE=`uname -m`
[ -z "$CC" ] && [ ! -z `which cc` ] && CC="cc" [ -z "$CC" ] && [ ! -z `which cc` ] && CC="cc"
BIN_DIR="$ROOT/build-$MACHINE-$CC-$BUILD" BIN_DIR="$ROOT/build-$MACHINE-$CC-$BUILD"
mkdir -p $BIN_DIR mkdir -p $BIN_DIR
rm -f $BUILD
ln -sf $BIN_DIR $BUILD ln -sf $BIN_DIR $BUILD
MACHINE=$(gcc -dumpmachine) MACHINE=$(gcc -dumpmachine)

View File

@ -49,7 +49,7 @@ void game_done(void)
calendar_cleanup(); calendar_cleanup();
#endif #endif
free_functions(); free_functions();
free_curses(); curses_done();
kernel_done(); kernel_done();
} }

View File

@ -57,7 +57,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <ctype.h> #include <ctype.h>
#define MAXENTITYHASH 7919 #define MAXENTITYHASH 7919
curse *cursehash[MAXENTITYHASH]; static curse *cursehash[MAXENTITYHASH];
void c_setflag(curse * c, unsigned int flags) void c_setflag(curse * c, unsigned int flags)
{ {
@ -74,17 +74,19 @@ void c_clearflag(curse * c, unsigned int flags)
void chash(curse * c) void chash(curse * c)
{ {
curse *old = cursehash[c->no % MAXENTITYHASH]; int i = c->no % MAXENTITYHASH;
cursehash[c->no % MAXENTITYHASH] = c; c->nexthash = cursehash[i];
c->nexthash = old; cursehash[i] = c;
assert(c->nexthash != c);
} }
static void cunhash(curse * c) static void cunhash(curse * c)
{ {
curse **show; curse **show;
int i = c->no % MAXENTITYHASH;
for (show = &cursehash[c->no % MAXENTITYHASH]; *show; for (show = &cursehash[i]; *show;
show = &(*show)->nexthash) { show = &(*show)->nexthash) {
if ((*show)->no == c->no) if ((*show)->no == c->no)
break; break;
@ -195,6 +197,7 @@ int curse_read(attrib * a, void *owner, gamedata *data)
int flags; int flags;
float flt; float flt;
assert(!c->no);
READ_INT(store, &c->no); READ_INT(store, &c->no);
chash(c); chash(c);
READ_TOK(store, cursename, sizeof(cursename)); READ_TOK(store, cursename, sizeof(cursename));
@ -824,9 +827,9 @@ double destr_curse(curse * c, int cast_level, double force)
return force; return force;
} }
void free_curses(void) { void curses_done(void) {
int i; int i;
for (i = 0; i != MAXCTHASH; ++i) { for (i = 0; i != MAXCTHASH; ++i) {
ql_free(cursetypes[i]); ql_free(cursetypes[i]);
} }
} }

View File

@ -216,7 +216,7 @@ extern "C" {
int duration; /* Dauer der Verzauberung. Wird jede Runde vermindert */ int duration; /* Dauer der Verzauberung. Wird jede Runde vermindert */
} curse; } curse;
void free_curses(void); /* de-register all curse-types */ void curses_done(void); /* de-register all curse-types */
void curse_write(const struct attrib *a, const void *owner, void curse_write(const struct attrib *a, const void *owner,
struct storage *store); struct storage *store);

View File

@ -2,6 +2,7 @@
#include <kernel/config.h> #include <kernel/config.h>
#include <kernel/region.h> #include <kernel/region.h>
#include <kernel/save.h>
#include <kernel/unit.h> #include <kernel/unit.h>
#include <kernel/version.h> #include <kernel/version.h>
#include <util/attrib.h> #include <util/attrib.h>
@ -53,6 +54,11 @@ static void setup_curse(curse_fixture *fix, const char *name) {
fix->c = create_curse(fix->u, &fix->r->attribs, ct_find(name), 1.0, 1, 1.0, 0); fix->c = create_curse(fix->u, &fix->r->attribs, ct_find(name), 1.0, 1, 1.0, 0);
} }
static void cleanup_curse(curse_fixture *fix) {
// destroy_curse(fix->c);
test_cleanup();
}
static void test_magicstreet(CuTest *tc) { static void test_magicstreet(CuTest *tc) {
curse_fixture fix; curse_fixture fix;
message *msg; message *msg;
@ -61,7 +67,7 @@ static void test_magicstreet(CuTest *tc) {
msg = fix.c->type->curseinfo(fix.r, TYP_REGION, fix.c, 0); msg = fix.c->type->curseinfo(fix.r, TYP_REGION, fix.c, 0);
CuAssertStrEquals(tc, "curseinfo::magicstreet", test_get_messagetype(msg)); CuAssertStrEquals(tc, "curseinfo::magicstreet", test_get_messagetype(msg));
msg_release(msg); msg_release(msg);
test_cleanup(); cleanup_curse(&fix);
} }
static void test_magicstreet_warning(CuTest *tc) { static void test_magicstreet_warning(CuTest *tc) {
@ -72,7 +78,7 @@ static void test_magicstreet_warning(CuTest *tc) {
msg = fix.c->type->curseinfo(fix.r, TYP_REGION, fix.c, 0); msg = fix.c->type->curseinfo(fix.r, TYP_REGION, fix.c, 0);
CuAssertStrEquals(tc, "curseinfo::magicstreetwarn", test_get_messagetype(msg)); CuAssertStrEquals(tc, "curseinfo::magicstreetwarn", test_get_messagetype(msg));
msg_release(msg); msg_release(msg);
test_cleanup(); cleanup_curse(&fix);
} }
static void test_good_dreams(CuTest *tc) { static void test_good_dreams(CuTest *tc) {
@ -83,7 +89,7 @@ static void test_good_dreams(CuTest *tc) {
msg = fix.c->type->curseinfo(fix.r, TYP_REGION, fix.c, 0); msg = fix.c->type->curseinfo(fix.r, TYP_REGION, fix.c, 0);
CuAssertStrEquals(tc, "curseinfo::gooddream", test_get_messagetype(msg)); CuAssertStrEquals(tc, "curseinfo::gooddream", test_get_messagetype(msg));
msg_release(msg); msg_release(msg);
test_cleanup(); cleanup_curse(&fix);
} }
static void test_bad_dreams(CuTest *tc) { static void test_bad_dreams(CuTest *tc) {
@ -94,7 +100,7 @@ static void test_bad_dreams(CuTest *tc) {
msg = fix.c->type->curseinfo(fix.r, TYP_REGION, fix.c, 0); msg = fix.c->type->curseinfo(fix.r, TYP_REGION, fix.c, 0);
CuAssertStrEquals(tc, "curseinfo::baddream", test_get_messagetype(msg)); CuAssertStrEquals(tc, "curseinfo::baddream", test_get_messagetype(msg));
msg_release(msg); msg_release(msg);
test_cleanup(); cleanup_curse(&fix);
} }
static void test_memstream(CuTest *tc) { static void test_memstream(CuTest *tc) {
@ -125,20 +131,31 @@ static void test_write_flag(CuTest *tc) {
curse_fixture fix; curse_fixture fix;
gamedata data; gamedata data;
storage store; storage store;
region * r;
curse * c;
int uid;
mstream_init(&data.strm); mstream_init(&data.strm);
gamedata_init(&data, &store, RELEASE_VERSION); gamedata_init(&data, &store, RELEASE_VERSION);
setup_curse(&fix, "gbdream"); setup_curse(&fix, "gbdream");
fix.c->flags = 42 | CURSE_ISNEW; c = fix.c;
curse_write(fix.r->attribs, fix.r, &store); r = fix.r;
uid = r->uid;
c->flags = CURSE_ISNEW;
write_game(&data);
free_gamedata();
data.strm.api->rewind(data.strm.handle); data.strm.api->rewind(data.strm.handle);
curse_read(fix.r->attribs, fix.r, &data); read_game(&data);
CuAssertIntEquals(tc, 42 | CURSE_ISNEW, ((curse *) fix.r->attribs->data.v)->flags); r = findregionbyid(uid);
CuAssertPtrNotNull(tc, r);
CuAssertPtrNotNull(tc, r->attribs);
c = (curse *)r->attribs->data.v;
CuAssertIntEquals(tc, CURSE_ISNEW, c->flags);
mstream_done(&data.strm); mstream_done(&data.strm);
gamedata_done(&data); gamedata_done(&data);
test_cleanup(); cleanup_curse(&fix);
} }
CuSuite *get_curse_suite(void) CuSuite *get_curse_suite(void)

View File

@ -1,4 +1,5 @@
#include <platform.h> #include <platform.h>
#include "config.h"
#include "types.h" #include "types.h"
#include "ally.h" #include "ally.h"
#include "group.h" #include "group.h"
@ -15,40 +16,88 @@
#include <stream.h> #include <stream.h>
#include <filestream.h> #include <filestream.h>
#include <storage.h> #include <storage.h>
#include <memstream.h>
#include <binarystore.h> #include <binarystore.h>
#include <CuTest.h> #include <CuTest.h>
#include <tests.h> #include <tests.h>
#include <assert.h> #include <assert.h>
static void test_group_readwrite_dead_faction(CuTest *tc) {
gamedata data;
storage store;
faction *f, *f2;
unit * u;
group *g;
ally *al;
int fno;
test_cleanup();
f = test_create_faction(0);
fno = f->no;
CuAssertPtrEquals(tc, f, factions);
CuAssertPtrEquals(tc, 0, f->next);
f2 = test_create_faction(0);
CuAssertPtrEquals(tc, f2, factions->next);
u = test_create_unit(f2, test_create_region(0, 0, 0));
CuAssertPtrNotNull(tc, u);
g = join_group(u, "group");
CuAssertPtrNotNull(tc, g);
al = ally_add(&g->allies, f);
CuAssertPtrNotNull(tc, al);
CuAssertPtrEquals(tc, f, factions);
destroyfaction(&factions);
CuAssertTrue(tc, !f->_alive);
CuAssertPtrEquals(tc, f2, factions);
mstream_init(&data.strm);
gamedata_init(&data, &store, RELEASE_VERSION);
write_game(&data);
free_gamedata();
f = f2 = NULL;
data.strm.api->rewind(data.strm.handle);
read_game(&data);
mstream_done(&data.strm);
gamedata_done(&data);
CuAssertPtrEquals(tc, 0, findfaction(fno));
f2 = factions;
CuAssertPtrNotNull(tc, f2);
u = f2->units;
CuAssertPtrNotNull(tc, u);
g = get_group(u);
CuAssertPtrNotNull(tc, g);
CuAssertPtrEquals(tc, 0, g->allies);
test_cleanup();
}
static void test_group_readwrite(CuTest * tc) static void test_group_readwrite(CuTest * tc)
{ {
faction * f; faction * f;
group *g; group *g;
ally *al; ally *al;
int i; int i;
gamedata *data; gamedata data;
storage store;
test_cleanup(); test_cleanup();
data = gamedata_open("test.dat", "wb", RELEASE_VERSION); mstream_init(&data.strm);
CuAssertPtrNotNull(tc, data); gamedata_init(&data, &store, RELEASE_VERSION);
f = test_create_faction(0); f = test_create_faction(0);
g = new_group(f, "NW", 42); g = new_group(f, "NW", 42);
g = new_group(f, "Egoisten", 43); g = new_group(f, "Egoisten", 43);
key_set(&g->attribs, 44); key_set(&g->attribs, 44);
al = ally_add(&g->allies, f); al = ally_add(&g->allies, f);
al->status = HELP_GIVE; al->status = HELP_GIVE;
write_groups(data->store, f); write_groups(&store, f);
WRITE_INT(data->store, 47); WRITE_INT(&store, 47);
binstore_done(data->store);
gamedata_close(data);
f->groups = 0;
free_group(g); free_group(g);
data = gamedata_open("test.dat", "rb", RELEASE_VERSION); f->groups = 0;
read_groups(data, f); data.strm.api->rewind(data.strm.handle);
READ_INT(data->store, &i); read_groups(&data, f);
gamedata_close(data); READ_INT(&store, &i);
mstream_done(&data.strm);
gamedata_done(&data);
CuAssertIntEquals(tc, 47, i); CuAssertIntEquals(tc, 47, i);
CuAssertPtrNotNull(tc, f->groups); CuAssertPtrNotNull(tc, f->groups);
@ -64,7 +113,6 @@ static void test_group_readwrite(CuTest * tc)
CuAssertPtrEquals(tc, 0, g->allies->next); CuAssertPtrEquals(tc, 0, g->allies->next);
CuAssertPtrEquals(tc, f, g->allies->faction); CuAssertPtrEquals(tc, f, g->allies->faction);
CuAssertIntEquals(tc, HELP_GIVE, g->allies->status); CuAssertIntEquals(tc, HELP_GIVE, g->allies->status);
remove("test.dat");
test_cleanup(); test_cleanup();
} }
@ -76,8 +124,7 @@ static void test_group(CuTest * tc)
group *g; group *g;
test_cleanup(); test_cleanup();
test_create_world(); r = test_create_region(0, 0, 0);
r = findregion(0, 0);
f = test_create_faction(0); f = test_create_faction(0);
assert(r && f); assert(r && f);
u = test_create_unit(f, r); u = test_create_unit(f, r);
@ -100,6 +147,7 @@ CuSuite *get_group_suite(void)
CuSuite *suite = CuSuiteNew(); CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_group); SUITE_ADD_TEST(suite, test_group);
SUITE_ADD_TEST(suite, test_group_readwrite); SUITE_ADD_TEST(suite, test_group_readwrite);
SUITE_ADD_TEST(suite, test_group_readwrite_dead_faction);
return suite; return suite;
} }

View File

@ -1461,16 +1461,8 @@ static int cb_sb_maxlevel(spellbook_entry *sbe, void *cbdata) {
int readgame(const char *filename, bool backup) int readgame(const char *filename, bool backup)
{ {
int n, p, nread; int n;
faction *f, **fp;
region *r;
building *b, **bp;
ship **shp;
unit *u;
int rmax = maxregions;
char path[MAX_PATH]; char path[MAX_PATH];
char name[DISPLAYSIZE];
const struct building_type *bt_lighthouse = bt_find("lighthouse");
gamedata gdata = { 0 }; gamedata gdata = { 0 };
storage store; storage store;
stream strm; stream strm;
@ -1508,10 +1500,27 @@ int readgame(const char *filename, bool backup)
READ_INT(&store, &build); READ_INT(&store, &build);
log_debug("data in %s created with build %d.", filename, build); log_debug("data in %s created with build %d.", filename, build);
} }
if (gdata.version >= SAVEGAMEID_VERSION) { n = read_game(&gdata);
binstore_done(&store);
fstream_done(&strm);
return n;
}
int read_game(gamedata *data) {
char name[DISPLAYSIZE];
int n, p, nread;
faction *f, **fp;
region *r;
building *b, **bp;
ship **shp;
unit *u;
int rmax = maxregions;
const struct building_type *bt_lighthouse = bt_find("lighthouse");
storage * store = data->store;
if (data->version >= SAVEGAMEID_VERSION) {
int gameid; int gameid;
READ_INT(&store, &gameid); READ_INT(store, &gameid);
if (gameid != game_id()) { if (gameid != game_id()) {
int c; int c;
log_warning("game mismatch: datafile contains game %d, but config is for %d", gameid, game_id()); log_warning("game mismatch: datafile contains game %d, but config is for %d", gameid, game_id());
@ -1524,25 +1533,25 @@ int readgame(const char *filename, bool backup)
} }
} }
else { else {
READ_STR(&store, NULL, 0); READ_STR(store, NULL, 0);
} }
read_attribs(&gdata, &global.attribs, NULL); read_attribs(data, &global.attribs, NULL);
READ_INT(&store, &turn); READ_INT(store, &turn);
global.data_turn = turn; global.data_turn = turn;
log_debug(" - reading turn %d\n", turn); log_debug(" - reading turn %d\n", turn);
rng_init(turn); rng_init(turn);
READ_INT(&store, &nread); /* max_unique_id = ignore */ READ_INT(store, NULL); /* max_unique_id = ignore */
READ_INT(&store, &nextborder); READ_INT(store, NULL);
/* Planes */ /* Planes */
planes = NULL; planes = NULL;
READ_INT(&store, &nread); READ_INT(store, &nread);
while (--nread >= 0) { while (--nread >= 0) {
int id; int id;
variant fno; variant fno;
plane *pl; plane *pl;
READ_INT(&store, &id); READ_INT(store, &id);
pl = getplanebyid(id); pl = getplanebyid(id);
if (pl == NULL) { if (pl == NULL) {
@ -1552,20 +1561,20 @@ int readgame(const char *filename, bool backup)
log_warning("the plane with id=%d already exists.\n", id); log_warning("the plane with id=%d already exists.\n", id);
} }
pl->id = id; pl->id = id;
READ_STR(&store, name, sizeof(name)); READ_STR(store, name, sizeof(name));
pl->name = _strdup(name); pl->name = _strdup(name);
READ_INT(&store, &pl->minx); READ_INT(store, &pl->minx);
READ_INT(&store, &pl->maxx); READ_INT(store, &pl->maxx);
READ_INT(&store, &pl->miny); READ_INT(store, &pl->miny);
READ_INT(&store, &pl->maxy); READ_INT(store, &pl->maxy);
READ_INT(&store, &pl->flags); READ_INT(store, &pl->flags);
/* read watchers */ /* read watchers */
if (gdata.version < FIX_WATCHERS_VERSION) { if (data->version < FIX_WATCHERS_VERSION) {
char rname[64]; char rname[64];
/* before this version, watcher storage was pretty broken. we are incompatible and don't read them */ /* before this version, watcher storage was pretty broken. we are incompatible and don't read them */
for (;;) { for (;;) {
READ_TOK(&store, rname, sizeof(rname)); READ_TOK(store, rname, sizeof(rname));
if (strcmp(rname, "end") == 0) { if (strcmp(rname, "end") == 0) {
break; /* this is most likely the end of the list */ break; /* this is most likely the end of the list */
} }
@ -1577,29 +1586,29 @@ int readgame(const char *filename, bool backup)
} }
else { else {
/* WATCHERS - eliminated in February 2016, ca. turn 966 */ /* WATCHERS - eliminated in February 2016, ca. turn 966 */
if (gdata.version < NOWATCH_VERSION) { if (data->version < NOWATCH_VERSION) {
fno = read_faction_reference(&gdata); fno = read_faction_reference(data);
while (fno.i) { while (fno.i) {
fno = read_faction_reference(&gdata); fno = read_faction_reference(data);
} }
} }
} }
read_attribs(&gdata, &pl->attribs, pl); read_attribs(data, &pl->attribs, pl);
if (pl->id != 1094969858) { // Regatta if (pl->id != 1094969858) { // Regatta
addlist(&planes, pl); addlist(&planes, pl);
} }
} }
/* Read factions */ /* Read factions */
read_alliances(&gdata); read_alliances(data);
READ_INT(&store, &nread); READ_INT(store, &nread);
log_debug(" - Einzulesende Parteien: %d\n", nread); log_debug(" - Einzulesende Parteien: %d\n", nread);
fp = &factions; fp = &factions;
while (*fp) while (*fp)
fp = &(*fp)->next; fp = &(*fp)->next;
while (--nread >= 0) { while (--nread >= 0) {
faction *f = readfaction(&gdata); faction *f = readfaction(data);
*fp = f; *fp = f;
fp = &f->next; fp = &f->next;
@ -1609,8 +1618,8 @@ int readgame(const char *filename, bool backup)
/* Regionen */ /* Regionen */
READ_INT(&store, &nread); READ_INT(store, &nread);
assert(nread < MAXREGIONS); assert(nread < MAXREGIONS && nread>=0);
if (rmax < 0) { if (rmax < 0) {
rmax = nread; rmax = nread;
} }
@ -1618,67 +1627,67 @@ int readgame(const char *filename, bool backup)
while (--nread >= 0) { while (--nread >= 0) {
unit **up; unit **up;
int x, y; int x, y;
READ_INT(&store, &x); READ_INT(store, &x);
READ_INT(&store, &y); READ_INT(store, &y);
if ((nread & 0x3FF) == 0) { /* das spart extrem Zeit */ if ((nread & 0x3FF) == 0) { /* das spart extrem Zeit */
log_debug(" - Einzulesende Regionen: %d/%d * %d,%d \r", rmax, nread, x, y); log_debug(" - Einzulesende Regionen: %d/%d * %d,%d \r", rmax, nread, x, y);
} }
--rmax; --rmax;
r = readregion(&gdata, x, y); r = readregion(data, x, y);
/* Burgen */ /* Burgen */
READ_INT(&store, &p); READ_INT(store, &p);
bp = &r->buildings; bp = &r->buildings;
while (--p >= 0) { while (--p >= 0) {
b = (building *)calloc(1, sizeof(building)); b = (building *)calloc(1, sizeof(building));
READ_INT(&store, &b->no); READ_INT(store, &b->no);
*bp = b; *bp = b;
bp = &b->next; bp = &b->next;
bhash(b); bhash(b);
READ_STR(&store, name, sizeof(name)); READ_STR(store, name, sizeof(name));
b->name = _strdup(name); b->name = _strdup(name);
if (lomem) { if (lomem) {
READ_STR(gdata.store, NULL, 0); READ_STR(store, NULL, 0);
} }
else { else {
READ_STR(&store, name, sizeof(name)); READ_STR(store, name, sizeof(name));
b->display = _strdup(name); b->display = _strdup(name);
} }
READ_INT(&store, &b->size); READ_INT(store, &b->size);
READ_STR(&store, name, sizeof(name)); READ_STR(store, name, sizeof(name));
b->type = bt_find(name); b->type = bt_find(name);
b->region = r; b->region = r;
read_attribs(&gdata, &b->attribs, b); read_attribs(data, &b->attribs, b);
if (b->type == bt_lighthouse) { if (b->type == bt_lighthouse) {
r->flags |= RF_LIGHTHOUSE; r->flags |= RF_LIGHTHOUSE;
} }
} }
/* Schiffe */ /* Schiffe */
READ_INT(&store, &p); READ_INT(store, &p);
shp = &r->ships; shp = &r->ships;
while (--p >= 0) { while (--p >= 0) {
ship *sh = (ship *)calloc(1, sizeof(ship)); ship *sh = (ship *)calloc(1, sizeof(ship));
sh->region = r; sh->region = r;
READ_INT(&store, &sh->no); READ_INT(store, &sh->no);
*shp = sh; *shp = sh;
shp = &sh->next; shp = &sh->next;
shash(sh); shash(sh);
READ_STR(&store, name, sizeof(name)); READ_STR(store, name, sizeof(name));
sh->name = _strdup(name); sh->name = _strdup(name);
if (lomem) { if (lomem) {
READ_STR(&store, NULL, 0); READ_STR(store, NULL, 0);
} }
else { else {
READ_STR(&store, name, sizeof(name)); READ_STR(store, name, sizeof(name));
sh->display = _strdup(name); sh->display = _strdup(name);
} }
READ_STR(&store, name, sizeof(name)); READ_STR(store, name, sizeof(name));
sh->type = st_find(name); sh->type = st_find(name);
if (sh->type == NULL) { if (sh->type == NULL) {
/* old datafiles */ /* old datafiles */
@ -1686,33 +1695,33 @@ int readgame(const char *filename, bool backup)
} }
assert(sh->type || !"ship_type not registered!"); assert(sh->type || !"ship_type not registered!");
READ_INT(&store, &sh->size); READ_INT(store, &sh->size);
READ_INT(&store, &sh->damage); READ_INT(store, &sh->damage);
if (gdata.version >= FOSS_VERSION) { if (data->version >= FOSS_VERSION) {
READ_INT(&store, &sh->flags); READ_INT(store, &sh->flags);
} }
/* Attribute rekursiv einlesen */ /* Attribute rekursiv einlesen */
READ_INT(&store, &n); READ_INT(store, &n);
sh->coast = (direction_t)n; sh->coast = (direction_t)n;
if (sh->type->flags & SFL_NOCOAST) { if (sh->type->flags & SFL_NOCOAST) {
sh->coast = NODIRECTION; sh->coast = NODIRECTION;
} }
read_attribs(&gdata, &sh->attribs, sh); read_attribs(data, &sh->attribs, sh);
} }
*shp = 0; *shp = 0;
/* Einheiten */ /* Einheiten */
READ_INT(&store, &p); READ_INT(store, &p);
up = &r->units; up = &r->units;
while (--p >= 0) { while (--p >= 0) {
unit *u = read_unit(&gdata); unit *u = read_unit(data);
if (gdata.version < JSON_REPORT_VERSION) { if (data->version < JSON_REPORT_VERSION) {
if (u->_name && fval(u->faction, FFL_NPC)) { if (u->_name && fval(u->faction, FFL_NPC)) {
if (!u->_name[0] || unit_name_equals_race(u)) { if (!u->_name[0] || unit_name_equals_race(u)) {
unit_setname(u, NULL); unit_setname(u, NULL);
@ -1727,10 +1736,8 @@ int readgame(const char *filename, bool backup)
update_interval(u->faction, u->region); update_interval(u->faction, u->region);
} }
} }
read_borders(&gdata); read_borders(data);
binstore_done(&store);
fstream_done(&strm);
/* Unaufgeloeste Zeiger initialisieren */ /* Unaufgeloeste Zeiger initialisieren */
log_debug("fixing unresolved references.\n"); log_debug("fixing unresolved references.\n");
resolve(); resolve();
@ -1758,7 +1765,7 @@ int readgame(const char *filename, bool backup)
} }
else { else {
for (u = f->units; u; u = u->nextF) { for (u = f->units; u; u = u->nextF) {
if (gdata.version < SPELL_LEVEL_VERSION) { if (data->version < SPELL_LEVEL_VERSION) {
sc_mage *mage = get_mage(u); sc_mage *mage = get_mage(u);
if (mage) { if (mage) {
faction *f = u->faction; faction *f = u->faction;
@ -1777,12 +1784,12 @@ int readgame(const char *filename, bool backup)
} }
if (u->number > 0) { if (u->number > 0) {
f->_alive = true; f->_alive = true;
if (gdata.version >= SPELL_LEVEL_VERSION) { if (data->version >= SPELL_LEVEL_VERSION) {
break; break;
} }
} }
} }
if (gdata.version < SPELL_LEVEL_VERSION && f->spellbook) { if (data->version < SPELL_LEVEL_VERSION && f->spellbook) {
spellbook_foreach(f->spellbook, cb_sb_maxlevel, f); spellbook_foreach(f->spellbook, cb_sb_maxlevel, f);
} }
} }
@ -1808,12 +1815,6 @@ static void clear_npc_orders(faction *f)
int writegame(const char *filename) int writegame(const char *filename)
{ {
int n; int n;
faction *f;
region *r;
building *b;
ship *sh;
unit *u;
plane *pl;
char path[MAX_PATH]; char path[MAX_PATH];
gamedata gdata; gamedata gdata;
storage store; storage store;
@ -1834,121 +1835,137 @@ int writegame(const char *filename)
gdata.store = &store; gdata.store = &store;
gdata.version = RELEASE_VERSION; gdata.version = RELEASE_VERSION;
n = STREAM_VERSION;
fwrite(&gdata.version, sizeof(int), 1, F); fwrite(&gdata.version, sizeof(int), 1, F);
n = STREAM_VERSION;
fwrite(&n, sizeof(int), 1, F); fwrite(&n, sizeof(int), 1, F);
fstream_init(&strm, F); fstream_init(&strm, F);
binstore_init(&store, &strm); binstore_init(&store, &strm);
/* globale Variablen */
WRITE_INT(&store, VERSION_BUILD); WRITE_INT(&store, VERSION_BUILD);
WRITE_INT(&store, game_id()); n = write_game(&gdata);
WRITE_SECTION(&store); binstore_done(&store);
fstream_done(&strm);
return n;
}
write_attribs(&store, global.attribs, NULL); void write_planes(storage *store) {
WRITE_SECTION(&store); plane *pl;
for (pl = planes; pl; pl = pl->next) {
WRITE_INT(store, pl->id);
WRITE_STR(store, pl->name);
WRITE_INT(store, pl->minx);
WRITE_INT(store, pl->maxx);
WRITE_INT(store, pl->miny);
WRITE_INT(store, pl->maxy);
WRITE_INT(store, pl->flags);
#if RELEASE_VERSION < NOWATCH_VERSION
write_faction_reference(NULL, store); /* mark the end of pl->watchers (gone since T966) */
#endif
a_write(store, pl->attribs, pl);
WRITE_SECTION(store);
}
}
WRITE_INT(&store, turn); int write_game(gamedata *data) {
WRITE_INT(&store, 0 /*max_unique_id */); storage * store = data->store;
WRITE_INT(&store, nextborder); region *r;
faction *f;
int n;
/* globale Variablen */
assert(data->version <= MAX_VERSION && data->version >= MIN_VERSION);
WRITE_INT(store, game_id());
WRITE_SECTION(store);
write_attribs(store, global.attribs, NULL);
WRITE_SECTION(store);
WRITE_INT(store, turn);
WRITE_INT(store, 0 /* max_unique_id */);
WRITE_INT(store, 0 /* nextborder */);
/* Write planes */ /* Write planes */
WRITE_SECTION(&store); WRITE_SECTION(store);
WRITE_INT(&store, listlen(planes)); WRITE_INT(store, listlen(planes));
WRITE_SECTION(&store); WRITE_SECTION(store);
for (pl = planes; pl; pl = pl->next) { write_planes(store);
WRITE_INT(&store, pl->id); write_alliances(data);
WRITE_STR(&store, pl->name);
WRITE_INT(&store, pl->minx);
WRITE_INT(&store, pl->maxx);
WRITE_INT(&store, pl->miny);
WRITE_INT(&store, pl->maxy);
WRITE_INT(&store, pl->flags);
#if RELEASE_VERSION < NOWATCH_VERSION
write_faction_reference(NULL, &store); /* mark the end of pl->watchers (gone since T966) */
#endif
a_write(&store, pl->attribs, pl);
WRITE_SECTION(&store);
}
/* Write factions */
write_alliances(&gdata);
n = listlen(factions); n = listlen(factions);
WRITE_INT(&store, n); WRITE_INT(store, n);
WRITE_SECTION(&store); WRITE_SECTION(store);
log_debug(" - Schreibe %d Parteien...\n", n); log_debug(" - Schreibe %d Parteien...\n", n);
for (f = factions; f; f = f->next) { for (f = factions; f; f = f->next) {
if (fval(f, FFL_NPC)) { if (fval(f, FFL_NPC)) {
clear_npc_orders(f); clear_npc_orders(f);
} }
writefaction(&gdata, f); writefaction(data, f);
WRITE_SECTION(&store); WRITE_SECTION(store);
} }
/* Write regions */ /* Write regions */
n = listlen(regions); n = listlen(regions);
WRITE_INT(&store, n); WRITE_INT(store, n);
WRITE_SECTION(&store); WRITE_SECTION(store);
log_debug(" - Schreibe Regionen: %d", n); log_debug(" - Schreibe Regionen: %d", n);
for (r = regions; r; r = r->next, --n) { for (r = regions; r; r = r->next, --n) {
ship *sh;
building *b;
unit *u;
/* plus leerzeile */ /* plus leerzeile */
if ((n % 1024) == 0) { /* das spart extrem Zeit */ if ((n % 1024) == 0) { /* das spart extrem Zeit */
log_debug(" - Schreibe Regionen: %d", n); log_debug(" - Schreibe Regionen: %d", n);
} }
WRITE_SECTION(&store); WRITE_SECTION(store);
WRITE_INT(&store, r->x); WRITE_INT(store, r->x);
WRITE_INT(&store, r->y); WRITE_INT(store, r->y);
writeregion(&gdata, r); writeregion(data, r);
WRITE_INT(&store, listlen(r->buildings)); WRITE_INT(store, listlen(r->buildings));
WRITE_SECTION(&store); WRITE_SECTION(store);
for (b = r->buildings; b; b = b->next) { for (b = r->buildings; b; b = b->next) {
write_building_reference(b, &store); write_building_reference(b, store);
WRITE_STR(&store, b->name); WRITE_STR(store, b->name);
WRITE_STR(&store, b->display ? b->display : ""); WRITE_STR(store, b->display ? b->display : "");
WRITE_INT(&store, b->size); WRITE_INT(store, b->size);
WRITE_TOK(&store, b->type->_name); WRITE_TOK(store, b->type->_name);
WRITE_SECTION(&store); WRITE_SECTION(store);
write_attribs(&store, b->attribs, b); write_attribs(store, b->attribs, b);
WRITE_SECTION(&store); WRITE_SECTION(store);
} }
WRITE_INT(&store, listlen(r->ships)); WRITE_INT(store, listlen(r->ships));
WRITE_SECTION(&store); WRITE_SECTION(store);
for (sh = r->ships; sh; sh = sh->next) { for (sh = r->ships; sh; sh = sh->next) {
assert(sh->region == r); assert(sh->region == r);
write_ship_reference(sh, &store); write_ship_reference(sh, store);
WRITE_STR(&store, (const char *)sh->name); WRITE_STR(store, (const char *)sh->name);
WRITE_STR(&store, sh->display ? (const char *)sh->display : ""); WRITE_STR(store, sh->display ? (const char *)sh->display : "");
WRITE_TOK(&store, sh->type->_name); WRITE_TOK(store, sh->type->_name);
WRITE_INT(&store, sh->size); WRITE_INT(store, sh->size);
WRITE_INT(&store, sh->damage); WRITE_INT(store, sh->damage);
WRITE_INT(&store, sh->flags & SFL_SAVEMASK); WRITE_INT(store, sh->flags & SFL_SAVEMASK);
assert((sh->type->flags & SFL_NOCOAST) == 0 || sh->coast == NODIRECTION); assert((sh->type->flags & SFL_NOCOAST) == 0 || sh->coast == NODIRECTION);
WRITE_INT(&store, sh->coast); WRITE_INT(store, sh->coast);
WRITE_SECTION(&store); WRITE_SECTION(store);
write_attribs(&store, sh->attribs, sh); write_attribs(store, sh->attribs, sh);
WRITE_SECTION(&store); WRITE_SECTION(store);
} }
WRITE_INT(&store, listlen(r->units)); WRITE_INT(store, listlen(r->units));
WRITE_SECTION(&store); WRITE_SECTION(store);
for (u = r->units; u; u = u->next) { for (u = r->units; u; u = u->next) {
write_unit(&gdata, u); write_unit(data, u);
} }
} }
WRITE_SECTION(&store); WRITE_SECTION(store);
write_borders(&store); write_borders(store);
WRITE_SECTION(&store); WRITE_SECTION(store);
binstore_done(&store);
fstream_done(&strm);
return 0; return 0;
} }

View File

@ -78,6 +78,9 @@ extern "C" {
void create_backup(char *file); void create_backup(char *file);
int write_game(gamedata *data);
int read_game(gamedata *data);
/* test-only functions that give access to internal implementation details (BAD) */ /* test-only functions that give access to internal implementation details (BAD) */
void _test_write_password(struct gamedata *data, const struct faction *f); void _test_write_password(struct gamedata *data, const struct faction *f);
void _test_read_password(struct gamedata *data, struct faction *f); void _test_read_password(struct gamedata *data, struct faction *f);

View File

@ -107,6 +107,11 @@ static void test_readwrite_dead_faction_group(CuTest *tc) {
group *g; group *g;
ally *al; ally *al;
int fno; int fno;
gamedata data;
storage store;
mstream_init(&data.strm);
gamedata_init(&data, &store, RELEASE_VERSION);
test_cleanup(); test_cleanup();
f = test_create_faction(0); f = test_create_faction(0);
@ -126,10 +131,11 @@ static void test_readwrite_dead_faction_group(CuTest *tc) {
destroyfaction(&factions); destroyfaction(&factions);
CuAssertTrue(tc, !f->_alive); CuAssertTrue(tc, !f->_alive);
CuAssertPtrEquals(tc, f2, factions); CuAssertPtrEquals(tc, f2, factions);
writegame("test.dat"); write_game(&data);
free_gamedata(); free_gamedata();
f = f2 = NULL; f = f2 = NULL;
readgame("test.dat", false); data.strm.api->rewind(data.strm.handle);
read_game(&data);
CuAssertPtrEquals(tc, 0, findfaction(fno)); CuAssertPtrEquals(tc, 0, findfaction(fno));
f2 = factions; f2 = factions;
CuAssertPtrNotNull(tc, f2); CuAssertPtrNotNull(tc, f2);
@ -138,12 +144,19 @@ static void test_readwrite_dead_faction_group(CuTest *tc) {
g = get_group(u); g = get_group(u);
CuAssertPtrNotNull(tc, g); CuAssertPtrNotNull(tc, g);
CuAssertPtrEquals(tc, 0, g->allies); CuAssertPtrEquals(tc, 0, g->allies);
mstream_done(&data.strm);
gamedata_done(&data);
test_cleanup(); test_cleanup();
} }
static void test_readwrite_dead_faction_regionowner(CuTest *tc) { static void test_readwrite_dead_faction_regionowner(CuTest *tc) {
faction *f; faction *f;
region *r; region *r;
gamedata data;
storage store;
mstream_init(&data.strm);
gamedata_init(&data, &store, RELEASE_VERSION);
test_cleanup(); test_cleanup();
config_set("rules.region_owners", "1"); config_set("rules.region_owners", "1");
@ -153,10 +166,13 @@ static void test_readwrite_dead_faction_regionowner(CuTest *tc) {
destroyfaction(&factions); destroyfaction(&factions);
CuAssertTrue(tc, !f->_alive); CuAssertTrue(tc, !f->_alive);
remove_empty_units(); remove_empty_units();
writegame("test.dat"); write_game(&data);
free_gamedata(); free_gamedata();
f = NULL; f = NULL;
readgame("test.dat", false); data.strm.api->rewind(data.strm.handle);
read_game(&data);
mstream_done(&data.strm);
gamedata_done(&data);
f = factions; f = factions;
CuAssertPtrEquals(tc, 0, f); CuAssertPtrEquals(tc, 0, f);
r = regions; r = regions;
@ -166,6 +182,8 @@ static void test_readwrite_dead_faction_regionowner(CuTest *tc) {
} }
static void test_readwrite_dead_faction_changefaction(CuTest *tc) { static void test_readwrite_dead_faction_changefaction(CuTest *tc) {
gamedata data;
storage store;
faction *f, *f2; faction *f, *f2;
region *r; region *r;
trigger *tr; trigger *tr;
@ -181,10 +199,15 @@ static void test_readwrite_dead_faction_changefaction(CuTest *tc) {
destroyfaction(&factions); destroyfaction(&factions);
CuAssertTrue(tc, !f->_alive); CuAssertTrue(tc, !f->_alive);
remove_empty_units(); remove_empty_units();
writegame("test.dat"); mstream_init(&data.strm);
gamedata_init(&data, &store, RELEASE_VERSION);
write_game(&data);
free_gamedata(); free_gamedata();
f = NULL; f = NULL;
readgame("test.dat", false); data.strm.api->rewind(data.strm.handle);
read_game(&data);
mstream_done(&data.strm);
gamedata_done(&data);
f = factions; f = factions;
CuAssertPtrNotNull(tc, f); CuAssertPtrNotNull(tc, f);
r = regions; r = regions;
@ -196,6 +219,8 @@ static void test_readwrite_dead_faction_changefaction(CuTest *tc) {
} }
static void test_readwrite_dead_faction_createunit(CuTest *tc) { static void test_readwrite_dead_faction_createunit(CuTest *tc) {
gamedata data;
storage store;
faction *f, *f2; faction *f, *f2;
region *r; region *r;
trigger *tr; trigger *tr;
@ -211,10 +236,15 @@ static void test_readwrite_dead_faction_createunit(CuTest *tc) {
destroyfaction(&factions); destroyfaction(&factions);
CuAssertTrue(tc, !f->_alive); CuAssertTrue(tc, !f->_alive);
remove_empty_units(); remove_empty_units();
writegame("test.dat"); mstream_init(&data.strm);
gamedata_init(&data, &store, RELEASE_VERSION);
write_game(&data);
free_gamedata(); free_gamedata();
f = NULL; f = NULL;
readgame("test.dat", false); data.strm.api->rewind(data.strm.handle);
read_game(&data);
mstream_done(&data.strm);
gamedata_done(&data);
f = factions; f = factions;
CuAssertPtrNotNull(tc, f); CuAssertPtrNotNull(tc, f);
r = regions; r = regions;
@ -226,26 +256,26 @@ static void test_readwrite_dead_faction_createunit(CuTest *tc) {
} }
static void test_read_password(CuTest *tc) { static void test_read_password(CuTest *tc) {
const char *path = "test.dat"; gamedata data;
gamedata *data; storage store;
faction *f; faction *f;
f = test_create_faction(0); f = test_create_faction(0);
faction_setpassword(f, password_encode("secret", PASSWORD_DEFAULT)); faction_setpassword(f, password_encode("secret", PASSWORD_DEFAULT));
data = gamedata_open(path, "wb", RELEASE_VERSION); mstream_init(&data.strm);
CuAssertPtrNotNull(tc, data); gamedata_init(&data, &store, RELEASE_VERSION);
_test_write_password(data, f); _test_write_password(&data, f);
gamedata_close(data); data.strm.api->rewind(data.strm.handle);
data = gamedata_open(path, "rb", RELEASE_VERSION); _test_read_password(&data, f);
CuAssertPtrNotNull(tc, data); mstream_done(&data.strm);
_test_read_password(data, f); gamedata_done(&data);
gamedata_close(data);
CuAssertTrue(tc, checkpasswd(f, "secret")); CuAssertTrue(tc, checkpasswd(f, "secret"));
CuAssertIntEquals(tc, 0, remove(path));
} }
static void test_read_password_external(CuTest *tc) { static void test_read_password_external(CuTest *tc) {
const char *path = "test.dat", *pwfile = "passwords.txt"; gamedata data;
gamedata *data; storage store;
const char *pwfile = "passwords.txt";
faction *f; faction *f;
FILE * F; FILE * F;
@ -253,24 +283,21 @@ static void test_read_password_external(CuTest *tc) {
f = test_create_faction(0); f = test_create_faction(0);
faction_setpassword(f, password_encode("secret", PASSWORD_DEFAULT)); faction_setpassword(f, password_encode("secret", PASSWORD_DEFAULT));
CuAssertPtrNotNull(tc, f->_password); CuAssertPtrNotNull(tc, f->_password);
data = gamedata_open(path, "wb", RELEASE_VERSION); mstream_init(&data.strm);
CuAssertPtrNotNull(tc, data); gamedata_init(&data, &store, RELEASE_VERSION);
WRITE_TOK(data->store, (const char *)f->_password); WRITE_TOK(data.store, (const char *)f->_password);
WRITE_TOK(data->store, (const char *)f->_password); WRITE_TOK(data.store, (const char *)f->_password);
gamedata_close(data); data.strm.api->rewind(data.strm.handle);
data = gamedata_open(path, "rb", RELEASE_VERSION); data.version = BADCRYPT_VERSION;
CuAssertPtrNotNull(tc, data); _test_read_password(&data, f);
data->version = BADCRYPT_VERSION;
_test_read_password(data, f);
CuAssertPtrEquals(tc, 0, f->_password); CuAssertPtrEquals(tc, 0, f->_password);
F = fopen(pwfile, "wt"); F = fopen(pwfile, "wt");
fprintf(F, "%s:secret\n", itoa36(f->no)); fprintf(F, "%s:secret\n", itoa36(f->no));
fclose(F); fclose(F);
_test_read_password(data, f); _test_read_password(&data, f);
CuAssertPtrNotNull(tc, f->_password); CuAssertPtrNotNull(tc, f->_password);
gamedata_close(data); gamedata_done(&data);
CuAssertTrue(tc, checkpasswd(f, "secret")); CuAssertTrue(tc, checkpasswd(f, "secret"));
CuAssertIntEquals(tc, 0, remove(path));
CuAssertIntEquals(tc, 0, remove(pwfile)); CuAssertIntEquals(tc, 0, remove(pwfile));
} }