rsys

Basic data structures and low-level features
git clone git://git.meso-star.fr/rsys.git
Log | Files | Refs | README | LICENSE

test_hash_table.c (21710B)


      1 /* Copyright (C) 2013-2023, 2025 Vincent Forest (vaplv@free.fr)
      2  *
      3  * The RSys library is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published
      5  * by the Free Software Foundation, either version 3 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * The RSys library is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */
     15 
     16 #include "dynamic_array_char.h"
     17 #include "hash.h"
     18 #include "hash_table.h"
     19 #include "str.h"
     20 #include "test_utils.h"
     21 #include <string.h>
     22 
     23 #define HTABLE_KEY int
     24 #define HTABLE_DATA float
     25 #define HTABLE_NAME int_float
     26 #include "hash_table.h"
     27 
     28 static void
     29 test_htbl_int_float(void)
     30 {
     31   struct mem_allocator allocator_proxy;
     32   struct htable_int_float htbl;
     33   int i;
     34   const int n = 678;
     35 
     36   htable_int_float_init(NULL, &htbl);
     37   htable_int_float_release(&htbl);
     38 
     39   mem_init_proxy_allocator(&allocator_proxy, &mem_default_allocator);
     40 
     41   htable_int_float_init(&allocator_proxy, &htbl);
     42   CHK(htable_int_float_reserve(&htbl, 30) == RES_OK);
     43 
     44   FOR_EACH(i, 0, n) {
     45     float f = (float)i;
     46     CHK(htable_int_float_set(&htbl, &i, &f) == RES_OK);
     47   }
     48 
     49   FOR_EACH(i, 0, n) {
     50     float* p = htable_int_float_find(&htbl, &i);
     51     struct htable_int_float_iterator it;
     52     struct htable_int_float_iterator end;
     53     htable_int_float_find_iterator(&htbl, &i, &it);
     54     htable_int_float_end(&htbl, &end);
     55     CHK(p != NULL);
     56     CHK(*p == (float) i);
     57     CHK(!htable_int_float_iterator_eq(&it, &end));
     58     CHK(*htable_int_float_iterator_key_get(&it) == i);
     59     CHK(*htable_int_float_iterator_data_get(&it) == (float)i);
     60   }
     61   CHK(htable_int_float_size_get(&htbl) == (size_t)n);
     62   FOR_EACH(i, 0, n / 2) {
     63     CHK(htable_int_float_erase(&htbl, &i) == 1);
     64   }
     65   CHK(htable_int_float_size_get(&htbl) == (size_t)(n/2));
     66   FOR_EACH(i, 0, n/2) {
     67     float* p = htable_int_float_find(&htbl, &i);
     68     struct htable_int_float_iterator it;
     69     struct htable_int_float_iterator end;
     70     htable_int_float_find_iterator(&htbl, &i, &it);
     71     htable_int_float_end(&htbl, &end);
     72     CHK(p == NULL);
     73     CHK(htable_int_float_iterator_eq(&it, &end));
     74   }
     75   FOR_EACH(i, n/2, n) {
     76     float* p = htable_int_float_find(&htbl, &i);
     77     struct htable_int_float_iterator it;
     78     struct htable_int_float_iterator end;
     79     htable_int_float_find_iterator(&htbl, &i, &it);
     80     htable_int_float_end(&htbl, &end);
     81     CHK(p != NULL);
     82     CHK(*p == (float) i);
     83     CHK(!htable_int_float_iterator_eq(&it, &end));
     84     CHK(*htable_int_float_iterator_key_get(&it) == i);
     85     CHK(*htable_int_float_iterator_data_get(&it) == (float)i);
     86   }
     87   htable_int_float_release(&htbl);
     88 
     89   check_memory_allocator(&allocator_proxy);
     90   mem_shutdown_proxy_allocator(&allocator_proxy);
     91 }
     92 
     93 static INLINE char
     94 eq_str(const struct str* a, const struct str* b)
     95 {
     96   return !strcmp(str_cget(a), str_cget(b));
     97 }
     98 
     99 static INLINE size_t
    100 hash_str(const struct str* a)
    101 {
    102   return hash_fnv32(str_cget(a), str_len(a));
    103 }
    104 
    105 #define HTABLE_KEY struct str
    106 #define HTABLE_DATA int
    107 #define HTABLE_NAME str_int
    108 #define HTABLE_KEY_FUNCTOR_INIT str_init
    109 #define HTABLE_KEY_FUNCTOR_RELEASE str_release
    110 #define HTABLE_KEY_FUNCTOR_COPY str_copy
    111 #define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release
    112 #define HTABLE_KEY_FUNCTOR_EQ eq_str
    113 #define HTABLE_KEY_FUNCTOR_HASH hash_str
    114 #include "hash_table.h"
    115 
    116 static void
    117 test_htbl_str_int(void)
    118 {
    119   struct mem_allocator allocator_proxy;
    120   struct htable_str_int htbl;
    121   struct htable_str_int_iterator it0;
    122   struct htable_str_int_iterator it1;
    123   struct htable_str_int_iterator it2;
    124   const char* str[] = {
    125     "analyse", "analysis", "analyst", "analytic", "analytical", "analytically",
    126     "analyze", "approach", "approachable", "area", "assess", "assessable",
    127     "assessment", "assume", "assumed", "assuming", "assumption",
    128     "authoritative", "authoritatively", "authority", "availability",
    129     "available", "beneficial", "beneficiary", "benefit", "blinker", "concept",
    130     "conception", "conceptual", "conceptualize", "conceptually", "consist",
    131     "consistency", "consistent", "consistently", "constituency", "constituent",
    132     "constitute", "constitution", "constitutional", "constitutionally",
    133     "constitutive", "context", "contextual", "contextualization",
    134     "contextualize", "contextually", "contract", "contractor", "create",
    135     "creation", "creative", "creatively", "creativity", "creator", "data",
    136     "definable", "define", "definition", "derivation", "derivative", "derive",
    137     "disestablish", "disestablishment", "dissimilar", "dissimilarity",
    138     "distribute", "distribution", "distributional", "distributive",
    139     "distributor", "economic", "economical", "economically", "economics",
    140     "economist", "economy", "environment", "environmental", "environmentalism",
    141     "environmentalist", "environmentally", "establish", "established",
    142     "establishment", "estimate", "estimation", "evidence", "evident",
    143     "evidential", "evidently", "export", "exporter", "factor", "finance",
    144     "financial", "financially", "financier", "financing", "formula"
    145   };
    146   char str_found[sizeof(str) / sizeof(const char*)];
    147   const int str_size = (int)(sizeof(str) / sizeof(const char*));
    148   int array[32];
    149   const int array_size = (int)(sizeof(array) / sizeof(int));
    150   struct str tmp;
    151   int i = 0;
    152   struct str* key = NULL;
    153   int* data = NULL;
    154   STATIC_ASSERT
    155     (sizeof(str)/sizeof(const char*) >= sizeof(array)/sizeof(int),
    156       Unexpected_array_size);
    157 
    158   mem_init_proxy_allocator(&allocator_proxy, &mem_default_allocator);
    159 
    160   FOR_EACH(i, 0, (int)array_size) {
    161     /* Compute a str id that is not already registered into array */
    162     int j = rand() % str_size;
    163     for(;;) {
    164       int k;
    165       FOR_EACH(k, 0, i) {
    166         if(array[k] == j) break;
    167       }
    168       if(k >= i) break;
    169       j = j + 1 % str_size;
    170     }
    171     array[i] = j;
    172   }
    173 
    174   str_init(&allocator_proxy, &tmp);
    175 
    176   htable_str_int_init(&allocator_proxy, &htbl);
    177   CHK(htable_str_int_is_empty(&htbl) == 1);
    178   str_set(&tmp, "empty");
    179   CHK(htable_str_int_find(&htbl, &tmp) == NULL);
    180   CHK(htable_str_int_size_get(&htbl) == 0);
    181   htable_str_int_find_iterator(&htbl, &tmp, &it0);
    182   htable_str_int_end(&htbl, &it1);
    183   CHK(htable_str_int_iterator_eq(&it0, &it1));
    184   htable_str_int_iterator_next(&it0);
    185   CHK(htable_str_int_iterator_eq(&it0, &it1));
    186   i = 0;
    187   str_set(&tmp, str[i]);
    188   CHK(htable_str_int_set(&htbl, &tmp, &i) == RES_OK);
    189   CHK(htable_str_int_is_empty(&htbl) == 0);
    190   CHK(htable_str_int_size_get(&htbl) == 1);
    191 
    192   FOR_EACH(i, 1, str_size) {
    193     str_set(&tmp, str[i]);
    194     CHK(htable_str_int_set(&htbl, &tmp, &i) == RES_OK);
    195   }
    196   CHK(htable_str_int_size_get(&htbl) == (size_t)str_size);
    197 
    198   str_set(&tmp, str[str_size/2]);
    199   htable_str_int_find_iterator(&htbl, &tmp, &it0);
    200   htable_str_int_end(&htbl, &it1);
    201   CHK(!htable_str_int_iterator_eq(&it0, &it1));
    202   while(!htable_str_int_iterator_eq(&it0, &it1)) {
    203     key = htable_str_int_iterator_key_get(&it0);
    204     data = htable_str_int_iterator_data_get(&it0);
    205     CHK(*htable_str_int_find(&htbl, key) == *data);
    206     htable_str_int_iterator_next(&it0);
    207   }
    208 
    209   str_set(&tmp, "Terra icognita");
    210   CHK(htable_str_int_find(&htbl, &tmp) == NULL);
    211   FOR_EACH(i, 0, 64) {
    212     int j = rand() % str_size;
    213     str_set(&tmp, str[j]);
    214     data = htable_str_int_find(&htbl, &tmp);
    215     CHK(data != NULL);
    216     CHK(*data == (int)j);
    217     htable_str_int_find_iterator(&htbl, &tmp, &it0);
    218     htable_str_int_end(&htbl, &it1);
    219     CHK(!htable_str_int_iterator_eq(&it0, &it1));
    220     CHK(!str_cmp(htable_str_int_iterator_key_get(&it0), &tmp));
    221     CHK(*htable_str_int_iterator_data_get(&it0) == (int)j);
    222   }
    223 
    224   str_set(&tmp, "Terra icognita");
    225   CHK(htable_str_int_erase(&htbl, &tmp) == 0);
    226   FOR_EACH(i, 0, array_size) {
    227     str_set(&tmp, str[array[i]]);
    228     CHK(htable_str_int_erase(&htbl, &tmp) == 1);
    229   }
    230   FOR_EACH(i, 0, array_size) {
    231     str_set(&tmp, str[array[i]]);
    232     CHK(htable_str_int_find(&htbl, &tmp) == 0);
    233     htable_str_int_find_iterator(&htbl, &tmp, &it0);
    234     htable_str_int_end(&htbl, &it1);
    235     CHK(htable_str_int_iterator_eq(&it0, &it1));
    236   }
    237   CHK(htable_str_int_size_get(&htbl) == (size_t)(str_size - array_size));
    238   FOR_EACH(i, 0, str_size) {
    239     int j = 0;
    240     FOR_EACH(j, 0, array_size) {
    241       if(array[j] == i)
    242         break;
    243     }
    244     if(j >= array_size) {
    245       str_set(&tmp, str[i]);
    246       data = htable_str_int_find(&htbl, &tmp);
    247       CHK(data != NULL);
    248       CHK(*data == (int)i);
    249       htable_str_int_find_iterator(&htbl, &tmp, &it0);
    250       htable_str_int_end(&htbl, &it1);
    251       CHK(!htable_str_int_iterator_eq(&it0, &it1));
    252       CHK(!str_cmp(htable_str_int_iterator_key_get(&it0), &tmp));
    253       CHK(*htable_str_int_iterator_data_get(&it0) == (int)i);
    254     }
    255   }
    256   FOR_EACH(i, 0, array_size) {
    257     str_set(&tmp, str[array[i]]);
    258     CHK(htable_str_int_set(&htbl, &tmp, array + i) == RES_OK);
    259   }
    260   CHK(htable_str_int_size_get(&htbl) == (size_t)str_size);
    261   CHK(htable_str_int_is_empty(&htbl) == 0);
    262 
    263   htable_str_int_begin(&htbl, &it0);
    264   htable_str_int_end(&htbl, &it1);
    265   CHK(htable_str_int_iterator_eq(&it0, &it0) == 1);
    266   CHK(htable_str_int_iterator_eq(&it0, &it1) == 0);
    267   memset(str_found, 0, sizeof(str_found));
    268   while(!htable_str_int_iterator_eq(&it0, &it1) ) {
    269     key = htable_str_int_iterator_key_get(&it0);
    270     data = htable_str_int_iterator_data_get(&it0);
    271     CHK(*htable_str_int_find(&htbl, key) == *data);
    272 
    273     htable_str_int_find_iterator(&htbl, key, &it2);
    274     CHK(htable_str_int_iterator_eq(&it0, &it2));
    275     CHK(!str_cmp(htable_str_int_iterator_key_get(&it2), key));
    276     CHK(*htable_str_int_iterator_data_get(&it2) == *data);
    277 
    278     CHK(str_found[*data] == 0);
    279     str_found[*data] = 1;
    280     htable_str_int_iterator_next(&it0);
    281   }
    282 
    283   FOR_EACH(i, 0, str_size) {
    284     CHK(str_found[i] == 1);
    285   }
    286 
    287   htable_str_int_purge(&htbl);
    288   htable_str_int_begin(&htbl, &it0);
    289   htable_str_int_end(&htbl, &it1);
    290   CHK(htable_str_int_iterator_eq(&it0, &it1) == 1);
    291 
    292   CHK(htable_str_int_is_empty(&htbl) == 1);
    293   CHK(htable_str_int_size_get(&htbl) == 0);
    294   htable_str_int_release(&htbl);
    295 
    296   htable_str_int_init(&allocator_proxy, &htbl);
    297   htable_str_int_reserve(&htbl, 3);
    298   str_set(&tmp, "Zero"), i = 0;
    299   CHK(htable_str_int_set(&htbl, &tmp, &i) == RES_OK);
    300   str_set(&tmp, "One"), i = 1;
    301   CHK(htable_str_int_set(&htbl, &tmp, &i) == RES_OK);
    302   str_set(&tmp, "Two"), i = 2;
    303   CHK(htable_str_int_set(&htbl, &tmp, &i) == RES_OK);
    304   str_set(&tmp, "Three"), i = 3;
    305   CHK(htable_str_int_set(&htbl, &tmp, &i) == RES_OK);
    306   str_set(&tmp, "Four"), i = 4;
    307   CHK(htable_str_int_set(&htbl, &tmp, &i) == RES_OK);
    308   CHK(htable_str_int_size_get(&htbl) == 5);
    309   str_set(&tmp, "Zero"), i = 'a';
    310   CHK(htable_str_int_set(&htbl, &tmp, &i) == RES_OK);
    311   CHK(htable_str_int_size_get(&htbl) == 5);
    312 
    313   data = htable_str_int_find(&htbl, &tmp);
    314   htable_str_int_find_iterator(&htbl, &tmp, &it0);
    315   htable_str_int_end(&htbl, &it1);
    316   CHK(data != NULL);
    317   CHK(*data == 'a');
    318   CHK(!htable_str_int_iterator_eq(&it0, &it1));
    319   CHK(!str_cmp(htable_str_int_iterator_key_get(&it0), &tmp));
    320   CHK(*htable_str_int_iterator_data_get(&it0) == *data);
    321 
    322   htable_str_int_clear(&htbl);
    323   htable_str_int_begin(&htbl, &it0);
    324   htable_str_int_end(&htbl, &it1);
    325   CHK(htable_str_int_iterator_eq(&it0, &it1) == 1);
    326   CHK(htable_str_int_is_empty(&htbl) == 1);
    327   CHK(htable_str_int_size_get(&htbl) == 0);
    328 
    329   htable_str_int_release(&htbl);
    330 
    331   str_release(&tmp);
    332 
    333   check_memory_allocator(&allocator_proxy);
    334   mem_shutdown_proxy_allocator(&allocator_proxy);
    335 }
    336 
    337 #define HTABLE_KEY struct str
    338 #define HTABLE_DATA struct darray_char
    339 #define HTABLE_NAME str_darray
    340 #define HTABLE_KEY_FUNCTOR_INIT str_init
    341 #define HTABLE_KEY_FUNCTOR_RELEASE str_release
    342 #define HTABLE_KEY_FUNCTOR_COPY str_copy
    343 #define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release
    344 #define HTABLE_KEY_FUNCTOR_EQ eq_str
    345 #define HTABLE_KEY_FUNCTOR_HASH hash_str
    346 #define HTABLE_DATA_FUNCTOR_INIT darray_char_init
    347 #define HTABLE_DATA_FUNCTOR_RELEASE darray_char_release
    348 #define HTABLE_DATA_FUNCTOR_COPY darray_char_copy
    349 #define HTABLE_DATA_FUNCTOR_COPY_AND_RELEASE darray_char_copy_and_release
    350 #include "hash_table.h"
    351 
    352 static void
    353 test_htbl_str_darray(void)
    354 {
    355   struct mem_allocator allocator_proxy;
    356   struct htable_str_darray htbl, htbl2, htbl3;
    357   struct htable_str_darray_iterator it0;
    358   struct htable_str_darray_iterator it1;
    359   struct darray_char darray;
    360   struct darray_char* data = NULL;
    361   struct str* key = NULL;
    362   struct str tmp;
    363   const char* str[] = {
    364 "Rcvfbqr 1, XARR-QRRC VA GUR QRNQ:\n\
    365 ---------------------------------",
    366 
    367 "BAPR LBH ORNG GUR OVT ONQNFFRF NAQ PYRNA BHG GUR ZBBA ONFR LBH'ER FHCCBFRQ GB\n\
    368 JVA, NERA'G LBH? NERA'G LBH? JURER'F LBHE SNG ERJNEQ NAQ GVPXRG UBZR? JUNG\n\
    369 GUR URYY VF GUVF? VG'F ABG FHCCBFRQ GB RAQ GUVF JNL!",
    370 
    371 "VG FGVAXF YVXR EBGGRA ZRNG, OHG YBBXF YVXR GUR YBFG QRVZBF ONFR. YBBXF YVXR\n\
    372 LBH'ER FGHPX BA GUR FUBERF BS URYY. GUR BAYL JNL BHG VF GUEBHTU.",
    373 
    374 "GB PBAGVAHR GUR QBBZ RKCREVRAPR, CYNL GUR FUBERF BS URYY NAQ VGF NZNMVAT\n\
    375 FRDHRY, VASREAB!",
    376 
    377 "Rcvfbqr 2, GUR FUBERF BS URYY:\n\
    378 ------------------------------",
    379 
    380 "LBH'IR QBAR VG! GUR UVQRBHF PLORE- QRZBA YBEQ GUNG EHYRQ GUR YBFG QRVZBF ZBBA\n\
    381 ONFR UNF ORRA FYNVA NAQ LBH NER GEVHZCUNAG! OHG ... JURER NER LBH? LBH\n\
    382 PYNZORE GB GUR RQTR BS GUR ZBBA NAQ YBBX QBJA GB FRR GUR NJSHY GEHGU.",
    383 
    384 "QRVZBF SYBNGF NOBIR URYY VGFRYS!  LBH'IR ARIRE URNEQ BS NALBAR RFPNCVAT SEBZ\n\
    385 URYY, OHG LBH'YY ZNXR GUR ONFGNEQF FBEEL GURL RIRE URNEQ BS LBH! DHVPXYL, LBH\n\
    386 ENCCRY QBJA GB GUR FHESNPR BS URYY.",
    387 
    388 "ABJ, VG'F BA GB GUR SVANY PUNCGRE BS QBBZ! -- VASREAB.",
    389 
    390 "Rcvfbqr 3, VASREAB:\n\
    391 -------------------",
    392 
    393 "GUR YBNGUFBZR FCVQREQRZBA GUNG ZNFGREZVAQRQ GUR VAINFVBA BS GUR ZBBA ONFRF\n\
    394 NAQ PNHFRQ FB ZHPU QRNGU UNF UNQ VGF NFF XVPXRQ SBE NYY GVZR.",
    395 
    396 "N UVQQRA QBBEJNL BCRAF NAQ LBH RAGRE.  LBH'IR CEBIRA GBB GBHTU SBE URYY GB\n\
    397 PBAGNVA, NAQ ABJ URYY NG YNFG CYNLF SNVE -- SBE LBH RZRETR SEBZ GUR QBBE GB\n\
    398 FRR GUR TERRA SVRYQF BS RNEGU!  UBZR NG YNFG.",
    399 
    400 "LBH JBAQRE JUNG'F ORRA UNCCRAVAT BA RNEGU JUVYR LBH JRER ONGGYVAT RIVY\n\
    401 HAYRNFURQ. VG'F TBBQ GUNG AB URYY- FCNJA PBHYQ UNIR PBZR GUEBHTU GUNG QBBE\n\
    402 JVGU LBH ...",
    403 
    404 "Rcvfbqr 4, GUL SYRFU PBAFHZRQ:\n\
    405 ------------------------------",
    406 
    407 "GUR FCVQRE ZNFGREZVAQ ZHFG UNIR FRAG SBEGU VGF YRTVBAF BS URYYFCNJA ORSBER\n\
    408 LBHE SVANY PBASEBAGNGVBA JVGU GUNG GREEVOYR ORNFG SEBZ URYY. OHG LBH FGRCCRQ\n\
    409 SBEJNEQ NAQ OEBHTUG SBEGU RGREANY QNZANGVBA NAQ FHSSREVAT HCBA GUR UBEQR NF N\n\
    410 GEHR UREB JBHYQ VA GUR SNPR BS FBZRGUVAT FB RIVY.",
    411 
    412 "ORFVQRF, FBZRBAR JNF TBAAN CNL SBE JUNG UNCCRARQ GB QNVFL, LBHE CRG ENOOVG.",
    413 
    414 "OHG ABJ, LBH FRR FCERNQ ORSBER LBH ZBER CBGRAGVNY CNVA NAQ TVOOVGHQR NF N\n\
    415 ANGVBA BS QRZBAF EHA NZBX VA BHE PVGVRF.",
    416 
    417 "ARKG FGBC, URYY BA RNEGU!"
    418   };
    419   size_t nstrs = sizeof(str)/sizeof(const char*);
    420   size_t i = 0, j = 0, k = 0;
    421   size_t buf[16];
    422   const size_t nerase = 3;
    423 
    424   mem_init_proxy_allocator(&allocator_proxy, &mem_default_allocator);
    425   htable_str_darray_init(&allocator_proxy, &htbl);
    426   htable_str_darray_init(&allocator_proxy, &htbl2);
    427   htable_str_darray_init(&allocator_proxy, &htbl3);
    428   darray_char_init(&allocator_proxy, &darray);
    429   str_init(&allocator_proxy, &tmp);
    430 
    431   FOR_EACH(i, 0, nstrs) {
    432     darray_char_clear(&darray);
    433     FOR_EACH(j, 0, strlen(str[i]) + 1) {
    434       CHK(darray_char_push_back(&darray, str[i] + j) == RES_OK);
    435     }
    436     str_set(&tmp, str[i]);
    437     CHK(htable_str_darray_set(&htbl, &tmp, &darray) == RES_OK);
    438   }
    439 
    440   CHK(htable_str_darray_size_get(&htbl) == nstrs);
    441   CHK(htable_str_darray_size_get(&htbl2) == 0);
    442   CHK(htable_str_darray_size_get(&htbl3) == 0);
    443 
    444   CHK(htable_str_darray_copy(&htbl3, &htbl) == RES_OK);
    445   CHK(htable_str_darray_copy(&htbl, &htbl2) == RES_OK);
    446 
    447   CHK(htable_str_darray_size_get(&htbl) == 0);
    448   CHK(htable_str_darray_size_get(&htbl2) == 0);
    449   CHK(htable_str_darray_size_get(&htbl3) == nstrs);
    450 
    451   CHK(htable_str_darray_copy(&htbl, &htbl3) == RES_OK);
    452   CHK(htable_str_darray_copy_and_clear(&htbl2, &htbl3) == RES_OK);
    453 
    454   CHK(htable_str_darray_size_get(&htbl) == nstrs);
    455   CHK(htable_str_darray_size_get(&htbl2) == nstrs);
    456   CHK(htable_str_darray_size_get(&htbl3) == 0);
    457 
    458   FOR_EACH(i, 0, nstrs) {
    459     darray_char_clear(&darray);
    460     FOR_EACH(j, 0, strlen(str[i]) + 1) {
    461       CHK(darray_char_push_back(&darray, str[i] + j) == RES_OK);
    462     }
    463     str_set(&tmp, str[i]);
    464     CHK(htable_str_darray_set(&htbl3, &tmp, &darray) == RES_OK);
    465   }
    466 
    467   CHK(htable_str_darray_size_get(&htbl3) == nstrs);
    468 
    469   FOR_EACH(i, 0, nstrs) {
    470     str_set(&tmp, str[i]);
    471 
    472     data = htable_str_darray_find(&htbl, &tmp);
    473     htable_str_darray_find_iterator(&htbl, &tmp, &it0);
    474     htable_str_darray_end(&htbl, &it1);
    475     CHK(data != NULL);
    476     CHK(strcmp(darray_char_cdata_get(data), str[i]) == 0);
    477     CHK(!htable_str_darray_iterator_eq(&it0, &it1));
    478     key = htable_str_darray_iterator_key_get(&it0);
    479     data = htable_str_darray_iterator_data_get(&it0);
    480     CHK(!str_cmp(key, &tmp));
    481     CHK(strcmp(darray_char_cdata_get(data), str[i]) == 0);
    482 
    483     data = htable_str_darray_find(&htbl2, &tmp);
    484     htable_str_darray_find_iterator(&htbl2, &tmp, &it0);
    485     htable_str_darray_end(&htbl2, &it1);
    486     CHK(data != NULL);
    487     CHK(strcmp(darray_char_cdata_get(data), str[i]) == 0);
    488     CHK(!htable_str_darray_iterator_eq(&it0, &it1));
    489     key = htable_str_darray_iterator_key_get(&it0);
    490     data = htable_str_darray_iterator_data_get(&it0);
    491     CHK(!str_cmp(key, &tmp));
    492     CHK(strcmp(darray_char_cdata_get(data), str[i]) == 0);
    493 
    494     data = htable_str_darray_find(&htbl3, &tmp);
    495     htable_str_darray_find_iterator(&htbl3, &tmp, &it0);
    496     htable_str_darray_end(&htbl3, &it1);
    497     CHK(data != NULL);
    498     CHK(strcmp(darray_char_cdata_get(data), str[i]) == 0);
    499     CHK(!htable_str_darray_iterator_eq(&it0, &it1));
    500     key = htable_str_darray_iterator_key_get(&it0);
    501     data = htable_str_darray_iterator_data_get(&it0);
    502     CHK(!str_cmp(key, &tmp));
    503     CHK(strcmp(darray_char_cdata_get(data), str[i]) == 0);
    504   }
    505 
    506   FOR_EACH(j, 0, nerase) {
    507     for(;;) {
    508       i = (size_t)rand() % nstrs;
    509       FOR_EACH(k, 0, j)
    510         if(buf[k] == i) break;
    511       if(k >= j) break;
    512     }
    513 
    514     buf[j] = i;
    515 
    516     str_set(&tmp, str[i]);
    517     data = htable_str_darray_find(&htbl, &tmp);
    518     htable_str_darray_find_iterator(&htbl, &tmp, &it0);
    519     htable_str_darray_end(&htbl, &it1);
    520     CHK(data != NULL);
    521     CHK(strcmp(darray_char_cdata_get(data), str_cget(&tmp)) == 0);
    522     key = htable_str_darray_iterator_key_get(&it0);
    523     data = htable_str_darray_find(&htbl, &tmp);
    524     CHK(!str_cmp(key, &tmp));
    525     CHK(strcmp(darray_char_cdata_get(data), str_cget(&tmp)) == 0);
    526     CHK(htable_str_darray_erase(&htbl, &tmp) == 1);
    527     CHK(htable_str_darray_erase(&htbl, &tmp) == 0);
    528   }
    529   CHK(htable_str_darray_size_get(&htbl) == nstrs - nerase);
    530 
    531   FOR_EACH(j, 0, nerase) {
    532     str_set(&tmp, str[buf[j]]);
    533 
    534     data = htable_str_darray_find(&htbl, &tmp);
    535     htable_str_darray_find_iterator(&htbl, &tmp, &it0);
    536     htable_str_darray_end(&htbl, &it1);
    537     CHK(data == NULL);
    538     CHK(htable_str_darray_iterator_eq(&it0, &it1));
    539 
    540     data = htable_str_darray_find(&htbl2, &tmp);
    541     htable_str_darray_find_iterator(&htbl2, &tmp, &it0);
    542     htable_str_darray_end(&htbl2, &it1);
    543     CHK(data != NULL);
    544     CHK(strcmp(darray_char_cdata_get(data), str[buf[j]]) == 0);
    545     CHK(!htable_str_darray_iterator_eq(&it0, &it1));
    546     key = htable_str_darray_iterator_key_get(&it0);
    547     data = htable_str_darray_iterator_data_get(&it0);
    548     CHK(!str_cmp(key, &tmp));
    549     CHK(strcmp(darray_char_cdata_get(data), str[buf[j]]) == 0);
    550 
    551     data = htable_str_darray_find(&htbl3, &tmp);
    552     htable_str_darray_find_iterator(&htbl3, &tmp, &it0);
    553     htable_str_darray_end(&htbl3, &it1);
    554     CHK(data != NULL);
    555     CHK(strcmp(darray_char_cdata_get(data), str[buf[j]]) == 0);
    556     CHK(!htable_str_darray_iterator_eq(&it0, &it1));
    557     key = htable_str_darray_iterator_key_get(&it0);
    558     data = htable_str_darray_iterator_data_get(&it0);
    559     CHK(!str_cmp(key, &tmp));
    560     CHK(strcmp(darray_char_cdata_get(data), str[buf[j]]) == 0);
    561   }
    562 
    563 
    564   htable_str_darray_begin(&htbl, &it0);
    565   htable_str_darray_end(&htbl, &it1);
    566   while(!htable_str_darray_iterator_eq(&it0, &it1)) {
    567     key = htable_str_darray_iterator_key_get(&it0);
    568     data = htable_str_darray_iterator_data_get(&it0);
    569     CHK(strcmp(str_cget(key), darray_char_cdata_get(data)) == 0);
    570     htable_str_darray_iterator_next(&it0);
    571   }
    572 
    573   CHK(htable_str_darray_reserve(&htbl, 2891) == RES_OK);
    574 
    575   FOR_EACH(j, 0, 5) {
    576     for(;;) {
    577       i = (size_t)rand() % nstrs;
    578       FOR_EACH(k, 0, nerase)
    579         if(buf[k] == i) break;
    580       if(k >= nerase) break;
    581     }
    582     str_set(&tmp, str[i]);
    583     data = htable_str_darray_find(&htbl, &tmp);
    584     CHK(data != NULL);
    585     CHK(strcmp(darray_char_cdata_get(data), str_cget(&tmp)) == 0);
    586   }
    587 
    588   htable_str_darray_copy_and_release(&htbl, &htbl3);
    589   FOR_EACH(i, 0, nstrs) {
    590     str_set(&tmp, str[i]);
    591 
    592     data = htable_str_darray_find(&htbl, &tmp);
    593     CHK(data != NULL);
    594     CHK(strcmp(darray_char_cdata_get(data), str[i]) == 0);
    595 
    596     data = htable_str_darray_find(&htbl2, &tmp);
    597     CHK(data != NULL);
    598     CHK(strcmp(darray_char_cdata_get(data), str[i]) == 0);
    599   }
    600 
    601   str_release(&tmp);
    602   darray_char_release(&darray);
    603   htable_str_darray_release(&htbl);
    604   htable_str_darray_release(&htbl2);
    605   check_memory_allocator(&allocator_proxy);
    606   mem_shutdown_proxy_allocator(&allocator_proxy);
    607 }
    608 
    609 int
    610 main(int argc, char** argv)
    611 {
    612   (void)argc, (void)argv;
    613   test_htbl_int_float();
    614   test_htbl_str_int();
    615   test_htbl_str_darray();
    616   return 0;
    617 }