Crossfire Server, Trunk
check_asset_load_write.cpp
Go to the documentation of this file.
1 #include <stdlib.h>
2 #include <string.h>
3 #include <check.h>
4 #include "global.h"
5 #include <toolkit_common.h>
6 #include <math.h>
7 #include "Archetypes.h"
8 #include "Treasures.h"
9 #include "TreasureLoader.h"
10 #include "TreasureWriter.h"
11 #include "AnimationWriter.h"
12 #include "FaceLoader.h"
13 #include "FaceWriter.h"
14 #include "Faces.h"
15 #include "Animations.h"
16 #include "assets.h"
17 #include "Quests.h"
18 #include "QuestLoader.h"
19 #include "QuestWriter.h"
20 
21 static void setup(void) {
23  assets_init();
24 }
25 
26 static void teardown(void) {
27  assets_free();
28 }
29 
30 char *generate_name(size_t max_length) {
31  static char buf[250];
32  size_t len = rndm(5, MIN(max_length, sizeof(buf) - 1));
33  buf[len] = 0;
34  for (size_t c = 0; c < len; c++) {
35  buf[c] = 'a' + rndm(0, 25);
36  }
37  return buf;
38 }
39 
40 template<class T>
41 static void write_load(T *asset, AssetWriter<T> &writer, AssetLoader &loader) {
43 
44  writer.write(asset, sb);
45 
46  auto length = stringbuffer_length(sb);
47  auto data = stringbuffer_finish(sb);
48  BufferReader *br = bufferreader_init_from_memory(NULL, data, length);
49 
50  loader.load(br, "dummy");
51 
53  free(data);
54 }
55 
56 treasure *generate_random_treasure(Archetypes &arches, int depth, bool single) {
57  treasure *trs = static_cast<treasure *>(calloc(1, sizeof(treasure)));
58  trs->chance = rndm(0, 15);
59  if (rndm(0, 1)) {
60  trs->name = add_string(generate_name(50));
61  trs->list_magic_adjustment = rndm(-3, 8);
62  trs->list_magic_value = rndm(0, 10);
63  } else {
64  trs->item = arches.get(generate_name(50));
65  trs->artifact = add_string(generate_name(49));
66  }
67  trs->magic = rndm(0, 6);
68  trs->nrof = rndm(0, 5);
69  if (rndm(0, 5 - depth) != 0) {
70  trs->next = generate_random_treasure(arches, depth + 1, single);
71  }
72  if (!single && rndm(0, 2) == 0) {
73  trs->next_no = generate_random_treasure(arches, depth + 1, single);
74  }
75  if (!single && rndm(0, 2) == 0) {
76  trs->next_yes = generate_random_treasure(arches, depth + 1, single);
77  }
78  return trs;
79 }
80 
82  treasurelist *list = static_cast<treasurelist *>(calloc(1, sizeof(treasurelist)));
83  list->name = add_string(generate_name(50));
84  bool single = rndm(0, 1) == 0;
85  list->items = generate_random_treasure(arches, 0, single);
86  if (single) {
87  auto i = list->items;
88  while (i) {
89  list->total_chance += i->chance;
90  i = i->next;
91  }
92  }
93  return list;
94 }
95 
96 bool equal(const treasure *left, treasure *right) {
97  if (left == nullptr) {
98  FAIL_UNLESS(right == nullptr, "left treasure == null but right treasure != null");
99  return true;
100  }
101  FAIL_UNLESS(right != nullptr, "left treasure != null but right treasure == null");
102  FAIL_UNLESS(left->item == right->item, "different arch");
103  FAIL_UNLESS(left->artifact == right->artifact, "different artifacts");
104  FAIL_UNLESS(left->name == right->name, "different list");
105  FAIL_UNLESS(left->chance == right->chance, "different chance %d %d", left->chance, right->chance);
106  FAIL_UNLESS(left->magic == right->magic, "different magic %d %d", left->magic, right->magic);
107  FAIL_UNLESS(left->nrof == right->nrof, "different nrof %d %d", left->nrof, right->nrof);
108  FAIL_UNLESS(left->list_magic_value == right->list_magic_value, "different list_magic_value %d %d", left->list_magic_value, right->list_magic_value);
109  FAIL_UNLESS(left->list_magic_adjustment == right->list_magic_adjustment, "different list_magic_adjustment %d %d", left->list_magic_adjustment, right->list_magic_adjustment);
110  return true;
111 }
112 
113 bool equal(const treasurelist *left, const treasurelist *right) {
114  if (left == nullptr) {
115  FAIL_UNLESS(right == nullptr, "left list == null but right list != null");
116  return true;
117  }
118  FAIL_UNLESS(right != nullptr, "left list != null but right list == null");
119  FAIL_UNLESS(strcmp(left->name, right->name) == 0, "left list name %s != right list name %s", left->name, right->name);
120  FAIL_UNLESS(equal(left->items, right->items), "left list items != right list items");
121  FAIL_UNLESS(left->total_chance == right->total_chance, "left list total_chance %d != right list total_chance %d", left->total_chance, right->total_chance);
122  return true;
123 }
124 
125 START_TEST(test_treasure) {
127  Treasures trs;
128  TreasureLoader loader(&trs, &arch, nullptr);
129  TreasureWriter writer;
130 
131  auto generated = generate_random_list(arch);
132 
133  write_load(generated, writer, loader);
134 
135  auto loaded = trs.find(generated->name);
136  FAIL_UNLESS(loaded, "Treasurelist should have been loaded!");
137  FAIL_UNLESS(equal(generated, loaded), "loaded treasurelist isn't the same as generated one");
138 
139  trs.define(generated->name, generated);
140  trs.clear();
141  arch.clear();
142 }
143 END_TEST
144 
146  auto anim = static_cast<Animations *>(calloc(1, sizeof(Animations)));
147  anim->name = generate_name(50);
148  anim->facings = pow(2, rndm(0, 3));
149  anim->num_animations = rndm(1, 16);
150  anim->faces = static_cast<const Face **>(calloc(anim->num_animations, sizeof(const Face *)));
151  for (uint8_t f = 0; f < anim->num_animations; f++) {
152  anim->faces[f] = faces.get(generate_name(25));
153  }
154  return anim;
155 }
156 
157 START_TEST(test_animation) {
158  Faces faces;
161 
162  AnimationWriter writer;
163  FaceLoader loader(&faces, &anims, nullptr);
164 
165  write_load(anim, writer, loader);
166 
167  auto loaded = anims.find(anim->name);
168  FAIL_UNLESS(loaded, "face should have been loaded");
169  ck_assert_str_eq(anim->name, loaded->name);
170  ck_assert_int_eq(anim->num_animations, loaded->num_animations);
171  for (uint8_t f = 0; f < anim->num_animations; f++) {
172  ck_assert_str_eq(anim->faces[f]->name, loaded->faces[f]->name);
173  }
174  ck_assert_int_eq(anim->facings, loaded->facings);
175 
176  anims.define(anim->name, anim);
177  faces.clear();
178  anims.clear();
179 }
180 END_TEST
181 
183  Face *face = static_cast<Face *>(calloc(1, sizeof(Face)));
184  face->name = generate_name(50);
185  if (rndm(0, 10) == 0) {
186  face->smoothface = faces.get(generate_name(50));
187  return face;
188  }
189 
190  face->magicmap = rndm(0, 10);
191  if (rndm(0, 3) == 0) {
192  face->magicmap |= FACE_FLOOR;
193  }
194  face->visibility = rndm(0, 50);
195  if (rndm(0, 3) == 0) {
196  face->smoothface = faces.get(generate_name(50));
197  }
198  return face;
199 }
200 
201 START_TEST(test_face) {
202  Faces faces;
204  FaceWriter writer;
205  FaceLoader loader(&faces, &anims, nullptr);
206 
207  Face *face = generate_face(faces);
208  write_load(face, writer, loader);
209 
210  auto loaded = faces.find(face->name);
211  ck_assert_int_eq(face->magicmap, loaded->magicmap);
212  ck_assert_int_eq(face->visibility, loaded->visibility);
213  if (face->smoothface) {
214  ck_assert(loaded->smoothface);
215  ck_assert_str_eq(face->smoothface->name, loaded->smoothface->name);
216  } else {
217  ck_assert(loaded->smoothface == nullptr);
218  }
219 
220  faces.define(face->name, face);
221  faces.clear();
222  anims.clear();
223 }
224 END_TEST
225 
227  auto c = static_cast<quest_condition *>(calloc(1, sizeof(quest_condition)));
228  c->quest_code = generate_name(33);
229  if (rndm(0, 3) == 0) {
230  c->minstep = -1;
231  c->maxstep = -1;
232  } else if (rndm(0, 2) == 0) {
233  c->minstep = rndm(4, 15);
234  c->maxstep = c->minstep;
235  } else if (rndm(0, 1)) {
236  c->maxstep = rndm(4, 15);
237  } else {
238  c->minstep = rndm(0, 14);
239  c->maxstep = c->minstep + rndm(1, 10);
240  }
241  return c;
242 }
243 
245  auto s = static_cast<quest_step_definition *>(calloc(1, sizeof(quest_step_definition)));
246  s->is_completion_step = rndm(0, 1);
247  s->step = rndm(1, 50);
248  s->step_description = rndm(0, 1) ? generate_name(40) : nullptr;
249  for (int i = rndm(0, 2); i != 0; i--) {
250  auto c = generate_condition();
251  s->conditions.push_back(c);
252  }
253  return s;
254 }
255 
257  auto q = static_cast<quest_definition *>(calloc(1, sizeof(quest_definition)));
258  q->quest_code = add_string(generate_name(30));
259  q->quest_description = add_string(generate_name(100));
260  q->quest_is_system = rndm(0, 1);
261  q->quest_restart = rndm(0, 1);
262  q->quest_title = add_string(generate_name(100));
263  q->quest_comment = rndm(0, 1) ? add_string(generate_name(90)) : nullptr;
264  if (rndm(0, 1)) {
265  q->parent = quests.get(generate_name(25));
266  }
267  if (rndm(0, 1)) {
268  q->face = faces.get(generate_name(25));
269  } else {
270  q->face = faces.get("quest_generic.111");
271  }
272  for (int i = rndm(0, 5); i != 0; i--) {
273  q->steps.push_back(generate_step());
274  }
275  return q;
276 }
277 
279  if (!lc) {
280  ck_assert(rc == nullptr);
281  return;
282  }
283  ck_assert(rc);
284  ck_assert_str_eq(lc->quest_code, rc->quest_code);
285  ck_assert_int_eq(lc->minstep, rc->minstep);
286  ck_assert_int_eq(lc->maxstep, rc->maxstep);
287 }
288 
290  if (!ls) {
291  ck_assert(rs == nullptr);
292  return;
293  }
294  ck_assert(rs);
295  if (ls->step_description)
296  ck_assert_str_eq(ls->step_description, rs->step_description);
297  else
298  ck_assert(rs->step_description == nullptr);
299  ck_assert_int_eq(ls->is_completion_step, rs->is_completion_step);
300  ck_assert_int_eq(ls->step, rs->step);
301 
302  ck_assert_int_eq(ls->conditions.size(), rs->conditions.size());
303  auto li = ls->conditions.cbegin(), ri = rs->conditions.cbegin();
304  while (li != ls->conditions.cend()) {
305  check_conditions(*li, *ri);
306  ++li;
307  ++ri;
308  }
309 }
310 
311 void check_steps(const std::vector<quest_step_definition *> &ls, const std::vector<quest_step_definition *> &rs) {
312  ck_assert(ls.size() == rs.size());
313  for (size_t i = 0; i < ls.size(); i++) {
314  check_step(ls[i], rs[i]);
315  }
316 }
317 
318 START_TEST(test_quest) {
319  Faces faces;
320  Quests quests;
321  QuestWriter writer;
322  QuestLoader loader(&quests, &faces, nullptr);
323 
324  auto quest = generate_quest(quests, faces);
325  write_load(quest, writer, loader);
326 
327  auto loaded = quests.find(quest->quest_code);
328  ck_assert_str_eq(quest->quest_description, loaded->quest_description);
329  ck_assert_str_eq(quest->quest_title, loaded->quest_title);
330  if (quest->quest_comment)
331  ck_assert_str_eq(quest->quest_comment, loaded->quest_comment);
332  else
333  ck_assert(loaded->quest_comment == nullptr);
334  ck_assert_int_eq(quest->quest_restart, loaded->quest_restart);
335  ck_assert_int_eq(quest->quest_is_system, loaded->quest_is_system);
336  ck_assert(quest->face == loaded->face);
337  ck_assert(quest->parent == loaded->parent);
338  check_steps(quest->steps, loaded->steps);
339 
340  quests.define(quest->quest_code, quest);
341  faces.clear();
342  quests.clear();
343 }
344 END_TEST
345 
346 static Suite *shstr_suite(void) {
347  Suite *s = suite_create("asset_load_write");
348  TCase *tc_core = tcase_create("Core");
349 
350  /*setup and teardown will be called before each test in testcase 'tc_core' */
351  tcase_add_checked_fixture(tc_core, setup, teardown);
352 
353  suite_add_tcase(s, tc_core);
354  tcase_add_loop_test(tc_core, test_treasure, 0, 25);
355  tcase_add_loop_test(tc_core, test_animation, 0, 25);
356  tcase_add_loop_test(tc_core, test_face, 0, 25);
357  tcase_add_loop_test(tc_core, test_quest, 0, 25);
358 
359  return s;
360 }
361 
362 int main(void) {
363  int nf;
364  Suite *s = shstr_suite();
365  SRunner *sr = srunner_create(s);
366 
367  srunner_set_xml(sr, LOGDIR "/unit/common/asset_load_write.xml");
368  srunner_set_log(sr, LOGDIR "/unit/common/asset_load_write.out");
369  srunner_set_fork_status(sr, CK_NOFORK);
370  srunner_run_all(sr, CK_ENV); /*verbosity from env variable*/
371  nf = srunner_ntests_failed(sr);
372  srunner_free(sr);
373  return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
374 }
generate_step
quest_step_definition * generate_step()
Definition: check_asset_load_write.cpp:244
Face::name
sstring name
Definition: face.h:19
Face
Definition: face.h:14
Face::smoothface
Face * smoothface
Definition: face.h:18
global.h
make_face_from_files.anims
list anims
Definition: make_face_from_files.py:59
stringbuffer_length
size_t stringbuffer_length(StringBuffer *sb)
Definition: stringbuffer.cpp:218
quest_condition::quest_code
sstring quest_code
Definition: quest.h:21
setup
static void setup(void)
Definition: check_asset_load_write.cpp:21
Archetypes
Definition: Archetypes.h:23
treasure::chance
uint8_t chance
Definition: treasure.h:73
quest_condition::maxstep
int maxstep
Definition: quest.h:24
archininventory.arch
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
Definition: archininventory.py:16
treasurelist::items
treasure * items
Definition: treasure.h:92
AssetLoader::load
virtual void load(BufferReader *reader, const std::string &filename)=0
c
static event_registration c
Definition: citylife.cpp:425
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.cpp:57
treasurelist::total_chance
int16_t total_chance
Definition: treasure.h:87
QuestWriter.h
guildoracle.list
list
Definition: guildoracle.py:87
treasure::list_magic_value
uint8_t list_magic_value
Definition: treasure.h:68
FaceWriter
Definition: FaceWriter.h:19
FaceWriter.h
MIN
#define MIN(x, y)
Definition: compat.h:21
bufferreader_destroy
void bufferreader_destroy(BufferReader *br)
Definition: bufferreader.cpp:40
TreasureLoader
Definition: TreasureLoader.h:25
TreasureLoader.h
START_TEST
START_TEST(test_treasure)
Definition: check_asset_load_write.cpp:125
main
int main(void)
Definition: check_asset_load_write.cpp:362
quest_step_definition::step
int step
Definition: quest.h:30
AssetLoader
Definition: AssetLoader.h:24
generate_random_list
treasurelist * generate_random_list(Archetypes &arches)
Definition: check_asset_load_write.cpp:81
rndm
int rndm(int min, int max)
Definition: utils.cpp:162
assets_free
void assets_free()
Definition: assets.cpp:72
buf
StringBuffer * buf
Definition: readable.cpp:1565
AssetsCollection::find
T * find(const Key &name)
Definition: AssetsCollection.h:108
quest_step_definition
Definition: quest.h:29
FAIL_UNLESS
#define FAIL_UNLESS(expr,...)
Definition: toolkit_common.h:11
AnimationWriter
Definition: AnimationWriter.h:19
shstr_suite
static END_TEST Suite * shstr_suite(void)
Definition: check_asset_load_write.cpp:346
check_conditions
void check_conditions(const quest_condition *lc, const quest_condition *rc)
Definition: check_asset_load_write.cpp:278
quest
Definition: quest.py:1
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.cpp:76
item.q
q
Definition: item.py:32
toolkit_common.h
Treasures
Definition: Treasures.h:21
treasure::name
sstring name
Definition: treasure.h:66
AnimationWriter.h
QuestLoader
Definition: QuestLoader.h:24
quest_step_definition::is_completion_step
int is_completion_step
Definition: quest.h:32
Quests
Definition: Quests.h:19
AssetsCollection::define
T * define(const Key &name, T *asset)
Definition: AssetsCollection.h:120
treasurelist
Definition: treasure.h:85
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
write_load
static void write_load(T *asset, AssetWriter< T > &writer, AssetLoader &loader)
Definition: check_asset_load_write.cpp:41
treasurelist::name
sstring name
Definition: treasure.h:86
treasure::nrof
uint16_t nrof
Definition: treasure.h:79
generate_face
static END_TEST Face * generate_face(Faces &faces)
Definition: check_asset_load_write.cpp:182
treasure::item
struct archetype * item
Definition: treasure.h:64
FACE_FLOOR
#define FACE_FLOOR
Definition: newclient.h:292
navar-midane_time.data
data
Definition: navar-midane_time.py:11
QuestWriter
Definition: QuestWriter.h:19
generate_random_treasure
treasure * generate_random_treasure(Archetypes &arches, int depth, bool single)
Definition: check_asset_load_write.cpp:56
Quests.h
AssetsCollection::get
T * get(const Key &name)
Definition: AssetsCollection.h:89
animate.anim
string anim
Definition: animate.py:20
Treasures.h
treasure::next
treasure * next
Definition: treasure.h:69
Faces
Definition: Faces.h:19
StringBuffer
Definition: stringbuffer.cpp:25
quest_condition::minstep
int minstep
Definition: quest.h:22
generate_animation
static END_TEST Animations * generate_animation(Faces &faces)
Definition: check_asset_load_write.cpp:145
equal
bool equal(const treasure *left, treasure *right)
Definition: check_asset_load_write.cpp:96
treasure::next_yes
treasure * next_yes
Definition: treasure.h:70
treasure::magic
uint8_t magic
Definition: treasure.h:74
QuestLoader.h
AllAnimations
Definition: Animations.h:19
bufferreader_init_from_memory
BufferReader * bufferreader_init_from_memory(BufferReader *br, const char *data, size_t length)
Definition: bufferreader.cpp:93
Face::visibility
uint8_t visibility
Definition: face.h:16
init_hash_table
void init_hash_table(void)
Definition: shstr.cpp:55
Faces.h
AssetWriter::write
virtual void write(const T *asset, StringBuffer *buf)=0
quest_condition
Definition: quest.h:20
teardown
static void teardown(void)
Definition: check_asset_load_write.cpp:26
check_step
void check_step(const quest_step_definition *ls, const quest_step_definition *rs)
Definition: check_asset_load_write.cpp:289
generate_quest
quest_definition * generate_quest(Quests &quests, Faces &faces)
Definition: check_asset_load_write.cpp:256
Animations
Definition: face.h:25
quest_definition
Definition: quest.h:37
generate_condition
END_TEST quest_condition * generate_condition()
Definition: check_asset_load_write.cpp:226
Animations.h
Face::magicmap
uint8_t magicmap
Definition: face.h:17
assets.h
Archetypes.h
dragon_attune.faces
dictionary faces
Definition: dragon_attune.py:31
FaceLoader.h
TreasureWriter
Definition: TreasureWriter.h:19
generate_name
char * generate_name(size_t max_length)
Definition: check_asset_load_write.cpp:30
check_steps
void check_steps(const std::vector< quest_step_definition * > &ls, const std::vector< quest_step_definition * > &rs)
Definition: check_asset_load_write.cpp:311
FaceLoader
Definition: FaceLoader.h:23
treasure::next_no
treasure * next_no
Definition: treasure.h:71
quest_step_definition::conditions
std::vector< quest_condition * > conditions
Definition: quest.h:33
AssetsCollection::clear
void clear()
Definition: AssetsCollection.h:69
quest_step_definition::step_description
sstring step_description
Definition: quest.h:31
TreasureWriter.h
treasure
Definition: treasure.h:63
quests
static struct_quest ** quests
Definition: mapper.cpp:892
treasure::artifact
sstring artifact
Definition: treasure.h:65
BufferReader
Definition: bufferreader.cpp:21
AssetWriter
Definition: AssetWriter.h:22
assets_init
void assets_init()
Definition: assets.cpp:65
treasure::list_magic_adjustment
int8_t list_magic_adjustment
Definition: treasure.h:67