text: /* vi:set ts=8 sts=4 sw=4:
   *
   * VIM - Vi IMproved	by Bram Moolenaar
   *
   * Do ":help uganda"  in Vim to read copying and usage conditions.
   * Do ":help credits" in Vim to see a list of people who contributed.
   * See README.txt for an overview of the Vim source code.
   */
  
  /*
   * memfile_test.c: Unittests for memfile.c
   * Mostly by Ivan Krasilnikov.
   */
  
  #undef NDEBUG
  #include <assert.h>
  
  /* Must include main.c because it contains much more than just main() */
  #define NO_VIM_MAIN
  #include "main.c"
  
  /* This file has to be included because the tested functions are static */
  #include "memfile.c"
  
  #define index_to_key(i) ((i) ^ 15167)
  #define TEST_COUNT 50000
  
  /*
   * Test mf_hash_*() functions.
   */
      static void
  test_mf_hash(void)
  {
      mf_hashtab_T   ht;
      mf_hashitem_T  *item;
      blocknr_T      key;
      long_u	   i;
      long_u	   num_buckets;
  
      mf_hash_init(&ht);
  
      /* insert some items and check invariants */
      for (i = 0; i < TEST_COUNT; i++)
      {
  	assert(ht.mht_count == i);
  
  	/* check that number of buckets is a power of 2 */
  	num_buckets = ht.mht_mask + 1;
  	assert(num_buckets > 0 && (num_buckets & (num_buckets - 1)) == 0);
  
  	/* check load factor */
  	assert(ht.mht_count <= (num_buckets << MHT_LOG_LOAD_FACTOR));
  
  	if (i < (MHT_INIT_SIZE << MHT_LOG_LOAD_FACTOR))
  	{
  	    /* first expansion shouldn't have occurred yet */
  	    assert(num_buckets == MHT_INIT_SIZE);
  	    assert(ht.mht_buckets == ht.mht_small_buckets);
  	}
  	else
  	{
  	    assert(num_buckets > MHT_INIT_SIZE);
  	    assert(ht.mht_buckets != ht.mht_small_buckets);
  	}
  
  	key = index_to_key(i);
  	assert(mf_hash_find(&ht, key) == NULL);
  
  	/* allocate and add new item */
  	item = (mf_hashitem_T *)lalloc_clear(sizeof(mf_hashtab_T), FALSE);
  	assert(item != NULL);
  	item->mhi_key = key;
  	mf_hash_add_item(&ht, item);
  
  	assert(mf_hash_find(&ht, key) == item);
  
  	if (ht.mht_mask + 1 != num_buckets)
  	{
  	    /* hash table was expanded */
  	    assert(ht.mht_mask + 1 == num_buckets * MHT_GROWTH_FACTOR);
  	    assert(i + 1 == (num_buckets << MHT_LOG_LOAD_FACTOR));
  	}
      }
  
      /* check presence of inserted items */
      for (i = 0; i < TEST_COUNT; i++)
      {
  	key = index_to_key(i);
  	item = mf_hash_find(&ht, key);
  	assert(item != NULL);
  	assert(item->mhi_key == key);
      }
  
      /* delete some items */
      for (i = 0; i < TEST_COUNT; i++)
      {
  	if (i % 100 < 70)
  	{
  	    key = index_to_key(i);
  	    item = mf_hash_find(&ht, key);
  	    assert(item != NULL);
  	    assert(item->mhi_key == key);
  
  	    mf_hash_rem_item(&ht, item);
  	    assert(mf_hash_find(&ht, key) == NULL);
  
  	    mf_hash_add_item(&ht, item);
  	    assert(mf_hash_find(&ht, key) == item);
  
  	    mf_hash_rem_item(&ht, item);
  	    assert(mf_hash_find(&ht, key) == NULL);
  
  	    vim_free(item);
  	}
      }
  
      /* check again */
      for (i = 0; i < TEST_COUNT; i++)
      {
  	key = index_to_key(i);
  	item = mf_hash_find(&ht, key);
  
  	if (i % 100 < 70)
  	{
  	    assert(item == NULL);
  	}
  	else
  	{
  	    assert(item != NULL);
  	    assert(item->mhi_key == key);
  	}
      }
  
      /* free hash table and all remaining items */
      mf_hash_free_all(&ht);
  }
  
      int
  main(void)
  {
      test_mf_hash();
      return 0;
  }
  