1 /***************************************************************************
2 begin : Fri Dec 06 2019
3 copyright : (C) 2019 by Martin Preuss
4 email : martin@libchipcard.de
5
6 ***************************************************************************
7 * *
8 * This library is free software; you can redistribute it and/or *
9 * modify it under the terms of the GNU Lesser General Public *
10 * License as published by the Free Software Foundation; either *
11 * version 2.1 of the License, or (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16 * Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public *
19 * License along with this library; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 * *
23 ***************************************************************************/
24
25
26 /* This file is included by "simpleptrlist.c" */
27
28
29 #include <gwenhywfar/testframework.h>
30 #include "simpleptrlist-t.h"
31
32
33 #ifdef GWENHYWFAR_ENABLE_TESTCODE
34
35
36 #include <gwenhywfar/mdigest.h>
37 #include <string.h>
38
39
40
41
42 /* ------------------------------------------------------------------------------------------------
43 * type definitions
44 * ------------------------------------------------------------------------------------------------
45 */
46
47 typedef struct TEST_TYPE TEST_TYPE;
48 GWEN_LIST_FUNCTION_DEFS(TEST_TYPE, TestType)
49 struct TEST_TYPE {
50 GWEN_LIST_ELEMENT(TEST_TYPE)
51 int _refCounter;
52 int testPosition;
53 char *testStringPtr;
54 uint8_t testHash[20];
55 };
56
57
58
59 /* ------------------------------------------------------------------------------------------------
60 * forward declarations
61 * ------------------------------------------------------------------------------------------------
62 */
63
64
65 static TEST_TYPE *TestType_new(const char *s, int pos);
66 static void TestType_Attach(TEST_TYPE *tt);
67 static void TestType_free(TEST_TYPE *tt);
68
69 static int TestType_CalcHash(TEST_TYPE *tt);
70 static int TestType_TestHash(const TEST_TYPE *tt);
71
72 static GWENHYWFAR_CB void _attachToTestType(GWEN_SIMPLEPTRLIST *pl, void *p);
73 static GWENHYWFAR_CB void _detachFromTestType(GWEN_SIMPLEPTRLIST *pl, void *p);
74
75
76 static int GWENHYWFAR_CB test1(GWEN_TEST_MODULE *mod);
77 static int GWENHYWFAR_CB test2(GWEN_TEST_MODULE *mod);
78 static int GWENHYWFAR_CB test3(GWEN_TEST_MODULE *mod);
79 static int GWENHYWFAR_CB test4(GWEN_TEST_MODULE *mod);
80 static int GWENHYWFAR_CB test5(GWEN_TEST_MODULE *mod);
81 static int GWENHYWFAR_CB test6(GWEN_TEST_MODULE *mod);
82
83 static TEST_TYPE *createTestType(int num);
84 static void dumpTestTypeList(TEST_TYPE_LIST *ttList);
85
86
87
88 /* ------------------------------------------------------------------------------------------------
89 * implementations
90 * ------------------------------------------------------------------------------------------------
91 */
92
93
GWEN_SimplePtrList_AddTests(GWEN_TEST_MODULE * mod)94 int GWEN_SimplePtrList_AddTests(GWEN_TEST_MODULE *mod)
95 {
96 GWEN_TEST_MODULE *newMod;
97
98 newMod=GWEN_Test_Module_AddModule(mod, "GWEN_SimplePtrList", NULL);
99
100 GWEN_Test_Module_AddTest(newMod, "test1", test1, NULL);
101 GWEN_Test_Module_AddTest(newMod, "test2", test2, NULL);
102 GWEN_Test_Module_AddTest(newMod, "test3", test3, NULL);
103 GWEN_Test_Module_AddTest(newMod, "test4", test4, NULL);
104 GWEN_Test_Module_AddTest(newMod, "test5", test5, NULL);
105 GWEN_Test_Module_AddTest(newMod, "test6", test6, NULL);
106
107 return 0;
108 }
109
110
111
GWEN_LIST_FUNCTIONS(TEST_TYPE,TestType)112 GWEN_LIST_FUNCTIONS(TEST_TYPE, TestType)
113
114
115
116
117 TEST_TYPE *TestType_new(const char *s, int pos)
118 {
119 TEST_TYPE *tt;
120
121 GWEN_NEW_OBJECT(TEST_TYPE, tt);
122 tt->_refCounter=1;
123 GWEN_LIST_INIT(TEST_TYPE, tt);
124 if (s)
125 tt->testStringPtr=strdup(s);
126 tt->testPosition=pos;
127 return tt;
128 }
129
130
131
TestType_Attach(TEST_TYPE * tt)132 void TestType_Attach(TEST_TYPE *tt)
133 {
134 assert(tt);
135 assert(tt->_refCounter);
136
137 if (tt && tt->_refCounter) {
138 tt->_refCounter++;
139 /*DBG_ERROR(GWEN_LOGDOMAIN, "Attached (%d: refcount=%d)", tt->testPosition, tt->_refCounter);*/
140 }
141 else {
142 DBG_ERROR(GWEN_LOGDOMAIN, "NULL pointer or already freed");
143 }
144 }
145
146
147
TestType_free(TEST_TYPE * tt)148 void TestType_free(TEST_TYPE *tt)
149 {
150 if (tt && tt->_refCounter) {
151 /*DBG_ERROR(GWEN_LOGDOMAIN, "Detaching (%d: refcount=%d)", tt->testPosition, tt->_refCounter);*/
152 if (tt->_refCounter==1) {
153 GWEN_LIST_FINI(TEST_TYPE, tt);
154 if (tt->testStringPtr)
155 free(tt->testStringPtr);
156 tt->_refCounter=0;
157 GWEN_FREE_OBJECT(tt);
158 }
159 else
160 tt->_refCounter--;
161 }
162 }
163
164
165
TestType_CalcHash(TEST_TYPE * tt)166 int TestType_CalcHash(TEST_TYPE *tt)
167 {
168 if (tt->testStringPtr && *(tt->testStringPtr)) {
169 GWEN_MDIGEST *md;
170 int rv;
171
172 md=GWEN_MDigest_Rmd160_new();
173 rv=GWEN_MDigest_Digest(md,
174 (const uint8_t *)tt->testStringPtr, strlen(tt->testStringPtr),
175 tt->testHash, sizeof(tt->testHash));
176 if (rv<0) {
177 DBG_ERROR(GWEN_LOGDOMAIN, "Error on GWEN_MDigest_Begin: %s (%d)", GWEN_Error_SimpleToString(rv), rv);
178 GWEN_MDigest_free(md);
179 return rv;
180 }
181 GWEN_MDigest_free(md);
182 }
183 return 0;
184 }
185
186
187
TestType_TestHash(const TEST_TYPE * tt)188 int TestType_TestHash(const TEST_TYPE *tt)
189 {
190 if (tt->testStringPtr && *(tt->testStringPtr)) {
191 GWEN_MDIGEST *md;
192 uint8_t hash[20];
193 int rv;
194
195 md=GWEN_MDigest_Rmd160_new();
196 rv=GWEN_MDigest_Digest(md,
197 (const uint8_t *)tt->testStringPtr, strlen(tt->testStringPtr),
198 hash, sizeof(hash));
199 if (rv<0) {
200 DBG_ERROR(GWEN_LOGDOMAIN, "Error on GWEN_MDigest_Digest: %s (%d)", GWEN_Error_SimpleToString(rv), rv);
201 GWEN_MDigest_free(md);
202 return rv;
203 }
204 GWEN_MDigest_free(md);
205
206 if (memcmp(hash, tt->testHash, sizeof(hash))!=0) {
207 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid hash, object was modified.");
208 return GWEN_ERROR_GENERIC;
209 }
210 }
211 return 0;
212 }
213
214
215
createTestType(int num)216 TEST_TYPE *createTestType(int num)
217 {
218 TEST_TYPE *tt;
219 char testString[256];
220 int rv;
221
222 snprintf(testString, sizeof(testString), "This is test string number %d", num);
223 tt=TestType_new(testString, num);
224 if (tt==NULL) {
225 DBG_ERROR(GWEN_LOGDOMAIN, "Could not create test object %d", num);
226 return NULL;
227 }
228 rv=TestType_CalcHash(tt);
229 if (rv<0) {
230 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
231 TestType_free(tt);
232 return NULL;
233 }
234 return tt;
235 }
236
237
238
_attachToTestType(GWEN_UNUSED GWEN_SIMPLEPTRLIST * pl,void * p)239 void _attachToTestType(GWEN_UNUSED GWEN_SIMPLEPTRLIST *pl, void *p)
240 {
241 TEST_TYPE *tt;
242
243 tt=(TEST_TYPE *) p;
244 TestType_Attach(tt);
245 }
246
247
248
_detachFromTestType(GWEN_UNUSED GWEN_SIMPLEPTRLIST * pl,void * p)249 void _detachFromTestType(GWEN_UNUSED GWEN_SIMPLEPTRLIST *pl, void *p)
250 {
251 TEST_TYPE *tt;
252
253 tt=(TEST_TYPE *) p;
254 TestType_free(tt);
255 }
256
257
258
dumpTestTypeList(TEST_TYPE_LIST * ttList)259 void dumpTestTypeList(TEST_TYPE_LIST *ttList)
260 {
261 TEST_TYPE *tt;
262
263 tt=TestType_List_First(ttList);
264 while (tt) {
265 fprintf(stderr, "%5d: %3d: %s\n", tt->testPosition, tt->_refCounter, tt->testStringPtr);
266 tt=TestType_List_Next(tt);
267 }
268 }
269
270
271
272 /* ------------------------------------------------------------------------------------------------
273 * test 1: test struct members after construction
274 * ------------------------------------------------------------------------------------------------
275 */
276
test1(GWEN_UNUSED GWEN_TEST_MODULE * mod)277 int test1(GWEN_UNUSED GWEN_TEST_MODULE *mod)
278 {
279 GWEN_SIMPLEPTRLIST *pl;
280 int i;
281
282 pl=GWEN_SimplePtrList_new(128, 128);
283 if (pl==NULL) {
284 DBG_ERROR(GWEN_LOGDOMAIN, "Could not create pointer list");
285 return GWEN_ERROR_GENERIC;
286 }
287
288 if (pl->refCount!=1) {
289 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid object field: refCounter");
290 GWEN_SimplePtrList_free(pl);
291 return GWEN_ERROR_GENERIC;
292 }
293
294 if (pl->maxEntries!=128) {
295 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid object field: maxEntries");
296 GWEN_SimplePtrList_free(pl);
297 return GWEN_ERROR_GENERIC;
298 }
299
300 if (pl->usedEntries!=0) {
301 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid object field: usedEntries");
302 GWEN_SimplePtrList_free(pl);
303 return GWEN_ERROR_GENERIC;
304 }
305
306 if (pl->steps!=128) {
307 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid object field: steps");
308 GWEN_SimplePtrList_free(pl);
309 return GWEN_ERROR_GENERIC;
310 }
311
312
313 if (pl->entryList->refCounter!=1) {
314 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid internal object field: refCounter");
315 GWEN_SimplePtrList_free(pl);
316 return GWEN_ERROR_GENERIC;
317 }
318
319 if (pl->entryList->storedEntries!=128) {
320 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid internal object field: storedEntries");
321 GWEN_SimplePtrList_free(pl);
322 return GWEN_ERROR_GENERIC;
323 }
324
325
326 for (i=0; i<128; i++) {
327 if (pl->entryList->entries[i]!=NULL) {
328 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid object entry: idx %d is not NULL", i);
329 GWEN_SimplePtrList_free(pl);
330 return GWEN_ERROR_GENERIC;
331 }
332 }
333
334
335 GWEN_SimplePtrList_free(pl);
336 return 0;
337 }
338
339
340
341 /* ------------------------------------------------------------------------------------------------
342 * test 2: test adding pointers
343 * ------------------------------------------------------------------------------------------------
344 */
345
test2(GWEN_UNUSED GWEN_TEST_MODULE * mod)346 int test2(GWEN_UNUSED GWEN_TEST_MODULE *mod)
347 {
348
349 GWEN_SIMPLEPTRLIST *pl;
350 int i;
351
352 pl=GWEN_SimplePtrList_new(128, 128);
353 for (i=0; i<1024; i++) {
354 TEST_TYPE *tt;
355 int64_t idx;
356
357 tt=createTestType(i);
358 idx=GWEN_SimplePtrList_AddPtr(pl, tt);
359 if (idx<0) {
360 DBG_ERROR(GWEN_LOGDOMAIN, "Error adding pointer %d to list: %s (%d)", i, GWEN_Error_SimpleToString((int)idx), (int)idx);
361 GWEN_SimplePtrList_free(pl);
362 return (int) idx;
363 }
364 } /* for */
365
366 if (pl->maxEntries!=1024) {
367 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid object field: maxEntries");
368 GWEN_SimplePtrList_free(pl);
369 return GWEN_ERROR_GENERIC;
370 }
371
372 if (pl->usedEntries!=1024) {
373 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid object field: usedEntries");
374 GWEN_SimplePtrList_free(pl);
375 return GWEN_ERROR_GENERIC;
376 }
377
378 for (i=0; i<1024; i++) {
379 TEST_TYPE *tt;
380 int rv;
381
382 tt=(TEST_TYPE *) GWEN_SimplePtrList_GetPtrAt(pl, i);
383 if (tt==NULL) {
384 DBG_ERROR(GWEN_LOGDOMAIN, "No object at position %d", i);
385 GWEN_SimplePtrList_free(pl);
386 return GWEN_ERROR_GENERIC;
387 }
388
389 rv=TestType_TestHash(tt);
390 if (rv<0) {
391 DBG_ERROR(GWEN_LOGDOMAIN, "Error testing hash of object %d: %s (%d)", i, GWEN_Error_SimpleToString(rv), rv);
392 GWEN_SimplePtrList_free(pl);
393 return rv;
394 }
395 } /* for */
396
397 /* free all objects */
398 for (i=0; i<1024; i++) {
399 TEST_TYPE *tt;
400
401 tt=(TEST_TYPE *) GWEN_SimplePtrList_GetPtrAt(pl, i);
402 if (tt==NULL) {
403 DBG_ERROR(GWEN_LOGDOMAIN, "No object at position %d", i);
404 GWEN_SimplePtrList_free(pl);
405 return GWEN_ERROR_GENERIC;
406 }
407 GWEN_SimplePtrList_SetPtrAt(pl, i, NULL);
408 TestType_free(tt);
409 } /* for */
410
411 GWEN_SimplePtrList_free(pl);
412 return 0;
413 }
414
415
416
417 /* ------------------------------------------------------------------------------------------------
418 * test 3: test lazy copying
419 * ------------------------------------------------------------------------------------------------
420 */
421
test3(GWEN_UNUSED GWEN_TEST_MODULE * mod)422 int test3(GWEN_UNUSED GWEN_TEST_MODULE *mod)
423 {
424
425 GWEN_SIMPLEPTRLIST *pl;
426 GWEN_SIMPLEPTRLIST *plCopy;
427 int i;
428
429 pl=GWEN_SimplePtrList_new(128, 128);
430 for (i=0; i<1000; i++) {
431 TEST_TYPE *tt;
432 int64_t idx;
433
434 tt=createTestType(i);
435 idx=GWEN_SimplePtrList_AddPtr(pl, tt);
436 if (idx<0) {
437 DBG_ERROR(GWEN_LOGDOMAIN, "Error adding pointer %d to list: %s (%d)", i, GWEN_Error_SimpleToString((int)idx), (int)idx);
438 GWEN_SimplePtrList_free(pl);
439 return (int) idx;
440 }
441 } /* for */
442
443 plCopy=GWEN_SimplePtrList_LazyCopy(pl);
444 if (plCopy==NULL) {
445 DBG_ERROR(GWEN_LOGDOMAIN, "Could not copy pointer list");
446 GWEN_SimplePtrList_free(plCopy);
447 GWEN_SimplePtrList_free(pl);
448 return GWEN_ERROR_INVALID;
449 }
450
451 if (!(plCopy->flags & GWEN_SIMPLEPTRLIST_FLAGS_COPYONWRITE)) {
452 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid object field: flags");
453 GWEN_SimplePtrList_free(plCopy);
454 GWEN_SimplePtrList_free(pl);
455 return GWEN_ERROR_GENERIC;
456 }
457
458 if (!(pl->flags & GWEN_SIMPLEPTRLIST_FLAGS_COPYONWRITE)) {
459 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid object field in old list: flags");
460 GWEN_SimplePtrList_free(plCopy);
461 GWEN_SimplePtrList_free(pl);
462 return GWEN_ERROR_GENERIC;
463 }
464
465 if (plCopy->entryList != pl->entryList) {
466 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid object field: entryList (should be the same after lazy copy)");
467 GWEN_SimplePtrList_free(plCopy);
468 GWEN_SimplePtrList_free(pl);
469 return GWEN_ERROR_GENERIC;
470 }
471
472 if (pl->entryList->refCounter!=2) {
473 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid internal object field: refCounter (should be 2)");
474 GWEN_SimplePtrList_free(pl);
475 return GWEN_ERROR_GENERIC;
476 }
477
478 for (i=1000; i<1024; i++) {
479 TEST_TYPE *tt;
480 int64_t idx;
481
482 tt=createTestType(i);
483 idx=GWEN_SimplePtrList_AddPtr(plCopy, tt);
484 if (idx<0) {
485 DBG_ERROR(GWEN_LOGDOMAIN, "Error adding pointer %d to list: %s (%d)", i, GWEN_Error_SimpleToString((int)idx), (int)idx);
486 GWEN_SimplePtrList_free(plCopy);
487 GWEN_SimplePtrList_free(pl);
488 return (int) idx;
489 }
490 } /* for */
491
492 if (plCopy->flags & GWEN_SIMPLEPTRLIST_FLAGS_COPYONWRITE) {
493 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid object field: flags (should have cleared GWEN_SIMPLEPTRLIST_FLAGS_COPYONWRITE)");
494 GWEN_SimplePtrList_free(plCopy);
495 GWEN_SimplePtrList_free(pl);
496 return GWEN_ERROR_GENERIC;
497 }
498
499 if (!(pl->flags & GWEN_SIMPLEPTRLIST_FLAGS_COPYONWRITE)) {
500 DBG_ERROR(GWEN_LOGDOMAIN,
501 "Invalid object field in old list: flags (should not have cleared GWEN_SIMPLEPTRLIST_FLAGS_COPYONWRITE)");
502 GWEN_SimplePtrList_free(plCopy);
503 GWEN_SimplePtrList_free(pl);
504 return GWEN_ERROR_GENERIC;
505 }
506
507 if (plCopy->entryList == pl->entryList) {
508 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid object field: entryList (should have changed)");
509 GWEN_SimplePtrList_free(plCopy);
510 GWEN_SimplePtrList_free(pl);
511 return GWEN_ERROR_GENERIC;
512 }
513
514 if (pl->entryList->refCounter!=1) {
515 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid internal object field: refCounter (should be back to 1)");
516 GWEN_SimplePtrList_free(pl);
517 return GWEN_ERROR_GENERIC;
518 }
519
520 if (plCopy->entryList->refCounter!=1) {
521 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid internal object field: refCounter (should be 1)");
522 GWEN_SimplePtrList_free(pl);
523 return GWEN_ERROR_GENERIC;
524 }
525
526 if (plCopy->maxEntries!=1024+128) {
527 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid object field: maxEntries (should be 1152)");
528 GWEN_SimplePtrList_free(pl);
529 return GWEN_ERROR_GENERIC;
530 }
531
532 if (plCopy->usedEntries!=1024) {
533 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid object field: usedEntries");
534 GWEN_SimplePtrList_free(pl);
535 return GWEN_ERROR_GENERIC;
536 }
537
538 if (pl->maxEntries!=1024) {
539 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid object field: maxEntries (should still be 1024)");
540 GWEN_SimplePtrList_free(pl);
541 return GWEN_ERROR_GENERIC;
542 }
543
544 if (pl->usedEntries!=1000) {
545 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid object field: usedEntries (should still be 1000)");
546 GWEN_SimplePtrList_free(pl);
547 return GWEN_ERROR_GENERIC;
548 }
549
550
551 for (i=0; i<1024; i++) {
552 TEST_TYPE *tt;
553 int rv;
554
555 tt=(TEST_TYPE *) GWEN_SimplePtrList_GetPtrAt(plCopy, i);
556 if (tt==NULL) {
557 DBG_ERROR(GWEN_LOGDOMAIN, "No object at position %d", i);
558 GWEN_SimplePtrList_free(plCopy);
559 GWEN_SimplePtrList_free(pl);
560 return GWEN_ERROR_GENERIC;
561 }
562
563 rv=TestType_TestHash(tt);
564 if (rv<0) {
565 DBG_ERROR(GWEN_LOGDOMAIN, "Error testing hash of object %d: %s (%d)", i, GWEN_Error_SimpleToString(rv), rv);
566 GWEN_SimplePtrList_free(plCopy);
567 GWEN_SimplePtrList_free(pl);
568 return rv;
569 }
570 } /* for */
571
572 /* free all objects */
573 for (i=0; i<1024; i++) {
574 TEST_TYPE *tt;
575
576 tt=(TEST_TYPE *) GWEN_SimplePtrList_GetPtrAt(plCopy, i);
577 if (tt==NULL) {
578 DBG_ERROR(GWEN_LOGDOMAIN, "No object at position %d", i);
579 GWEN_SimplePtrList_free(plCopy);
580 GWEN_SimplePtrList_free(pl);
581 return GWEN_ERROR_GENERIC;
582 }
583 GWEN_SimplePtrList_SetPtrAt(plCopy, i, NULL);
584 TestType_free(tt);
585 } /* for */
586
587
588 GWEN_SimplePtrList_free(plCopy);
589 GWEN_SimplePtrList_free(pl);
590 return 0;
591 }
592
593
594
595 /* ------------------------------------------------------------------------------------------------
596 * test 4: test adding pointers with attach/detach
597 * ------------------------------------------------------------------------------------------------
598 */
599
test4(GWEN_UNUSED GWEN_TEST_MODULE * mod)600 int test4(GWEN_UNUSED GWEN_TEST_MODULE *mod)
601 {
602
603 GWEN_SIMPLEPTRLIST *pl;
604 TEST_TYPE_LIST *ttList;
605 int i;
606
607 pl=GWEN_SimplePtrList_new(128, 128);
608 GWEN_SimplePtrList_SetAttachObjectFn(pl, _attachToTestType);
609 GWEN_SimplePtrList_SetFreeObjectFn(pl, _detachFromTestType);
610 GWEN_SimplePtrList_AddFlags(pl, GWEN_SIMPLEPTRLIST_FLAGS_ATTACHTOOBJECTS);
611 GWEN_SimplePtrList_AddFlags(pl, GWEN_SIMPLEPTRLIST_FLAGS_DETACHFROMOBJECTS);
612
613 ttList=TestType_List_new();
614
615 for (i=0; i<1024; i++) {
616 TEST_TYPE *tt;
617 int64_t idx;
618
619 tt=createTestType(i);
620 TestType_List_Add(tt, ttList);
621
622 idx=GWEN_SimplePtrList_AddPtr(pl, tt);
623 if (idx<0) {
624 DBG_ERROR(GWEN_LOGDOMAIN, "Error adding pointer %d to list: %s (%d)", i, GWEN_Error_SimpleToString((int)idx), (int)idx);
625 GWEN_SimplePtrList_free(pl);
626 return (int) idx;
627 }
628 } /* for */
629
630 if (1) {
631 TEST_TYPE *tt;
632 int cnt=0;
633
634 tt=TestType_List_First(ttList);
635 while (tt) {
636 if (tt->_refCounter!=2) {
637 DBG_ERROR(GWEN_LOGDOMAIN, "Refcounter of object is not 2");
638 TestType_List_free(ttList);
639 GWEN_SimplePtrList_free(pl);
640 return GWEN_ERROR_GENERIC;
641 }
642 cnt++;
643 tt=TestType_List_Next(tt);
644 }
645 if (cnt!=1024) {
646 DBG_ERROR(GWEN_LOGDOMAIN, "Too few objects in list (%d instead of %d)", cnt, 1024);
647 }
648 }
649
650 for (i=0; i<1024; i++) {
651 TEST_TYPE *tt;
652 int rv;
653
654 tt=(TEST_TYPE *) GWEN_SimplePtrList_GetPtrAt(pl, i);
655 if (tt==NULL) {
656 DBG_ERROR(GWEN_LOGDOMAIN, "No object at position %d", i);
657 TestType_List_free(ttList);
658 GWEN_SimplePtrList_free(pl);
659 return GWEN_ERROR_GENERIC;
660 }
661
662 rv=TestType_TestHash(tt);
663 if (rv<0) {
664 DBG_ERROR(GWEN_LOGDOMAIN, "Error testing hash of object %d: %s (%d)", i, GWEN_Error_SimpleToString(rv), rv);
665 TestType_List_free(ttList);
666 GWEN_SimplePtrList_free(pl);
667 return rv;
668 }
669 } /* for */
670
671 GWEN_SimplePtrList_free(pl);
672
673 if (1) {
674 TEST_TYPE *tt;
675 int cnt=0;
676
677 tt=TestType_List_First(ttList);
678 while (tt) {
679 if (tt->_refCounter!=1) {
680 DBG_ERROR(GWEN_LOGDOMAIN, "Refcounter of object is not 1");
681 TestType_List_free(ttList);
682 return GWEN_ERROR_GENERIC;
683 }
684 cnt++;
685 tt=TestType_List_Next(tt);
686 }
687 if (cnt!=1024) {
688 DBG_ERROR(GWEN_LOGDOMAIN, "Too few objects in list (%d instead of %d)", cnt, 1024);
689 }
690 }
691
692 TestType_List_free(ttList);
693
694 return 0;
695 }
696
697
698
699 /* ------------------------------------------------------------------------------------------------
700 * test 5: test lazy copying with attach/detach
701 * ------------------------------------------------------------------------------------------------
702 */
703
test5(GWEN_UNUSED GWEN_TEST_MODULE * mod)704 int test5(GWEN_UNUSED GWEN_TEST_MODULE *mod)
705 {
706
707 GWEN_SIMPLEPTRLIST *pl;
708 GWEN_SIMPLEPTRLIST *plCopy;
709 TEST_TYPE_LIST *ttList;
710 int i;
711
712 pl=GWEN_SimplePtrList_new(128, 128);
713 GWEN_SimplePtrList_SetAttachObjectFn(pl, _attachToTestType);
714 GWEN_SimplePtrList_SetFreeObjectFn(pl, _detachFromTestType);
715 GWEN_SimplePtrList_AddFlags(pl, GWEN_SIMPLEPTRLIST_FLAGS_ATTACHTOOBJECTS);
716 GWEN_SimplePtrList_AddFlags(pl, GWEN_SIMPLEPTRLIST_FLAGS_DETACHFROMOBJECTS);
717
718 ttList=TestType_List_new();
719 for (i=0; i<1000; i++) {
720 TEST_TYPE *tt;
721 int64_t idx;
722
723 tt=createTestType(i);
724 TestType_List_Add(tt, ttList);
725 idx=GWEN_SimplePtrList_AddPtr(pl, tt);
726 if (idx<0) {
727 DBG_ERROR(GWEN_LOGDOMAIN, "Error adding pointer %d to list: %s (%d)", i, GWEN_Error_SimpleToString((int)idx), (int)idx);
728 GWEN_SimplePtrList_free(pl);
729 return (int) idx;
730 }
731 } /* for */
732
733 plCopy=GWEN_SimplePtrList_LazyCopy(pl);
734 if (plCopy==NULL) {
735 DBG_ERROR(GWEN_LOGDOMAIN, "Could not copy pointer list");
736 GWEN_SimplePtrList_free(plCopy);
737 GWEN_SimplePtrList_free(pl);
738 return GWEN_ERROR_INVALID;
739 }
740
741 if (!(plCopy->flags & GWEN_SIMPLEPTRLIST_FLAGS_ATTACHTOOBJECTS)) {
742 DBG_ERROR(GWEN_LOGDOMAIN,
743 "Invalid object field in list: flags (should have set GWEN_SIMPLEPTRLIST_FLAGS_ATTACHTOOBJECTS)");
744 GWEN_SimplePtrList_free(plCopy);
745 GWEN_SimplePtrList_free(pl);
746 return GWEN_ERROR_GENERIC;
747 }
748
749 if (!(plCopy->flags & GWEN_SIMPLEPTRLIST_FLAGS_DETACHFROMOBJECTS)) {
750 DBG_ERROR(GWEN_LOGDOMAIN,
751 "Invalid object field in list: flags (should have set GWEN_SIMPLEPTRLIST_FLAGS_DETACHFROMOBJECTS)");
752 GWEN_SimplePtrList_free(plCopy);
753 GWEN_SimplePtrList_free(pl);
754 return GWEN_ERROR_GENERIC;
755 }
756
757
758 for (i=1000; i<1024; i++) {
759 TEST_TYPE *tt;
760 int64_t idx;
761
762 tt=createTestType(i);
763 TestType_List_Add(tt, ttList);
764 idx=GWEN_SimplePtrList_AddPtr(plCopy, tt);
765 if (idx<0) {
766 DBG_ERROR(GWEN_LOGDOMAIN, "Error adding pointer %d to list: %s (%d)", i, GWEN_Error_SimpleToString((int)idx), (int)idx);
767 GWEN_SimplePtrList_free(plCopy);
768 GWEN_SimplePtrList_free(pl);
769 return (int) idx;
770 }
771 } /* for */
772
773
774 for (i=0; i<1024; i++) {
775 TEST_TYPE *tt;
776 int rv;
777
778 tt=(TEST_TYPE *) GWEN_SimplePtrList_GetPtrAt(plCopy, i);
779 if (tt==NULL) {
780 DBG_ERROR(GWEN_LOGDOMAIN, "No object at position %d", i);
781 TestType_List_free(ttList);
782 GWEN_SimplePtrList_free(plCopy);
783 GWEN_SimplePtrList_free(pl);
784 return GWEN_ERROR_GENERIC;
785 }
786
787 rv=TestType_TestHash(tt);
788 if (rv<0) {
789 DBG_ERROR(GWEN_LOGDOMAIN, "Error testing hash of object %d: %s (%d)", i, GWEN_Error_SimpleToString(rv), rv);
790 TestType_List_free(ttList);
791 GWEN_SimplePtrList_free(plCopy);
792 GWEN_SimplePtrList_free(pl);
793 return rv;
794 }
795 } /* for */
796
797
798 if (1) {
799 TEST_TYPE *tt;
800 int cnt=0;
801
802 tt=TestType_List_First(ttList);
803 while (tt) {
804 if (cnt<1000) {
805 if (tt->_refCounter!=3) {
806 DBG_ERROR(GWEN_LOGDOMAIN, "Refcounter of object %d is not 3 (%d)", cnt, tt->_refCounter);
807 dumpTestTypeList(ttList);
808 TestType_List_free(ttList);
809 GWEN_SimplePtrList_free(pl);
810 return GWEN_ERROR_GENERIC;
811 }
812 }
813 else {
814 if (tt->_refCounter!=2) {
815 DBG_ERROR(GWEN_LOGDOMAIN, "Refcounter of object is not 2");
816 TestType_List_free(ttList);
817 GWEN_SimplePtrList_free(pl);
818 return GWEN_ERROR_GENERIC;
819 }
820 }
821 cnt++;
822 tt=TestType_List_Next(tt);
823 }
824 if (cnt!=1024) {
825 DBG_ERROR(GWEN_LOGDOMAIN, "Too few objects in list (%d instead of %d)", cnt, 1024);
826 }
827 }
828
829
830 GWEN_SimplePtrList_free(plCopy);
831
832 if (1) {
833 TEST_TYPE *tt;
834 int cnt=0;
835
836 tt=TestType_List_First(ttList);
837 while (tt) {
838 if (cnt<1000) {
839 if (tt->_refCounter!=2) {
840 DBG_ERROR(GWEN_LOGDOMAIN, "Refcounter of object is not 2");
841 TestType_List_free(ttList);
842 GWEN_SimplePtrList_free(pl);
843 return GWEN_ERROR_GENERIC;
844 }
845 }
846 else {
847 if (tt->_refCounter!=1) {
848 DBG_ERROR(GWEN_LOGDOMAIN, "Refcounter of object is not 1");
849 TestType_List_free(ttList);
850 GWEN_SimplePtrList_free(pl);
851 return GWEN_ERROR_GENERIC;
852 }
853 }
854 cnt++;
855 tt=TestType_List_Next(tt);
856 }
857 if (cnt!=1024) {
858 DBG_ERROR(GWEN_LOGDOMAIN, "Too few objects in list (%d instead of %d)", cnt, 1024);
859 }
860 }
861
862
863 GWEN_SimplePtrList_free(pl);
864
865 if (1) {
866 TEST_TYPE *tt;
867 int cnt=0;
868
869 tt=TestType_List_First(ttList);
870 while (tt) {
871 if (tt->_refCounter!=1) {
872 DBG_ERROR(GWEN_LOGDOMAIN, "Refcounter of object is not 1");
873 TestType_List_free(ttList);
874 GWEN_SimplePtrList_free(pl);
875 return GWEN_ERROR_GENERIC;
876 }
877 cnt++;
878 tt=TestType_List_Next(tt);
879 }
880 if (cnt!=1024) {
881 DBG_ERROR(GWEN_LOGDOMAIN, "Too few objects in list (%d instead of %d)", cnt, 1024);
882 }
883 }
884
885 TestType_List_free(ttList);
886
887 return 0;
888 }
889
890
891
892 /* ------------------------------------------------------------------------------------------------
893 * test 6: test lazy copying with attach/detach and setPtr
894 * ------------------------------------------------------------------------------------------------
895 */
896
test6(GWEN_UNUSED GWEN_TEST_MODULE * mod)897 int test6(GWEN_UNUSED GWEN_TEST_MODULE *mod)
898 {
899
900 GWEN_SIMPLEPTRLIST *pl;
901 GWEN_SIMPLEPTRLIST *plCopy;
902 TEST_TYPE_LIST *ttList;
903 int i;
904
905 pl=GWEN_SimplePtrList_new(128, 128);
906 GWEN_SimplePtrList_SetAttachObjectFn(pl, _attachToTestType);
907 GWEN_SimplePtrList_SetFreeObjectFn(pl, _detachFromTestType);
908 GWEN_SimplePtrList_AddFlags(pl, GWEN_SIMPLEPTRLIST_FLAGS_ATTACHTOOBJECTS);
909 GWEN_SimplePtrList_AddFlags(pl, GWEN_SIMPLEPTRLIST_FLAGS_DETACHFROMOBJECTS);
910
911 ttList=TestType_List_new();
912 for (i=0; i<1024; i++) {
913 TEST_TYPE *tt;
914 int64_t idx;
915
916 tt=createTestType(i);
917 TestType_List_Add(tt, ttList);
918 idx=GWEN_SimplePtrList_AddPtr(pl, tt);
919 if (idx<0) {
920 DBG_ERROR(GWEN_LOGDOMAIN, "Error adding pointer %d to list: %s (%d)", i, GWEN_Error_SimpleToString((int)idx), (int)idx);
921 GWEN_SimplePtrList_free(pl);
922 return (int) idx;
923 }
924 } /* for */
925
926 plCopy=GWEN_SimplePtrList_LazyCopy(pl);
927 if (plCopy==NULL) {
928 DBG_ERROR(GWEN_LOGDOMAIN, "Could not copy pointer list");
929 GWEN_SimplePtrList_free(plCopy);
930 GWEN_SimplePtrList_free(pl);
931 return GWEN_ERROR_INVALID;
932 }
933
934 if (!(plCopy->flags & GWEN_SIMPLEPTRLIST_FLAGS_ATTACHTOOBJECTS)) {
935 DBG_ERROR(GWEN_LOGDOMAIN,
936 "Invalid object field in list: flags (should have set GWEN_SIMPLEPTRLIST_FLAGS_ATTACHTOOBJECTS)");
937 GWEN_SimplePtrList_free(plCopy);
938 GWEN_SimplePtrList_free(pl);
939 return GWEN_ERROR_GENERIC;
940 }
941
942 if (!(plCopy->flags & GWEN_SIMPLEPTRLIST_FLAGS_DETACHFROMOBJECTS)) {
943 DBG_ERROR(GWEN_LOGDOMAIN,
944 "Invalid object field in list: flags (should have set GWEN_SIMPLEPTRLIST_FLAGS_DETACHFROMOBJECTS)");
945 GWEN_SimplePtrList_free(plCopy);
946 GWEN_SimplePtrList_free(pl);
947 return GWEN_ERROR_GENERIC;
948 }
949
950
951 if (1) {
952 TEST_TYPE *tt;
953 int rv;
954
955 tt=createTestType(1024);
956 TestType_List_Add(tt, ttList);
957 rv=GWEN_SimplePtrList_SetPtrAt(plCopy, 100, tt);
958 if (rv<0) {
959 DBG_ERROR(GWEN_LOGDOMAIN, "Error setting pointer %d in list: %s (%d)", 100, GWEN_Error_SimpleToString(rv), rv);
960 GWEN_SimplePtrList_free(plCopy);
961 GWEN_SimplePtrList_free(pl);
962 return rv;
963 }
964 }
965
966
967 for (i=0; i<1024; i++) {
968 TEST_TYPE *tt;
969 int rv;
970
971 tt=(TEST_TYPE *) GWEN_SimplePtrList_GetPtrAt(plCopy, i);
972 if (tt==NULL) {
973 DBG_ERROR(GWEN_LOGDOMAIN, "No object at position %d", i);
974 TestType_List_free(ttList);
975 GWEN_SimplePtrList_free(plCopy);
976 GWEN_SimplePtrList_free(pl);
977 return GWEN_ERROR_GENERIC;
978 }
979
980 rv=TestType_TestHash(tt);
981 if (rv<0) {
982 DBG_ERROR(GWEN_LOGDOMAIN, "Error testing hash of object %d: %s (%d)", i, GWEN_Error_SimpleToString(rv), rv);
983 TestType_List_free(ttList);
984 GWEN_SimplePtrList_free(plCopy);
985 GWEN_SimplePtrList_free(pl);
986 return rv;
987 }
988 } /* for */
989
990
991 if (1) {
992 TEST_TYPE *tt;
993 int cnt=0;
994
995 tt=TestType_List_First(ttList);
996 while (tt) {
997 if (cnt==1024 || cnt==100) {
998 if (tt->_refCounter!=2) {
999 DBG_ERROR(GWEN_LOGDOMAIN, "Refcounter of object %d is not 2 (%d)", cnt, tt->_refCounter);
1000 TestType_List_free(ttList);
1001 GWEN_SimplePtrList_free(plCopy);
1002 GWEN_SimplePtrList_free(pl);
1003 return GWEN_ERROR_GENERIC;
1004 }
1005 }
1006 else {
1007 if (tt->_refCounter!=3) {
1008 DBG_ERROR(GWEN_LOGDOMAIN, "Refcounter of object %d is not 3 (%d)", cnt, tt->_refCounter);
1009 TestType_List_free(ttList);
1010 GWEN_SimplePtrList_free(plCopy);
1011 GWEN_SimplePtrList_free(pl);
1012 return GWEN_ERROR_GENERIC;
1013 }
1014 }
1015 cnt++;
1016 tt=TestType_List_Next(tt);
1017 }
1018 if (cnt!=1025) {
1019 DBG_ERROR(GWEN_LOGDOMAIN, "Too few objects in list (%d instead of %d)", cnt, 1024);
1020 }
1021 }
1022
1023 if (1) {
1024 TEST_TYPE *tt1;
1025 TEST_TYPE *tt2;
1026
1027 tt1=(TEST_TYPE *) GWEN_SimplePtrList_GetPtrAt(plCopy, 100);
1028 tt2=(TEST_TYPE *) GWEN_SimplePtrList_GetPtrAt(pl, 100);
1029 if (!(tt1 && tt2 && tt1!=tt2)) {
1030 DBG_ERROR(GWEN_LOGDOMAIN, "Pointers 100 are unexpectedly equal in both lists");
1031 TestType_List_free(ttList);
1032 GWEN_SimplePtrList_free(plCopy);
1033 GWEN_SimplePtrList_free(pl);
1034 return GWEN_ERROR_GENERIC;
1035 }
1036
1037 if (tt1->_refCounter!=2) {
1038 DBG_ERROR(GWEN_LOGDOMAIN, "Refcounter in copy list object 100 is not 2 (%d)", tt1->_refCounter);
1039 TestType_List_free(ttList);
1040 GWEN_SimplePtrList_free(plCopy);
1041 GWEN_SimplePtrList_free(pl);
1042 return GWEN_ERROR_GENERIC;
1043 }
1044 }
1045
1046 GWEN_SimplePtrList_free(plCopy);
1047 GWEN_SimplePtrList_free(pl);
1048 TestType_List_free(ttList);
1049
1050 return 0;
1051 }
1052
1053
1054
1055
1056
1057
1058
1059 #else
1060
GWEN_SimplePtrList_AddTests(GWEN_TEST_MODULE * mod)1061 int GWEN_SimplePtrList_AddTests(GWEN_TEST_MODULE *mod)
1062 {
1063 DBG_ERROR(GWEN_LOGDOMAIN, "Gwenhywfar was compiled without test code enabled.");
1064 return GWEN_ERROR_GENERIC;
1065 }
1066
1067
1068 #endif
1069
1070
1071