From a9ecd1f55e14ec881c915a95f98101cbf23b6d2c Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 19 Aug 2015 14:37:51 +0200 Subject: [PATCH] replace all at_travelunit code with travelthru_map calls. welcome to callback hell. this should stop the buffer for travelthru from running over. tests for this should be hell, and I still owe writing them. --- res/core/de/strings.xml | 11 +--- src/CMakeLists.txt | 1 + src/creport.c | 78 ++++++++++++++---------- src/move.c | 4 +- src/report.c | 103 ++++++++++++++++++++++++++++++- src/report.h | 3 +- src/reports.c | 112 ++++++++++++++++++++++------------ src/reports.h | 2 + src/reports.test.c | 26 ++++++-- src/test_eressea.c | 1 + src/travelthru.c | 130 ++++++++++++---------------------------- src/travelthru.h | 9 +-- src/travelthru.test.c | 80 +++++++++++++++++++++++++ 13 files changed, 374 insertions(+), 186 deletions(-) create mode 100644 src/travelthru.test.c diff --git a/res/core/de/strings.xml b/res/core/de/strings.xml index d5b6dba34..ffd0f82dd 100644 --- a/res/core/de/strings.xml +++ b/res/core/de/strings.xml @@ -6947,14 +6947,9 @@ is helping - - hat die Region durchquert. - passed through the region. - - - - haben die Region durchquert. - passed through the region. + + Die Region wurde durchquert von + The region was crossed by diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b04631e6a..a67ad35b4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -181,6 +181,7 @@ set(TESTS_SRC vortex.test.c tests.test.c reports.test.c + travelthru.test.c callback.test.c direction.test.c economy.test.c diff --git a/src/creport.c b/src/creport.c index 6794c33d6..cbfd0f181 100644 --- a/src/creport.c +++ b/src/creport.c @@ -1190,7 +1190,7 @@ static void cr_output_resources(FILE * F, report_context * ctx, seen_region * sr) { char cbuf[BUFFERSIZE], *pos = cbuf; - region *r = sr->r; + const region *r = sr->r; faction *f = ctx->f; resource_report result[MAX_RAWMATERIALS]; int n, size = report_resources(sr, result, MAX_RAWMATERIALS, f); @@ -1236,6 +1236,49 @@ cr_region_header(FILE * F, int plid, int nx, int ny, int uid) fprintf(F, "%d;id\n", uid); } +typedef struct travel_data { + const faction *f; + FILE *file; + int n; +} travel_data; + +static void cb_cr_travelthru_ship(const region *r, unit *u, void *cbdata) { + travel_data *data = (travel_data *)cbdata; + const faction *f = data->f; + FILE *F = data->file; + + if (u->ship && travelthru_cansee(r, f, u)) { + if (data->n++ == 0) { + fprintf(F, "DURCHSCHIFFUNG\n"); + } + fprintf(F, "\"%s\"\n", shipname(u->ship)); + } +} + +static void cb_cr_travelthru_unit(const region *r, unit *u, void *cbdata) { + travel_data *data = (travel_data *)cbdata; + const faction *f = data->f; + FILE *F = data->file; + + if (!u->ship && travelthru_cansee(r, f, u)) { + if (data->n++ == 0) { + fprintf(F, "DURCHREISE\n"); + } + fprintf(F, "\"%s\"\n", unitname(u)); + } +} + +static void cr_output_travelthru(FILE *F, region *r, const faction *f) { + /* describe both passed and inhabited regions */ + travel_data cbdata = { 0 }; + cbdata.f = f; + cbdata.file = F; + cbdata.n = 0; + travelthru_map(r, cb_cr_travelthru_ship, &cbdata); + cbdata.n = 0; + travelthru_map(r, cb_cr_travelthru_unit, &cbdata); +} + static void cr_output_region(FILE * F, report_context * ctx, seen_region * sr) { faction *f = ctx->f; @@ -1410,38 +1453,7 @@ static void cr_output_region(FILE * F, report_context * ctx, seen_region * sr) } } - /* describe both passed and inhabited regions */ - if (fval(r, RF_TRAVELUNIT)) { - bool seeunits = false, seeships = false; - const attrib *ru; - /* show units pulled through region */ - for (ru = a_find(r->attribs, &at_travelunit); - ru && ru->type == &at_travelunit; ru = ru->next) { - unit *u = (unit *)ru->data.v; - if (cansee_durchgezogen(f, r, u, 0) && r != u->region) { - if (u->ship && ship_owner(u->ship) == u) { - if (!seeships) { - fprintf(F, "DURCHSCHIFFUNG\n"); - } - seeships = true; - fprintf(F, "\"%s\"\n", shipname(u->ship)); - } - } - } - for (ru = a_find(r->attribs, &at_travelunit); - ru && ru->type == &at_travelunit; ru = ru->next) { - unit *u = (unit *)ru->data.v; - if (cansee_durchgezogen(f, r, u, 0) && r != u->region) { - if (!u->ship) { - if (!seeunits) { - fprintf(F, "DURCHREISE\n"); - } - seeunits = true; - fprintf(F, "\"%s\"\n", unitname(u)); - } - } - } - } + cr_output_travelthru(F, r, f); if (sr->mode == see_unit || sr->mode == see_travel) { message_list *mlist = r_getmessages(r, f); cr_output_messages(F, r->msgs, f); diff --git a/src/move.c b/src/move.c index de1cb05bd..f775acb79 100644 --- a/src/move.c +++ b/src/move.c @@ -567,12 +567,12 @@ static void leave_trail(ship * sh, region * from, region_list * route) } static void -mark_travelthru(const unit * u, region * r, const region_list * route, +mark_travelthru(unit * u, region * r, const region_list * route, const region_list * route_end) { /* kein travelthru in der letzten region! */ while (route != route_end) { - travelthru(u, r); + travelthru_add(r, u); r = route->data; route = route->next; } diff --git a/src/report.c b/src/report.c index d02d9a7fc..b63b45755 100644 --- a/src/report.c +++ b/src/report.c @@ -141,6 +141,7 @@ void write_spaces(stream *out, size_t num) { } } + static void centre(stream *out, const char *s, bool breaking) { /* Bei Namen die genau 80 Zeichen lang sind, kann es hier Probleme @@ -164,7 +165,7 @@ static void centre(stream *out, const char *s, bool breaking) } } -void +static void paragraph(stream *out, const char *str, ptrdiff_t indent, int hanging_indent, char marker) { @@ -1929,6 +1930,104 @@ static void nr_paragraph(stream *out, message * m, faction * f) paragraph(out, buf, 0, 0, 0); } +typedef struct cb_data { + stream *out; + char *start, *writep; + size_t size; + const faction *f; + int maxtravel, counter; +} cb_data; + +static void init_cb(cb_data *data, stream *out, char *buffer, size_t size, const faction *f) { + data->out = out; + data->writep = buffer; + data->start = buffer; + data->size = size; + data->f = f; + data->maxtravel = 0; + data->counter = 0; +} + +static void cb_write_travelthru(region *r, unit *u, void *cbdata) { + cb_data *data = (cb_data *)cbdata; + const faction *f = data->f; + + if (data->counter >= data->maxtravel) { + return; + } + if (travelthru_cansee(r, f, u)) { + ++data->counter; + do { + size_t len, size = data->size - (data->writep - data->start); + const char *str; + char *writep = data->writep; + + if (u->ship != NULL) { + str = shipname(u->ship); + } + else { + str = unitname(u); + } + len = strlen(str); + if (len < size && data->counter <= data->maxtravel) { + memcpy(writep, str, len); + writep += len; + size -= len; + if (data->counter == data->maxtravel) { + str = "."; + } + else if (data->counter + 1 == data->maxtravel) { + str = LOC(f->locale, "list_and"); + } + else { + str = ", "; + } + len = strlen(str); + if (len < size) { + memcpy(writep, str, len); + writep += len; + size -= len; + data->writep = writep; + } + } + if (len >= size || data->counter == data->maxtravel) { + // buffer is full + *writep = 0; + paragraph(data->out, data->start, 0, 0, 0); + data->writep = data->start; + if (data->counter == data->maxtravel) { + break; + } + } + } while (data->writep == data->start); + } +} + +void write_travelthru(stream *out, region * r, const faction * f) +{ + int maxtravel; + char buf[8192]; + + assert(r); + assert(f); + if (!fval(r, RF_TRAVELUNIT)) { + return; + } + + /* How many are we listing? For grammar. */ + maxtravel = count_travelthru(r, f); + if (maxtravel > 0) { + cb_data cbdata; + + init_cb(&cbdata, out, buf, sizeof(buf), f); + cbdata.maxtravel = maxtravel; + cbdata.writep += + strlcpy(buf, LOC(f->locale, "travelthru_header"), sizeof(buf)); + travelthru_map(r, cb_write_travelthru, &cbdata); + return; + } +} + int report_plaintext(const char *filename, report_context * ctx, const char *charset) @@ -2040,7 +2139,7 @@ const char *charset) } if (no_people != f->num_people) { f->num_people = no_people; - } +} #else no_units = count_units(f); no_people = count_all(f); diff --git a/src/report.h b/src/report.h index 69f64702c..657bef36b 100644 --- a/src/report.h +++ b/src/report.h @@ -25,8 +25,7 @@ extern "C" { void register_nr(void); void report_cleanup(void); void write_spaces(struct stream *out, size_t num); - - void paragraph(struct stream *out, const char *str, ptrdiff_t indent, int hanging_indent, char marker); + void write_travelthru(struct stream *out, const struct region * r, const struct faction * f); #ifdef __cplusplus } #endif diff --git a/src/reports.c b/src/reports.c index 7cd67d010..6612c5d48 100644 --- a/src/reports.c +++ b/src/reports.c @@ -982,6 +982,38 @@ void add_seen_faction(faction *self, faction *seen) { add_seen_faction_i(&self->seen_factions, seen); } +typedef struct address_data { + faction *f, *lastf; + quicklist **flist; + int stealthmod; +} address_data; + +static void cb_add_address(const region *r, unit *ut, void *cbdata) { + address_data *data = (address_data *)cbdata; + faction *f = data->f; + + if (ut->faction==f) { + unit *u; + for (u = r->units; u; u = u->next) { + faction *sf = visible_faction(f, u); + assert(u->faction != f); /* if this is see_travel only, then I shouldn't be here. */ + if (data->lastf != sf && cansee_unit(u, ut, data->stealthmod)) { + add_seen_faction_i(data->flist, sf); + data->lastf = sf; + break; + } + } + } +} + +static void add_travelthru_addresses(region *r, faction *f, quicklist **flist, int stealthmod) { + // for each traveling unit: add the faction of any unit is can see + address_data cbdata = { 0 }; + cbdata.f = f; + cbdata.flist = flist; + cbdata.stealthmod = stealthmod; + travelthru_map(r, cb_add_address, &cbdata); +} static void get_addresses(report_context * ctx) { @@ -1026,26 +1058,9 @@ static void get_addresses(report_context * ctx) } } else if (sr->mode == see_travel) { - unit *u = r->units; - while (u) { - faction *sf = visible_faction(ctx->f, u); - assert(u->faction != ctx->f); /* if this is see_travel only, then I shouldn't be here. */ - if (lastf != sf) { - attrib *a = a_find(r->attribs, &at_travelunit); - while (a && a->type == &at_travelunit) { - unit *u2 = (unit *)a->data.v; - if (u2->faction == ctx->f) { - if (cansee_unit(u2, u, stealthmod)) { - add_seen_faction_i(&flist, sf); - lastf = sf; - break; - } - } - a = a->next; - } - } - u = u->next; - } + /* when we travel through a region, then we must add + * the factions of any units we saw */ + add_travelthru_addresses(r, ctx->f, &flist, stealthmod); } else if (sr->mode > see_travel) { const unit *u = r->units; @@ -1466,6 +1481,13 @@ void reorder_units(region * r) } } +static void cb_add_seen(region *r, unit *u, void *cbdata) { + unused_arg(cbdata); + if (u->faction) { + add_seen(u->faction->seen, r, see_travel, false); + } +} + static void prepare_reports(void) { region *r; @@ -1479,7 +1501,6 @@ static void prepare_reports(void) } for (r = regions; r; r = r->next) { - attrib *ru; unit *u; plane *p = rplane(r); @@ -1533,19 +1554,18 @@ static void prepare_reports(void) if (fval(r, RF_TRAVELUNIT)) { - for (ru = a_find(r->attribs, &at_travelunit); - ru && ru->type == &at_travelunit; ru = ru->next) { - unit *u = (unit *)ru->data.v; - - /* make sure the faction has not been removed this turn: */ - if (u->faction) { - add_seen(u->faction->seen, r, see_travel, false); - } - } + travelthru_map(r, cb_add_seen, r); } } } +static void cb_set_last(region *r, unit *u, void *cbdata) { + faction *f = (faction *)cbdata; + if (u->faction == f) { + f->last = r; + } +} + static region *lastregion(faction * f) { #ifdef SMART_INTERVALS @@ -1572,15 +1592,7 @@ static region *lastregion(faction * f) /* search the region for travelthru-attributes: */ if (fval(r, RF_TRAVELUNIT)) { - attrib *ru = a_find(r->attribs, &at_travelunit); - while (ru && ru->type == &at_travelunit) { - u = (unit *)ru->data.v; - if (u->faction == f) { - f->last = r; - break; - } - ru = ru->next; - } + travelthru_map(r, cb_set_last, f); } if (f->last == r) continue; @@ -2379,6 +2391,28 @@ int stream_printf(struct stream * out, const char *format, ...) { return result; } +typedef struct count_data { + int n; + const struct faction *f; +} count_data; + +static void count_cb(const region *r, unit *u, void *cbdata) { + count_data *data = (count_data *)cbdata; + const struct faction *f = data->f; + if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) { + if (cansee_durchgezogen(f, r, u, 0)) { + ++data->n; + } + } +} + +int count_travelthru(struct region *r, const struct faction *f) { + count_data data = { 0 }; + data.f = f; + travelthru_map(r, count_cb, &data); + return data.n; +} + void register_reports(void) { /* register datatypes for the different message objects */ diff --git a/src/reports.h b/src/reports.h index ed0687985..c72cebab1 100644 --- a/src/reports.h +++ b/src/reports.h @@ -157,6 +157,8 @@ extern "C" { int stream_printf(struct stream * out, const char *format, ...); + int count_travelthru(struct region *r, const struct faction *f); + #define GR_PLURAL 0x01 /* grammar: plural */ #define MAX_INVENTORY 128 /* maimum number of different items in an inventory */ #define MAX_RAWMATERIALS 8 /* maximum kinds of raw materials in a regions */ diff --git a/src/reports.test.c b/src/reports.test.c index c9679827e..90e21e89a 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -13,6 +13,8 @@ #include #include +#include + #include #include #include @@ -180,6 +182,11 @@ static void test_cr_unit(CuTest *tc) { test_cleanup(); } +static void reset_stream(stream *out) { + out->api->rewind(out->handle); + out->api->write(out->handle, "", 0); +} + static void test_write_travelthru(CuTest *tc) { stream out = { 0 }; char buf[1024]; @@ -187,30 +194,39 @@ static void test_write_travelthru(CuTest *tc) { region *r; faction *f; unit *u; + struct locale *lang; test_cleanup(); + lang = get_or_create_locale("de"); + locale_setstring(lang, "travelthru_header", "Durchreise: "); mstream_init(&out); r = test_create_region(0, 0, 0); r->flags |= RF_TRAVELUNIT; f = test_create_faction(0); + f->locale = lang; u = test_create_unit(f, 0); + unit_setname(u, "Hodor"); + unit_setid(u, 1); write_travelthru(&out, r, f); out.api->rewind(out.handle); len = out.api->read(out.handle, buf, sizeof(buf)); CuAssertIntEquals_Msg(tc, "no travelers, no report", 0, (int)len); - travelthru(u, r); - out.api->rewind(out.handle); + reset_stream(&out); + travelthru_add(r, u); write_travelthru(&out, r, f); + out.api->rewind(out.handle); len = out.api->read(out.handle, buf, sizeof(buf)); - CuAssertIntEquals_Msg(tc, "report units that moved through", 0, (int)len); + buf[len] = '\0'; + CuAssertStrEquals_Msg(tc, "list one unit", "Durchreise: Hodor (1).\n", buf); + reset_stream(&out); move_unit(u, r, 0); - out.api->rewind(out.handle); write_travelthru(&out, r, f); + out.api->rewind(out.handle); len = out.api->read(out.handle, buf, sizeof(buf)); - CuAssertPtrNotNull(tc, strstr(buf, unitname(u))); + CuAssertIntEquals_Msg(tc, "do not list units that stopped in the region", 0, len); mstream_done(&out); test_cleanup(); diff --git a/src/test_eressea.c b/src/test_eressea.c index e434f6c7f..cef5193cd 100644 --- a/src/test_eressea.c +++ b/src/test_eressea.c @@ -79,6 +79,7 @@ int RunAllTests(void) RUN_TESTS(suite, messages); /* gamecode */ RUN_TESTS(suite, battle); + RUN_TESTS(suite, travelthru); RUN_TESTS(suite, economy); RUN_TESTS(suite, give); RUN_TESTS(suite, laws); diff --git a/src/travelthru.c b/src/travelthru.c index bbb4674b9..754a93530 100644 --- a/src/travelthru.c +++ b/src/travelthru.c @@ -31,7 +31,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include + #include +#include #include #include @@ -48,92 +50,6 @@ attrib_type at_travelunit = { NO_READ }; -static int count_travelthru(const struct region *r, const struct faction *f, attrib *alist) { - int maxtravel = 0; - attrib *a; - for (a = alist; a && a->type == &at_travelunit; a = a->next) { - unit *u = (unit *)a->data.v; - - if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) { - if (cansee_durchgezogen(f, r, u, 0)) { - ++maxtravel; - } - } - } - return maxtravel; -} - -void write_travelthru(stream *out, const region * r, const faction * f) -{ - attrib *abegin, *a; - int counter = 0, maxtravel = 0; - char buf[8192]; - char *bufp = buf; - int bytes; - size_t size = sizeof(buf) - 1; - - assert(r); - assert(f); - if (!fval(r, RF_TRAVELUNIT)) { - return; - } - abegin = a_find(r->attribs, &at_travelunit); - - /* How many are we listing? For grammar. */ - maxtravel = count_travelthru(r, f, abegin); - if (maxtravel == 0) { - return; - } - - /* Auflisten. */ - for (a = abegin; a && a->type == &at_travelunit; a = a->next) { - unit *u = (unit *)a->data.v; - - if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) { - if (cansee_durchgezogen(f, r, u, 0)) { - ++counter; - if (u->ship != NULL) { - bytes = (int)strlcpy(bufp, shipname(u->ship), size); - } - else { - bytes = (int)strlcpy(bufp, unitname(u), size); - } - if (wrptr(&bufp, &size, bytes) != 0) { - INFO_STATIC_BUFFER(); - break; - } - - if (counter + 1 < maxtravel) { - bytes = (int)strlcpy(bufp, ", ", size); - if (wrptr(&bufp, &size, bytes) != 0) { - INFO_STATIC_BUFFER(); - break; - } - } - else if (counter + 1 == maxtravel) { - bytes = (int)strlcpy(bufp, LOC(f->locale, "list_and"), size); - if (wrptr(&bufp, &size, bytes) != 0) { - INFO_STATIC_BUFFER(); - break; - } - } - } - } - } - if (size > 0) { - if (maxtravel == 1) { - bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "has_moved_one")); - } - else { - bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "has_moved_many")); - } - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER_EX("write_travelthru"); - } - *bufp = 0; - paragraph(out, buf, 0, 0, 0); -} - /** sets a marker in the region telling that the unit has travelled through it * this is used for two distinctly different purposes: * - to report that a unit has travelled through. the report function @@ -141,19 +57,51 @@ void write_travelthru(stream *out, const region * r, const faction * f) * themselves * - to report the region to the traveller */ -void travelthru(const unit * u, region * r) +void travelthru_add(region * r, unit * u) { - attrib *ru = a_add(&r->attribs, a_new(&at_travelunit)); + attrib *a; + quicklist *ql; + + assert(r); + assert(u); + + a = a_find(r->attribs, &at_travelunit); + if (!a) { + a = a_add(&r->attribs, a_new(&at_travelunit)); + } + ql = (quicklist *)a->data.v; fset(r, RF_TRAVELUNIT); + ql_push(&ql, u); + a->data.v = ql; - ru->data.v = (void *)u; - +#ifdef SMART_INTERVALS /* the first and last region of the faction gets reset, because travelthrough * could be in regions that are located before the [first, last] interval, * and recalculation is needed */ -#ifdef SMART_INTERVALS update_interval(u->faction, r); #endif } +bool travelthru_cansee(const struct region *r, const struct faction *f, const struct unit *u) { + if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) { + return cansee_durchgezogen(f, r, u, 0); + } + return false; +} + +void travelthru_map(region * r, void(*cb)(region *, struct unit *, void *), void *cbdata) +{ + attrib *a; + assert(r); + a = a_find(r->attribs, &at_travelunit); + if (a) { + quicklist *ql; + ql_iter qi; + ql = (quicklist *)a->data.v; + for (qi = qli_init(&ql); qli_more(qi);) { + unit *u = (unit *)qli_next(&qi); + cb(r, u, cbdata); + } + } +} diff --git a/src/travelthru.h b/src/travelthru.h index 29ecf4261..4e43dd25a 100644 --- a/src/travelthru.h +++ b/src/travelthru.h @@ -6,13 +6,14 @@ extern "C" { #endif - extern struct attrib_type at_travelunit; - + struct attrib; struct stream; struct region; struct faction; - void write_travelthru(struct stream *out, const struct region * r, const struct faction * f); - void travelthru(const struct unit * u, struct region * r); + struct unit; + void travelthru_map(struct region * r, void(*cb)(struct region *r, struct unit *, void *), void *cbdata); + bool travelthru_cansee(const struct region *r, const struct faction *f, const struct unit *u); + void travelthru_add(struct region * r, struct unit * u); #ifdef __cplusplus } diff --git a/src/travelthru.test.c b/src/travelthru.test.c new file mode 100644 index 000000000..9f735fbe3 --- /dev/null +++ b/src/travelthru.test.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include +#include +#include + +#include "travelthru.h" +#include "reports.h" +#include "tests.h" + +#include + +struct attrib; + +static void count_travelers(const region *r, unit *u, void *cbdata) { + int *n = (int *)cbdata; + unused_arg(r); + *n += u->number; +} + +typedef struct travel_fixture { + region *r; + faction *f; +} travel_fixture; + +static void setup_travelthru(travel_fixture *fix, int nunits) { + region *r; + faction *f; + + test_cleanup(); + r = test_create_region(0, 0, 0); + while (r->attribs) { + a_remove(&r->attribs, r->attribs); + } + f = test_create_faction(0); + while (nunits--) { + unit *u = test_create_unit(f, 0); + travelthru_add(r, u); + } + fix->r = r; + fix->f = f; +} + +static void test_travelthru_count(CuTest *tc) { + travel_fixture fix; + setup_travelthru(&fix, 0); + CuAssertIntEquals(tc, 0, count_travelthru(fix.r, fix.f)); + + setup_travelthru(&fix, 1); + CuAssertIntEquals(tc, 1, count_travelthru(fix.r, fix.f)); + + setup_travelthru(&fix, 2); + CuAssertIntEquals(tc, 2, count_travelthru(fix.r, fix.f)); + + test_cleanup(); +} + +static void test_travelthru_map(CuTest *tc) { + int n = 0; + travel_fixture fix; + + setup_travelthru(&fix, 0); + travelthru_map(fix.r, count_travelers, &n); + CuAssertIntEquals(tc, 0, n); + + setup_travelthru(&fix, 1); + travelthru_map(fix.r, count_travelers, &n); + CuAssertIntEquals(tc, 1, n); + + test_cleanup(); +} + +CuSuite *get_travelthru_suite(void) +{ + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_travelthru_count); + SUITE_ADD_TEST(suite, test_travelthru_map); + return suite; +}