blob: 652057559393208432e867a76618203cb8c44d6d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "qpid/dispatch/hash.h"
#include "test_case.h"
#include "qpid/dispatch/iterator.h"
#include <stdio.h>
#include <string.h>
static const unsigned char *keys[] = {
(const unsigned char *) "/global/foo",
(const unsigned char *) "non-address key",
(const unsigned char *) "amqp://host/global/sub",
(const unsigned char *) "",
};
enum { key_count = sizeof(keys) / sizeof(keys[0]) };
// add using iterator key, lookup and remove using string key
//
static char *test_iter_keys(void *context)
{
char *result = 0;
qd_hash_handle_t *handles[key_count];
qd_iterator_t *i_key = 0;
qd_hash_t *hash = qd_hash(4, 10, false);
if (!hash)
return "hash table allocation failed";
//
// add using iterator, lookup and remove using string
//
for (int i = 0; i < key_count; ++i) {
const unsigned char *key = keys[i];
qd_hash_handle_t **handle = &handles[i];
i_key = qd_iterator_string((const char *)key, ITER_VIEW_ALL);
if (qd_hash_insert(hash, i_key, (void *)key, handle) != QD_ERROR_NONE) {
result = "hash table insert failed";
goto done;
}
if (strcmp((const char *) qd_hash_key_by_handle(*handle), (const char *)key) != 0) {
result = "hash handle key did not match";
goto done;
}
qd_iterator_free(i_key);
i_key = 0;
}
if (qd_hash_size(hash) != key_count) {
result = "hash size is incorrect";
goto done;
}
for (int i = 0; i < key_count; ++i) {
const unsigned char *key = keys[i];
unsigned char *value;
if (qd_hash_retrieve_str(hash, key, (void **)&value) != QD_ERROR_NONE) {
result = "Key lookup failed";
goto done;
}
if (strcmp((const char *)value, (const char *)key) != 0) {
result= "key value mismatch";
goto done;
}
}
for (int i = 0; i < key_count; ++i) {
const unsigned char *key = keys[i];
if (qd_hash_remove_str(hash, key) != QD_ERROR_NONE) {
result = "str key remove failed";
goto done;
}
qd_hash_handle_free(handles[i]);
}
done:
qd_iterator_free(i_key);
qd_hash_free(hash);
return result;
}
// add using string key, lookup and remove using iterator key
//
static char *test_str_keys(void *context)
{
char *result = 0;
qd_iterator_t *i_key = 0;
qd_hash_handle_t *handles[key_count];
qd_hash_t *hash = qd_hash(4, 10, false);
if (!hash)
return "hash table allocation failed";
for (int i = 0; i < key_count; ++i) {
const unsigned char *key = keys[i];
qd_hash_handle_t **handle = &handles[i];
if (qd_hash_insert_str(hash, key, (void *)key, handle) != QD_ERROR_NONE) {
result = "hash table insert failed";
goto done;
}
if (strcmp((const char *) qd_hash_key_by_handle(*handle), (const char *)key) != 0) {
result = "hash handle key did not match";
goto done;
}
}
if (qd_hash_size(hash) != key_count) {
result = "hash size is incorrect";
goto done;
}
for (int i = 0; i < key_count; ++i) {
i_key = qd_iterator_string((const char *)keys[i], ITER_VIEW_ALL);
unsigned char *value;
if (qd_hash_retrieve(hash, i_key, (void **)&value) != QD_ERROR_NONE) {
result = "Iterator key lookup failed";
goto done;
}
if (strcmp((const char *)value, (const char *)keys[i]) != 0) {
result = "key value mismatch";
goto done;
}
qd_iterator_free(i_key);
i_key = 0;
}
for (int i = 0; i < key_count; ++i) {
i_key = qd_iterator_string((const char *)keys[i], ITER_VIEW_ALL);
if (qd_hash_remove(hash, i_key) != QD_ERROR_NONE) {
result = "str key remove failed";
goto done;
}
qd_hash_handle_free(handles[i]);
qd_iterator_free(i_key);
i_key = 0;
}
done:
qd_iterator_free(i_key);
qd_hash_free(hash);
return result;
}
// test lookup and remove failures using iterators
//
static char *test_iter_bad(void *context)
{
char *result = 0;
qd_iterator_t *i_key = 0;
qd_hash_handle_t *handles[key_count];
qd_hash_t *hash = qd_hash(4, 10, false);
if (!hash)
return "hash table allocation failed";
for (int i = 0; i < key_count; ++i) {
const unsigned char *key = keys[i];
qd_hash_handle_t **handle = &handles[i];
i_key = qd_iterator_string((const char *)key, ITER_VIEW_ALL);
if (qd_hash_insert(hash, i_key, (void *)key, handle) != QD_ERROR_NONE) {
result = "hash table insert failed";
goto done;
}
if (strcmp((const char *) qd_hash_key_by_handle(*handle), (const char *)key) != 0) {
result = "hash handle key did not match";
goto done;
}
qd_iterator_free(i_key);
i_key = 0;
}
if (qd_hash_size(hash) != key_count) {
result = "hash size is incorrect";
goto done;
}
i_key = qd_iterator_string((const char *)"I DO NOT EXIST", ITER_VIEW_ALL);
void *value = (void *)i_key; // just a non-zero value
// key not found
qd_hash_retrieve(hash, i_key, &value); // does not return error code, but sets value to 0
if (value != 0) {
result = "expected hash retrieve to find nothing";
goto done;
}
// remove should return error
if (qd_hash_remove(hash, i_key) != QD_ERROR_NOT_FOUND) {
result = "expected hash remove to fail (not found)";
goto done;
}
qd_iterator_free(i_key);
i_key = 0;
// cleanup
for (int i = 0; i < key_count; ++i) {
const unsigned char *key = keys[i];
if (qd_hash_remove_str(hash, key) != QD_ERROR_NONE) {
result = "str key remove failed";
goto done;
}
qd_hash_handle_free(handles[i]);
}
done:
qd_iterator_free(i_key);
qd_hash_free(hash);
return result;
}
// test lookup and remove failures using strings
//
static char *test_str_bad(void *context)
{
char *result = 0;
qd_hash_handle_t *handles[key_count];
qd_hash_t *hash = qd_hash(4, 10, false);
if (!hash)
return "hash table allocation failed";
for (int i = 0; i < key_count; ++i) {
const unsigned char *key = keys[i];
qd_hash_handle_t **handle = &handles[i];
if (qd_hash_insert_str(hash, key, (void *)key, handle) != QD_ERROR_NONE) {
result = "hash table insert failed";
goto done;
}
if (strcmp((const char *) qd_hash_key_by_handle(*handle), (const char *)key) != 0) {
result = "hash handle key did not match";
goto done;
}
}
if (qd_hash_size(hash) != key_count) {
result = "hash size is incorrect";
goto done;
}
const unsigned char *key = (const unsigned char *) "I DO NOT EXIST";
void *value = (void *)key; // just a non-zero value
// key not found
qd_hash_retrieve_str(hash, key, &value); // does not return error code, but sets value to 0
if (value != 0) {
result = "expected hash retrieve to find nothing";
goto done;
}
// remove should return error
if (qd_hash_remove_str(hash, key) != QD_ERROR_NOT_FOUND) {
result = "expected hash remove to fail (not found)";
goto done;
}
// cleanup
for (int i = 0; i < key_count; ++i) {
key = keys[i];
if (qd_hash_remove_str(hash, key) != QD_ERROR_NONE) {
result = "str key remove failed";
goto done;
}
qd_hash_handle_free(handles[i]);
}
done:
qd_hash_free(hash);
return result;
}
int hash_tests(void)
{
int result = 0;
char *test_group = "hash_tests";
TEST_CASE(test_iter_keys, 0);
TEST_CASE(test_str_keys, 0);
TEST_CASE(test_iter_bad, 0);
TEST_CASE(test_str_bad, 0);
return result;
}