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