From 07d10d9ab0c396bdcbb2a4b0c7c0092ca73fd28c Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 25 Jun 2014 07:22:39 -0700 Subject: [PATCH 1/4] add tests for get_param functions --- src/kernel/CMakeLists.txt | 1 + src/kernel/config.c | 56 ++++++++++++++++++++++----------------- src/kernel/config.test.c | 49 ++++++++++++++++++++++++++++++++++ src/test_eressea.c | 2 ++ 4 files changed, 84 insertions(+), 24 deletions(-) create mode 100644 src/kernel/config.test.c diff --git a/src/kernel/CMakeLists.txt b/src/kernel/CMakeLists.txt index a10dbf21b..f6b940ef2 100644 --- a/src/kernel/CMakeLists.txt +++ b/src/kernel/CMakeLists.txt @@ -1,6 +1,7 @@ project(kernel C) SET(_TEST_FILES +config.test.c ship.test.c spell.test.c ally.test.c diff --git a/src/kernel/config.c b/src/kernel/config.c index b09aa3fff..93fe0a9da 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -1808,22 +1808,23 @@ int getid(void) const char *get_param(const struct param *p, const char *key) { - while (p != NULL) { - if (strcmp(p->name, key) == 0) - return p->data; - p = p->next; - } - return NULL; + while (p != NULL) { + int cmp = strcmp(p->name, key); + if (cmp == 0) { + return p->data; + } + else if (cmp>0) { + break; + } + p = p->next; + } + return NULL; } int get_param_int(const struct param *p, const char *key, int def) { - while (p != NULL) { - if (strcmp(p->name, key) == 0) - return atoi(p->data); - p = p->next; - } - return def; + const char * str = get_param(p, key); + return str ? atoi(str) : def; } static const char *g_datadir; @@ -1879,19 +1880,26 @@ float get_param_flt(const struct param *p, const char *key, float def) void set_param(struct param **p, const char *key, const char *data) { - ++global.cookie; - while (*p != NULL) { - if (strcmp((*p)->name, key) == 0) { - free((*p)->data); - (*p)->data = _strdup(data); - return; + struct param *par; + + ++global.cookie; + while (*p != NULL) { + int cmp = strcmp((*p)->name, key); + if (cmp == 0) { + free((*p)->data); + (*p)->data = _strdup(data); + return; + } + else if (cmp>0) { + break; + } + p = &(*p)->next; } - p = &(*p)->next; - } - *p = malloc(sizeof(param)); - (*p)->name = _strdup(key); - (*p)->data = _strdup(data); - (*p)->next = NULL; + par = malloc(sizeof(param)); + par->name = _strdup(key); + par->data = _strdup(data); + par->next = *p; + *p = par; } void kernel_done(void) diff --git a/src/kernel/config.test.c b/src/kernel/config.test.c new file mode 100644 index 000000000..78562f5dd --- /dev/null +++ b/src/kernel/config.test.c @@ -0,0 +1,49 @@ +#include +#include + +#include + +#include +#include + +static void test_get_set_param(CuTest * tc) +{ + struct param *par = 0; + test_cleanup(); + CuAssertStrEquals(tc, 0, get_param(par, "foo")); + set_param(&par, "foo", "bar"); + set_param(&par, "bar", "foo"); + CuAssertStrEquals(tc, "bar", get_param(par, "foo")); + CuAssertStrEquals(tc, "foo", get_param(par, "bar")); +} + +static void test_param_int(CuTest * tc) +{ + struct param *par = 0; + test_cleanup(); + CuAssertIntEquals(tc, 13, get_param_int(par, "foo", 13)); + set_param(&par, "foo", "23"); + set_param(&par, "bar", "42"); + CuAssertIntEquals(tc, 23, get_param_int(par, "foo", 0)); + CuAssertIntEquals(tc, 42, get_param_int(par, "bar", 0)); +} + +static void test_param_flt(CuTest * tc) +{ + struct param *par = 0; + test_cleanup(); + CuAssertDblEquals(tc, 13, get_param_flt(par, "foo", 13), 0.01); + set_param(&par, "foo", "23.0"); + set_param(&par, "bar", "42.0"); + CuAssertDblEquals(tc, 23.0, get_param_flt(par, "foo", 0.0), 0.01); + CuAssertDblEquals(tc, 42.0, get_param_flt(par, "bar", 0.0), 0.01); +} + +CuSuite *get_config_suite(void) +{ + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_get_set_param); + SUITE_ADD_TEST(suite, test_param_int); + SUITE_ADD_TEST(suite, test_param_flt); + return suite; +} diff --git a/src/test_eressea.c b/src/test_eressea.c index 82f75b6c6..b887f0e59 100644 --- a/src/test_eressea.c +++ b/src/test_eressea.c @@ -21,6 +21,7 @@ CuSuite *get_ship_suite(void); CuSuite *get_spellbook_suite(void); CuSuite *get_spell_suite(void); CuSuite *get_base36_suite(void); +CuSuite *get_config_suite(void); CuSuite *get_bsdstring_suite(void); CuSuite *get_functions_suite(void); CuSuite *get_umlaut_suite(void); @@ -45,6 +46,7 @@ int RunAllTests(void) CuSuiteAddSuite(suite, get_skill_suite()); CuSuiteAddSuite(suite, get_keyword_suite()); /* util */ + CuSuiteAddSuite(suite, get_config_suite()); CuSuiteAddSuite(suite, get_base36_suite()); CuSuiteAddSuite(suite, get_bsdstring_suite()); CuSuiteAddSuite(suite, get_functions_suite()); From af77a1d8e5a8450dfab91f2196edd6f8a3c4fd7a Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 25 Jun 2014 07:25:54 -0700 Subject: [PATCH 2/4] speed up float params, exploiting alphabetic sorting --- src/kernel/config.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/kernel/config.c b/src/kernel/config.c index 93fe0a9da..d697411d3 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -1870,12 +1870,8 @@ void set_basepath(const char *path) float get_param_flt(const struct param *p, const char *key, float def) { - while (p != NULL) { - if (strcmp(p->name, key) == 0) - return (float)atof(p->data); - p = p->next; - } - return def; + const char *str = get_param(p, key); + return str ? (float)atof(str) : def; } void set_param(struct param **p, const char *key, const char *data) From 12e15978b813bb80fe5d334cb912cc7c2b059991 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 25 Jun 2014 08:00:09 -0700 Subject: [PATCH 3/4] read weight, capacity and flags of items --- src/kernel/item.h | 10 +++++----- src/kernel/jsonconf.c | 22 +++++++++++++++++++++- src/kernel/jsonconf.test.c | 17 ++++++++++++++--- src/util/log.c | 3 ++- 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/kernel/item.h b/src/kernel/item.h index 8a1b19e45..fd4073300 100644 --- a/src/kernel/item.h +++ b/src/kernel/item.h @@ -113,11 +113,11 @@ extern "C" { /* bitfield values for item_type::flags */ #define ITF_NONE 0x0000 #define ITF_HERB 0x0001 /* this item is a herb */ -#define ITF_CURSED 0x0010 /* cursed object, cannot be given away */ -#define ITF_NOTLOST 0x0020 /* special object (quests), cannot be lost through death etc. */ -#define ITF_BIG 0x0040 /* big item, e.g. does not fit in a bag of holding */ -#define ITF_ANIMAL 0x0080 /* an animal */ -#define ITF_VEHICLE 0x0100 /* a vehicle, drawn by two animals */ +#define ITF_CURSED 0x0002 /* cursed object, cannot be given away */ +#define ITF_NOTLOST 0x0004 /* special object (quests), cannot be lost through death etc. */ +#define ITF_BIG 0x0008 /* big item, e.g. does not fit in a bag of holding */ +#define ITF_ANIMAL 0x0010 /* an animal */ +#define ITF_VEHICLE 0x0020 /* a vehicle, drawn by two animals */ /* error codes for item_type::use */ #define ECUSTOM -1 diff --git a/src/kernel/jsonconf.c b/src/kernel/jsonconf.c index dbc999d85..415684e1b 100644 --- a/src/kernel/jsonconf.c +++ b/src/kernel/jsonconf.c @@ -139,14 +139,34 @@ void json_building(cJSON *json, building_type *bt) { } } -void json_item(cJSON *json, item_type *st) { +void json_item(cJSON *json, item_type *itype) { cJSON *child; + const char *flags[] = { + "herb", "cursed", "nodrop", "big", "animal", "vehicle", 0 + }; if (json->type!=cJSON_Object) { log_error_n("ship %s is not a json object: %d", json->string, json->type); return; } for (child=json->child;child;child=child->next) { switch(child->type) { + case cJSON_Number: + if (strcmp(child->string, "weight")==0) { + itype->weight = child->valueint; + break; + } + if (strcmp(child->string, "capacity")==0) { + itype->capacity = child->valueint; + break; + } + log_error_n("item %s contains unknown attribute %s", json->string, child->string); + break; + case cJSON_Array: + if (strcmp(child->string, "flags")==0) { + itype->flags = json_flags(child, flags); + break; + } + log_error_n("item %s contains unknown attribute %s", json->string, child->string); case cJSON_Object: default: log_error_n("item %s contains unknown attribute %s", json->string, child->string); diff --git a/src/kernel/jsonconf.test.c b/src/kernel/jsonconf.test.c index 9b9d3ed61..2e104448e 100644 --- a/src/kernel/jsonconf.test.c +++ b/src/kernel/jsonconf.test.c @@ -86,10 +86,11 @@ static void test_races(CuTest * tc) static void test_items(CuTest * tc) { const char * data = "{\"items\": { " - "\"axe\" : {}," - "\"horse\" : {}" + "\"axe\" : { \"weight\" : 2}," + "\"horse\" : { \"flags\" : [ \"animal\", \"big\" ], \"capacity\" : 20 }" "}}"; cJSON *json = cJSON_Parse(data); + const item_type * itype; test_cleanup(); @@ -99,7 +100,17 @@ static void test_items(CuTest * tc) CuAssertPtrEquals(tc, 0, (void *)get_resourcetype(R_HORSE)); json_config(json); - CuAssertPtrNotNull(tc, it_find("axe")); + + itype = it_find("axe"); + CuAssertPtrNotNull(tc, itype); + CuAssertIntEquals(tc, 2, itype->weight); + CuAssertIntEquals(tc, 0, itype->flags); + + itype = it_find("horse"); + CuAssertPtrNotNull(tc, itype); + CuAssertIntEquals(tc, 20, itype->capacity); + CuAssertIntEquals(tc, ITF_ANIMAL|ITF_BIG, itype->flags); + CuAssertPtrNotNull(tc, rt_find("axe")); CuAssertPtrNotNull(tc, (void *)get_resourcetype(R_HORSE)); } diff --git a/src/util/log.c b/src/util/log.c index 3cab62b42..6b371332b 100644 --- a/src/util/log.c +++ b/src/util/log.c @@ -235,6 +235,7 @@ void log_error_n(const char *format, ...) va_list args; va_start(args, format); _log_write(logfile, 0, prefix, format, args); + fputc('\n', logfile); va_end(args); } @@ -245,7 +246,7 @@ void log_error_n(const char *format, ...) va_list args; va_start(args, format); _log_write(stderr, stdio_codepage, prefix, format, args); - fputc('\n', logfile); + fputc('\n', stderr); va_end(args); } } From d0e2ad542ad9be73891901b0370de4bcf576174a Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 25 Jun 2014 14:30:24 -0700 Subject: [PATCH 4/4] tests for basic movement --- src/kernel/jsonconf.c | 3 ++ src/kernel/jsonconf.test.c | 3 +- src/report.c | 2 + tests/init.lua | 2 +- tests/movement.lua | 87 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 tests/movement.lua diff --git a/src/kernel/jsonconf.c b/src/kernel/jsonconf.c index 415684e1b..3f977478f 100644 --- a/src/kernel/jsonconf.c +++ b/src/kernel/jsonconf.c @@ -260,6 +260,9 @@ void json_race(cJSON *json, race *rc) { else if (strcmp(child->string, "weight")==0) { rc->weight = child->valueint; } + else if (strcmp(child->string, "speed")==0) { + rc->speed = child->valueint; + } else if (strcmp(child->string, "capacity")==0) { rc->capacity = child->valueint; } diff --git a/src/kernel/jsonconf.test.c b/src/kernel/jsonconf.test.c index 2e104448e..52a4746f0 100644 --- a/src/kernel/jsonconf.test.c +++ b/src/kernel/jsonconf.test.c @@ -19,7 +19,7 @@ static void check_flag(CuTest *tc, const char *name, int flag) { char data[1024]; const struct race *rc; cJSON *json; - sprintf(data, "{\"races\" : { \"orc\": { \"flags\" : [ \"%s\"] }}}", name); + sprintf(data, "{\"races\" : { \"orc\": { \"speed\" : 1, \"flags\" : [ \"%s\"] }}}", name); json = cJSON_Parse(data); free_races(); @@ -27,6 +27,7 @@ static void check_flag(CuTest *tc, const char *name, int flag) { rc = rc_find("orc"); CuAssertPtrNotNull(tc, rc); CuAssertIntEquals(tc, flag, rc->flags); + CuAssertIntEquals(tc, 1, rc->speed); } static void test_flags(CuTest *tc) { diff --git a/src/report.c b/src/report.c index c7b97e566..9477e26b7 100644 --- a/src/report.c +++ b/src/report.c @@ -648,6 +648,8 @@ static void rps_nowrap(FILE * F, const char *s) const char *x = s; size_t indent = 0; + if (!x) return; + while (*x++ == ' ') ; indent = x - s - 1; if (*(x - 1) && indent && *x == ' ') diff --git a/tests/init.lua b/tests/init.lua index b45439c8d..225e28d9d 100644 --- a/tests/init.lua +++ b/tests/init.lua @@ -1,9 +1,9 @@ -- new tests 2014-06-11 - require "tests.settings" require "tests.config" require "tests.locale" require "tests.regions" require "tests.ships" require "tests.study" +require "tests.movement" diff --git a/tests/movement.lua b/tests/movement.lua new file mode 100644 index 000000000..0685c33dc --- /dev/null +++ b/tests/movement.lua @@ -0,0 +1,87 @@ +require "lunit" + +module("tests.movement", package.seeall, lunit.testcase) + +function setup() + eressea.free_game() + eressea.settings.set("nmr.removenewbie", "0") + eressea.settings.set("nmr.timeout", "0") + eressea.settings.set("rules.ships.storms", "0") + conf = [[{ + "races": { + "human" : { "speed" : 1, "flags" : [ "walk" ] }, + "troll" : {} + }, + "items" : { + "horse" : { + "capacity" : 7000, + "weight" : 5000, + "flags" : [ "big", "animal" ] + } + }, + "terrains" : { + "ocean": { "flags" : [ "sea", "sail" ] }, + "plain": { "flags" : [ "land", "walk", "sail" ] }, + "glacier": { "flags" : [ "land", "walk" ] } + }, + "directions" : { + "de" : { + "east" : "OSTEN", + "west" : "WESTEN" + } + }, + "keywords" : { + "de" : { + "move" : "NACH" + } + } + }]] + + eressea.config.reset() + eressea.config.parse(conf) +end + +function test_walk_to_land() + local r1 = region.create(0, 0, "plain") + local r2 = region.create(1, 0, "plain") + local f = faction.create("test@example.com", "human", "de") + local u = unit.create(f, r1, 1) + u:add_order("NACH O") + process_orders() + assert_equal(r2, u.region) +end + +function test_walk_to_ocean() + local r1 = region.create(0, 0, "plain") + local r2 = region.create(1, 0, "ocean") + local f = faction.create("test@example.com", "human", "de") + local u = unit.create(f, r1, 1) + u:add_order("NACH O") + process_orders() + assert_equal(r1, u.region) +end + +function test_walk_distance() + local r1 = region.create(0, 0, "plain") + local r2 = region.create(1, 0, "plain") + local r3 = region.create(2, 0, "plain") + local f = faction.create("test@example.com", "human", "de") + local u = unit.create(f, r1, 1) + u:add_order("NACH O O") + process_orders() + assert_equal(r2, u.region) +end + +function test_ride_distance() + local r1 = region.create(0, 0, "plain") + local r2 = region.create(1, 0, "plain") + local r3 = region.create(2, 0, "plain") + local f = faction.create("test@example.com", "human", "de") + local u = unit.create(f, r1, 1) + u:add_item("horse", 1) + u:set_skill("riding", 2) + u:add_order("NACH O O") + process_orders() + assert_equal(r3, u.region) +end +