From 96b7c92d81e6e50962a854783b6c2e151bbbe7ef Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Tue, 31 May 2016 01:48:21 +0200 Subject: [PATCH 1/4] fail fast for wrong message parameters simplifies debugging --- src/kernel/messages.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/kernel/messages.c b/src/kernel/messages.c index 330c2feeb..ecdc588a8 100644 --- a/src/kernel/messages.c +++ b/src/kernel/messages.c @@ -194,6 +194,7 @@ message *msg_message(const char *name, const char *sig, ...) } else { log_error("invalid parameter %s for message type %s\n", paramname, mtype->name); + assert(!"invalid parameter for message type"); } while (*ic && !isalnum(*ic)) ic++; @@ -201,6 +202,7 @@ message *msg_message(const char *name, const char *sig, ...) va_end(vargs); if (argnum != mtype->nparameters) { log_error("not enough parameters for message type %s\n", mtype->name); + assert(!"not enough parameters for message type"); } return msg_create(mtype, args); From ce312afc95caac39420b5173a3429646f6f4f218 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Tue, 31 May 2016 01:49:37 +0200 Subject: [PATCH 2/4] fix dragon growl for regions with an apostrophe --- res/core/messages.xml | 11 ++++++ src/monsters.c | 30 ++++------------ src/monsters.test.c | 84 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 24 deletions(-) diff --git a/res/core/messages.xml b/res/core/messages.xml index 15de4a153..410b673e1 100644 --- a/res/core/messages.xml +++ b/res/core/messages.xml @@ -8441,4 +8441,15 @@ "$unit($unit) in $region($region): '$order($command)' - Heroes cannot recruit." + + + + + + + + "$unit($dragon): \"$if($eq($choice,0), "Groaaaam... ", "")$if($eq($choice,1), "Chrrrr... ", "")$if($eq($choice,2), "Roooarrr... ", "")$if($eq($choice,3), "Tschrrrk... ", "")$if($eq($choice,4), "Shhhhhh... ", "")$if($eq($number,1), "Ich rieche", "Wir riechen") etwas in $region($target)\"." + "$unit($dragon): \"$if($eq($choice,0), "Groaaaam... ", "")$if($eq($choice,1), "Chrrrr... ", "")$if($eq($choice,2), "Roooarrr... ", "")$if($eq($choice,3), "Tschrrrk... ", "")$if($eq($choice,4), "Shhhhhh... ", "")$if($eq($number,1), "I smell", "We smell") something in $region($target)\"." + + diff --git a/src/monsters.c b/src/monsters.c index 674ab0999..e5f07c2f8 100644 --- a/src/monsters.c +++ b/src/monsters.c @@ -547,21 +547,13 @@ static order *monster_seeks_target(region * r, unit * u) } #endif -static const char *random_growl(void) +void random_growl(const unit *u, region *target, int rand) { - switch (rng_int() % 5) { - case 0: - return "Groammm"; - case 1: - return "Roaaarrrr"; - case 2: - return "Chhhhhhhhhh"; - case 3: - return "Tschrrrkk"; - case 4: - return "Schhhh"; + const struct locale *lang = u->faction->locale; + if (rname(target, lang)) { + message *msg = msg_message("dragon_growl", "dragon number target choice", u, u->number, target, rand); + ADDMSG(&u->region->msgs, msg); } - return ""; } extern struct attrib_type at_direction; @@ -707,17 +699,7 @@ static order *plan_dragon(unit * u) reduce_weight(u); } if (rng_int() % 100 < 15) { - const struct locale *lang = u->faction->locale; - /* do a growl */ - if (rname(tr, lang)) { - addlist(&u->orders, - create_order(K_MAIL, lang, "%s '%s... %s %s %s'", - LOC(lang, parameters[P_REGION]), - random_growl(), - u->number == - 1 ? "Ich rieche" : "Wir riechen", - "etwas in", rname(tr, u->faction->locale))); - } + random_growl(u, tr, rng_int() % 5); } } else { diff --git a/src/monsters.test.c b/src/monsters.test.c index a7a4d9b18..41b655cd6 100644 --- a/src/monsters.test.c +++ b/src/monsters.test.c @@ -12,10 +12,13 @@ #include "monster.h" #include "guard.h" +#include "reports.h" #include "skill.h" #include "study.h" #include +#include +#include #include #include @@ -185,11 +188,83 @@ static void test_dragon_attacks_the_rich(CuTest * tc) test_cleanup(); } +typedef struct msg_info { + const char *name; + int numpar; + const char **argv; + const char **pnames, **tnames; + variant *values; +} msg_info; + +static msg_info *test_create_messagetype(const struct locale *lang, const char *name, int num_args, ...) { + va_list vargs; + const message_type *mtype; + char zBuffer[128]; + int i; + msg_info *info = malloc(sizeof(msg_info)); + info->argv = calloc(num_args + 1, sizeof(char *)); + info->pnames = calloc(num_args, sizeof(char *)); + info->tnames = calloc(num_args, sizeof(char *)); + info->values = calloc(num_args, sizeof(variant_type)); + + va_start(vargs, num_args); + + info->numpar = num_args; + info->name = name; + + for(i = 0; ipnames[i] = va_arg(vargs, char *); + info->tnames[i] = va_arg(vargs, char *); + sprintf(zBuffer, "%s:%s", info->pnames[i], info->tnames[i]); + info->argv[i] = _strdup(zBuffer); + } + + mtype = mt_register(mt_new(name, info->argv)); + nrt_register(mtype, lang, "mocktext", 0, "mocksection"); + + for(i = 0; itypes[i]->vtype == VAR_VOIDPTR) { + info->values[i].v = va_arg(vargs, char *); + } else if (mtype->types[i]->vtype == VAR_INT) { + info->values[i].i = va_arg(vargs, int); + } else { + assert(!"unknown variant type"); + } + } + va_end(vargs); + return info; +} + +static void assert_message(CuTest * tc, message *msg, msg_info *info) +{ + const message_type *mtype = msg->type; + assert(mtype); + int i; + + CuAssertStrEquals(tc, info->name, mtype->name); + CuAssertIntEquals(tc, info->numpar, mtype->nparameters); + for (i = 0; i != mtype->nparameters; ++i) { + CuAssertStrEquals(tc, info->pnames[i], mtype->pnames[i]); + CuAssertStrEquals(tc, info->tnames[i], mtype->types[i]->name); + if (mtype->types[i]->vtype == VAR_VOIDPTR) { + CuAssertPtrEquals(tc, info->values[i].v, msg->parameters[i].v); + } else if (mtype->types[i]->vtype == VAR_INT) { + CuAssertIntEquals(tc, info->values[i].i, msg->parameters[i].i); + } else { + assert(!"unknown variant type"); + } + } +} + +extern void random_growl(const unit *u, region *tr, int rand); + static void test_dragon_moves(CuTest * tc) { faction *f, *f2; region *r; unit *u, *m; + struct message *msg; + struct msg_info *msginfo; create_monsters(&f, &f2, &u, &m); rsetmoney(findregion(1, 0), 1000); @@ -202,6 +277,15 @@ static void test_dragon_moves(CuTest * tc) plan_monsters(f2); CuAssertPtrNotNull(tc, find_order("move east", m)); + + register_reports(); + msginfo = test_create_messagetype(f->locale, "dragon_growl", 4, "dragon", "unit", "number", "int", "target", "region", "choice", "int", m, 1, findregion(1,0), 3); + + random_growl(m, findregion(1, 0), 3); + + msg = test_get_last_message(r->msgs); + assert_message(tc, msg, msginfo); + test_cleanup(); } From cafa29426f5a295a4d131d6f135970f11e9f9513 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Tue, 31 May 2016 10:37:01 +0200 Subject: [PATCH 3/4] simplified message_test --- src/monsters.test.c | 74 ++------------------------------------------- src/tests.c | 23 ++++++++++++++ src/tests.h | 1 + 3 files changed, 26 insertions(+), 72 deletions(-) diff --git a/src/monsters.test.c b/src/monsters.test.c index 41b655cd6..387ac3d5d 100644 --- a/src/monsters.test.c +++ b/src/monsters.test.c @@ -188,74 +188,6 @@ static void test_dragon_attacks_the_rich(CuTest * tc) test_cleanup(); } -typedef struct msg_info { - const char *name; - int numpar; - const char **argv; - const char **pnames, **tnames; - variant *values; -} msg_info; - -static msg_info *test_create_messagetype(const struct locale *lang, const char *name, int num_args, ...) { - va_list vargs; - const message_type *mtype; - char zBuffer[128]; - int i; - msg_info *info = malloc(sizeof(msg_info)); - info->argv = calloc(num_args + 1, sizeof(char *)); - info->pnames = calloc(num_args, sizeof(char *)); - info->tnames = calloc(num_args, sizeof(char *)); - info->values = calloc(num_args, sizeof(variant_type)); - - va_start(vargs, num_args); - - info->numpar = num_args; - info->name = name; - - for(i = 0; ipnames[i] = va_arg(vargs, char *); - info->tnames[i] = va_arg(vargs, char *); - sprintf(zBuffer, "%s:%s", info->pnames[i], info->tnames[i]); - info->argv[i] = _strdup(zBuffer); - } - - mtype = mt_register(mt_new(name, info->argv)); - nrt_register(mtype, lang, "mocktext", 0, "mocksection"); - - for(i = 0; itypes[i]->vtype == VAR_VOIDPTR) { - info->values[i].v = va_arg(vargs, char *); - } else if (mtype->types[i]->vtype == VAR_INT) { - info->values[i].i = va_arg(vargs, int); - } else { - assert(!"unknown variant type"); - } - } - va_end(vargs); - return info; -} - -static void assert_message(CuTest * tc, message *msg, msg_info *info) -{ - const message_type *mtype = msg->type; - assert(mtype); - int i; - - CuAssertStrEquals(tc, info->name, mtype->name); - CuAssertIntEquals(tc, info->numpar, mtype->nparameters); - for (i = 0; i != mtype->nparameters; ++i) { - CuAssertStrEquals(tc, info->pnames[i], mtype->pnames[i]); - CuAssertStrEquals(tc, info->tnames[i], mtype->types[i]->name); - if (mtype->types[i]->vtype == VAR_VOIDPTR) { - CuAssertPtrEquals(tc, info->values[i].v, msg->parameters[i].v); - } else if (mtype->types[i]->vtype == VAR_INT) { - CuAssertIntEquals(tc, info->values[i].i, msg->parameters[i].i); - } else { - assert(!"unknown variant type"); - } - } -} - extern void random_growl(const unit *u, region *tr, int rand); static void test_dragon_moves(CuTest * tc) @@ -264,7 +196,6 @@ static void test_dragon_moves(CuTest * tc) region *r; unit *u, *m; struct message *msg; - struct msg_info *msginfo; create_monsters(&f, &f2, &u, &m); rsetmoney(findregion(1, 0), 1000); @@ -278,13 +209,12 @@ static void test_dragon_moves(CuTest * tc) CuAssertPtrNotNull(tc, find_order("move east", m)); - register_reports(); - msginfo = test_create_messagetype(f->locale, "dragon_growl", 4, "dragon", "unit", "number", "int", "target", "region", "choice", "int", m, 1, findregion(1,0), 3); + mt_register(mt_new_va("dragon_growl", "dragon:unit", "number:int", "target:region", "choice:int", 0)); random_growl(m, findregion(1, 0), 3); msg = test_get_last_message(r->msgs); - assert_message(tc, msg, msginfo); + assert_message(tc, msg, "dragon_growl", 4, m, 1, findregion(1,0), 3); test_cleanup(); } diff --git a/src/tests.c b/src/tests.c index a0d54a4cc..c50065e9c 100644 --- a/src/tests.c +++ b/src/tests.c @@ -390,6 +390,29 @@ void test_clear_messages(faction *f) { } } +void assert_message(CuTest * tc, message *msg, char *name, int numpar, ...) +{ + va_list vargs; + const message_type *mtype = msg->type; + assert(mtype); + int i; + + va_start(vargs, numpar); + + CuAssertStrEquals(tc, name, mtype->name); + CuAssertIntEquals(tc, numpar, mtype->nparameters); + for (i = 0; i != mtype->nparameters; ++i) { + variant value = va_arg(vargs, variant); + if (mtype->types[i]->vtype == VAR_VOIDPTR) { + CuAssertPtrEquals(tc, value.v, msg->parameters[i].v); + } else if (mtype->types[i]->vtype == VAR_INT) { + CuAssertIntEquals(tc, value.i, msg->parameters[i].i); + } else { + assert(!"unknown variant type"); + } + } +} + void disabled_test(void *suite, void (*test)(CuTest *), const char *name) { (void)test; fprintf(stderr, "%s: SKIP\n", name); diff --git a/src/tests.h b/src/tests.h index 9836c42ab..fafb1755d 100644 --- a/src/tests.h +++ b/src/tests.h @@ -54,6 +54,7 @@ extern "C" { struct message * test_find_messagetype(struct message_list *msgs, const char *name); struct message * test_get_last_message(struct message_list *mlist); void test_clear_messages(struct faction *f); + void assert_message(struct CuTest * tc, struct message *msg, char *name, int numpar, ...); void disabled_test(void *suite, void (*)(struct CuTest *), const char *name); From c5014fd76691f792bcd0d169ad4321e86a0609ca Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Sat, 11 Jun 2016 13:47:38 +0200 Subject: [PATCH 4/4] integrated Ennos suggestions for dragon growls Dragons now growl 20% more elegantly! --- res/core/de/strings.xml | 18 ++++++++++++++++++ res/core/messages.xml | 6 +++--- src/kernel/messages.c | 2 -- src/monsters.c | 12 +++++++++++- src/monsters.test.c | 8 ++++++-- src/tests.c | 32 ++++++++++++++++---------------- src/tests.h | 6 +++++- src/util/log.test.c | 4 ++-- 8 files changed, 61 insertions(+), 27 deletions(-) diff --git a/res/core/de/strings.xml b/res/core/de/strings.xml index 75f57a6b0..c9a2ae616 100644 --- a/res/core/de/strings.xml +++ b/res/core/de/strings.xml @@ -7574,4 +7574,22 @@ + + Groaamm... + + + Tschrrrk... + Tshrrrk... + + + Schhhhh... + Shhhhhh... + + + Roaarrr... + + + Chrrr... + + diff --git a/res/core/messages.xml b/res/core/messages.xml index 410b673e1..99cf4d145 100644 --- a/res/core/messages.xml +++ b/res/core/messages.xml @@ -8446,10 +8446,10 @@ - + - "$unit($dragon): \"$if($eq($choice,0), "Groaaaam... ", "")$if($eq($choice,1), "Chrrrr... ", "")$if($eq($choice,2), "Roooarrr... ", "")$if($eq($choice,3), "Tschrrrk... ", "")$if($eq($choice,4), "Shhhhhh... ", "")$if($eq($number,1), "Ich rieche", "Wir riechen") etwas in $region($target)\"." - "$unit($dragon): \"$if($eq($choice,0), "Groaaaam... ", "")$if($eq($choice,1), "Chrrrr... ", "")$if($eq($choice,2), "Roooarrr... ", "")$if($eq($choice,3), "Tschrrrk... ", "")$if($eq($choice,4), "Shhhhhh... ", "")$if($eq($number,1), "I smell", "We smell") something in $region($target)\"." + "$unit($dragon): \"$localize($growl) $if($eq($number,1), "Ich rieche", "Wir riechen") etwas in $region($target)\"." + "$unit($dragon): \"$localize($growl) $if($eq($number,1), "I smell", "We smell") something in $region($target)\"." diff --git a/src/kernel/messages.c b/src/kernel/messages.c index ecdc588a8..330c2feeb 100644 --- a/src/kernel/messages.c +++ b/src/kernel/messages.c @@ -194,7 +194,6 @@ message *msg_message(const char *name, const char *sig, ...) } else { log_error("invalid parameter %s for message type %s\n", paramname, mtype->name); - assert(!"invalid parameter for message type"); } while (*ic && !isalnum(*ic)) ic++; @@ -202,7 +201,6 @@ message *msg_message(const char *name, const char *sig, ...) va_end(vargs); if (argnum != mtype->nparameters) { log_error("not enough parameters for message type %s\n", mtype->name); - assert(!"not enough parameters for message type"); } return msg_create(mtype, args); diff --git a/src/monsters.c b/src/monsters.c index e5f07c2f8..2fc2fcde3 100644 --- a/src/monsters.c +++ b/src/monsters.c @@ -550,8 +550,18 @@ static order *monster_seeks_target(region * r, unit * u) void random_growl(const unit *u, region *target, int rand) { const struct locale *lang = u->faction->locale; + const char *growl; + switch(rand){ + case 1: growl = "growl1"; break; + case 2: growl = "growl2"; break; + case 3: growl = "growl3"; break; + case 4: growl = "growl4"; break; + default: growl = "growl0"; + } + + if (rname(target, lang)) { - message *msg = msg_message("dragon_growl", "dragon number target choice", u, u->number, target, rand); + message *msg = msg_message("dragon_growl", "dragon number target growl", u, u->number, target, growl); ADDMSG(&u->region->msgs, msg); } } diff --git a/src/monsters.test.c b/src/monsters.test.c index 387ac3d5d..06c434940 100644 --- a/src/monsters.test.c +++ b/src/monsters.test.c @@ -209,12 +209,16 @@ static void test_dragon_moves(CuTest * tc) CuAssertPtrNotNull(tc, find_order("move east", m)); - mt_register(mt_new_va("dragon_growl", "dragon:unit", "number:int", "target:region", "choice:int", 0)); + mt_register(mt_new_va("dragon_growl", "dragon:unit", "number:int", "target:region", "growl:string", 0)); random_growl(m, findregion(1, 0), 3); msg = test_get_last_message(r->msgs); - assert_message(tc, msg, "dragon_growl", 4, m, 1, findregion(1,0), 3); + assert_message(tc, msg, "dragon_growl", 4); + assert_pointer_parameter(tc, msg, 0, m); + assert_int_parameter(tc, msg, 1, 1); + assert_pointer_parameter(tc, msg, 2, findregion(1,0)); + assert_string_parameter(tc, msg, 3, "growl3"); test_cleanup(); } diff --git a/src/tests.c b/src/tests.c index c50065e9c..5b8c2a945 100644 --- a/src/tests.c +++ b/src/tests.c @@ -390,27 +390,27 @@ void test_clear_messages(faction *f) { } } -void assert_message(CuTest * tc, message *msg, char *name, int numpar, ...) -{ - va_list vargs; +void assert_message(CuTest * tc, message *msg, char *name, int numpar) { const message_type *mtype = msg->type; assert(mtype); - int i; - - va_start(vargs, numpar); CuAssertStrEquals(tc, name, mtype->name); CuAssertIntEquals(tc, numpar, mtype->nparameters); - for (i = 0; i != mtype->nparameters; ++i) { - variant value = va_arg(vargs, variant); - if (mtype->types[i]->vtype == VAR_VOIDPTR) { - CuAssertPtrEquals(tc, value.v, msg->parameters[i].v); - } else if (mtype->types[i]->vtype == VAR_INT) { - CuAssertIntEquals(tc, value.i, msg->parameters[i].i); - } else { - assert(!"unknown variant type"); - } - } +} + +void assert_pointer_parameter(CuTest * tc, message *msg, int index, void *arg) { + const message_type *mtype = (msg)->type; + CuAssertIntEquals((tc), VAR_VOIDPTR, mtype->types[(index)]->vtype);CuAssertPtrEquals((tc), (arg), msg->parameters[(index)].v); +} + +void assert_int_parameter(CuTest * tc, message *msg, int index, int arg) { + const message_type *mtype = (msg)->type; + CuAssertIntEquals((tc), VAR_INT, mtype->types[(index)]->vtype);CuAssertIntEquals((tc), (arg), msg->parameters[(index)].i); +} + +void assert_string_parameter(CuTest * tc, message *msg, int index, const char *arg) { + const message_type *mtype = (msg)->type; + CuAssertIntEquals((tc), VAR_VOIDPTR, mtype->types[(index)]->vtype);CuAssertStrEquals((tc), (arg), msg->parameters[(index)].v); } void disabled_test(void *suite, void (*test)(CuTest *), const char *name) { diff --git a/src/tests.h b/src/tests.h index fafb1755d..d18ff6456 100644 --- a/src/tests.h +++ b/src/tests.h @@ -54,7 +54,11 @@ extern "C" { struct message * test_find_messagetype(struct message_list *msgs, const char *name); struct message * test_get_last_message(struct message_list *mlist); void test_clear_messages(struct faction *f); - void assert_message(struct CuTest * tc, struct message *msg, char *name, int numpar, ...); + void assert_message(struct CuTest * tc, struct message *msg, char *name, int numpar); + + void assert_pointer_parameter(struct CuTest * tc, struct message *msg, int index, void *arg); + void assert_int_parameter(struct CuTest * tc, struct message *msg, int index, int arg); + void assert_string_parameter(struct CuTest * tc, struct message *msg, int index, const char *arg); void disabled_test(void *suite, void (*)(struct CuTest *), const char *name); diff --git a/src/util/log.test.c b/src/util/log.test.c index 2750d4b1e..95cbefa96 100644 --- a/src/util/log.test.c +++ b/src/util/log.test.c @@ -23,10 +23,10 @@ static void test_logging(CuTest * tc) struct log_t * id2 = log_create(LOG_CPWARNING, str2, log_string); CuAssertTrue(tc, id1!=id2); log_warning("Hello %s", "World"); - CuAssertStrEquals(tc, str1, "World"); - CuAssertStrEquals(tc, str2, "World"); log_destroy(id1); log_destroy(id2); + CuAssertStrEquals(tc, "World", str1); + CuAssertStrEquals(tc, "World", str2); } CuSuite *get_log_suite(void)