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