Skip to content
Snippets Groups Projects
Commit 9c98624e authored by 20041679's avatar 20041679
Browse files

exam sample 2

parent b1a44370
Branches master
No related tags found
No related merge requests found
CFLAGS += -Wall -Wextra -std=c11 -pedantic
CFLAGS += -g
CFLAGS += -I./include
LDFLAGS += -L./lib
LDLIBS += -lupoalglib -lm
.PHONY: all clean
all: test/bst_subtree_count_even test/ht_sepchain_odelete
test/bst_subtree_count_even: test/bst_subtree_count_even.o exam.o
test/ht_sepchain_odelete: test/ht_sepchain_odelete.o exam.o
clean:
$(RM) test/bst_subtree_count_even
$(RM) test/ht_sepchain_odelete
$(RM) *.o test/*.o
/* vim: set tabstop=4 expandtab shiftwidth=4 softtabstop=4: */
/******************************************************************************/
/*** NOME: ***/
/*** COGNOME: ***/
/*** MATRICOLA: ***/
/******************************************************************************/
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <upo/bst.h>
#include <upo/hashtable.h>
/**** BEGIN of EXERCISE #1 ****/
size_t upo_bst_subtree_count_skip_2_impl(upo_bst_node_t *node)
{
if (!node) { return 0; }
size_t count = 1;
if (node->left) {
count += upo_bst_subtree_count_skip_2_impl(node->left->left)
+ upo_bst_subtree_count_skip_2_impl(node->left->right);
}
if (node->right) {
count += upo_bst_subtree_count_skip_2_impl(node->right->left)
+ upo_bst_subtree_count_skip_2_impl(node->right->right);
}
return count;
}
size_t upo_bst_subtree_count_even(const upo_bst_t bst, const void *key)
{
if (!bst) {
return 0;
}
if (upo_bst_is_empty(bst)) {
return 0;
}
upo_bst_node_t *node = bst->root;
upo_bst_comparator_t cmp = upo_bst_get_comparator(bst);
int res;
int even = 1;
while (node && (res = cmp(key, node->key)) != 0)
{
node = res < 0 ? node->left : node->right;
even = !even;
}
if (!node)
{
return 0;
}
if (even)
{
return upo_bst_subtree_count_skip_2_impl(node);
}
size_t count = 0;
if (node->left) {
count += upo_bst_subtree_count_skip_2_impl(node->left);
}
if (node->right) {
count += upo_bst_subtree_count_skip_2_impl(node->right);
}
return count;
}
/**** END of EXERCISE #1 ****/
/**** BEGIN of EXERCISE #2 ****/
void upo_ht_sepchain_odelete(upo_ht_sepchain_t ht, const void *key, int destroy_data)
{
if (!ht)
{
perror("Uninitialized hash table");
return;
}
upo_ht_hasher_t h = upo_ht_sepchain_get_hasher(ht);
size_t i = h(key, upo_ht_sepchain_capacity(ht));
if (ht->slots[i].head)
{
upo_ht_comparator_t cmp = upo_ht_sepchain_get_comparator(ht);
upo_ht_sepchain_list_node_t **before = &ht->slots[i].head;
while (*before && cmp((*before)->key, key) != 0)
{
before = &(*before)->next;
}
if (*before)
{
upo_ht_sepchain_list_node_t *next = (*before)->next;
if (destroy_data)
{
free((*before)->key);
free((*before)->value);
}
free(*before);
*before = next;
--ht->size;
}
}
}
/**** END of EXERCISE #2 ****/
File added
/* vim: set tabstop=4 expandtab shiftwidth=4 softtabstop=4: */
/**
* \file upo/bst.h
*
* \brief The Binary Search Tree (BST) abstract data type.
*
* Trees are nonlinear containers where data is structured according to
* hierarchical organization.
* Trees are made of nodes that are connected to each other according to a
* parent-child relationship.
* Binary Search Trees are Binary Trees where:
* - Each node has a key and an associated value (possibly, the
* key itself),
* - The key in node v is greater than the keys in all nodes in the
* left subtree of v, and
* - The key in node v is less than the keys in all nodes in the right
* subtree of v.
* .
*
* \author Marco Guazzone (marco.guazzone@uniupo.it)
*
* \copyright 2015 University of Piemonte Orientale, Computer Science Institute
*
* This file is part of UPOalglib.
*
* UPOalglib is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* UPOalglib 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 UPOalglib. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UPO_BST_H
#define UPO_BST_H
#include <stddef.h>
/**
* \brief The type for key comparison functions.
*
* Declares the type for key comparison functions that are used to compare keys
* stored in the binary search tree.
* A comparison function takes two parameters:
* - The first parameter is a pointer to the first key to compare.
* - The second parameter is a pointer to the second key to compare.
* A comparison function returns a number less than, equal to, or greater than
* zero if the first key (first argument) is less than, equal to, or greater
* than the second key (second argument), respectively.
*/
typedef int (*upo_bst_comparator_t)(const void*, const void*);
/** \brief Alias for binary search tree node type. */
typedef struct upo_bst_node_s upo_bst_node_t;
/** \brief Type for nodes of a binary search tree. */
struct upo_bst_node_s
{
void* key; /**< Pointer to user-provided key. */
void* value; /**< Pointer to user-provided value. */
upo_bst_node_t* left; /**< Pointer to the left child node. */
upo_bst_node_t* right; /**< Pointer to the right child node. */
};
/** \brief Defines a binary tree. */
struct upo_bst_s
{
upo_bst_node_t* root; /**< The root of the binary tree. */
upo_bst_comparator_t key_cmp; /**< Pointer to the key comparison function. */
};
/** \brief Declares the Binary Search Tree type. */
typedef struct upo_bst_s* upo_bst_t;
/**
* \brief Creates a new empty binary search tree.
*
* \param key_cmp A pointer to the function used to compare keys.
* \return An empty binary search tree.
*
* Worst-case complexity: constant, `O(1)`.
*/
upo_bst_t upo_bst_create(upo_bst_comparator_t key_cmp);
/**
* \brief Destroys the given binary search tree together with data stored on it.
*
* \param tree The binary search tree to destroy.
* \param destroy_data Tells whether the previously allocated memory for keys
* and values stored in this binary search tree must be freed (value `1`) or
* not (value `0`).
*
* Memory deallocation (if requested) is performed by means of the `free()`
* standard C function.
*
* Worst-case complexity: linear in the number `n` of elements, `O(n)`.
*/
void upo_bst_destroy(upo_bst_t tree, int destroy_data);
/**
* \brief Removes all elements from the given binary search tree and destroys
* all data stored on it.
*
* \param tree The binary search tree to clear.
* \param destroy_data Tells whether the previously allocated memory for keys
* and values stored in this binary search tree must be freed (value `1`) or
* not (value `0`).
*
* Memory deallocation (if requested) is performed by means of the `free()`
* standard C function.
*
* Worst-case complexity: linear in the number `n` of elements, `O(n)`.
*/
void upo_bst_clear(upo_bst_t tree, int destroy_data);
/**
* \brief Returns the comparison function stored in the binary search tree.
*
* \param tree The binary search tree.
* \return The comparison function.
*/
upo_bst_comparator_t upo_bst_get_comparator(const upo_bst_t tree);
/**
* \brief Tells if the given binary search tree is empty.
*
* \param tree The binary search tree.
* \return `1` if the binary search tree is empty or `0` otherwise.
*
* A binary search tree is empty if it doesn't contain any node.
*
* Worst-case complexity: constant, `O(1)`.
*/
int upo_bst_is_empty(const upo_bst_t tree);
/**
* \brief Counts the number of nodes of the subtree rooted at the node of the
* binary search tree containing the given key and that are located at an
* even depth.
*
* \param tree The binary search tree.
* \param key The key for which this function must return the number of nodes of
* the subtree rooted at the associated node and located at an even depth.
* \return The number of nodes of the subtree rooted at the node containing the
* given key and located at an even depth, or `0` if the tree is empty or if
* the given key does not belong to the tree.
*/
size_t upo_bst_subtree_count_even(const upo_bst_t tree, const void* key);
#endif /* UPO_BST_H */
/* vim: set tabstop=4 expandtab shiftwidth=4 softtabstop=4: */
/**
* \file upo/hashtable.h
*
* \brief The Hash Table (HT) abstract data type.
*
* Hash Tables are containers composed of unique keys (containing at most one of
* each key value) that associates values of another type with the keys.
*
* \author Marco Guazzone (marco.guazzone@uniupo.it)
*
* \copyright 2015 University of Piemonte Orientale, Computer Science Institute
*
* This file is part of UPOalglib.
*
* UPOalglib is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* UPOalglib 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 UPOalglib. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UPO_HASHTABLE_H
#define UPO_HASHTABLE_H
#include <stddef.h>
/*** BEGIN of COMMON TYPES ***/
/** \brief The type for hash functions.
*
* Declares the type for key hash functions that are used to map key
* space into the index space to use for indexing the hash table.
* A hash function takes two parameters:
* - The first parameter is a pointer to the key to hash.
* - The second parameter is the capacity of the hash table.
* A hash function returns a nonnegative number which represents a position
* (index) in the hash table.
*/
typedef size_t (*upo_ht_hasher_t)(const void*, size_t);
/**
* \brief The type for key comparison functions.
*
* Declares the type for key comparison functions that are used to compare keys
* stored in the hash table.
* A comparison function takes two parameters:
* - The first parameter is a pointer to the first key to compare.
* - The second parameter is a pointer to the second key to compare.
* A comparison function returns a number less than, equal to, or greater than
* zero if the first key (first argument) is less than, equal to, or greater
* than the second key (second argument), respectively.
*/
typedef int (*upo_ht_comparator_t)(const void*, const void*);
/*** END of COMMON TYPES ***/
/*** BEGIN of HASH TABLE with SEPARATE CHAINING ***/
/** \brief Default capacity of hash tables with separate chaining. */
#define UPO_HT_SEPCHAIN_DEFAULT_CAPACITY 997U
/** \brief Type for nodes of the list of collisions. */
struct upo_ht_sepchain_list_node_s
{
void *key; /**< Pointer to the user-provided key. */
void *value; /**< Pointer to the value associated to the key. */
struct upo_ht_sepchain_list_node_s *next; /**< Pointer to the next node in the list. */
};
/** \brief Alias for the type for nodes of the list of collisions. */
typedef struct upo_ht_sepchain_list_node_s upo_ht_sepchain_list_node_t;
/** \brief Type for slots of hash tables with separate chaining. */
struct upo_ht_sepchain_slot_s
{
upo_ht_sepchain_list_node_t *head; /**< Pointer to the head of the list of collisions. */
};
/** \brief Alias for the type for slots of hash tables with separate chaining. */
typedef struct upo_ht_sepchain_slot_s upo_ht_sepchain_slot_t;
/** \brief Type for hash tables with separate chaining. */
struct upo_ht_sepchain_s
{
upo_ht_sepchain_slot_t *slots; /**< The hash table as array of slots. */
size_t capacity; /**< The capacity of the hash table. */
size_t size; /**< The number of elements stored in the hash table. */
upo_ht_hasher_t key_hash; /**< The key hash function. */
upo_ht_comparator_t key_cmp; /**< The key comparison function. */
};
/** \brief Type for hash tables with separate chaining. */
typedef struct upo_ht_sepchain_s* upo_ht_sepchain_t;
/**
* \brief Creates a new empty hash table.
*
* \param m The initial capacity of the hash table.
* \param key_hash A pointer to the function used to hash keys.
* \param key_cmp A pointer to the function used to compare keys.
* \return An empty hash table.
*
* Worst-case complexity: linear in the capacity `m` of the hash table, `O(m)`.
*/
upo_ht_sepchain_t upo_ht_sepchain_create(size_t m, upo_ht_hasher_t key_hash, upo_ht_comparator_t key_cmp);
/**
* \brief Destroys the given hash table.
*
* \param ht The hash table to destroy.
* \param destroy_data Tells whether the previously allocated memory for data
* stored in the hash table must be freed (value `1`) or not (value `0`).
*
* Memory deallocation (if requested) is performed by means of the `free()`
* standard C function.
*
* Worst-case complexity: linear in the capacity `m` of the hash table, `O(m)`.
*/
void upo_ht_sepchain_destroy(upo_ht_sepchain_t ht, int destroy_data);
/**
* \brief Removes all key-value pairs from the given hash table.
*
* \param ht The hash table to clear.
* \param destroy_data Tells whether the previously allocated memory for data
* stored in the hash table must be freed (value `1`) or not (value `0`).
*
* Memory deallocation (if requested) is performed by means of the `free()`
* standard C function.
*
* Worst-case complexity: linear in the capacity `m` of the hash table, `O(m)`.
*/
void upo_ht_sepchain_clear(upo_ht_sepchain_t ht, int destroy_data);
/**
* \brief Tells if the given hash table is empty.
*
* \param ht The hash table.
* \return `1` if the hash table is empty or `0` otherwise.
*
* A hash table is empty if it doesn't contain any node.
*
* Worst-case complexity: constant, `O(1)`.
*/
int upo_ht_sepchain_is_empty(const upo_ht_sepchain_t ht);
/**
* \brief Returns the capacity of the hash table.
*
* \param ht The hash table.
* \return The total number of slots of the hash tables.
*
* Worst-case complexity: constant, `O(1)`.
*/
size_t upo_ht_sepchain_capacity(const upo_ht_sepchain_t ht);
/**
* \brief Returns the size of the hash table.
*
* \param ht The hash table.
* \return The number of keys stored in the hash tables.
*
* Worst-case complexity: linear in the capacity `m` of the hash table, `O(m)`.
*/
size_t upo_ht_sepchain_size(const upo_ht_sepchain_t ht);
/**
* \brief Returns the load factor of the hash table.
*
* \param ht The hash table.
* \return The load factor which is defined as the ratio between the number of
* stored keys (i.e., the keys) and the number of slots (i.e., the capacity).
*
* Worst-case complexity: constant, `O(1)`.
*/
double upo_ht_sepchain_load_factor(const upo_ht_sepchain_t ht);
/**
* \brief Returns the key comparator function.
*
* \param ht The hash table.
* \return The key comparator function.
*/
upo_ht_comparator_t upo_ht_sepchain_get_comparator(const upo_ht_sepchain_t ht);
/**
* \brief Returns the key hasher function.
*
* \param ht The hash table.
* \return The key hasher function.
*/
upo_ht_hasher_t upo_ht_sepchain_get_hasher(const upo_ht_sepchain_t ht);
/**
* \brief Removes the value identified by the provided key in the given
* hash table.
*
* \param ht The hash table.
* \param key The key.
* \param destroy_data Tells whether the previously allocated memory for data,
* that is to be removed, must be freed (value `1`) or not (value `0`).
*
* Memory deallocation (if requested) is performed by means of the `free()`
* standard C function.
*
* Worst-case complexity: linear in the number `n` of elements, `O(n)`.
*/
void upo_ht_sepchain_odelete(upo_ht_sepchain_t ht, const void *key, int destroy_data);
/*** END of HASH TABLE with SEPARATE CHAINING ***/
/*** BEGIN of HASH FUNCTIONS ***/
/**
* \brief Hash function for integers that uses the division method.
*
* \param x The integer to be hashed.
* \param m The number of possible hash values.
* \return The hash value which is an integer number in \f$\{0,\ldots,m-1\}\f$.
*
* The division method is defined as:
* \f[
* h(x) = x \bmod m
* \f]
* where:
* - \f$y \bmod z\f$ means the remainder of the division \f$y / z\f$.
* .
*/
size_t upo_ht_hash_int_div(const void *x, size_t m);
/**
* \brief Hash function for integers that uses the multiplication method.
*
* \param x The integer to be hashed.
* \param a A multiplicative constant in the range of (0,1).
* \param m The number of possible hash values.
* \return The hash value which is an integer number in \f$\{0,\ldots,m-1\}\f$.
*
* The multiplication method is defined as:
* \f[
* h(x) = m \lfloor a x \bmod 1 \rfloor
* \f]
* where:
* - \f$\lfloor y \rfloor\f$ means the floor of \f$y\f$, that is the greatest
* integer less than or equal to \f$y\f$.
* - \f$y \bmod z\f$ means the remainder of the division \f$y / z\f$.
* - \f$y \bmod 1\f$ is the fractional part of \f$y\f$, that is
* the result of \f$y - \lfloor y \rfloor\f$.
* .
*/
size_t upo_ht_hash_int_mult(const void *x, double a, size_t m);
/**
* \brief Hash function for integers that uses the multiplication method and
* the value of the multiplicative constant as proposed by Knuth.
*
* \param x The integer to be hashed.
* \param m The number of possible hash values.
* \return The hash value which is an integer number in \f$\{0,\ldots,m-1\}\f$.
*/
size_t upo_ht_hash_int_mult_knuth(const void *x, size_t m);
/**
* \brief Hash function for strings.
*
* \param s The string to be hashed.
* \param h0 The initial value for the hash value that is usually chosen
* randomly from a universal family mapping integer domain
* \f$\{0,\ldots,p-1\} \mapsto \{0,\ldots,m-1\}\f$.
* \param a A multiplicative factor such that \f$a \in \{0,\ldots,p-1\}\f$ which
* is usually uniformly random.
* \param m The number of possible hash values.
* \return The hash value which is an integer number in \f$\{0,\ldots,m-1\}\f$.
*
* The implemented hash function is the following:
* \f[
* h(k) = h_0 \left( \big(\sum_{i=0}^{\ell-1} k_i\cdot a^i \big) \bmod m \right),
* \f]
* where:
* - \f$k=(k_0,\ldots,k_{\ell-1})\f$ is an array of characters of size \$\ell\$
*/
size_t upo_ht_hash_str(const void *s, size_t h0, size_t a, size_t m);
/**
* \brief The Bernstein's hash function `djb2`.
*
* This hash function was first reported by Daniel J. Bernstein in comp.lang.c on 1991.
*
* See:
* - https://groups.google.com/forum/#!msg/comp.lang.c/lSKWXiuNOAk/zstZ3SRhCjgJ
* - http://www.cse.yorku.ca/~oz/hash.html
* .
*/
size_t upo_ht_hash_str_djb2(const void *s, size_t m);
/**
* \brief The Bernstein's hash function `djb2a`.
*
* This hash function is an alternative to the 'djb2' hash function that was
* first reported by Daniel J. Bernstein in comp.lang.c on 1991.
* Instead of using the sum operator it uses the XOR operator.
*
* See:
* - https://groups.google.com/forum/#!msg/comp.lang.c/lSKWXiuNOAk/zstZ3SRhCjgJ
* - http://www.cse.yorku.ca/~oz/hash.html
* .
*/
size_t upo_ht_hash_str_djb2a(const void *s, size_t m);
/**
* \brief The Java's hash function `hashCode`.
*
* See:
* - https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#hashCode--
* .
*/
size_t upo_ht_hash_str_java(const void *s, size_t m);
/**
* \brief The Kernighan and Ritchie's hash function proposed in the second
* edition of their C book.
*/
size_t upo_ht_hash_str_kr2e(const void *s, size_t m);
/**
* \brief The SGI STL's hash function `hash_fun`.
*
*/
size_t upo_ht_hash_str_sgistl(const void *s, size_t m);
/*** END of HASH FUNCTIONS ***/
#endif /* UPO_HASHTABLE_H */
/* vim: set tabstop=4 expandtab shiftwidth=4 softtabstop=4: */
/**
* \file upo/test/utility.h
*
* \brief Collection of useful functions for testing.
*
* \author Marco Guazzone (marco.guazzone@uniupo.it)
*
* \copyright 2015 University of Piemonte Orientale, Computer Science Institute
*
* This file is part of UPOalglib.
*
* UPOalglib is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* UPOalglib 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 UPOalglib. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UPO_TEST_H
#define UPO_TEST_H
int upo_test_int_cmp(const void* a, const void* b);
int upo_test_str_cmp(const void* a, const void* b);
char* upo_test_int_to_string(const void *pval);
char* upo_test_str_to_string(const void *pval);
char* upo_test_array_to_string(const void *base, size_t nelem, size_t elem_sz, char* (*to_string)(const void*));
#endif /* UPO_TEST_H */
File added
File added
File added
/* vim: set tabstop=4 expandtab shiftwidth=4 softtabstop=4: */
/*
* Copyright 2016 University of Piemonte Orientale, Computer Science Institute
*
* This file is part of UPOalglib.
*
* UPOalglib is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* UPOalglib 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 UPOalglib. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <upo/bst.h>
#include <upo/test.h>
#define TEST_OK 1
#define TEST_FAIL 0
static int test_bst1();
static int test_bst2();
static int test_bst3();
static int test_bst4();
static int test_bst5();
static int test_empty_bst();
static int test_int_bst(int *keys, int *values, size_t n, int *no_keys, size_t m);
static int test_str_bst(char **keys, int *values, size_t n, char **no_keys, size_t m);
static int test_bst(void *keys, size_t key_sz, void *values, size_t value_sz, size_t n, void *no_keys, size_t m, upo_bst_comparator_t key_cmp, char* (*key_to_string)(const void*), char* (*value_to_string)(const void*));
extern size_t upo_bst_check(const upo_bst_t x, const void *y);
extern void upo_bst_dump(const upo_bst_t, FILE *, char* (*)(const void*), int, char* (*)(const void*), int);
extern void* upo_bst_put(upo_bst_t, void*, void*);
int main()
{
size_t n = 5;
size_t i = 0;
int ret = 0;
printf("*** [DISCLAIMER] ***************************************************************\n");
printf("The following tests are provided as is, to allow you to quickly test your code.\n");
printf("However, passing these tests is a necessary but not sufficient condition,\n");
printf("meaning that they do not guarantee that your code is correct.\n");
printf("In fact, your code may be wrong even it passes all these tests\n");
printf("********************************************************************************\n\n");
for (i = 1; i <= n; ++i)
{
switch (i)
{
case 1:
ret = test_bst1();
break;
case 2:
ret = test_bst2();
break;
case 3:
ret = test_bst3();
break;
case 4:
ret = test_bst4();
break;
case 5:
ret = test_bst5();
break;
default:
fprintf(stderr, "ERROR: Unexpected test case number");
abort();
}
printf("Test BST #%lu => %s\n", i, (ret == TEST_OK) ? "[OK]" : "[FAIL]");
}
ret = test_empty_bst();
printf("Test Empty BST => %s\n", (ret == TEST_OK) ? "[OK]" : "[FAIL]");
return 0;
}
int test_bst1()
{
/*
* BST:
* 8
* / \
* 3 10
* / \ \
* 1 6 14
* / \ /
* 4 7 13
*/
int keys[] = {8, 3, 1, 6, 4, 7, 10, 14, 13};
int values[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
int no_keys[] = {0, 2, 5, 9, 11, 16};
size_t n = sizeof keys/sizeof keys[0];
size_t m = sizeof no_keys/sizeof no_keys[0];
assert( n == sizeof keys/sizeof keys[0] );
assert( n == sizeof values/sizeof values[0] );
assert( m == sizeof no_keys/sizeof no_keys[0] );
return test_int_bst(keys, values, n, no_keys, m);
}
int test_bst2()
{
/*
* BST:
* 11
* / \
* 3 13
* / \ \
* 1 9 19
* / /
* 7 15
* / \
* 5 17
*/
int keys[] = {11, 3, 1, 9, 7, 5, 13, 19, 15, 17};
int values[] = {-11, -3, -1, -9, -7, -5, -13, -19, -15, -17};
int no_keys[] = {0, 6, 10, 12, 14, 20};
size_t n = sizeof keys/sizeof keys[0];
size_t m = sizeof no_keys/sizeof no_keys[0];
assert( n == sizeof keys/sizeof keys[0] );
assert( n == sizeof values/sizeof values[0] );
assert( m == sizeof no_keys/sizeof no_keys[0] );
return test_int_bst(keys, values, n, no_keys, m);
}
int test_bst3()
{
/*
* BST:
* 11
* /
* 9
* /
* 7
* /
* 5
* /
* 3
* /
* 1
*/
int keys[] = {11, 9, 7, 5, 3, 1};
int values[] = {0, 1, 2, 3, 4, 5};
int no_keys[] = {0, 2, 4, 6, 8, 10, 12};
size_t n = sizeof keys/sizeof keys[0];
size_t m = sizeof no_keys/sizeof no_keys[0];
assert( n == sizeof keys/sizeof keys[0] );
assert( n == sizeof values/sizeof values[0] );
assert( m == sizeof no_keys/sizeof no_keys[0] );
return test_int_bst(keys, values, n, no_keys, m);
}
int test_bst4()
{
/*
* BST:
* 1
* \
* 3
* \
* 5
* \
* 7
* \
* 9
* \
* 11
*/
int keys[] = {1, 3, 5, 7, 9, 11};
int values[] = {0, 1, 2, 3, 4, 5};
int no_keys[] = {0, 2, 4, 6, 8, 10, 12};
size_t n = sizeof keys/sizeof keys[0];
size_t m = sizeof no_keys/sizeof no_keys[0];
assert( n == sizeof keys/sizeof keys[0] );
assert( n == sizeof values/sizeof values[0] );
assert( m == sizeof no_keys/sizeof no_keys[0] );
return test_int_bst(keys, values, n, no_keys, m);
}
int test_bst5()
{
/*
* BST:
* "aae"
* / \
* "aac" "aaj"
* / \ \
* "aaa" "aad" "aak"
*/
char *keys[] = {"aae", "aaj", "aac", "aad", "aaa", "aak"};
int values[] = {-5, -10, -3, -4, -1, -11};
char *no_keys[] = {"AAA", "xyz", "aaf"};
size_t n = sizeof keys/sizeof keys[0];
size_t m = sizeof no_keys/sizeof no_keys[0];
assert( n == sizeof keys/sizeof keys[0] );
assert( n == sizeof values/sizeof values[0] );
assert( m == sizeof no_keys/sizeof no_keys[0] );
return test_str_bst(keys, values, n, no_keys, m);
}
int test_empty_bst()
{
return test_int_bst(NULL, NULL, 0, NULL, 0);
}
int test_int_bst(int *keys, int *values, size_t n, int *no_keys, size_t m)
{
return test_bst(keys, sizeof keys[0], values, sizeof values[0], n, no_keys, m, upo_test_int_cmp, upo_test_int_to_string, upo_test_int_to_string);
}
int test_str_bst(char **keys, int *values, size_t n, char **no_keys, size_t m)
{
return test_bst(keys, sizeof keys[0], values, sizeof values[0], n, no_keys, m, upo_test_str_cmp, upo_test_str_to_string, upo_test_int_to_string);
}
int test_bst(void *keys, size_t key_sz, void *values, size_t value_sz, size_t n, void *no_keys, size_t m, upo_bst_comparator_t key_cmp, char* (*key_to_string)(const void*), char* (*value_to_string)(const void*))
{
upo_bst_t bst = NULL;
unsigned char *pck = keys;
unsigned char *pcv = values;
unsigned char *pcnk = no_keys;
int ret = TEST_OK;
/* Creates BST */
bst = upo_bst_create(key_cmp);
assert( bst != NULL );
if (n > 0)
{
// Non-empty BST
for (size_t i = 0; i < n; ++i)
{
upo_bst_put(bst, pck + i*key_sz, pcv + i*value_sz);
}
// Keys
for (size_t i = 0; i < n && ret == TEST_OK; ++i)
{
void *pkey = NULL;
size_t count = 0;
size_t count_check = 0;
pkey = malloc(key_sz);
if (pkey == NULL)
{
perror("[ERROR] Unable to allocate memory for key");
abort();
}
memcpy(pkey, pck + i*key_sz, key_sz);
count = upo_bst_subtree_count_even(bst, pkey);
count_check = upo_bst_check(bst, pkey);
if (count != count_check)
{
char *key_str = key_to_string(pkey);
fprintf(stderr, "[file: %s, line: %d] ERROR: Key: '%s' -> Expected count %lu, got %lu.\n", __FILE__, __LINE__, key_str, count_check, count);
free(key_str);
fprintf(stderr, "[file: %s, line: %d] <BST>:\n", __FILE__, __LINE__);
upo_bst_dump(bst, stderr, key_to_string, 1, value_to_string, 1);
fprintf(stderr, "[file: %s, line: %d] </BST>:\n", __FILE__, __LINE__);
ret = TEST_FAIL;
}
free(pkey);
}
// No keys
for (size_t i = 0; i < m && ret == TEST_OK; ++i)
{
void *pkey = NULL;
size_t count = 0;
size_t count_check = 0;
pkey = malloc(key_sz);
if (pkey == NULL)
{
perror("[ERROR] Unable to allocate memory for key");
abort();
}
memcpy(pkey, pcnk + i*key_sz, key_sz);
count = upo_bst_subtree_count_even(bst, pkey);
count_check = upo_bst_check(bst, pkey);
if (count != count_check)
{
char *key_str = key_to_string(pkey);
fprintf(stderr, "[file: %s, line: %d] ERROR: Key: '%s' -> Expected count '%lu', got %lu.\n", __FILE__, __LINE__, key_str, count_check, count);
free(key_str);
fprintf(stderr, "[file: %s, line: %d] <BST>:\n", __FILE__, __LINE__);
upo_bst_dump(bst, stderr, key_to_string, 1, value_to_string, 1);
fprintf(stderr, "[file: %s, line: %d] </BST>:\n", __FILE__, __LINE__);
ret = TEST_FAIL;
}
free(pkey);
}
}
else
{
// Empty BST
int dummy_key = 0;
size_t count = 0;
count = upo_bst_subtree_count_even(bst, &dummy_key);
if (count != 0)
{
fprintf(stderr, "[file: %s, line: %d] ERROR: Empty BST -> Expected count 0, got %lu.\n", __FILE__, __LINE__, count);
ret = TEST_FAIL;
}
}
/* Destroy */
upo_bst_destroy(bst, 0);
return ret;
}
/* vim: set tabstop=4 expandtab shiftwidth=4 softtabstop=4: */
/*
* Copyright 2015 University of Piemonte Orientale, Computer Science Institute
*
* This file is part of UPOalglib.
*
* UPOalglib is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* UPOalglib 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 UPOalglib. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <upo/hashtable.h>
#include <upo/test.h>
#define TEST_OK 1
#define TEST_FAIL 0
static int test_ht1();
static int test_ht2();
static int test_ht3();
static int test_ht4();
static int test_ht5();
static int test_ht6();
static int test_empty_ht();
static int test_int_ht(int *keys, int *values, size_t n, int *no_keys, size_t m);
static int test_str_ht(char **keys, int *values, size_t n, char **no_keys, size_t m);
static int test_ht(void *keys, size_t key_sz, void *values, size_t value_sz, size_t n, void *no_keys, size_t m, upo_ht_hasher_t key_hasher, upo_ht_comparator_t key_cmp, char* (*key_to_string)(const void*), char* (*value_to_string)(const void*));
extern upo_ht_sepchain_list_node_t* upo_ht_sepchain_check_order(const upo_ht_sepchain_t ht);
extern int upo_ht_sepchain_contains(const upo_ht_sepchain_t ht, const void *key);
extern void upo_ht_sepchain_dump(const upo_ht_sepchain_t, FILE *, char* (*)(const void*), int, char* (*)(const void*), int);
extern void* upo_ht_sepchain_put(upo_ht_sepchain_t ht, void *key, void *value);
int main()
{
size_t n = 6;
size_t i = 0;
int ret = 0;
printf("*** [DISCLAIMER] ***************************************************************\n");
printf("The following tests are provided as is, to allow you to quickly test your code.\n");
printf("However, passing these tests is a necessary but not sufficient condition,\n");
printf("meaning that they do not guarantee that your code is correct.\n");
printf("In fact, your code may be wrong even it passes all these tests\n");
printf("********************************************************************************\n\n");
for (i = 1; i <= n; ++i)
{
switch (i)
{
case 1:
ret = test_ht1();
break;
case 2:
ret = test_ht2();
break;
case 3:
ret = test_ht3();
break;
case 4:
ret = test_ht4();
break;
case 5:
ret = test_ht5();
break;
case 6:
ret = test_ht6();
break;
default:
fprintf(stderr, "ERROR: Unexpected test case number");
abort();
}
printf("Test HT #%zu => %s\n", i, (ret == TEST_OK) ? "[OK]" : "[FAIL]");
}
ret = test_empty_ht();
printf("Test Empty HT => %s\n", (ret == TEST_OK) ? "[OK]" : "[FAIL]");
return 0;
}
int test_ht1()
{
int keys[] = {0,1,2,3,4,5,6,7,8,9,1000,2000,3000,4000,5000,6000,7000,8000,9000};
int values[] = {0,1,2,3,4,5,6,7,8,9,1000,2000,3000,4000,5000,6000,7000,8000,9000};
int no_keys[] = {10,11,12,13,14,15,16,19,1010,2010,3010,4010,5010};
size_t n = sizeof keys/sizeof keys[0];
size_t m = sizeof no_keys/sizeof no_keys[0];
assert( n == (sizeof keys/sizeof keys[0]) );
assert( n == (sizeof values/sizeof values[0]) );
assert( m == (sizeof no_keys/sizeof no_keys[0]) );
return test_int_ht(keys, values, n, no_keys, m);
}
int test_ht2()
{
int keys[] = {0,10,20,30,40,50,60,70,80,90,100,200,300,400,500,600,700,800,900};
int values[] = {0,1,2,3,4,5,6,7,8,9,1000,2000,3000,4000,5000,6000,7000,8000,9000};
int no_keys[] = {1,11,21,31,41,51,61,71,81,91,101,201,301,401,501,601,701,801,901,1001,1101,1201,1301,1401,1501};
size_t n = sizeof keys/sizeof keys[0];
size_t m = sizeof no_keys/sizeof no_keys[0];
assert( n == (sizeof keys/sizeof keys[0]) );
assert( n == (sizeof values/sizeof values[0]) );
assert( m == (sizeof no_keys/sizeof no_keys[0]) );
return test_int_ht(keys, values, n, no_keys, m);
}
int test_ht3()
{
int keys[] = {0,1,2,3,4,10,11,12,13,14,1000,2000,3000,4000,5000,6000,7000,8000,9000};
int values[] = {0,1,2,3,4,5,6,7,8,9,1000,2000,3000,4000,5000,6000,7000,8000,9000};
int no_keys[] = {5,6,7,8,9,15,16,17,18,19,1500,1600,1700,1800,1900};
size_t n = sizeof keys/sizeof keys[0];
size_t m = sizeof no_keys/sizeof no_keys[0];
assert( n == (sizeof keys/sizeof keys[0]) );
assert( n == (sizeof values/sizeof values[0]) );
assert( m == (sizeof no_keys/sizeof no_keys[0]) );
return test_int_ht(keys, values, n, no_keys, m);
}
int test_ht4()
{
char *keys[] = {"AA","AB","AQ","Aa","Aq","Ba","Ca","Da","Ea","Fa","AAA", "Ab"};
int values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
char *no_keys[] = {"xAA","xAB","xAQ","xAa","xAq","xBa","xCa","xDa","xEa","xFa","xAAA", "xAb", "yAA", "yAB"};
size_t n = sizeof keys/sizeof keys[0];
size_t m = sizeof no_keys/sizeof no_keys[0];
assert( n == (sizeof keys/sizeof keys[0]) );
assert( n == (sizeof values/sizeof values[0]) );
assert( m == (sizeof no_keys/sizeof no_keys[0]) );
return test_str_ht(keys, values, n, no_keys, m);
}
int test_ht5()
{
char *keys[] = {"aaa","aba","aca","ada","aea","afa","aga","aha","aia","aja"};
int values[] = {0,1,2,3,4,5,6,7,8,9};
char *no_keys[] = {"a1a","a2a","a3a","a4a","a5a","a6a","a7a","a9a","a9a","a10a"};
size_t n = sizeof keys/sizeof keys[0];
size_t m = sizeof no_keys/sizeof no_keys[0];
assert( n == (sizeof keys/sizeof keys[0]) );
assert( n == (sizeof values/sizeof values[0]) );
assert( m == (sizeof no_keys/sizeof no_keys[0]) );
return test_str_ht(keys, values, n, no_keys, m);
}
int test_ht6()
{
char *keys[] = {"aaa","aab","aac","aad","aba","abb","abc","abd","abe","abf"};
int values[] = {0,1,2,3,4,5,6,7,8,9};
char *no_keys[] = {"aax","abx","acx","adx","aex","afx"};
size_t n = sizeof keys/sizeof keys[0];
size_t m = sizeof no_keys/sizeof no_keys[0];
assert( n == (sizeof keys/sizeof keys[0]) );
assert( n == (sizeof values/sizeof values[0]) );
assert( m == (sizeof no_keys/sizeof no_keys[0]) );
return test_str_ht(keys, values, n, no_keys, m);
}
int test_empty_ht()
{
int dummy1 = 0;
int dummy2 = 1;
return test_int_ht(&dummy1, &dummy1, 0, &dummy2, 0);
}
int test_int_ht(int *keys, int *values, size_t n, int *no_keys, size_t m)
{
assert( keys );
assert( values );
assert( no_keys );
return test_ht(keys, sizeof keys[0], values, sizeof values[0], n, no_keys, m, upo_ht_hash_int_div, upo_test_int_cmp, upo_test_int_to_string, upo_test_int_to_string);
}
int test_str_ht(char **keys, int *values, size_t n, char **no_keys, size_t m)
{
assert( keys );
assert( values );
assert( no_keys );
return test_ht(keys, sizeof keys[0], values, sizeof values[0], n, no_keys, m, upo_ht_hash_str_kr2e, upo_test_str_cmp, upo_test_str_to_string, upo_test_int_to_string);
}
int test_ht(void *keys, size_t key_sz, void *values, size_t value_sz, size_t n, void *no_keys, size_t m, upo_ht_hasher_t key_hasher, upo_ht_comparator_t key_cmp, char* (*key_to_string)(const void*), char* (*value_to_string)(const void*))
{
upo_ht_sepchain_t ht = NULL;
size_t base_cap = 3;
size_t caps[4];
size_t nc;
unsigned char *pck = keys;
unsigned char *pcv = values;
unsigned char *pcnk = no_keys;
int ret = TEST_OK;
/*
caps[0] = 2*n+UPO_HT_SEPCHAIN_DEFAULT_CAPACITY;
caps[1] = n*UPO_HT_SEPCHAIN_DEFAULT_CAPACITY;
caps[2] = UPO_HT_SEPCHAIN_DEFAULT_CAPACITY;
*/
caps[0] = 3*n+base_cap;
caps[1] = 2*n+base_cap;
caps[2] = n*base_cap;
caps[3] = base_cap;
nc = sizeof caps/sizeof caps[0];
for (size_t k = 0; k < nc && ret == TEST_OK; ++k)
{
ht = upo_ht_sepchain_create(caps[k], key_hasher, key_cmp);
assert( ht != NULL );
if (n > 0)
{
// Non-empty HT
// Populate the HT
for (size_t i = 0; i < n; ++i)
{
upo_ht_sepchain_put(ht, pck + i*key_sz, pcv + i*value_sz);
}
// Remove from HT
for (size_t i = 0; i < n && ret == TEST_OK; ++i)
{
size_t old_size = 0;
size_t new_size = 0;
int found = 0;
void *key = NULL;
key = malloc(key_sz);
if (key == NULL)
{
perror("Unable to allocate memory for key");
abort();
}
memcpy(key, pck + i*key_sz, key_sz);
old_size = upo_ht_sepchain_size(ht);
upo_ht_sepchain_odelete(ht, key, 0);
new_size = upo_ht_sepchain_size(ht);
found = upo_ht_sepchain_contains(ht, key);
if (found == 1)
{
char *key_str = key_to_string(key);
fprintf(stderr, "[file: %s, line: %d] ERROR: HT Alternative #: %lu, Key: '%s' -> Found key after its deletion.\n", __FILE__, __LINE__, k, key_str);
fprintf(stderr, "[file: %s, line: %d]: <HT>\n", __FILE__, __LINE__);
upo_ht_sepchain_dump(ht, stderr, key_to_string, 1, value_to_string, 1);
fprintf(stderr, "[file: %s, line: %d]: </HT>\n", __FILE__, __LINE__);
fflush(stderr);
free(key_str);
ret = TEST_FAIL;
}
else if (new_size != (old_size-1))
{
char *key_str = key_to_string(key);
fprintf(stderr, "[file: %s, line: %d] ERROR: HT Alternative #: %lu, Key: '%s' -> Expected size: %lu, got %lu.\n", __FILE__, __LINE__, k, key_str, (old_size-1), new_size);
fprintf(stderr, "[file: %s, line: %d]: <HT>\n", __FILE__, __LINE__);
upo_ht_sepchain_dump(ht, stderr, key_to_string, 1, value_to_string, 1);
fprintf(stderr, "[file: %s, line: %d]: </HT>\n", __FILE__, __LINE__);
fflush(stderr);
free(key_str);
ret = TEST_FAIL;
}
free(key);
// Check order of stored values
upo_ht_sepchain_list_node_t *node = upo_ht_sepchain_check_order(ht);
if (node != NULL)
{
char *key_str1 = key_to_string(node->key);
char *key_str2 = key_to_string(node->next->key);
fprintf(stderr, "[file: %s, line: %d] ERROR: HT Alternative #: %zu, Keys: '%s' and '%s' are out of order.\n", __FILE__, __LINE__, k, key_str1, key_str2);
free(key_str1);
free(key_str2);
fprintf(stderr, "[file: %s, line: %d]: <HT>\n", __FILE__, __LINE__);
upo_ht_sepchain_dump(ht, stderr, key_to_string, 1, value_to_string, 1);
fprintf(stderr, "[file: %s, line: %d]: </HT>\n", __FILE__, __LINE__);
fflush(stderr);
ret = TEST_FAIL;
}
}
upo_ht_sepchain_clear(ht, 0);
// Now for each key to be removed, fill the HT with all keys, remove the given key and then check that the other keys are still present in the HT
for (size_t j = 0; j < n && ret == TEST_OK; ++j)
{
// Populate the HT
for (size_t i = 0; i < n && ret == TEST_OK; ++i)
{
upo_ht_sepchain_put(ht, pck + i*key_sz, pcv + i*value_sz);
}
// Remove from the HT
void *key = NULL;
key = malloc(key_sz);
if (key == NULL)
{
perror("Unable to allocate memory for key");
abort();
}
memcpy(key, pck + j*key_sz, key_sz);
size_t old_size = 0;
size_t new_size = 0;
int found = 0;
old_size = upo_ht_sepchain_size(ht);
upo_ht_sepchain_odelete(ht, key, 0);
new_size = upo_ht_sepchain_size(ht);
found = upo_ht_sepchain_contains(ht, key);
if (found == 1)
{
char *key_str = key_to_string(key);
fprintf(stderr, "[file: %s, line: %d] ERROR: HT Alternative #: %lu, Key: '%s' -> Found key after its deletion.\n", __FILE__, __LINE__, k, key_str);
fprintf(stderr, "[file: %s, line: %d]: <HT>\n", __FILE__, __LINE__);
upo_ht_sepchain_dump(ht, stderr, key_to_string, 1, value_to_string, 1);
fprintf(stderr, "[file: %s, line: %d]: </HT>\n", __FILE__, __LINE__);
fflush(stderr);
free(key_str);
ret = TEST_FAIL;
}
else if (new_size != (old_size-1))
{
char *key_str = key_to_string(key);
fprintf(stderr, "[file: %s, line: %d] ERROR: HT Alternative #: %lu, Key: '%s' -> Expected size: %lu, got %lu.\n", __FILE__, __LINE__, k, key_str, (old_size-1), new_size);
fprintf(stderr, "[file: %s, line: %d]: <HT>\n", __FILE__, __LINE__);
upo_ht_sepchain_dump(ht, stderr, key_to_string, 1, value_to_string, 1);
fprintf(stderr, "[file: %s, line: %d]: </HT>\n", __FILE__, __LINE__);
fflush(stderr);
free(key_str);
ret = TEST_FAIL;
}
for (size_t i = 0; i < n && ret == TEST_OK; ++i)
{
if (i == j)
{
// Skip the remove key
continue;
}
found = upo_ht_sepchain_contains(ht, pck + i*key_sz);
if (found == 0)
{
ret = TEST_FAIL;
char *key_str = key_to_string(key);
char *key2_str = key_to_string(pck + i*key_sz);
fprintf(stderr, "[file: %s, line: %d] ERROR: HT Alternative #: %lu, Key: '%s' -> Key '%s' not found after the deletion of another key.\n", __FILE__, __LINE__, k, key_str, key2_str);
fprintf(stderr, "[file: %s, line: %d]: <HT>\n", __FILE__, __LINE__);
upo_ht_sepchain_dump(ht, stderr, key_to_string, 1, value_to_string, 1);
fprintf(stderr, "[file: %s, line: %d]: </HT>\n", __FILE__, __LINE__);
fflush(stderr);
free(key_str);
free(key2_str);
ret = TEST_FAIL;
}
}
/* Clean-up */
free(key);
// Clear the HT
upo_ht_sepchain_clear(ht, 0);
}
// Now populate again the HT and try to remove a key not stored in it.
// Populate the HT
for (size_t i = 0; i < n; ++i)
{
upo_ht_sepchain_put(ht, pck + i*key_sz, pcv + i*value_sz);
}
// Remove from HT
for (size_t i = 0; i < m && ret == TEST_OK; ++i)
{
size_t old_size = 0;
size_t new_size = 0;
int found = 0;
// Use a different pointer for key to catch comparison-by-pointers issues
void *key = NULL;
key = malloc(key_sz);
if (key == NULL)
{
perror("Unable to allocate memory for key");
abort();
}
memcpy(key, pcnk + i*key_sz, key_sz);
old_size = upo_ht_sepchain_size(ht);
upo_ht_sepchain_odelete(ht, key, 0);
new_size = upo_ht_sepchain_size(ht);
found = upo_ht_sepchain_contains(ht, key);
if (found == 1)
{
char *key_str = key_to_string(key);
fprintf(stderr, "[file: %s, line: %d] ERROR: HT Alternative #: %lu, Key: '%s' -> Found key not belonging to the HT.\n", __FILE__, __LINE__, k, key_str);
fprintf(stderr, "[file: %s, line: %d]: <HT>\n", __FILE__, __LINE__);
upo_ht_sepchain_dump(ht, stderr, key_to_string, 1, value_to_string, 1);
fprintf(stderr, "[file: %s, line: %d]: </HT>\n", __FILE__, __LINE__);
fflush(stderr);
free(key_str);
ret = TEST_FAIL;
}
else if (new_size != old_size)
{
char *key_str = key_to_string(key);
fprintf(stderr, "[file: %s, line: %d] ERROR: HT Alternative #: %lu, Key: '%s' -> Expected size: %lu, got %lu.\n", __FILE__, __LINE__, k, key_str, old_size, new_size);
fprintf(stderr, "[file: %s, line: %d]: <HT>\n", __FILE__, __LINE__);
upo_ht_sepchain_dump(ht, stderr, key_to_string, 1, value_to_string, 1);
fprintf(stderr, "[file: %s, line: %d]: </HT>\n", __FILE__, __LINE__);
fflush(stderr);
free(key_str);
ret = TEST_FAIL;
}
free(key);
// Check order of stored values
upo_ht_sepchain_list_node_t *node = upo_ht_sepchain_check_order(ht);
if (node != NULL)
{
char *key_str1 = key_to_string(node->key);
char *key_str2 = key_to_string(node->next->key);
fprintf(stderr, "[file: %s, line: %d] ERROR: HT Alternative #: %zu, Keys: '%s' and '%s' are out of order.\n", __FILE__, __LINE__, k, key_str1, key_str2);
free(key_str1);
free(key_str2);
fprintf(stderr, "[file: %s, line: %d]: <HT>\n", __FILE__, __LINE__);
upo_ht_sepchain_dump(ht, stderr, key_to_string, 1, value_to_string, 1);
fprintf(stderr, "[file: %s, line: %d]: </HT>\n", __FILE__, __LINE__);
fflush(stderr);
ret = TEST_FAIL;
}
}
upo_ht_sepchain_clear(ht, 0);
}
else
{
// Empty HT: no test
}
upo_ht_sepchain_destroy(ht, 0);
}
return ret;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment