]>
Commit | Line | Data |
---|---|---|
eab6aa62 VB |
1 | /* -*- mode: c; c-file-style: "openbsd" -*- */ |
2 | /* | |
3 | * Copyright (c) 2015 Vincent Bernat <bernat@luffy.cx> | |
4 | * | |
5 | * Permission to use, copy, modify, and/or distribute this software for any | |
6 | * purpose with or without fee is hereby granted, provided that the above | |
7 | * copyright notice and this permission notice appear in all copies. | |
8 | * | |
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
16 | */ | |
17 | ||
6bf5e749 VB |
18 | #include <stdlib.h> |
19 | #include <unistd.h> | |
db323555 | 20 | #include <check.h> |
6bf5e749 | 21 | #include <sys/queue.h> |
db323555 | 22 | |
6bf5e749 | 23 | #define MARSHAL_EXPORT |
a0cd2b9a | 24 | #include "check-compat.h" |
6bf5e749 | 25 | #include "../src/marshal.h" |
4b292b55 | 26 | #include "../src/log.h" |
db323555 VB |
27 | |
28 | /* This suite can be run in valgrind for memory leaks: | |
29 | CK_FORK=no valgrind -v --leak-check=yes ./tests/check_marshal | |
30 | */ | |
31 | ||
4b292b55 VB |
32 | /* Use this callback to avoid some logs */ |
33 | void donothing(int pri, const char *msg) {}; | |
34 | ||
db323555 VB |
35 | struct struct_simple { |
36 | int a1; | |
37 | long a2; | |
38 | char a3; | |
39 | time_t a4; | |
40 | char a5[7]; | |
41 | }; | |
5e73393b | 42 | MARSHAL(struct_simple); |
db323555 VB |
43 | |
44 | START_TEST(test_simple_structure) { | |
45 | struct struct_simple source = { | |
46 | .a1 = 78452, | |
47 | .a2 = 48751424, | |
48 | .a3 = 'h', | |
49 | .a4 = 784254, | |
50 | .a5 = { 'A', 'B', 'C', 'D', 'E', 'F', 'G'}, | |
51 | }; | |
52 | struct struct_simple *destination; | |
53 | void *buffer; | |
54 | size_t len, len2; | |
55 | ||
985a4cb5 | 56 | len = struct_simple_serialize(&source, &buffer); |
db323555 VB |
57 | fail_unless(len > 0, "Unable to serialize"); |
58 | memset(&source, 0, sizeof(struct struct_simple)); | |
985a4cb5 | 59 | len2 = struct_simple_unserialize(buffer, len, &destination); |
db323555 VB |
60 | fail_unless(len2 > 0, "Unable to deserialize"); |
61 | free(buffer); | |
62 | ck_assert_int_eq(len, len2); | |
63 | ck_assert_int_eq(destination->a1, 78452); | |
64 | ck_assert_int_eq(destination->a2, 48751424); | |
65 | ck_assert_int_eq(destination->a3, 'h'); | |
66 | ck_assert_int_eq(destination->a4, 784254); | |
67 | ck_assert_int_eq(destination->a5[0], 'A'); | |
68 | ck_assert_int_eq(destination->a5[1], 'B'); | |
69 | ck_assert_int_eq(destination->a5[2], 'C'); | |
70 | ck_assert_int_eq(destination->a5[3], 'D'); | |
71 | ck_assert_int_eq(destination->a5[4], 'E'); | |
72 | ck_assert_int_eq(destination->a5[5], 'F'); | |
73 | ck_assert_int_eq(destination->a5[6], 'G'); | |
74 | free(destination); | |
75 | } | |
76 | END_TEST | |
77 | ||
78 | struct struct_sub { | |
79 | int e1; | |
80 | struct struct_simple e2; | |
81 | char e3; | |
82 | }; | |
5e73393b VB |
83 | MARSHAL_BEGIN(struct_sub) |
84 | MARSHAL_SUBSTRUCT(struct_sub, struct_simple, e2) | |
985a4cb5 | 85 | MARSHAL_END(struct_sub); |
db323555 VB |
86 | |
87 | START_TEST(test_substruct_structure) { | |
88 | struct struct_sub source = { | |
89 | .e1 = -5122, | |
90 | .e2 = { | |
91 | .a1 = 78452, | |
92 | .a2 = 48751424, | |
93 | .a3 = 'h', | |
94 | .a4 = 784254, | |
95 | .a5 = { 'A', 'B', 'C', 'D', 'E', 'F', 'G'}, | |
96 | }, | |
97 | .e3 = 'a', | |
98 | }; | |
99 | ||
100 | struct struct_sub *destination; | |
101 | void *buffer; | |
102 | size_t len, len2; | |
103 | ||
985a4cb5 | 104 | len = struct_sub_serialize(&source, &buffer); |
db323555 VB |
105 | fail_unless(len > 0, "Unable to serialize"); |
106 | memset(&source, 0, sizeof(struct struct_sub)); | |
985a4cb5 | 107 | len2 = struct_sub_unserialize(buffer, len, &destination); |
db323555 VB |
108 | fail_unless(len2 > 0, "Unable to deserialize"); |
109 | free(buffer); | |
110 | ck_assert_int_eq(len, len2); | |
111 | ck_assert_int_eq(destination->e1, -5122); | |
112 | ck_assert_int_eq(destination->e2.a1, 78452); | |
113 | ck_assert_int_eq(destination->e2.a2, 48751424); | |
114 | ck_assert_int_eq(destination->e2.a3, 'h'); | |
115 | ck_assert_int_eq(destination->e2.a4, 784254); | |
116 | ck_assert_int_eq(destination->e2.a5[0], 'A'); | |
117 | ck_assert_int_eq(destination->e2.a5[1], 'B'); | |
118 | ck_assert_int_eq(destination->e2.a5[2], 'C'); | |
119 | ck_assert_int_eq(destination->e2.a5[3], 'D'); | |
120 | ck_assert_int_eq(destination->e2.a5[4], 'E'); | |
121 | ck_assert_int_eq(destination->e2.a5[5], 'F'); | |
122 | ck_assert_int_eq(destination->e2.a5[6], 'G'); | |
123 | ck_assert_int_eq(destination->e3, 'a'); | |
124 | free(destination); | |
125 | } | |
126 | END_TEST | |
127 | ||
128 | struct struct_onepointer { | |
129 | int b1; | |
130 | long b2; | |
131 | char b3; | |
132 | struct struct_simple *b4; | |
133 | int b5; | |
134 | }; | |
5e73393b VB |
135 | MARSHAL_BEGIN(struct_onepointer) |
136 | MARSHAL_POINTER(struct_onepointer, struct_simple, b4) | |
985a4cb5 | 137 | MARSHAL_END(struct_onepointer); |
db323555 VB |
138 | |
139 | START_TEST(test_pointer_structure) { | |
140 | struct struct_simple source_simple = { | |
141 | .a1 = 78452, | |
142 | .a2 = 48751424, | |
143 | .a3 = 'h', | |
144 | .a4 = 784254, | |
145 | .a5 = { 'A', 'B', 'C', 'D', 'E', 'F', 'G'}, | |
146 | }; | |
147 | struct struct_onepointer source = { | |
148 | .b1 = 18, | |
149 | .b2 = 15454, | |
150 | .b3 = 'o', | |
151 | .b4 = &source_simple, | |
152 | .b5 = 333333, | |
153 | }; | |
154 | ||
155 | struct struct_onepointer *destination; | |
156 | void *buffer; | |
157 | size_t len, len2; | |
158 | ||
985a4cb5 | 159 | len = struct_onepointer_serialize(&source, &buffer); |
db323555 VB |
160 | fail_unless(len > 0, "Unable to serialize"); |
161 | memset(&source_simple, 0, sizeof(struct struct_simple)); | |
162 | memset(&source, 0, sizeof(struct struct_onepointer)); | |
985a4cb5 | 163 | len2 = struct_onepointer_unserialize(buffer, len, &destination); |
db323555 VB |
164 | fail_unless(len2 > 0, "Unable to deserialize"); |
165 | free(buffer); | |
166 | ck_assert_int_eq(len, len2); | |
167 | ck_assert_int_eq(destination->b1, 18); | |
168 | ck_assert_int_eq(destination->b2, 15454); | |
169 | ck_assert_int_eq(destination->b3, 'o'); | |
170 | ck_assert_int_eq(destination->b4->a1, 78452); | |
171 | ck_assert_int_eq(destination->b4->a2, 48751424); | |
172 | ck_assert_int_eq(destination->b4->a3, 'h'); | |
173 | ck_assert_int_eq(destination->b4->a4, 784254); | |
174 | ck_assert_int_eq(destination->b4->a5[0], 'A'); | |
175 | ck_assert_int_eq(destination->b4->a5[1], 'B'); | |
176 | ck_assert_int_eq(destination->b4->a5[2], 'C'); | |
177 | ck_assert_int_eq(destination->b4->a5[3], 'D'); | |
178 | ck_assert_int_eq(destination->b4->a5[4], 'E'); | |
179 | ck_assert_int_eq(destination->b4->a5[5], 'F'); | |
180 | ck_assert_int_eq(destination->b4->a5[6], 'G'); | |
181 | ck_assert_int_eq(destination->b5, 333333); | |
182 | free(destination->b4); free(destination); | |
183 | } | |
184 | END_TEST | |
185 | ||
186 | struct struct_nestedpointers { | |
187 | int c1; | |
188 | long c2; | |
189 | struct struct_simple *c3; | |
190 | struct struct_onepointer *c4; | |
191 | int c5; | |
192 | }; | |
5e73393b VB |
193 | MARSHAL_BEGIN(struct_nestedpointers) |
194 | MARSHAL_POINTER(struct_nestedpointers, struct_simple, c3) | |
195 | MARSHAL_POINTER(struct_nestedpointers, struct_onepointer, c4) | |
985a4cb5 | 196 | MARSHAL_END(struct_nestedpointers); |
db323555 VB |
197 | |
198 | START_TEST(test_several_pointers_structure) { | |
199 | struct struct_simple source_simple1 = { | |
200 | .a1 = 78452, | |
201 | .a2 = 48751424, | |
202 | .a3 = 'h', | |
203 | .a4 = 784254, | |
204 | .a5 = { 'A', 'B', 'C', 'D', 'E', 'F', 'G'}, | |
205 | }; | |
206 | struct struct_simple source_simple2 = { | |
207 | .a1 = 451, | |
208 | .a2 = 451424, | |
209 | .a3 = 'o', | |
210 | .a4 = 74, | |
211 | .a5 = { 'a', 'b', 'c', 'd', 'e', 'f', 'g'}, | |
212 | }; | |
213 | struct struct_onepointer source_onepointer = { | |
214 | .b1 = 18, | |
215 | .b2 = 15454, | |
216 | .b3 = 'o', | |
217 | .b4 = &source_simple1, | |
218 | .b5 = 333333, | |
219 | }; | |
220 | struct struct_nestedpointers source = { | |
221 | .c1 = 4542, | |
222 | .c2 = 5665454, | |
223 | .c3 = &source_simple2, | |
224 | .c4 = &source_onepointer, | |
225 | .c5 = -545424, | |
226 | }; | |
227 | ||
228 | struct struct_nestedpointers *destination; | |
229 | void *buffer; | |
230 | size_t len, len2; | |
231 | ||
985a4cb5 | 232 | len = struct_nestedpointers_serialize(&source, &buffer); |
db323555 VB |
233 | fail_unless(len > 0, "Unable to serialize"); |
234 | memset(&source_simple1, 0, sizeof(struct struct_simple)); | |
235 | memset(&source_simple2, 0, sizeof(struct struct_simple)); | |
236 | memset(&source_onepointer, 0, sizeof(struct struct_onepointer)); | |
237 | memset(&source, 0, sizeof(struct struct_nestedpointers)); | |
985a4cb5 | 238 | len2 = struct_nestedpointers_unserialize(buffer, len, &destination); |
db323555 VB |
239 | fail_unless(len2 > 0, "Unable to deserialize"); |
240 | free(buffer); | |
241 | ck_assert_int_eq(len, len2); | |
242 | ck_assert_int_eq(destination->c1, 4542); | |
243 | ck_assert_int_eq(destination->c2, 5665454); | |
244 | ck_assert_int_eq(destination->c3->a1, 451); | |
245 | ck_assert_int_eq(destination->c3->a2, 451424); | |
246 | ck_assert_int_eq(destination->c3->a3, 'o'); | |
247 | ck_assert_int_eq(destination->c3->a4, 74); | |
248 | ck_assert_int_eq(destination->c3->a5[3], 'd'); | |
249 | ck_assert_int_eq(destination->c3->a5[4], 'e'); | |
250 | ck_assert_int_eq(destination->c3->a5[6], 'g'); | |
251 | ck_assert_int_eq(destination->c4->b1, 18); | |
252 | ck_assert_int_eq(destination->c4->b2, 15454); | |
253 | ck_assert_int_eq(destination->c4->b3, 'o'); | |
254 | ck_assert_int_eq(destination->c4->b4->a1, 78452); | |
255 | ck_assert_int_eq(destination->c4->b4->a2, 48751424); | |
256 | ck_assert_int_eq(destination->c4->b4->a3, 'h'); | |
257 | ck_assert_int_eq(destination->c4->b4->a4, 784254); | |
258 | ck_assert_int_eq(destination->c4->b4->a5[0], 'A'); | |
259 | ck_assert_int_eq(destination->c4->b4->a5[1], 'B'); | |
260 | ck_assert_int_eq(destination->c4->b4->a5[2], 'C'); | |
261 | ck_assert_int_eq(destination->c4->b4->a5[3], 'D'); | |
262 | ck_assert_int_eq(destination->c4->b4->a5[4], 'E'); | |
263 | ck_assert_int_eq(destination->c4->b4->a5[5], 'F'); | |
264 | ck_assert_int_eq(destination->c4->b4->a5[6], 'G'); | |
265 | ck_assert_int_eq(destination->c4->b5, 333333); | |
266 | free(destination->c3); free(destination->c4->b4); | |
267 | free(destination->c4); free(destination); | |
268 | } | |
269 | END_TEST | |
270 | ||
271 | START_TEST(test_null_pointers) { | |
272 | struct struct_simple source_simple2 = { | |
273 | .a1 = 451, | |
274 | .a2 = 451424, | |
275 | .a3 = 'o', | |
276 | .a4 = 74, | |
277 | .a5 = { 'a', 'b', 'c', 'd', 'e', 'f', 'g'}, | |
278 | }; | |
279 | struct struct_nestedpointers source = { | |
280 | .c1 = 4542, | |
281 | .c2 = 5665454, | |
282 | .c3 = &source_simple2, | |
283 | .c4 = NULL, | |
284 | .c5 = -545424, | |
285 | }; | |
286 | ||
287 | struct struct_nestedpointers *destination; | |
288 | void *buffer; | |
289 | size_t len, len2; | |
290 | ||
985a4cb5 | 291 | len = struct_nestedpointers_serialize(&source, &buffer); |
db323555 VB |
292 | fail_unless(len > 0, "Unable to serialize"); |
293 | memset(&source_simple2, 0, sizeof(struct struct_simple)); | |
294 | memset(&source, 0, sizeof(struct struct_nestedpointers)); | |
985a4cb5 | 295 | len2 = struct_nestedpointers_unserialize(buffer, len, &destination); |
db323555 VB |
296 | fail_unless(len2 > 0, "Unable to deserialize"); |
297 | free(buffer); | |
298 | ck_assert_int_eq(len, len2); | |
299 | ck_assert_int_eq(destination->c1, 4542); | |
300 | ck_assert_int_eq(destination->c2, 5665454); | |
301 | ck_assert_int_eq(destination->c3->a1, 451); | |
302 | ck_assert_int_eq(destination->c3->a2, 451424); | |
303 | ck_assert_int_eq(destination->c3->a3, 'o'); | |
304 | ck_assert_int_eq(destination->c3->a4, 74); | |
305 | ck_assert_int_eq(destination->c3->a5[3], 'd'); | |
306 | ck_assert_int_eq(destination->c3->a5[4], 'e'); | |
307 | ck_assert_int_eq(destination->c3->a5[6], 'g'); | |
1e8952da | 308 | ck_assert_ptr_eq(destination->c4, NULL); |
db323555 VB |
309 | free(destination->c3); free(destination); |
310 | } | |
311 | END_TEST | |
312 | ||
313 | struct struct_multipleref { | |
314 | int f1; | |
315 | struct struct_simple* f2; | |
316 | struct struct_simple* f3; | |
317 | struct struct_nestedpointers* f4; | |
318 | }; | |
5e73393b VB |
319 | MARSHAL_BEGIN(struct_multipleref) |
320 | MARSHAL_POINTER(struct_multipleref, struct_simple, f2) | |
321 | MARSHAL_POINTER(struct_multipleref, struct_simple, f3) | |
322 | MARSHAL_POINTER(struct_multipleref, struct_nestedpointers, f4) | |
985a4cb5 | 323 | MARSHAL_END(struct_multipleref); |
db323555 VB |
324 | |
325 | START_TEST(test_multiple_references) { | |
326 | struct struct_simple source_simple = { | |
327 | .a1 = 451, | |
328 | .a2 = 451424, | |
329 | .a3 = 'o', | |
330 | .a4 = 74, | |
331 | .a5 = { 'a', 'b', 'c', 'd', 'e', 'f', 'g'}, | |
332 | }; | |
333 | struct struct_nestedpointers source_nested = { | |
334 | .c3 = &source_simple, | |
335 | .c4 = NULL, | |
336 | }; | |
337 | struct struct_multipleref source = { | |
338 | .f1 = 15, | |
339 | .f2 = &source_simple, | |
340 | .f3 = &source_simple, | |
341 | .f4 = &source_nested, | |
342 | }; | |
343 | ||
344 | struct struct_multipleref *destination; | |
345 | void *buffer = NULL; | |
346 | size_t len, len2; | |
347 | ||
985a4cb5 | 348 | len = struct_multipleref_serialize(&source, &buffer); |
db323555 VB |
349 | fail_unless(buffer != NULL, "Buffer is empty"); |
350 | fail_unless(len > 0, "Unable to serialize"); | |
351 | memset(&source_simple, 0, sizeof(struct struct_simple)); | |
352 | memset(&source_nested, 0, sizeof(struct struct_nestedpointers)); | |
353 | memset(&source, 0, sizeof(struct struct_multipleref)); | |
985a4cb5 | 354 | len2 = struct_multipleref_unserialize(buffer, len, &destination); |
db323555 VB |
355 | fail_unless(len2 > 0, "Unable to deserialize"); |
356 | free(buffer); | |
357 | ck_assert_int_eq(len, len2); | |
358 | ck_assert_int_eq(destination->f1, 15); | |
1e8952da VB |
359 | ck_assert_ptr_eq(destination->f2, destination->f3); |
360 | ck_assert_ptr_eq(destination->f2, destination->f4->c3); | |
db323555 VB |
361 | ck_assert_int_eq(destination->f2->a1, 451); |
362 | ck_assert_int_eq(destination->f2->a2, 451424); | |
363 | ck_assert_int_eq(destination->f2->a3, 'o'); | |
364 | ck_assert_int_eq(destination->f2->a4, 74); | |
1e8952da | 365 | ck_assert_ptr_eq(destination->f4->c4, NULL); |
db323555 VB |
366 | free(destination->f2); free(destination->f4); free(destination); |
367 | } | |
368 | END_TEST | |
369 | ||
370 | struct struct_circularref { | |
371 | int g1; | |
372 | struct struct_circularref* g2; | |
373 | }; | |
5e73393b VB |
374 | MARSHAL_BEGIN(struct_circularref) |
375 | MARSHAL_POINTER(struct_circularref, struct_circularref, g2) | |
985a4cb5 | 376 | MARSHAL_END(struct_circularref); |
db323555 VB |
377 | |
378 | START_TEST(test_circular_references) { | |
379 | struct struct_circularref source = { | |
380 | .g1 = 42, | |
381 | .g2 = &source, | |
382 | }; | |
383 | ||
384 | struct struct_circularref *destination; | |
385 | void *buffer = NULL; | |
386 | size_t len, len2; | |
387 | ||
985a4cb5 | 388 | len = struct_circularref_serialize(&source, &buffer); |
db323555 VB |
389 | fail_unless(len > 0, "Unable to serialize"); |
390 | memset(&source, 0, sizeof(struct struct_circularref)); | |
985a4cb5 | 391 | len2 = struct_circularref_unserialize(buffer, len, &destination); |
db323555 VB |
392 | fail_unless(len2 > 0, "Unable to deserialize"); |
393 | free(buffer); | |
394 | ck_assert_int_eq(len, len2); | |
395 | ck_assert_int_eq(destination->g1, 42); | |
396 | ck_assert_int_eq(destination->g2->g1, 42); | |
1e8952da | 397 | ck_assert_ptr_eq(destination->g2, destination->g2->g2); |
db323555 VB |
398 | free(destination); |
399 | } | |
400 | END_TEST | |
401 | ||
402 | START_TEST(test_too_small_unmarshal) { | |
403 | struct struct_simple source_simple1; | |
404 | struct struct_onepointer source_onepointer = { | |
405 | .b4 = &source_simple1, | |
406 | }; | |
407 | struct struct_nestedpointers source = { | |
408 | .c3 = &source_simple1, | |
409 | .c4 = &source_onepointer, | |
410 | }; | |
411 | ||
412 | struct struct_nestedpointers *destination; | |
413 | void *buffer; | |
414 | size_t len, len2; | |
5fd6695c | 415 | int i, j; |
db323555 | 416 | |
4b292b55 VB |
417 | log_register(donothing); |
418 | ||
985a4cb5 | 419 | len = struct_nestedpointers_serialize(&source, &buffer); |
db323555 VB |
420 | fail_unless(len > 0, "Unable to serialize"); |
421 | memset(&source_simple1, 0, sizeof(struct struct_simple)); | |
422 | memset(&source_onepointer, 0, sizeof(struct struct_onepointer)); | |
423 | memset(&source, 0, sizeof(struct struct_nestedpointers)); | |
db323555 VB |
424 | /* Loop 30 times to ease debugging leaks with valgrind */ |
425 | for (j = 0; j < 30; j++) { | |
426 | for (i = 0; i < len; i++) { | |
985a4cb5 | 427 | len2 = struct_nestedpointers_unserialize(buffer, 1, &destination); |
db323555 VB |
428 | fail_unless(len2 == 0, |
429 | "Should not be able to deserialize, too small (%d<%d)", | |
430 | i, len); | |
431 | } | |
432 | } | |
985a4cb5 | 433 | len2 = struct_nestedpointers_unserialize(buffer, len + 5, &destination); |
db323555 VB |
434 | fail_unless(len2 == len, "Deserialized too much"); |
435 | free(destination->c3); | |
436 | free(destination->c4); free(destination); free(buffer); | |
4b292b55 VB |
437 | |
438 | log_register(NULL); | |
db323555 VB |
439 | } |
440 | END_TEST | |
441 | ||
442 | struct struct_simpleentry { | |
443 | TAILQ_ENTRY(struct_simpleentry) s_entries; | |
444 | int g1; | |
445 | struct struct_simple *g2; | |
446 | }; | |
5e73393b VB |
447 | MARSHAL_BEGIN(struct_simpleentry) |
448 | MARSHAL_TQE(struct_simpleentry, s_entries) | |
449 | MARSHAL_POINTER(struct_simpleentry, struct_simple, g2) | |
985a4cb5 | 450 | MARSHAL_END(struct_simpleentry); |
db323555 VB |
451 | |
452 | TAILQ_HEAD(list_simple, struct_simpleentry); | |
5e73393b | 453 | MARSHAL_TQ(list_simple, struct_simpleentry); |
db323555 VB |
454 | |
455 | START_TEST(test_simple_list) { | |
456 | struct struct_simple source_simple = { | |
457 | .a1 = 451, | |
458 | .a2 = 451424, | |
459 | .a3 = 'o', | |
460 | .a4 = 74, | |
461 | .a5 = { 'a', 'b', 'c', 'd', 'e', 'f', 'g'}, | |
462 | }; | |
463 | struct list_simple source; | |
464 | struct struct_simpleentry entry1 = { | |
465 | .g1 = 47, | |
466 | .g2 = &source_simple, | |
467 | }; | |
468 | struct struct_simpleentry entry2 = { | |
469 | .g1 = 49, | |
470 | .g2 = &source_simple, | |
471 | }; | |
472 | struct struct_simpleentry entry3 = { | |
473 | .g1 = 4700, | |
474 | .g2 = NULL, | |
475 | }; | |
476 | struct struct_simpleentry entry4 = { | |
477 | .g1 = -47, | |
478 | .g2 = &source_simple, | |
479 | }; | |
5fd6695c VB |
480 | struct list_simple *destination; |
481 | void *buffer; | |
482 | size_t len, len2; | |
483 | struct struct_simpleentry *e1, *e2; | |
484 | struct struct_simple *s; | |
485 | ||
db323555 VB |
486 | TAILQ_INIT(&source); |
487 | TAILQ_INSERT_TAIL(&source, &entry1, s_entries); | |
488 | TAILQ_INSERT_TAIL(&source, &entry2, s_entries); | |
489 | TAILQ_INSERT_TAIL(&source, &entry3, s_entries); | |
490 | TAILQ_INSERT_TAIL(&source, &entry4, s_entries); | |
491 | ||
985a4cb5 | 492 | len = list_simple_serialize(&source, &buffer); |
db323555 VB |
493 | fail_unless(len > 0, "Unable to serialize"); |
494 | memset(&source, 0, sizeof(struct list_simple)); | |
495 | memset(&entry1, 0, sizeof(struct struct_simpleentry)); | |
496 | memset(&entry2, 0, sizeof(struct struct_simpleentry)); | |
497 | memset(&entry3, 0, sizeof(struct struct_simpleentry)); | |
498 | memset(&entry4, 0, sizeof(struct struct_simpleentry)); | |
985a4cb5 | 499 | len2 = list_simple_unserialize(buffer, len, &destination); |
db323555 VB |
500 | fail_unless(len2 > 0, "Unable to deserialize"); |
501 | free(buffer); | |
502 | ||
db323555 VB |
503 | e1 = TAILQ_FIRST(destination); |
504 | ck_assert_int_eq(e1->g1, 47); | |
505 | s = e1->g2; | |
506 | e2 = TAILQ_NEXT(e1, s_entries); | |
507 | free(e1); | |
508 | ck_assert_int_eq(e2->g1, 49); | |
7afbe16a | 509 | ck_assert_ptr_eq(e2->g2, s); |
db323555 VB |
510 | e1 = TAILQ_NEXT(e2, s_entries); |
511 | free(e2); | |
512 | ck_assert_int_eq(e1->g1, 4700); | |
7afbe16a | 513 | ck_assert_ptr_eq(e1->g2, NULL); |
db323555 VB |
514 | e2 = TAILQ_NEXT(e1, s_entries); |
515 | free(e1); | |
516 | ck_assert_int_eq(e2->g1, -47); | |
7afbe16a | 517 | ck_assert_ptr_eq(e2->g2, s); |
db323555 VB |
518 | e1 = TAILQ_NEXT(e2, s_entries); |
519 | free(e2); | |
7afbe16a | 520 | ck_assert_ptr_eq(e1, NULL); |
db323555 VB |
521 | free(s); |
522 | free(destination); | |
523 | } | |
524 | END_TEST | |
525 | ||
2e043f72 VB |
526 | START_TEST(test_simple_repaired_list) { |
527 | struct struct_simple source_simple = { | |
528 | .a1 = 451, | |
529 | .a2 = 451424, | |
530 | .a3 = 'o', | |
531 | .a4 = 74, | |
532 | .a5 = { 'a', 'b', 'c', 'd', 'e', 'f', 'g'}, | |
533 | }; | |
534 | struct list_simple source; | |
535 | struct struct_simpleentry entry1 = { | |
536 | .g1 = 47, | |
537 | .g2 = &source_simple, | |
538 | }; | |
539 | struct struct_simpleentry entry2 = { | |
540 | .g1 = 49, | |
541 | .g2 = &source_simple, | |
542 | }; | |
543 | struct struct_simpleentry entry3 = { | |
544 | .g1 = 4700, | |
545 | .g2 = NULL, | |
546 | }; | |
547 | struct struct_simpleentry entry4 = { | |
548 | .g1 = -47, | |
549 | .g2 = &source_simple, | |
550 | }; | |
551 | struct struct_simpleentry entry5 = { | |
552 | .g1 = -1000, | |
553 | .g2 = NULL, | |
554 | }; | |
555 | struct list_simple *destination; | |
556 | void *buffer; | |
557 | size_t len, len2; | |
558 | struct struct_simpleentry *e1, *e2, *e3, *e4; | |
559 | ||
560 | TAILQ_INIT(&source); | |
561 | TAILQ_INSERT_TAIL(&source, &entry1, s_entries); | |
562 | TAILQ_INSERT_TAIL(&source, &entry2, s_entries); | |
563 | TAILQ_INSERT_TAIL(&source, &entry3, s_entries); | |
564 | TAILQ_INSERT_TAIL(&source, &entry4, s_entries); | |
565 | ||
566 | len = list_simple_serialize(&source, &buffer); | |
567 | fail_unless(len > 0, "Unable to serialize"); | |
568 | memset(&source, 0, sizeof(struct list_simple)); | |
569 | memset(&entry1, 0, sizeof(struct struct_simpleentry)); | |
570 | memset(&entry2, 0, sizeof(struct struct_simpleentry)); | |
571 | memset(&entry3, 0, sizeof(struct struct_simpleentry)); | |
572 | memset(&entry4, 0, sizeof(struct struct_simpleentry)); | |
573 | len2 = list_simple_unserialize(buffer, len, &destination); | |
574 | fail_unless(len2 > 0, "Unable to deserialize"); | |
575 | free(buffer); | |
576 | ||
577 | marshal_repair_tailq(struct_simpleentry, destination, s_entries); | |
578 | ||
579 | e1 = TAILQ_FIRST(destination); | |
580 | ck_assert_int_eq(e1->g1, 47); | |
581 | e4 = TAILQ_LAST(destination, list_simple); | |
582 | ck_assert_int_eq(e4->g1, -47); | |
583 | e3 = TAILQ_PREV(e4, list_simple, s_entries); | |
584 | ck_assert_int_eq(e3->g1, 4700); | |
585 | e2 = TAILQ_PREV(e3, list_simple, s_entries); | |
586 | ck_assert_int_eq(e2->g1, 49); | |
587 | ||
588 | TAILQ_INSERT_TAIL(destination, &entry5, s_entries); | |
589 | free(e1->g2); | |
590 | free(e1); | |
591 | free(e2); | |
592 | free(e3); | |
593 | free(e4); | |
594 | free(destination); | |
595 | } | |
596 | END_TEST | |
597 | ||
598 | START_TEST(test_empty_repaired_list) { | |
599 | struct list_simple source; | |
600 | size_t len, len2; | |
601 | struct list_simple *destination; | |
602 | void *buffer; | |
603 | struct struct_simpleentry *e1; | |
604 | struct struct_simpleentry entry5 = { | |
605 | .g1 = -1000, | |
606 | .g2 = NULL, | |
607 | }; | |
608 | TAILQ_INIT(&source); | |
609 | ||
610 | len = list_simple_serialize(&source, &buffer); | |
611 | fail_unless(len > 0, "Unable to serialize"); | |
612 | memset(&source, 0, sizeof(struct list_simple)); | |
613 | len2 = list_simple_unserialize(buffer, len, &destination); | |
614 | fail_unless(len2 > 0, "Unable to deserialize"); | |
615 | free(buffer); | |
616 | ||
617 | marshal_repair_tailq(struct_simpleentry, destination, s_entries); | |
618 | ||
619 | e1 = TAILQ_FIRST(destination); | |
620 | ck_assert_ptr_eq(e1, NULL); | |
621 | e1 = TAILQ_LAST(destination, list_simple); | |
622 | ck_assert_ptr_eq(e1, NULL); | |
623 | ||
624 | TAILQ_INSERT_TAIL(destination, &entry5, s_entries); | |
625 | ||
626 | free(destination); | |
627 | } | |
628 | END_TEST | |
629 | ||
db323555 VB |
630 | struct struct_withlist { |
631 | int i1; | |
632 | TAILQ_HEAD(, struct_simpleentry) i2; | |
633 | int i3; | |
634 | }; | |
5e73393b VB |
635 | MARSHAL_BEGIN(struct_withlist) |
636 | MARSHAL_SUBTQ(struct_withlist, struct_simpleentry, i2) | |
985a4cb5 | 637 | MARSHAL_END(struct_withlist); |
db323555 VB |
638 | |
639 | START_TEST(test_embedded_list) { | |
640 | struct struct_withlist source = { | |
641 | .i1 = 45424, | |
642 | .i3 = 4542, | |
643 | }; | |
644 | struct struct_simple source_simple = { | |
645 | .a1 = 451, | |
646 | .a2 = 451424, | |
647 | .a3 = 'o', | |
648 | .a4 = 74, | |
649 | .a5 = { 'a', 'b', 'c', 'd', 'e', 'f', 'g'}, | |
650 | }; | |
651 | struct struct_simpleentry entry1 = { | |
652 | .g1 = 47, | |
653 | .g2 = &source_simple, | |
654 | }; | |
655 | struct struct_simpleentry entry2 = { | |
656 | .g1 = 49, | |
657 | .g2 = &source_simple, | |
658 | }; | |
659 | struct struct_simpleentry entry3 = { | |
660 | .g1 = 4700, | |
661 | .g2 = NULL, | |
662 | }; | |
663 | struct struct_simpleentry entry4 = { | |
664 | .g1 = -47, | |
665 | .g2 = &source_simple, | |
666 | }; | |
5fd6695c VB |
667 | struct struct_withlist *destination; |
668 | void *buffer; | |
669 | size_t len, len2; | |
670 | struct struct_simpleentry *e1, *e2; | |
671 | struct struct_simple *s; | |
672 | ||
db323555 VB |
673 | TAILQ_INIT(&source.i2); |
674 | TAILQ_INSERT_TAIL(&source.i2, &entry1, s_entries); | |
675 | TAILQ_INSERT_TAIL(&source.i2, &entry2, s_entries); | |
676 | TAILQ_INSERT_TAIL(&source.i2, &entry3, s_entries); | |
677 | TAILQ_INSERT_TAIL(&source.i2, &entry4, s_entries); | |
678 | ||
985a4cb5 | 679 | len = struct_withlist_serialize(&source, &buffer); |
db323555 VB |
680 | fail_unless(len > 0, "Unable to serialize"); |
681 | memset(&source, 0, sizeof(struct list_simple)); | |
682 | memset(&entry1, 0, sizeof(struct struct_simpleentry)); | |
683 | memset(&entry2, 0, sizeof(struct struct_simpleentry)); | |
684 | memset(&entry3, 0, sizeof(struct struct_simpleentry)); | |
685 | memset(&entry4, 0, sizeof(struct struct_simpleentry)); | |
985a4cb5 | 686 | len2 = struct_withlist_unserialize(buffer, len, &destination); |
db323555 VB |
687 | fail_unless(len2 > 0, "Unable to deserialize"); |
688 | free(buffer); | |
689 | ||
690 | ck_assert_int_eq(destination->i1, 45424); | |
691 | ck_assert_int_eq(destination->i3, 4542); | |
db323555 VB |
692 | e1 = TAILQ_FIRST(&destination->i2); |
693 | ck_assert_int_eq(e1->g1, 47); | |
694 | ck_assert_int_eq(e1->g2->a4, 74); | |
695 | s = e1->g2; | |
696 | e2 = TAILQ_NEXT(e1, s_entries); | |
697 | free(e1); | |
698 | ck_assert_int_eq(e2->g1, 49); | |
7afbe16a | 699 | ck_assert_ptr_eq(e2->g2, s); |
db323555 VB |
700 | e1 = TAILQ_NEXT(e2, s_entries); |
701 | free(e2); | |
702 | ck_assert_int_eq(e1->g1, 4700); | |
7afbe16a | 703 | ck_assert_ptr_eq(e1->g2, NULL); |
db323555 VB |
704 | e2 = TAILQ_NEXT(e1, s_entries); |
705 | free(e1); | |
706 | ck_assert_int_eq(e2->g1, -47); | |
7afbe16a | 707 | ck_assert_ptr_eq(e2->g2, s); |
db323555 VB |
708 | e1 = TAILQ_NEXT(e2, s_entries); |
709 | free(e2); | |
7afbe16a | 710 | ck_assert_ptr_eq(e1, NULL); |
db323555 VB |
711 | free(s); |
712 | free(destination); | |
713 | } | |
714 | END_TEST | |
715 | ||
da781141 VB |
716 | struct struct_string { |
717 | int s1; | |
718 | char *s2; | |
719 | char *s3; | |
720 | }; | |
721 | MARSHAL_BEGIN(struct_string) | |
722 | MARSHAL_STR(struct_string, s2) | |
723 | MARSHAL_STR(struct_string, s3) | |
985a4cb5 | 724 | MARSHAL_END(struct_string); |
da781141 VB |
725 | |
726 | START_TEST(test_string) { | |
727 | struct struct_string source = { | |
728 | .s1 = 44444, | |
729 | .s2 = "String 2", | |
730 | .s3 = "String 3", | |
731 | }; | |
732 | struct struct_string *destination; | |
733 | void *buffer; | |
734 | size_t len, len2; | |
735 | ||
985a4cb5 | 736 | len = struct_string_serialize(&source, &buffer); |
da781141 VB |
737 | fail_unless(len > 0, "Unable to serialize"); |
738 | memset(&source, 0, sizeof(struct struct_string)); | |
985a4cb5 | 739 | len2 = struct_string_unserialize(buffer, len, &destination); |
da781141 VB |
740 | fail_unless(len2 > 0, "Unable to deserialize"); |
741 | free(buffer); | |
742 | ck_assert_int_eq(len, len2); | |
743 | ck_assert_int_eq(destination->s1, 44444); | |
744 | ck_assert_str_eq(destination->s2, "String 2"); | |
745 | ck_assert_str_eq(destination->s3, "String 3"); | |
746 | free(destination->s2); free(destination->s3); | |
747 | free(destination); | |
748 | } | |
749 | END_TEST | |
305e061c | 750 | |
ca4ed9da VB |
751 | struct struct_fixedstring { |
752 | int s1; | |
753 | char *s2; | |
754 | int s2_len; | |
755 | char *s3; | |
756 | }; | |
757 | MARSHAL_BEGIN(struct_fixedstring) | |
758 | MARSHAL_FSTR(struct_fixedstring, s2, s2_len) | |
759 | MARSHAL_STR(struct_fixedstring, s3) | |
985a4cb5 | 760 | MARSHAL_END(struct_fixedstring); |
ca4ed9da VB |
761 | |
762 | START_TEST(test_fixed_string) { | |
763 | struct struct_fixedstring source = { | |
764 | .s1 = 44444, | |
765 | .s2 = "String 2 Bla", | |
4b292b55 | 766 | .s2_len = 8, /* Not 12! */ |
ca4ed9da VB |
767 | .s3 = "String 3", |
768 | }; | |
769 | struct struct_fixedstring *destination; | |
770 | void *buffer; | |
771 | size_t len, len2; | |
772 | ||
985a4cb5 | 773 | len = struct_fixedstring_serialize(&source, &buffer); |
ca4ed9da | 774 | fail_unless(len > 0, "Unable to serialize"); |
305e061c | 775 | memset(&source, 0, sizeof(struct struct_fixedstring)); |
985a4cb5 | 776 | len2 = struct_fixedstring_unserialize(buffer, len, &destination); |
ca4ed9da VB |
777 | fail_unless(len2 > 0, "Unable to deserialize"); |
778 | free(buffer); | |
779 | ck_assert_int_eq(len, len2); | |
780 | ck_assert_int_eq(destination->s1, 44444); | |
781 | ck_assert_int_eq(destination->s2_len, 8); | |
782 | ck_assert_int_eq(destination->s2[0], 'S'); | |
783 | ck_assert_int_eq(destination->s2[2], 'r'); | |
784 | ck_assert_int_eq(destination->s2[4], 'n'); | |
785 | ck_assert_int_eq(destination->s2[5], 'g'); | |
786 | ck_assert_int_eq(destination->s2[6], ' '); | |
787 | ck_assert_int_eq(destination->s2[7], '2'); | |
4b292b55 | 788 | ck_assert_int_eq(destination->s2[8], '\0'); /* fixed string are null-terminated too */ |
ca4ed9da VB |
789 | ck_assert_str_eq(destination->s3, "String 3"); |
790 | free(destination->s2); free(destination->s3); | |
791 | free(destination); | |
792 | } | |
793 | END_TEST | |
da781141 | 794 | |
305e061c VB |
795 | struct struct_ignore { |
796 | int t1; | |
797 | void *t2; | |
798 | int t3; | |
799 | }; | |
800 | MARSHAL_BEGIN(struct_ignore) | |
801 | MARSHAL_IGNORE(struct_ignore, t2) | |
985a4cb5 | 802 | MARSHAL_END(struct_ignore); |
305e061c VB |
803 | |
804 | START_TEST(test_ignore) { | |
805 | struct struct_ignore source = { | |
806 | .t1 = 4544, | |
807 | .t2 = (void *)"String 2 Bla", | |
808 | .t3 = 11111, | |
809 | }; | |
810 | struct struct_ignore *destination; | |
811 | void *buffer; | |
812 | size_t len, len2; | |
813 | ||
985a4cb5 | 814 | len = struct_ignore_serialize(&source, &buffer); |
305e061c VB |
815 | fail_unless(len > 0, "Unable to serialize"); |
816 | memset(&source, 0, sizeof(struct struct_ignore)); | |
985a4cb5 | 817 | len2 = struct_ignore_unserialize(buffer, len, &destination); |
305e061c VB |
818 | fail_unless(len2 > 0, "Unable to deserialize"); |
819 | free(buffer); | |
820 | ck_assert_int_eq(len, len2); | |
821 | ck_assert_int_eq(destination->t1, 4544); | |
7afbe16a | 822 | ck_assert_ptr_eq(destination->t2, NULL); |
305e061c VB |
823 | ck_assert_int_eq(destination->t3, 11111); |
824 | free(destination); | |
825 | } | |
826 | END_TEST | |
827 | ||
47862f89 VB |
828 | START_TEST(test_equality) { |
829 | struct struct_simple source_simple1 = { | |
830 | .a1 = 451, | |
831 | .a2 = 451424, | |
832 | .a3 = 'o', | |
833 | .a4 = 74, | |
834 | .a5 = { 'a', 'b', 'c', 'd', 'e', 'f', 'g'}, | |
835 | }; | |
836 | struct struct_simpleentry entry1 = { | |
837 | .g1 = 47, | |
838 | .g2 = &source_simple1, | |
839 | }; | |
840 | ||
841 | struct struct_simple source_simple2; | |
842 | struct struct_simpleentry entry2; | |
843 | ||
844 | void *buffer1, *buffer2; | |
845 | memcpy(&source_simple2, &source_simple1, sizeof(source_simple1)); | |
846 | memcpy(&entry2, &entry1, sizeof(entry1)); | |
847 | entry2.g2 = &source_simple2; | |
985a4cb5 VB |
848 | ssize_t len1 = struct_simpleentry_serialize(&entry1, &buffer1); |
849 | ssize_t len2 = struct_simpleentry_serialize(&entry2, &buffer2); | |
47862f89 VB |
850 | fail_unless(len1 > 0, "Unable to serialize"); |
851 | fail_unless(len2 > 0, "Unable to serialize"); | |
852 | ck_assert_int_eq(len1, len2); | |
853 | fail_unless(!memcmp(buffer1, buffer2, len1), "Same content should give the same serialization"); | |
854 | free(buffer1); free(buffer2); | |
855 | } | |
856 | END_TEST | |
857 | ||
db323555 VB |
858 | Suite * |
859 | marshal_suite(void) | |
860 | { | |
861 | Suite *s = suite_create("Marshalling"); | |
862 | ||
863 | TCase *tc_marshal = tcase_create("Marshalling"); | |
864 | tcase_add_test(tc_marshal, test_simple_structure); | |
865 | tcase_add_test(tc_marshal, test_substruct_structure); | |
866 | tcase_add_test(tc_marshal, test_pointer_structure); | |
867 | tcase_add_test(tc_marshal, test_several_pointers_structure); | |
868 | tcase_add_test(tc_marshal, test_null_pointers); | |
869 | tcase_add_test(tc_marshal, test_multiple_references); | |
870 | tcase_add_test(tc_marshal, test_circular_references); | |
871 | tcase_add_test(tc_marshal, test_too_small_unmarshal); | |
872 | tcase_add_test(tc_marshal, test_simple_list); | |
2e043f72 VB |
873 | tcase_add_test(tc_marshal, test_simple_repaired_list); |
874 | tcase_add_test(tc_marshal, test_empty_repaired_list); | |
db323555 | 875 | tcase_add_test(tc_marshal, test_embedded_list); |
da781141 | 876 | tcase_add_test(tc_marshal, test_string); |
ca4ed9da | 877 | tcase_add_test(tc_marshal, test_fixed_string); |
305e061c | 878 | tcase_add_test(tc_marshal, test_ignore); |
47862f89 | 879 | tcase_add_test(tc_marshal, test_equality); |
db323555 VB |
880 | suite_add_tcase(s, tc_marshal); |
881 | ||
882 | return s; | |
883 | } | |
884 | ||
885 | int | |
886 | main() | |
887 | { | |
888 | int number_failed; | |
889 | Suite *s = marshal_suite(); | |
890 | SRunner *sr = srunner_create(s); | |
891 | srunner_run_all(sr, CK_ENV); | |
892 | number_failed = srunner_ntests_failed(sr); | |
893 | srunner_free(sr); | |
894 | return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; | |
895 | } |