LCOV - code coverage report
Current view: top level - funk - fd_funk.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 241 298 80.9 %
Date: 2025-07-05 04:47:39 Functions: 7 9 77.8 %

          Line data    Source code
       1             : #include "fd_funk.h"
       2             : #include "fd_funk_base.h"
       3             : #include <stdio.h>
       4             : 
       5             : ulong
       6         147 : fd_funk_align( void ) {
       7         147 :   return FD_FUNK_ALIGN;
       8         147 : }
       9             : 
      10             : ulong
      11             : fd_funk_footprint( ulong txn_max,
      12          57 :                    ulong rec_max ) {
      13          57 :   if( FD_UNLIKELY( rec_max>UINT_MAX ) ) return 0UL;
      14             : 
      15          57 :   ulong l = FD_LAYOUT_INIT;
      16             : 
      17          57 :   l = FD_LAYOUT_APPEND( l, alignof(fd_funk_shmem_t), sizeof(fd_funk_shmem_t) );
      18             : 
      19          57 :   ulong txn_chain_cnt = fd_funk_txn_map_chain_cnt_est( txn_max );
      20          57 :   l = FD_LAYOUT_APPEND( l, fd_funk_txn_map_align(), fd_funk_txn_map_footprint( txn_chain_cnt ) );
      21          57 :   l = FD_LAYOUT_APPEND( l, fd_funk_txn_pool_align(), fd_funk_txn_pool_footprint() );
      22          57 :   l = FD_LAYOUT_APPEND( l, alignof(fd_funk_txn_t), sizeof(fd_funk_txn_t) * txn_max );
      23             : 
      24          57 :   ulong rec_chain_cnt = fd_funk_rec_map_chain_cnt_est( rec_max );
      25          57 :   l = FD_LAYOUT_APPEND( l, fd_funk_rec_map_align(), fd_funk_rec_map_footprint( rec_chain_cnt ) );
      26          57 :   l = FD_LAYOUT_APPEND( l, fd_funk_rec_pool_align(), fd_funk_rec_pool_footprint() );
      27          57 :   l = FD_LAYOUT_APPEND( l, alignof(fd_funk_rec_t), sizeof(fd_funk_rec_t) * rec_max );
      28             : 
      29          57 :   l = FD_LAYOUT_APPEND( l, fd_alloc_align(), fd_alloc_footprint() );
      30             : 
      31          57 :   return l;
      32          57 : }
      33             : 
      34             : /* TODO: Consider letter user just passing a join of alloc to use,
      35             :    inferring the backing wksp and cgroup_hint from that and then
      36             :    allocating exclusively from that? */
      37             : 
      38             : void *
      39             : fd_funk_new( void * shmem,
      40             :              ulong  wksp_tag,
      41             :              ulong  seed,
      42             :              ulong  txn_max,
      43          48 :              ulong  rec_max ) {
      44          48 :   fd_funk_shmem_t * funk = shmem;
      45          48 :   fd_wksp_t *       wksp = fd_wksp_containing( funk );
      46             : 
      47          48 :   if( FD_UNLIKELY( !funk ) ) {
      48           3 :     FD_LOG_WARNING(( "NULL funk" ));
      49           3 :     return NULL;
      50           3 :   }
      51             : 
      52          45 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)funk, fd_funk_align() ) ) ) {
      53           3 :     FD_LOG_WARNING(( "misaligned funk" ));
      54           3 :     return NULL;
      55           3 :   }
      56             : 
      57          42 :   if( FD_UNLIKELY( !wksp_tag ) ) {
      58           3 :     FD_LOG_WARNING(( "bad wksp_tag" ));
      59           3 :     return NULL;
      60           3 :   }
      61             : 
      62          39 :   if( FD_UNLIKELY( !wksp ) ) {
      63           3 :     FD_LOG_WARNING(( "shmem must be part of a workspace" ));
      64           3 :     return NULL;
      65           3 :   }
      66             : 
      67          36 :   if( FD_UNLIKELY( txn_max>FD_FUNK_TXN_IDX_NULL ) ) { /* See note in fd_funk.h about this limit */
      68           3 :     FD_LOG_WARNING(( "txn_max too large for index compression" ));
      69           3 :     return NULL;
      70           3 :   }
      71             : 
      72          33 :   if( FD_UNLIKELY( rec_max>UINT_MAX ) ) {
      73           0 :     FD_LOG_WARNING(( "invalid rec_max" ));
      74           0 :     return NULL;
      75           0 :   }
      76             : 
      77          33 :   FD_SCRATCH_ALLOC_INIT( l, funk+1 );
      78             : 
      79          33 :   ulong txn_chain_cnt = fd_funk_txn_map_chain_cnt_est( txn_max );
      80          33 :   void * txn_map = FD_SCRATCH_ALLOC_APPEND( l, fd_funk_txn_map_align(), fd_funk_txn_map_footprint( txn_chain_cnt ) );
      81          33 :   void * txn_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_funk_txn_pool_align(), fd_funk_txn_pool_footprint() );
      82          33 :   fd_funk_txn_t * txn_ele = (fd_funk_txn_t *)FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_funk_txn_t), sizeof(fd_funk_txn_t) * txn_max );
      83             : 
      84           0 :   ulong rec_chain_cnt = fd_funk_rec_map_chain_cnt_est( rec_max );
      85          33 :   void * rec_map = FD_SCRATCH_ALLOC_APPEND( l, fd_funk_rec_map_align(), fd_funk_rec_map_footprint( rec_chain_cnt ) );
      86          33 :   void * rec_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_funk_rec_pool_align(), fd_funk_rec_pool_footprint() );
      87          33 :   fd_funk_rec_t * rec_ele = (fd_funk_rec_t *)FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_funk_rec_t), sizeof(fd_funk_rec_t) * rec_max );
      88             : 
      89          33 :   void * alloc = FD_SCRATCH_ALLOC_APPEND( l, fd_alloc_align(), fd_alloc_footprint() );
      90             : 
      91          33 :   FD_TEST( _l == (ulong)funk + fd_funk_footprint( txn_max, rec_max ) );
      92             : 
      93          33 :   fd_memset( funk, 0, sizeof(fd_funk_shmem_t) );
      94             : 
      95          33 :   funk->funk_gaddr = fd_wksp_gaddr_fast( wksp, funk );
      96          33 :   funk->wksp_tag   = wksp_tag;
      97          33 :   funk->seed       = seed;
      98          33 :   funk->cycle_tag  = 3UL; /* various verify functions use tags 0-2 */
      99             : 
     100          33 :   funk->txn_map_gaddr = fd_wksp_gaddr_fast( wksp, fd_funk_txn_map_new( txn_map, txn_chain_cnt, seed ) );
     101          33 :   void * txn_pool2 = fd_funk_txn_pool_new( txn_pool );
     102          33 :   funk->txn_pool_gaddr = fd_wksp_gaddr_fast( wksp, txn_pool2 );
     103          33 :   fd_funk_txn_pool_t txn_join[1];
     104          33 :   fd_funk_txn_pool_join( txn_join, txn_pool2, txn_ele, txn_max );
     105          33 :   fd_funk_txn_pool_reset( txn_join, 0UL );
     106          33 :   funk->txn_ele_gaddr = fd_wksp_gaddr_fast( wksp, txn_ele );
     107          33 :   funk->txn_max = txn_max;
     108          33 :   funk->child_head_cidx = fd_funk_txn_cidx( FD_FUNK_TXN_IDX_NULL );
     109          33 :   funk->child_tail_cidx = fd_funk_txn_cidx( FD_FUNK_TXN_IDX_NULL );
     110             : 
     111          33 :   fd_funk_txn_xid_set_root( funk->root         );
     112          33 :   fd_funk_txn_xid_set_root( funk->last_publish );
     113             : 
     114          33 :   funk->rec_map_gaddr = fd_wksp_gaddr_fast( wksp, fd_funk_rec_map_new( rec_map, rec_chain_cnt, seed ) );
     115          33 :   void * rec_pool2 = fd_funk_rec_pool_new( rec_pool );
     116          33 :   funk->rec_pool_gaddr = fd_wksp_gaddr_fast( wksp, rec_pool2 );
     117          33 :   fd_funk_rec_pool_t rec_join[1];
     118          33 :   fd_funk_rec_pool_join( rec_join, rec_pool2, rec_ele, rec_max );
     119          33 :   fd_funk_rec_pool_reset( rec_join, 0UL );
     120          33 :   funk->rec_ele_gaddr = fd_wksp_gaddr_fast( wksp, rec_ele );
     121          33 :   funk->rec_max = (uint)rec_max;
     122          33 :   funk->rec_head_idx  = FD_FUNK_REC_IDX_NULL;
     123          33 :   funk->rec_tail_idx  = FD_FUNK_REC_IDX_NULL;
     124             : 
     125          33 :   funk->alloc_gaddr = fd_wksp_gaddr_fast( wksp, fd_alloc_join( fd_alloc_new( alloc, wksp_tag ), 0UL ) );
     126             : 
     127          33 :   funk->lock = 0;
     128             : 
     129          33 :   FD_COMPILER_MFENCE();
     130          33 :   FD_VOLATILE( funk->magic ) = FD_FUNK_MAGIC;
     131          33 :   FD_COMPILER_MFENCE();
     132             : 
     133          33 :   return (void *)funk;
     134          33 : }
     135             : 
     136             : fd_funk_t *
     137             : fd_funk_join( fd_funk_t * ljoin,
     138          45 :               void *      shfunk ) {
     139          45 :   if( FD_UNLIKELY( !shfunk ) ) {
     140           3 :     FD_LOG_WARNING(( "NULL shfunk" ));
     141           3 :     return NULL;
     142           3 :   }
     143             : 
     144          42 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shfunk, fd_funk_align() ) ) ) {
     145           3 :     FD_LOG_WARNING(( "misaligned shfunk" ));
     146           3 :     return NULL;
     147           3 :   }
     148             : 
     149          39 :   fd_wksp_t * wksp = fd_wksp_containing( shfunk );
     150          39 :   if( FD_UNLIKELY( !wksp ) ) {
     151           3 :     FD_LOG_WARNING(( "shfunk must be part of a workspace" ));
     152           3 :     return NULL;
     153           3 :   }
     154             : 
     155          36 :   fd_funk_shmem_t * shmem = shfunk;
     156          36 :   if( FD_UNLIKELY( shmem->magic!=FD_FUNK_MAGIC ) ) {
     157           3 :     if (shmem->magic == FD_FUNK_MAGIC+1) {
     158           0 :       FD_LOG_WARNING(( "attempted to join a funk that crashed in a critical section" ));
     159           3 :     } else {
     160           3 :       FD_LOG_WARNING(( "bad magic" ));
     161           3 :     }
     162           3 :     return NULL;
     163           3 :   }
     164             : 
     165          33 :   if( FD_UNLIKELY( !ljoin ) ) {
     166           0 :     FD_LOG_WARNING(( "NULL ljoin" ));
     167           0 :     return NULL;
     168           0 :   }
     169             : 
     170             : #ifdef FD_FUNK_WKSP_PROTECT
     171             :   fd_wksp_mprotect( wksp, 1 );
     172             : #endif
     173             : 
     174          33 :   fd_funk_t * funk = ljoin;
     175          33 :   memset( funk, 0, sizeof(fd_funk_t) );
     176             : 
     177          33 :   funk->shmem = shfunk;
     178          33 :   funk->wksp  = wksp;
     179             : 
     180          33 :   if( FD_UNLIKELY( !fd_funk_txn_pool_join( funk->txn_pool, fd_wksp_laddr( wksp, shmem->txn_pool_gaddr ), fd_wksp_laddr( wksp, shmem->txn_ele_gaddr ), shmem->txn_max ) ) ) {
     181           0 :     FD_LOG_WARNING(( "failed to join txn_pool" ));
     182           0 :     return NULL;
     183           0 :   }
     184          33 :   if( FD_UNLIKELY( !fd_funk_txn_map_join( funk->txn_map, fd_wksp_laddr( wksp, shmem->txn_map_gaddr ), fd_wksp_laddr_fast( wksp, shmem->txn_ele_gaddr ), shmem->txn_max ) ) ) {
     185           0 :     FD_LOG_WARNING(( "failed to join txn_map" ));
     186           0 :     return NULL;
     187           0 :   }
     188          33 :   if( FD_UNLIKELY( !fd_funk_rec_map_join( funk->rec_map, fd_wksp_laddr( wksp, shmem->rec_map_gaddr ), fd_wksp_laddr( wksp, shmem->rec_ele_gaddr ), shmem->rec_max ) ) ) {
     189           0 :     FD_LOG_WARNING(( "failed to join rec_map" ));
     190           0 :     return NULL;
     191           0 :   }
     192          33 :   if( FD_UNLIKELY( !fd_funk_rec_pool_join( funk->rec_pool, fd_wksp_laddr( wksp, shmem->rec_pool_gaddr ), fd_wksp_laddr_fast( wksp, shmem->rec_ele_gaddr ), shmem->rec_max ) ) ) {
     193           0 :     FD_LOG_WARNING(( "failed to join rec_pool" ));
     194           0 :     return NULL;
     195           0 :   }
     196          33 :   funk->alloc = fd_wksp_laddr( wksp, shmem->alloc_gaddr );
     197          33 :   if( FD_UNLIKELY( !fd_alloc_join( funk->alloc, fd_tile_idx() ) ) ) {
     198           0 :     FD_LOG_WARNING(( "failed to join funk alloc" ));
     199           0 :     return NULL;
     200           0 :   }
     201             : 
     202          33 :   return funk;
     203          33 : }
     204             : 
     205             : int
     206           0 : fd_funk_purify( void * shfunk ) {
     207             :   /* Join should work even if there was a crash */
     208           0 :   fd_funk_t ljoin[1];
     209           0 :   fd_funk_t * funk = fd_funk_join( ljoin, shfunk );
     210           0 :   if( funk == NULL ) return FD_FUNK_ERR_PURIFY;
     211             : 
     212             :   /* Reset the txn map. We discard any pending transactions. */
     213           0 :   fd_funk_txn_map_reset( funk->txn_map );
     214           0 :   fd_funk_txn_pool_reset( funk->txn_pool, 0 );
     215           0 :   funk->shmem->child_head_cidx = funk->shmem->child_tail_cidx = fd_funk_txn_cidx( FD_FUNK_TXN_IDX_NULL );
     216             : 
     217           0 :   return fd_funk_rec_purify( funk );
     218           0 : }
     219             : 
     220             : void *
     221             : fd_funk_leave( fd_funk_t * funk,
     222          30 :                void **     opt_shfunk ) {
     223             : 
     224          30 :   if( FD_UNLIKELY( !funk ) ) {
     225           3 :     FD_LOG_WARNING(( "NULL funk" ));
     226           3 :     if( opt_shfunk ) *opt_shfunk = NULL;
     227           3 :     return NULL;
     228           3 :   }
     229          27 :   void * shfunk = funk->shmem;
     230             : 
     231          27 :   memset( funk, 0, sizeof(fd_funk_t) );
     232             : 
     233          27 :   if( opt_shfunk ) *opt_shfunk = shfunk;
     234          27 :   return (void *)funk;
     235          30 : }
     236             : 
     237             : void *
     238          39 : fd_funk_delete( void * shfunk ) {
     239             : 
     240          39 :   if( FD_UNLIKELY( !shfunk ) ) {
     241           3 :     FD_LOG_WARNING(( "NULL shfunk" ));
     242           3 :     return NULL;
     243           3 :   }
     244             : 
     245          36 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shfunk, fd_funk_align() ) ) ) {
     246           3 :     FD_LOG_WARNING(( "misaligned shfunk" ));
     247           3 :     return NULL;
     248           3 :   }
     249             : 
     250          33 :   fd_wksp_t * wksp = fd_wksp_containing( shfunk );
     251          33 :   if( FD_UNLIKELY( !wksp ) ) {
     252           3 :     FD_LOG_WARNING(( "shfunk must be part of a workspace" ));
     253           3 :     return NULL;
     254           3 :   }
     255             : 
     256          30 :   fd_funk_shmem_t * shmem = shfunk;
     257          30 :   if( FD_UNLIKELY( shmem->magic!=FD_FUNK_MAGIC ) ) {
     258           6 :     FD_LOG_WARNING(( "bad magic" ));
     259           6 :     return NULL;
     260           6 :   }
     261             : 
     262             :   /* Free all fd_alloc allocations made, individually
     263             :      (FIXME consider walking the element pool instead of the map?) */
     264             : 
     265          24 :   fd_alloc_t * alloc = fd_alloc_join( fd_wksp_laddr_fast( wksp, shmem->alloc_gaddr ), fd_tile_idx() );
     266             : 
     267          24 :   void * shmap = fd_wksp_laddr_fast( wksp, shmem->rec_map_gaddr );
     268          24 :   void * shele = fd_wksp_laddr_fast( wksp, shmem->rec_ele_gaddr );
     269          24 :   fd_funk_rec_map_t rec_map[1];
     270          24 :   if( FD_UNLIKELY( !fd_funk_rec_map_join( rec_map, shmap, shele, 0UL ) ) ) {
     271           0 :     FD_LOG_ERR(( "failed to join rec_map (corrupt funk?)" ));
     272           0 :     return NULL;
     273           0 :   }
     274          24 :   ulong chain_cnt = fd_funk_rec_map_chain_cnt( rec_map );
     275     2360334 :   for( ulong chain_idx=0UL; chain_idx<chain_cnt; chain_idx++ ) {
     276     2360310 :     for(
     277     2360310 :         fd_funk_rec_map_iter_t iter = fd_funk_rec_map_iter( rec_map, chain_idx );
     278     5506425 :         !fd_funk_rec_map_iter_done( iter );
     279     3146115 :         iter = fd_funk_rec_map_iter_next( iter )
     280     3146115 :     ) {
     281     3146115 :       fd_funk_val_flush( fd_funk_rec_map_iter_ele( iter ), alloc, wksp );
     282     3146115 :     }
     283     2360310 :   }
     284             : 
     285          24 :   fd_funk_rec_map_leave( rec_map );
     286             : 
     287             :   /* Free the fd_alloc instance */
     288             : 
     289          24 :   fd_wksp_free_laddr( fd_alloc_delete( fd_alloc_leave( alloc ) ) );
     290             : 
     291          24 :   FD_COMPILER_MFENCE();
     292          24 :   FD_VOLATILE( shmem->magic ) = 0UL;
     293          24 :   FD_COMPILER_MFENCE();
     294             : 
     295          24 :   return shmem;
     296          24 : }
     297             : 
     298             : void
     299           0 : fd_funk_delete_fast( void * shfunk ) {
     300             : 
     301           0 :   if( FD_UNLIKELY( !shfunk ) ) {
     302           0 :     FD_LOG_WARNING(( "NULL shfunk" ));
     303           0 :   }
     304             : 
     305           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shfunk, fd_funk_align() ) ) ) {
     306           0 :     FD_LOG_WARNING(( "misaligned shfunk" ));
     307           0 :   }
     308             : 
     309           0 :   fd_funk_shmem_t * shmem = shfunk;
     310           0 :   if( FD_UNLIKELY( shmem->magic!=FD_FUNK_MAGIC ) ) {
     311           0 :     FD_LOG_WARNING(( "bad magic" ));
     312           0 :   }
     313             : 
     314           0 :   fd_wksp_t * wksp = fd_wksp_containing( shmem );
     315           0 :   if( FD_UNLIKELY( !wksp ) ) {
     316           0 :     FD_LOG_WARNING(( "shfunk must be part of a workspace" ));
     317           0 :   }
     318             : 
     319           0 :   ulong const tags[1] = { shmem->wksp_tag };
     320           0 :   fd_wksp_tag_free( wksp, tags, 1UL );
     321             : 
     322           0 : }
     323             : 
     324             : int
     325          12 : fd_funk_verify( fd_funk_t * join ) {
     326          12 :   fd_funk_shmem_t * funk = join->shmem;
     327             : 
     328         336 : # define TEST(c) do {                                                                           \
     329         336 :     if( FD_UNLIKELY( !(c) ) ) { FD_LOG_WARNING(( "FAIL: %s", #c )); return FD_FUNK_ERR_INVAL; } \
     330         336 :   } while(0)
     331             : 
     332          12 :   TEST( funk );
     333             : 
     334             :   /* Test metadata */
     335             : 
     336          12 :   TEST( funk->magic==FD_FUNK_MAGIC );
     337             : 
     338          12 :   ulong funk_gaddr = funk->funk_gaddr;
     339          12 :   TEST( funk_gaddr );
     340          12 :   fd_wksp_t * wksp = fd_funk_wksp( join );
     341          12 :   TEST( wksp );
     342          12 :   TEST( fd_wksp_laddr_fast( wksp, funk_gaddr )==(void *)funk );
     343          12 :   TEST( fd_wksp_gaddr_fast( wksp, funk       )==funk_gaddr   );
     344             : 
     345          12 :   ulong wksp_tag = fd_funk_wksp_tag( join );
     346          12 :   TEST( !!wksp_tag );
     347             : 
     348          12 :   ulong seed = funk->seed; /* seed can be anything */
     349             : 
     350          12 :   TEST( funk->cycle_tag>2UL );
     351             : 
     352             :   /* Test transaction map */
     353             : 
     354          12 :   ulong txn_max = fd_funk_txn_pool_ele_max( join->txn_pool );
     355          12 :   TEST( txn_max<=FD_FUNK_TXN_IDX_NULL );
     356             : 
     357          12 :   ulong txn_map_gaddr = funk->txn_map_gaddr;
     358          12 :   TEST( txn_map_gaddr );
     359          12 :   fd_funk_txn_map_t * txn_map = fd_funk_txn_map( join );
     360          12 :   ulong txn_chain_cnt = fd_funk_txn_map_chain_cnt_est( txn_max );
     361          12 :   TEST( txn_chain_cnt==fd_funk_txn_map_chain_cnt( txn_map ) );
     362          12 :   TEST( seed==fd_funk_txn_map_seed( txn_map ) );
     363             : 
     364          12 :   ulong child_head_idx = fd_funk_txn_idx( funk->child_head_cidx );
     365          12 :   ulong child_tail_idx = fd_funk_txn_idx( funk->child_tail_cidx );
     366             : 
     367          12 :   int null_child_head = fd_funk_txn_idx_is_null( child_head_idx );
     368          12 :   int null_child_tail = fd_funk_txn_idx_is_null( child_tail_idx );
     369             : 
     370          12 :   if( !txn_max ) TEST( null_child_head & null_child_tail );
     371           6 :   else {
     372           6 :     if( null_child_head ) TEST( null_child_tail );
     373           0 :     else                  TEST( child_head_idx<txn_max );
     374             : 
     375           6 :     if( null_child_tail ) TEST( null_child_head );
     376           0 :     else                  TEST( child_tail_idx<txn_max );
     377           6 :   }
     378             : 
     379          12 :   if( !txn_max ) TEST( fd_funk_txn_idx_is_null( child_tail_idx ) );
     380             : 
     381          12 :   fd_funk_txn_xid_t const * root = fd_funk_root( join );
     382          12 :   TEST( root ); /* Practically guaranteed */
     383          12 :   TEST( fd_funk_txn_xid_eq_root( root ) );
     384             : 
     385          12 :   fd_funk_txn_xid_t * last_publish = funk->last_publish;
     386          12 :   TEST( last_publish ); /* Practically guaranteed */
     387             :   /* (*last_publish) only be root at creation and anything but root post
     388             :      creation.  But we don't know which situation applies here so this
     389             :      could be anything. */
     390             : 
     391          12 :   TEST( !fd_funk_txn_verify( join ) );
     392             : 
     393             :   /* Test record map */
     394             : 
     395          12 :   ulong rec_max = fd_funk_rec_pool_ele_max( join->rec_pool );
     396          12 :   TEST( rec_max<=FD_FUNK_TXN_IDX_NULL );
     397             : 
     398          12 :   ulong rec_map_gaddr = funk->rec_map_gaddr;
     399          12 :   TEST( rec_map_gaddr );
     400          12 :   fd_funk_rec_map_t * rec_map = fd_funk_rec_map( join );
     401          12 :   ulong rec_chain_cnt = fd_funk_rec_map_chain_cnt_est( rec_max );
     402          12 :   TEST( rec_chain_cnt==fd_funk_rec_map_chain_cnt( rec_map ) );
     403          12 :   TEST( seed==fd_funk_rec_map_seed( rec_map ) );
     404             : 
     405          12 :   uint rec_head_idx = funk->rec_head_idx;
     406          12 :   uint rec_tail_idx = funk->rec_tail_idx;
     407             : 
     408          12 :   int null_rec_head = fd_funk_rec_idx_is_null( rec_head_idx );
     409          12 :   int null_rec_tail = fd_funk_rec_idx_is_null( rec_tail_idx );
     410             : 
     411          12 :   if( !rec_max ) TEST( null_rec_head & null_rec_tail );
     412           6 :   else {
     413           6 :     if( null_rec_head ) TEST( null_rec_tail );
     414           0 :     else                TEST( rec_head_idx<rec_max );
     415             : 
     416           6 :     if( null_rec_tail ) TEST( null_rec_head );
     417           0 :     else                TEST( rec_tail_idx<rec_max );
     418           6 :   }
     419             : 
     420          12 :   if( !rec_max ) TEST( fd_funk_rec_idx_is_null( rec_tail_idx ) );
     421             : 
     422          12 :   TEST( !fd_funk_rec_verify( join ) );
     423             : 
     424             :   /* Test values */
     425             : 
     426          12 :   ulong alloc_gaddr = funk->alloc_gaddr;
     427          12 :   TEST( alloc_gaddr );
     428          12 :   fd_alloc_t * alloc = fd_funk_alloc( join );
     429          12 :   TEST( alloc );
     430             : 
     431          12 :   TEST( !fd_funk_val_verify( join ) );
     432             : 
     433          12 : # undef TEST
     434             : 
     435          12 :   return FD_FUNK_SUCCESS;
     436          12 : }

Generated by: LCOV version 1.14