forked from github/server
add a test and fix potential crashes in SABOTAGE command.
sometimes even a simple test will uncover a ton of small errors.
This commit is contained in:
parent
e25d3c8ed1
commit
1e669472a6
37
src/spy.c
37
src/spy.c
|
@ -394,7 +394,7 @@ static int try_destruction(unit * u, unit * u2, const ship * sh, int skilldiff)
|
||||||
return 1; /* success */
|
return 1; /* success */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur)
|
static void sink_ship(region * r, ship * sh, unit * saboteur)
|
||||||
{
|
{
|
||||||
unit **ui, *u;
|
unit **ui, *u;
|
||||||
region *safety = r;
|
region *safety = r;
|
||||||
|
@ -404,6 +404,9 @@ static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur)
|
||||||
message *sink_msg = NULL;
|
message *sink_msg = NULL;
|
||||||
faction *f;
|
faction *f;
|
||||||
|
|
||||||
|
assert(r);
|
||||||
|
assert(sh);
|
||||||
|
assert(saboteur);
|
||||||
for (f = NULL, u = r->units; u; u = u->next) {
|
for (f = NULL, u = r->units; u; u = u->next) {
|
||||||
/* slight optimization to avoid dereferencing u->faction each time */
|
/* slight optimization to avoid dereferencing u->faction each time */
|
||||||
if (f != u->faction) {
|
if (f != u->faction) {
|
||||||
|
@ -426,7 +429,7 @@ static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (ui = &r->units; *ui; ui = &(*ui)->next) {
|
for (ui = &r->units; *ui;) {
|
||||||
unit *u = *ui;
|
unit *u = *ui;
|
||||||
|
|
||||||
/* inform this faction about the sinking ship: */
|
/* inform this faction about the sinking ship: */
|
||||||
|
@ -471,13 +474,14 @@ static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur)
|
||||||
add_message(&u->faction->msgs, msg);
|
add_message(&u->faction->msgs, msg);
|
||||||
msg_release(msg);
|
msg_release(msg);
|
||||||
if (dead == u->number) {
|
if (dead == u->number) {
|
||||||
/* the poor creature, she dies */
|
if (remove_unit(ui, u) == 0) {
|
||||||
if (remove_unit(ui, u) != 0) {
|
/* ui is already pointing at u->next */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
ui = &u->next;
|
ui = &u->next;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sink_msg)
|
if (sink_msg)
|
||||||
msg_release(sink_msg);
|
msg_release(sink_msg);
|
||||||
/* finally, get rid of the ship */
|
/* finally, get rid of the ship */
|
||||||
|
@ -487,19 +491,21 @@ static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur)
|
||||||
int sabotage_cmd(unit * u, struct order *ord)
|
int sabotage_cmd(unit * u, struct order *ord)
|
||||||
{
|
{
|
||||||
const char *s;
|
const char *s;
|
||||||
int i;
|
param_t p;
|
||||||
ship *sh;
|
ship *sh;
|
||||||
unit *u2;
|
unit *u2;
|
||||||
char buffer[DISPLAYSIZE];
|
region *r;
|
||||||
region *r = u->region;
|
int skdiff = INT_MAX;
|
||||||
int skdiff;
|
|
||||||
|
assert(u);
|
||||||
|
assert(ord);
|
||||||
|
|
||||||
init_order(ord);
|
init_order(ord);
|
||||||
s = getstrtoken();
|
s = getstrtoken();
|
||||||
|
|
||||||
i = findparam(s, u->faction->locale);
|
p = findparam(s, u->faction->locale);
|
||||||
|
|
||||||
switch (i) {
|
switch (p) {
|
||||||
case P_SHIP:
|
case P_SHIP:
|
||||||
sh = u->ship;
|
sh = u->ship;
|
||||||
if (!sh) {
|
if (!sh) {
|
||||||
|
@ -507,10 +513,13 @@ int sabotage_cmd(unit * u, struct order *ord)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
u2 = ship_owner(sh);
|
u2 = ship_owner(sh);
|
||||||
|
r = u->region;
|
||||||
|
if (u2->faction != u->faction) {
|
||||||
skdiff =
|
skdiff =
|
||||||
eff_skill(u, SK_SPY, r) - crew_skill(r, u2->faction, sh, SK_PERCEPTION);
|
eff_skill(u, SK_SPY, r) - crew_skill(r, u2->faction, sh, SK_PERCEPTION);
|
||||||
|
}
|
||||||
if (try_destruction(u, u2, sh, skdiff)) {
|
if (try_destruction(u, u2, sh, skdiff)) {
|
||||||
sink_ship(r, sh, buffer, u);
|
sink_ship(r, sh, u);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -5,9 +5,11 @@
|
||||||
#include <kernel/region.h>
|
#include <kernel/region.h>
|
||||||
#include <kernel/unit.h>
|
#include <kernel/unit.h>
|
||||||
#include <kernel/faction.h>
|
#include <kernel/faction.h>
|
||||||
|
#include <kernel/order.h>
|
||||||
#include <kernel/item.h>
|
#include <kernel/item.h>
|
||||||
#include <kernel/messages.h>
|
#include <kernel/messages.h>
|
||||||
#include <util/attrib.h>
|
#include <util/attrib.h>
|
||||||
|
#include <util/language.h>
|
||||||
#include <util/message.h>
|
#include <util/message.h>
|
||||||
#include <util/crmessage.h>
|
#include <util/crmessage.h>
|
||||||
#include <tests.h>
|
#include <tests.h>
|
||||||
|
@ -16,6 +18,7 @@
|
||||||
|
|
||||||
#include "spy.h"
|
#include "spy.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <CuTest.h>
|
#include <CuTest.h>
|
||||||
|
@ -98,12 +101,36 @@ static void test_all_spy_message(CuTest *tc) {
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_sabotage_self(CuTest *tc) {
|
||||||
|
unit *u;
|
||||||
|
region *r;
|
||||||
|
order *ord;
|
||||||
|
struct locale *lang;
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
lang = get_or_create_locale("de");
|
||||||
|
locale_setstring(lang, parameters[P_SHIP], "SCHIFF");
|
||||||
|
test_create_world();
|
||||||
|
init_locales();
|
||||||
|
|
||||||
|
r = test_create_region(0, 0, NULL);
|
||||||
|
assert(r);
|
||||||
|
u = test_create_unit(test_create_faction(NULL), r);
|
||||||
|
assert(u && u->faction && u->region==r);
|
||||||
|
u->ship = test_create_ship(r, test_create_shiptype("boat"));
|
||||||
|
assert(u->ship);
|
||||||
|
ord = create_order(K_SABOTAGE, lang, "SCHIFF");
|
||||||
|
assert(ord);
|
||||||
|
CuAssertIntEquals(tc, 0, sabotage_cmd(u, ord));
|
||||||
|
CuAssertPtrEquals(tc, 0, r->ships);
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
CuSuite *get_spy_suite(void)
|
CuSuite *get_spy_suite(void)
|
||||||
{
|
{
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
SUITE_ADD_TEST(suite, test_simple_spy_message);
|
SUITE_ADD_TEST(suite, test_simple_spy_message);
|
||||||
SUITE_ADD_TEST(suite, test_all_spy_message);
|
SUITE_ADD_TEST(suite, test_all_spy_message);
|
||||||
|
SUITE_ADD_TEST(suite, test_sabotage_self);
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue