/* * Unit tests for hash table. * * Author: Yasuhito Takamiya <yasuhito@gmail.com> * * Copyright (C) 2008-2012 NEC Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include <setjmp.h> #include <stdarg.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "checks.h" #include "cmockery_trema.h" #include "hash_table.h" #include "utility.h" /******************************************************************************** * Test functions. ********************************************************************************/ static hash_table *table; static char alpha[] = "alpha"; static char bravo[] = "bravo"; static char charlie[] = "charlie"; static void test_lookup_empty_table_returns_NULL() { table = create_hash( compare_string, hash_string ); assert_true( lookup_hash_entry( table, alpha ) == NULL ); delete_hash( table ); } static void test_insert_and_lookup() { table = create_hash( compare_string, hash_string ); insert_hash_entry( table, alpha, alpha ); assert_string_equal( lookup_hash_entry( table, alpha ), "alpha" ); delete_hash( table ); } typedef struct { const char *key; } key; static void test_insert_and_lookup_by_atom_hash() { key mykey = { "alpha" }; table = create_hash( compare_atom, hash_atom ); insert_hash_entry( table, &mykey, alpha ); assert_string_equal( lookup_hash_entry( table, &mykey ), "alpha" ); delete_hash( table ); } static void test_insert_twice_overwrites_old_value() { char *prev; char key[] = "key"; table = create_hash( compare_string, hash_string ); char old_value[] = "old value"; char new_value[] = "new value"; insert_hash_entry( table, key, old_value ); prev = insert_hash_entry( table, key, new_value ); assert_string_equal( lookup_hash_entry( table, key ), "new value" ); assert_string_equal( prev, "old value" ); delete_hash( table ); } static void test_delete_entry() { table = create_hash( compare_string, hash_string ); insert_hash_entry( table, alpha, alpha ); insert_hash_entry( table, bravo, bravo ); insert_hash_entry( table, charlie, charlie ); delete_hash_entry( table, bravo ); assert_string_equal( lookup_hash_entry( table, alpha ), "alpha" ); assert_true( lookup_hash_entry( table, bravo ) == NULL ); assert_string_equal( lookup_hash_entry( table, charlie ), "charlie" ); delete_hash( table ); } static void test_nonexistent_entry_returns_NULL() { table = create_hash( compare_string, hash_string ); assert_true( delete_hash_entry( table, "NO SUCH KEY" ) == NULL ); delete_hash( table ); } static char *abc[ 3 ] = { NULL, NULL, NULL }; static void append_back_foreach( void *key, void *value, void *user_data ) { assert_true( strcmp( key, value ) == 0 ); assert_true( user_data == NULL ); int i; for ( i = 0; i < 3; i++ ) { if ( abc[ i ] == NULL ) { abc[ i ] = value; return; } } } static void test_foreach() { table = create_hash( compare_string, hash_string ); insert_hash_entry( table, alpha, alpha ); insert_hash_entry( table, bravo, bravo ); insert_hash_entry( table, charlie, charlie ); delete_hash_entry( table, bravo ); delete_hash_entry( table, charlie ); foreach_hash( table, append_back_foreach, NULL ); assert_string_equal( abc[ 0 ], "alpha" ); assert_true( abc[ 1 ] == NULL ); assert_true( abc[ 2 ] == NULL ); delete_hash( table ); } static void test_iterator() { table = create_hash( compare_string, hash_string ); char one[] = "one"; insert_hash_entry( table, one, ( void * ) 1 ); char two[] = "two"; insert_hash_entry( table, two, ( void * ) 2 ); char three[] = "three"; insert_hash_entry( table, three, ( void * ) 3 ); char four[] = "four"; insert_hash_entry( table, four, ( void * ) 4 ); char five[] = "five"; insert_hash_entry( table, five, ( void * ) 5 ); char six[] = "six"; insert_hash_entry( table, six, ( void * ) 6 ); char seven[] = "seven"; insert_hash_entry( table, seven, ( void * ) 7 ); char eight[] = "eight"; insert_hash_entry( table, eight, ( void * ) 8 ); char nine[] = "nine"; insert_hash_entry( table, nine, ( void * ) 9 ); char ten[] = "ten"; insert_hash_entry( table, ten, ( void * ) 10 ); int sum = 0; hash_iterator iter; hash_entry *e; init_hash_iterator( table, &iter ); while ( ( e = iterate_hash_next( &iter ) ) != NULL ) { sum += ( int ) ( uintptr_t ) e->value; delete_hash_entry( table, e->key ); } assert_true( sum == 55 ); delete_hash( table ); } static void test_multiple_inserts_and_deletes_then_iterate() { table = create_hash( compare_string, hash_string ); char one[] = "one"; insert_hash_entry( table, one, ( void * ) 1 ); delete_hash_entry( table, one ); insert_hash_entry( table, one, ( void * ) 1 ); delete_hash_entry( table, one ); insert_hash_entry( table, one, ( void * ) 1 ); int sum = 0; hash_iterator iter; hash_entry *e; init_hash_iterator( table, &iter ); while ( ( e = iterate_hash_next( &iter ) ) != NULL ) { sum += ( int ) ( uintptr_t ) e->value; delete_hash_entry( table, e->key ); } assert_true( sum == 1 ); delete_hash( table ); } static void test_iterate_empty_hash() { hash_iterator iter; table = create_hash( compare_atom, hash_atom ); init_hash_iterator( table, &iter ); while ( iterate_hash_next( &iter ) != NULL ) { UNREACHABLE(); } delete_hash( table ); } /******************************************************************************** * Run tests. ********************************************************************************/ int main() { const UnitTest tests[] = { unit_test( test_lookup_empty_table_returns_NULL ), unit_test( test_insert_and_lookup ), unit_test( test_insert_and_lookup_by_atom_hash ), unit_test( test_insert_twice_overwrites_old_value ), unit_test( test_delete_entry ), unit_test( test_nonexistent_entry_returns_NULL ), unit_test( test_foreach ), unit_test( test_iterator ), unit_test( test_multiple_inserts_and_deletes_then_iterate ), unit_test( test_iterate_empty_hash ), }; setup_leak_detector(); return run_tests( tests ); } /* * Local variables: * c-basic-offset: 2 * indent-tabs-mode: nil * End: */