comparison tests/test-action.c @ 136:30b68089ae70

core: rework actions and a bit of drawables, closes #2492 In the effort of having as less as possible memory allocation in libcore, the usage of actions and drawable no longer copy the original source parameter to let user pass a heap allocated variable or a static storage one. Update predefined drawable and actions to match these new needs.
author David Demelier <markand@malikania.fr>
date Tue, 13 Oct 2020 09:38:44 +0200
parents
children fea0cc899931
comparison
equal deleted inserted replaced
135:eadfed7674ac 136:30b68089ae70
1 /*
2 * test-action.c -- test actions
3 *
4 * Copyright (c) 2020 David Demelier <markand@malikania.fr>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #define GREATEST_USE_ABBREVS 0
20 #include <greatest.h>
21
22 #include <core/action.h>
23 #include <core/event.h>
24
25 struct invokes {
26 bool handle;
27 bool update;
28 bool draw;
29 bool end;
30 bool finish;
31 };
32
33 static union event dummy;
34
35 #define INIT(dat, up) { \
36 .data = (dat), \
37 .handle = my_handle, \
38 .update = (up), \
39 .draw = my_draw, \
40 .end = my_end, \
41 .finish = my_finish \
42 }
43
44 static void
45 my_handle(struct action *act, const union event *ev)
46 {
47 (void)ev;
48
49 ((struct invokes *)act->data)->handle = true;
50 }
51
52 static bool
53 my_update_false(struct action *act, unsigned int ticks)
54 {
55 (void)ticks;
56
57 ((struct invokes *)act->data)->update = true;
58
59 return false;
60 }
61
62 static bool
63 my_update_true(struct action *act, unsigned int ticks)
64 {
65 (void)ticks;
66
67 ((struct invokes *)act->data)->update = true;
68
69 return true;
70 }
71
72 static void
73 my_draw(struct action *act)
74 {
75 ((struct invokes *)act->data)->draw = true;
76 }
77
78 static void
79 my_end(struct action *act)
80 {
81 ((struct invokes *)act->data)->end = true;
82 }
83
84 static void
85 my_finish(struct action *act)
86 {
87 ((struct invokes *)act->data)->finish = true;
88 }
89
90 GREATEST_TEST
91 basics_handle(void)
92 {
93 struct invokes inv = {0};
94 struct action act = INIT(&inv, my_update_true);
95
96 action_handle(&act, &dummy);
97
98 GREATEST_ASSERT(inv.handle);
99 GREATEST_ASSERT(!inv.update);
100 GREATEST_ASSERT(!inv.draw);
101 GREATEST_ASSERT(!inv.end);
102 GREATEST_ASSERT(!inv.finish);
103 GREATEST_PASS();
104 }
105
106 GREATEST_TEST
107 basics_update(void)
108 {
109 struct {
110 struct invokes inv;
111 struct action act;
112 } table[] = {
113 { .act = INIT(&table[0], my_update_true) },
114 { .act = INIT(&table[1], my_update_false) }
115 };
116
117 /* True version. */
118 GREATEST_ASSERT(action_update(&table[0].act, 0));
119 GREATEST_ASSERT(!table[0].inv.handle);
120 GREATEST_ASSERT(table[0].inv.update);
121 GREATEST_ASSERT(!table[0].inv.draw);
122 GREATEST_ASSERT(!table[0].inv.end);
123 GREATEST_ASSERT(!table[0].inv.finish);
124
125 /* False version. */
126 GREATEST_ASSERT(!action_update(&table[1].act, 0));
127 GREATEST_ASSERT(!table[1].inv.handle);
128 GREATEST_ASSERT(table[1].inv.update);
129 GREATEST_ASSERT(!table[1].inv.draw);
130 GREATEST_ASSERT(!table[1].inv.end);
131 GREATEST_ASSERT(!table[1].inv.finish);
132
133 GREATEST_PASS();
134 }
135
136 GREATEST_TEST
137 basics_draw(void)
138 {
139 struct invokes inv;
140 struct action act = INIT(&inv, my_update_true);
141
142 action_draw(&act);
143
144 GREATEST_ASSERT(!inv.handle);
145 GREATEST_ASSERT(!inv.update);
146 GREATEST_ASSERT(inv.draw);
147 GREATEST_ASSERT(!inv.end);
148 GREATEST_ASSERT(!inv.finish);
149 GREATEST_PASS();
150 }
151
152 GREATEST_TEST
153 basics_end(void)
154 {
155 struct invokes inv;
156 struct action act = INIT(&inv, my_update_true);
157
158 action_end(&act);
159
160 GREATEST_ASSERT(!inv.handle);
161 GREATEST_ASSERT(!inv.update);
162 GREATEST_ASSERT(!inv.draw);
163 GREATEST_ASSERT(inv.end);
164 GREATEST_ASSERT(!inv.finish);
165 GREATEST_PASS();
166 }
167
168 GREATEST_TEST
169 basics_finish(void)
170 {
171 struct invokes inv;
172 struct action act = INIT(&inv, my_update_true);
173
174 action_finish(&act);
175
176 GREATEST_ASSERT(!inv.handle);
177 GREATEST_ASSERT(!inv.update);
178 GREATEST_ASSERT(!inv.draw);
179 GREATEST_ASSERT(!inv.end);
180 GREATEST_ASSERT(inv.finish);
181 GREATEST_PASS();
182 }
183
184 GREATEST_SUITE(suite_basics)
185 {
186 GREATEST_RUN_TEST(basics_handle);
187 GREATEST_RUN_TEST(basics_update);
188 GREATEST_RUN_TEST(basics_draw);
189 GREATEST_RUN_TEST(basics_end);
190 GREATEST_RUN_TEST(basics_finish);
191 }
192
193 GREATEST_TEST
194 stack_add(void)
195 {
196 struct action_stack st = {0};
197 struct action act = {0};
198
199 GREATEST_ASSERT(action_stack_add(&st, &act));
200
201 /* Now fill up. */
202 for (int i = 0; i < ACTION_STACK_MAX - 1; ++i)
203 GREATEST_ASSERT(action_stack_add(&st, &act));
204
205 /* This one should not fit in. */
206 GREATEST_ASSERT(!action_stack_add(&st, &act));
207
208 GREATEST_PASS();
209 }
210
211 GREATEST_TEST
212 stack_handle(void)
213 {
214 struct {
215 bool called;
216 struct action act;
217 } table[] = {
218 { false, { .data = &table[0].called, .handle = my_handle } },
219 { false, { .data = &table[1].called, .handle = my_handle } },
220 { false, { .data = &table[2].called, .handle = my_handle } },
221 };
222
223 struct action_stack st = {0};
224
225 action_stack_add(&st, &table[0].act);
226 action_stack_add(&st, &table[1].act);
227 action_stack_add(&st, &table[2].act);
228 action_stack_handle(&st, &dummy);
229
230 GREATEST_ASSERT(table[0].called);
231 GREATEST_ASSERT(table[1].called);
232 GREATEST_ASSERT(table[2].called);
233 GREATEST_PASS();
234 }
235
236 GREATEST_TEST
237 stack_update(void)
238 {
239 struct {
240 struct invokes inv;
241 struct action act;
242 } table[] = {
243 { .act = INIT(&table[0], my_update_false) },
244 { .act = INIT(&table[1], my_update_true) },
245 { .act = INIT(&table[2], my_update_false) },
246 { .act = INIT(&table[3], my_update_false) },
247 { .act = INIT(&table[4], my_update_true) },
248 { .act = INIT(&table[5], my_update_true) },
249 { .act = INIT(&table[6], my_update_false) },
250 };
251
252 struct action_stack st = {0};
253
254 action_stack_add(&st, &table[0].act);
255 action_stack_add(&st, &table[1].act);
256 action_stack_add(&st, &table[2].act);
257 action_stack_add(&st, &table[3].act);
258 action_stack_add(&st, &table[4].act);
259 action_stack_add(&st, &table[5].act);
260 action_stack_add(&st, &table[6].act);
261
262 GREATEST_ASSERT(!action_stack_update(&st, 0));
263
264 GREATEST_ASSERT(!table[0].inv.handle);
265 GREATEST_ASSERT(!table[1].inv.handle);
266 GREATEST_ASSERT(!table[2].inv.handle);
267 GREATEST_ASSERT(!table[3].inv.handle);
268 GREATEST_ASSERT(!table[4].inv.handle);
269 GREATEST_ASSERT(!table[5].inv.handle);
270 GREATEST_ASSERT(!table[6].inv.handle);
271
272 GREATEST_ASSERT(table[0].inv.update);
273 GREATEST_ASSERT(table[1].inv.update);
274 GREATEST_ASSERT(table[2].inv.update);
275 GREATEST_ASSERT(table[3].inv.update);
276 GREATEST_ASSERT(table[4].inv.update);
277 GREATEST_ASSERT(table[5].inv.update);
278 GREATEST_ASSERT(table[6].inv.update);
279
280 GREATEST_ASSERT(!table[0].inv.draw);
281 GREATEST_ASSERT(!table[1].inv.draw);
282 GREATEST_ASSERT(!table[2].inv.draw);
283 GREATEST_ASSERT(!table[3].inv.draw);
284 GREATEST_ASSERT(!table[4].inv.draw);
285 GREATEST_ASSERT(!table[5].inv.draw);
286 GREATEST_ASSERT(!table[6].inv.draw);
287
288 GREATEST_ASSERT(!table[0].inv.end);
289 GREATEST_ASSERT(table[1].inv.end);
290 GREATEST_ASSERT(!table[2].inv.end);
291 GREATEST_ASSERT(!table[3].inv.end);
292 GREATEST_ASSERT(table[4].inv.end);
293 GREATEST_ASSERT(table[5].inv.end);
294 GREATEST_ASSERT(!table[6].inv.end);
295
296 GREATEST_ASSERT(!table[0].inv.finish);
297 GREATEST_ASSERT(table[1].inv.finish);
298 GREATEST_ASSERT(!table[2].inv.finish);
299 GREATEST_ASSERT(!table[3].inv.finish);
300 GREATEST_ASSERT(table[4].inv.finish);
301 GREATEST_ASSERT(table[5].inv.finish);
302 GREATEST_ASSERT(!table[6].inv.finish);
303
304 /* The following must still be there. */
305 GREATEST_ASSERT_EQ(st.actions[0], &table[0].act);
306 GREATEST_ASSERT_EQ(st.actions[2], &table[2].act);
307 GREATEST_ASSERT_EQ(st.actions[3], &table[3].act);
308 GREATEST_ASSERT_EQ(st.actions[6], &table[6].act);
309
310 /* The following must have been NULL-ed. */
311 GREATEST_ASSERT_EQ(st.actions[1], NULL);
312 GREATEST_ASSERT_EQ(st.actions[4], NULL);
313 GREATEST_ASSERT_EQ(st.actions[5], NULL);
314
315 /*
316 * Now make all actions to return true and check if it cleans the stack.
317 */
318 table[0].act.update =
319 table[2].act.update =
320 table[3].act.update =
321 table[6].act.update = my_update_true;
322
323 GREATEST_ASSERT(action_stack_update(&st, 0));
324 GREATEST_ASSERT_EQ(st.actions[0], NULL);
325 GREATEST_ASSERT_EQ(st.actions[1], NULL);
326 GREATEST_ASSERT_EQ(st.actions[2], NULL);
327 GREATEST_ASSERT_EQ(st.actions[3], NULL);
328 GREATEST_ASSERT_EQ(st.actions[4], NULL);
329 GREATEST_ASSERT_EQ(st.actions[5], NULL);
330 GREATEST_ASSERT_EQ(st.actions[6], NULL);
331
332 GREATEST_PASS();
333 }
334
335 GREATEST_TEST
336 stack_finish(void)
337 {
338 struct {
339 struct invokes inv;
340 struct action act;
341 } table[] = {
342 { .act = INIT(&table[0], my_update_true) },
343 { .act = INIT(&table[0], my_update_false) },
344 };
345 struct action_stack st = {0};
346
347 action_stack_add(&st, &table[0].act);
348 action_stack_add(&st, &table[1].act);
349 action_stack_finish(&st);
350
351 GREATEST_ASSERT(!table[0].inv.handle);
352 GREATEST_ASSERT(!table[0].inv.update);
353 GREATEST_ASSERT(!table[0].inv.draw);
354 GREATEST_ASSERT(table[0].inv.end);
355 GREATEST_ASSERT(table[0].inv.finish);
356
357 GREATEST_ASSERT(!table[0].inv.handle);
358 GREATEST_ASSERT(!table[0].inv.update);
359 GREATEST_ASSERT(!table[0].inv.draw);
360 GREATEST_ASSERT(table[0].inv.end);
361 GREATEST_ASSERT(table[0].inv.finish);
362
363 /* They should also be NULL'ed. */
364 GREATEST_ASSERT_EQ(st.actions[0], NULL);
365 GREATEST_ASSERT_EQ(st.actions[1], NULL);
366
367 GREATEST_PASS();
368 }
369
370 GREATEST_SUITE(suite_stack)
371 {
372 GREATEST_RUN_TEST(stack_add);
373 GREATEST_RUN_TEST(stack_handle);
374 GREATEST_RUN_TEST(stack_update);
375 GREATEST_RUN_TEST(stack_finish);
376 }
377
378 GREATEST_MAIN_DEFS();
379
380 int
381 main(int argc, char **argv)
382 {
383 GREATEST_MAIN_BEGIN();
384 GREATEST_RUN_SUITE(suite_basics);
385 GREATEST_RUN_SUITE(suite_stack);
386 GREATEST_MAIN_END();
387
388 return 0;
389 }