From 5bc4f7f144055afa1a093716c7654b2c46532cc1 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 18 Aug 2015 17:08:02 +0200 Subject: [PATCH 1/5] add some simple tests for writing travelthru information to the report, fix test that sets errno as a side effect (thanks, Microsoft!) --- src/report.c | 147 +++++++++++++++++++++----------------- src/report.h | 4 +- src/reports.test.c | 38 ++++++++++ src/tests.c | 5 ++ src/util/bsdstring.test.c | 2 + 5 files changed, 129 insertions(+), 67 deletions(-) diff --git a/src/report.c b/src/report.c index 7b8680ed8..ce71d78fa 100644 --- a/src/report.c +++ b/src/report.c @@ -183,7 +183,7 @@ char marker) str = x + 2; hanging_indent -= 2; } - } + } else { mark = ▮ } @@ -1344,84 +1344,99 @@ static void statistics(stream *out, const region * r, const faction * f) i_free(i_remove(&items, items)); } -static void durchreisende(stream *out, const region * r, const faction * f) -{ - if (fval(r, RF_TRAVELUNIT)) { - attrib *abegin = a_find(r->attribs, &at_travelunit), *a; - int counter = 0, maxtravel = 0; - char buf[8192]; - char *bufp = buf; - int bytes; - size_t size = sizeof(buf) - 1; - /* How many are we listing? For grammar. */ - for (a = abegin; a && a->type == &at_travelunit; a = a->next) { - unit *u = (unit *)a->data.v; +static int count_travelthru(const region *r, const 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; - } + if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) { + if (cansee_durchgezogen(f, r, u, 0)) { + ++maxtravel; } } + } + return maxtravel; +} - if (maxtravel == 0) { - return; - } +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; - /* Auflisten. */ - newline(out); + assert(r); + assert(f); + if (!fval(r, RF_TRAVELUNIT)) { + return; + } + CHECK_ERRNO(); + abegin = a_find(r->attribs, &at_travelunit); - for (a = abegin; a && a->type == &at_travelunit; a = a->next) { - unit *u = (unit *)a->data.v; + /* How many are we listing? For grammar. */ + maxtravel = count_travelthru(r, f, abegin); + if (maxtravel == 0) { + return; + } - 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); - } + /* Auflisten. */ + newline(out); + 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); + } + CHECK_ERRNO(); + if (wrptr(&bufp, &size, bytes) != 0) { + INFO_STATIC_BUFFER(); + break; + } + + if (counter + 1 < maxtravel) { + bytes = (int)strlcpy(bufp, ", ", size); + CHECK_ERRNO(); 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; - } + } + else if (counter + 1 == maxtravel) { + bytes = (int)strlcpy(bufp, LOC(f->locale, "list_and"), size); + CHECK_ERRNO(); + if (wrptr(&bufp, &size, bytes) != 0) { + INFO_STATIC_BUFFER(); + break; } } } } - if (size > 0) { - CHECK_ERRNO(); - 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")); - } - CHECK_ERRNO(); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER_EX("durchreisende"); - CHECK_ERRNO(); - } - *bufp = 0; - paragraph(out, buf, 0, 0, 0); } + if (size > 0) { + CHECK_ERRNO(); + 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")); + } + CHECK_ERRNO(); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER_EX("write_travelthru"); + CHECK_ERRNO(); + } + *bufp = 0; + paragraph(out, buf, 0, 0, 0); } static int buildingmaintenance(const building * b, const resource_type * rtype) @@ -2325,21 +2340,21 @@ const char *charset) } } guards(out, r, f); - durchreisende(out, r, f); + write_travelthru(out, r, f); } else { if (sr->mode == see_far) { describe(out, sr, f); guards(out, r, f); - durchreisende(out, r, f); + write_travelthru(out, r, f); } else if (sr->mode == see_lighthouse) { describe(out, sr, f); - durchreisende(out, r, f); + write_travelthru(out, r, f); } else { describe(out, sr, f); - durchreisende(out, r, f); + write_travelthru(out, r, f); } } /* Statistik */ diff --git a/src/report.h b/src/report.h index 189a38f0f..4a2299969 100644 --- a/src/report.h +++ b/src/report.h @@ -16,10 +16,12 @@ extern "C" { #endif struct stream; + struct region; + struct faction; void register_nr(void); void report_cleanup(void); void write_spaces(struct stream *out, size_t num); - + void write_travelthru(struct stream *out, const struct region * r, const struct faction * f); #ifdef __cplusplus } #endif diff --git a/src/reports.test.c b/src/reports.test.c index 89bca6e05..780d69b4d 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -3,6 +3,7 @@ #include "reports.h" #include "report.h" #include "creport.h" +#include "move.h" #include #include @@ -178,6 +179,42 @@ static void test_cr_unit(CuTest *tc) { test_cleanup(); } +static void test_write_travelthru(CuTest *tc) { + stream out = { 0 }; + char buf[1024]; + size_t len; + region *r; + faction *f; + unit *u; + + test_cleanup(); + mstream_init(&out); + r = test_create_region(0, 0, 0); + r->flags |= RF_TRAVELUNIT; + f = test_create_faction(0); + u = test_create_unit(f, 0); + + 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); + write_travelthru(&out, r, f); + len = out.api->read(out.handle, buf, sizeof(buf)); + CuAssertIntEquals_Msg(tc, "report units that moved through", 0, (int)len); + + move_unit(u, r, 0); + out.api->rewind(out.handle); + write_travelthru(&out, r, f); + len = out.api->read(out.handle, buf, sizeof(buf)); + CuAssertPtrNotNull(tc, strstr(buf, unitname(u))); + + mstream_done(&out); + test_cleanup(); +} + CuSuite *get_reports_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -188,5 +225,6 @@ CuSuite *get_reports_suite(void) SUITE_ADD_TEST(suite, test_write_spaces); SUITE_ADD_TEST(suite, test_write_many_spaces); SUITE_ADD_TEST(suite, test_sparagraph); + SUITE_ADD_TEST(suite, test_write_travelthru); return suite; } diff --git a/src/tests.c b/src/tests.c index 028fb888d..2f4dae59c 100644 --- a/src/tests.c +++ b/src/tests.c @@ -85,6 +85,11 @@ void test_cleanup(void) mt_register(mt_new_va("missing_message", "name:string", 0)); mt_register(mt_new_va("missing_feedback", "unit:unit", "region:region", "command:order", "name:string", 0)); } + if (errno) { + int error = errno; + errno = 0; + log_error("errno: %d", error); + } } terrain_type * diff --git a/src/util/bsdstring.test.c b/src/util/bsdstring.test.c index 6fcb86515..0fffd187c 100644 --- a/src/util/bsdstring.test.c +++ b/src/util/bsdstring.test.c @@ -1,5 +1,6 @@ #include #include "bsdstring.h" +#include #include static void test_strlcat(CuTest * tc) @@ -38,6 +39,7 @@ static void test_strlcpy(CuTest * tc) CuAssertIntEquals(tc, 8, (int)strlcpy(buffer, "herpderp", 8)); CuAssertStrEquals(tc, "herpder", buffer); CuAssertIntEquals(tc, 0x7f, buffer[8]); + errno = 0; } static void test_slprintf(CuTest * tc) From 1f4c8d58587ed4bfaa110d45e33e6cfad79aca90 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 18 Aug 2015 17:28:07 +0200 Subject: [PATCH 2/5] fix linux build, missing include --- src/tests.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tests.c b/src/tests.c index 2f4dae59c..bcbd18c29 100644 --- a/src/tests.c +++ b/src/tests.c @@ -24,6 +24,7 @@ #include #include +#include #include #include From ebe365fd6ed1aba669a1d7cd63ffe131dcb5c0d3 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 18 Aug 2015 18:57:04 +0200 Subject: [PATCH 3/5] move travelthru logic to a separate module. todo: split off the report writing from the collection of units. --- src/CMakeLists.txt | 1 + src/creport.c | 1 + src/kernel/region.c | 12 ---- src/kernel/region.h | 1 - src/move.c | 24 +------ src/move.h | 1 - src/report.c | 102 ++-------------------------- src/report.h | 7 +- src/reports.c | 1 + src/reports.test.c | 1 + src/travelthru.c | 159 ++++++++++++++++++++++++++++++++++++++++++++ src/travelthru.h | 20 ++++++ 12 files changed, 197 insertions(+), 133 deletions(-) create mode 100644 src/travelthru.c create mode 100644 src/travelthru.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c2cd21396..b04631e6a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -108,6 +108,7 @@ set (ERESSEA_SRC spy.c study.c summary.c + travelthru.c monsters.c wormhole.c ${SPELLS_SRC} diff --git a/src/creport.c b/src/creport.c index 6f8be4f2c..6794c33d6 100644 --- a/src/creport.c +++ b/src/creport.c @@ -11,6 +11,7 @@ without prior permission by the authors of Eressea. #include #include "buildno.h" #include "creport.h" +#include "travelthru.h" /* tweakable features */ #define RENDER_CRMESSAGES diff --git a/src/kernel/region.c b/src/kernel/region.c index ddaab10d1..999b8dc33 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -525,18 +525,6 @@ attrib_type at_woodcount = { ATF_UNIQUE }; -/*********************/ -/* at_travelunit */ -/*********************/ -attrib_type at_travelunit = { - "travelunit", - DEFAULT_INIT, - DEFAULT_FINALIZE, - DEFAULT_AGE, - NO_WRITE, - NO_READ -}; - void rsetroad(region * r, direction_t d, int val) { connection *b; diff --git a/src/kernel/region.h b/src/kernel/region.h index 5c2c3a17c..c29732b78 100644 --- a/src/kernel/region.h +++ b/src/kernel/region.h @@ -169,7 +169,6 @@ extern "C" { extern struct attrib_type at_horseluck; extern struct attrib_type at_woodcount; extern struct attrib_type at_deathcount; - extern struct attrib_type at_travelunit; void initrhash(void); void rhash(struct region *r); diff --git a/src/move.c b/src/move.c index 131d87e74..de1cb05bd 100644 --- a/src/move.c +++ b/src/move.c @@ -23,6 +23,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "laws.h" #include "reports.h" #include "alchemy.h" +#include "travelthru.h" #include "vortex.h" #include "monster.h" #include "lighthouse.h" @@ -501,29 +502,6 @@ static ship *do_maelstrom(region * r, unit * u) return u->ship; } -/** 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 - * makes sure to only report the ships of travellers, not the travellers - * themselves - * - to report the region to the traveller - */ -void travelthru(const unit * u, region * r) -{ - attrib *ru = a_add(&r->attribs, a_new(&at_travelunit)); - - fset(r, RF_TRAVELUNIT); - - ru->data.v = (void *)u; - - /* 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 -} - static direction_t koor_reldirection(int ax, int ay, int bx, int by, const struct plane *pl) { diff --git a/src/move.h b/src/move.h index 7674c43d7..013885564 100644 --- a/src/move.h +++ b/src/move.h @@ -64,7 +64,6 @@ extern "C" { int enoughsailors(const struct ship *sh, int sumskill); bool canswim(struct unit *u); bool canfly(struct unit *u); - void travelthru(const struct unit *u, struct region *r); struct ship *move_ship(struct ship *sh, struct region *from, struct region *to, struct region_list *route); int walkingcapacity(const struct unit *u); diff --git a/src/report.c b/src/report.c index ce71d78fa..d02d9a7fc 100644 --- a/src/report.c +++ b/src/report.c @@ -23,6 +23,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "reports.h" #include "laws.h" +#include "travelthru.h" #include "monster.h" /* modules includes */ @@ -163,7 +164,7 @@ static void centre(stream *out, const char *s, bool breaking) } } -static void +void paragraph(stream *out, const char *str, ptrdiff_t indent, int hanging_indent, char marker) { @@ -1345,100 +1346,6 @@ static void statistics(stream *out, const region * r, const faction * f) } -static int count_travelthru(const region *r, const 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; - } - CHECK_ERRNO(); - 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. */ - newline(out); - 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); - } - CHECK_ERRNO(); - if (wrptr(&bufp, &size, bytes) != 0) { - INFO_STATIC_BUFFER(); - break; - } - - if (counter + 1 < maxtravel) { - bytes = (int)strlcpy(bufp, ", ", size); - CHECK_ERRNO(); - 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); - CHECK_ERRNO(); - if (wrptr(&bufp, &size, bytes) != 0) { - INFO_STATIC_BUFFER(); - break; - } - } - } - } - } - if (size > 0) { - CHECK_ERRNO(); - 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")); - } - CHECK_ERRNO(); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER_EX("write_travelthru"); - CHECK_ERRNO(); - } - *bufp = 0; - paragraph(out, buf, 0, 0, 0); -} - static int buildingmaintenance(const building * b, const resource_type * rtype) { const building_type *bt = b->type; @@ -2340,20 +2247,25 @@ const char *charset) } } guards(out, r, f); + newline(out); write_travelthru(out, r, f); } else { if (sr->mode == see_far) { describe(out, sr, f); + newline(out); guards(out, r, f); + newline(out); write_travelthru(out, r, f); } else if (sr->mode == see_lighthouse) { describe(out, sr, f); + newline(out); write_travelthru(out, r, f); } else { describe(out, sr, f); + newline(out); write_travelthru(out, r, f); } } diff --git a/src/report.h b/src/report.h index 4a2299969..69f64702c 100644 --- a/src/report.h +++ b/src/report.h @@ -1,3 +1,4 @@ +#pragma once /* +-------------------+ Christian Schlittchen | | Enno Rehling @@ -11,6 +12,9 @@ */ #ifndef H_GC_REPORT #define H_GC_REPORT + +#include + #ifdef __cplusplus extern "C" { #endif @@ -21,7 +25,8 @@ extern "C" { void register_nr(void); void report_cleanup(void); void write_spaces(struct stream *out, size_t num); - void write_travelthru(struct stream *out, const struct region * r, const struct faction * f); + + void paragraph(struct stream *out, const char *str, ptrdiff_t indent, int hanging_indent, char marker); #ifdef __cplusplus } #endif diff --git a/src/reports.c b/src/reports.c index c381ac831..7cd67d010 100644 --- a/src/reports.c +++ b/src/reports.c @@ -20,6 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include "reports.h" #include "laws.h" +#include "travelthru.h" #include "lighthouse.h" /* kernel includes */ diff --git a/src/reports.test.c b/src/reports.test.c index 780d69b4d..c9679827e 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -4,6 +4,7 @@ #include "report.h" #include "creport.h" #include "move.h" +#include "travelthru.h" #include #include diff --git a/src/travelthru.c b/src/travelthru.c new file mode 100644 index 000000000..bbb4674b9 --- /dev/null +++ b/src/travelthru.c @@ -0,0 +1,159 @@ +/* +Copyright (c) 1998-2015, Enno Rehling +Katja Zedel + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +**/ + +#include +#include + +#include "travelthru.h" +#include "laws.h" +#include "report.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/*********************/ +/* at_travelunit */ +/*********************/ +attrib_type at_travelunit = { + "travelunit", + DEFAULT_INIT, + DEFAULT_FINALIZE, + DEFAULT_AGE, + NO_WRITE, + 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 +* makes sure to only report the ships of travellers, not the travellers +* themselves +* - to report the region to the traveller +*/ +void travelthru(const unit * u, region * r) +{ + attrib *ru = a_add(&r->attribs, a_new(&at_travelunit)); + + fset(r, RF_TRAVELUNIT); + + ru->data.v = (void *)u; + + /* 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 +} + diff --git a/src/travelthru.h b/src/travelthru.h new file mode 100644 index 000000000..29ecf4261 --- /dev/null +++ b/src/travelthru.h @@ -0,0 +1,20 @@ +#pragma once + +#ifndef H_TRAVELTHRU +#define H_TRAVELTHRU +#ifdef __cplusplus +extern "C" { +#endif + + extern struct attrib_type at_travelunit; + + 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); + +#ifdef __cplusplus +} +#endif +#endif From a9ecd1f55e14ec881c915a95f98101cbf23b6d2c Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 19 Aug 2015 14:37:51 +0200 Subject: [PATCH 4/5] 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; +} From fc308940b5a14c636687955c304d1e77d08affde Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 19 Aug 2015 14:50:19 +0200 Subject: [PATCH 5/5] fix linux build --- src/creport.c | 4 ++-- src/reports.c | 4 ++-- src/reports.test.c | 15 ++++++--------- src/travelthru.test.c | 2 +- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/creport.c b/src/creport.c index cbfd0f181..55e2bccce 100644 --- a/src/creport.c +++ b/src/creport.c @@ -1242,7 +1242,7 @@ typedef struct travel_data { int n; } travel_data; -static void cb_cr_travelthru_ship(const region *r, unit *u, void *cbdata) { +static void cb_cr_travelthru_ship(region *r, unit *u, void *cbdata) { travel_data *data = (travel_data *)cbdata; const faction *f = data->f; FILE *F = data->file; @@ -1255,7 +1255,7 @@ static void cb_cr_travelthru_ship(const region *r, unit *u, void *cbdata) { } } -static void cb_cr_travelthru_unit(const region *r, unit *u, void *cbdata) { +static void cb_cr_travelthru_unit(region *r, unit *u, void *cbdata) { travel_data *data = (travel_data *)cbdata; const faction *f = data->f; FILE *F = data->file; diff --git a/src/reports.c b/src/reports.c index 6612c5d48..9d4d7f21c 100644 --- a/src/reports.c +++ b/src/reports.c @@ -988,7 +988,7 @@ typedef struct address_data { int stealthmod; } address_data; -static void cb_add_address(const region *r, unit *ut, void *cbdata) { +static void cb_add_address(region *r, unit *ut, void *cbdata) { address_data *data = (address_data *)cbdata; faction *f = data->f; @@ -2396,7 +2396,7 @@ typedef struct count_data { const struct faction *f; } count_data; -static void count_cb(const region *r, unit *u, void *cbdata) { +static void count_cb(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)) { diff --git a/src/reports.test.c b/src/reports.test.c index 90e21e89a..b30c3214b 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -182,11 +182,6 @@ 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]; @@ -212,21 +207,23 @@ static void test_write_travelthru(CuTest *tc) { out.api->rewind(out.handle); len = out.api->read(out.handle, buf, sizeof(buf)); CuAssertIntEquals_Msg(tc, "no travelers, no report", 0, (int)len); - - reset_stream(&out); + mstream_done(&out); + + mstream_init(&out); travelthru_add(r, u); write_travelthru(&out, r, f); out.api->rewind(out.handle); len = out.api->read(out.handle, buf, sizeof(buf)); buf[len] = '\0'; CuAssertStrEquals_Msg(tc, "list one unit", "Durchreise: Hodor (1).\n", buf); + mstream_done(&out); - reset_stream(&out); + mstream_init(&out); move_unit(u, r, 0); write_travelthru(&out, r, f); out.api->rewind(out.handle); len = out.api->read(out.handle, buf, sizeof(buf)); - CuAssertIntEquals_Msg(tc, "do not list units that stopped in the region", 0, len); + CuAssertIntEquals_Msg(tc, "do not list units that stopped in the region", 0, (int)len); mstream_done(&out); test_cleanup(); diff --git a/src/travelthru.test.c b/src/travelthru.test.c index 9f735fbe3..f92188751 100644 --- a/src/travelthru.test.c +++ b/src/travelthru.test.c @@ -13,7 +13,7 @@ struct attrib; -static void count_travelers(const region *r, unit *u, void *cbdata) { +static void count_travelers(region *r, unit *u, void *cbdata) { int *n = (int *)cbdata; unused_arg(r); *n += u->number;