mirror of
https://github.com/AuxXxilium/kmod.git
synced 2024-11-23 23:10:53 +07:00
b5a2cd070d
Drop the lengthy license from each file and just use SPDX like most projects nowadays. This doesn't have any change to license, just how they are recorded in each file. This follows the kernel approach: header files use '/*' for comments while .c files use '//'. For .m4, use "#". Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Link: https://lore.kernel.org/r/20240723185921.1005569-2-lucas.de.marchi@gmail.com Signed-off-by: Lucas De Marchi <lucas.de.marchi@gmail.com>
271 lines
5.9 KiB
C
271 lines
5.9 KiB
C
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
/*
|
|
* Copyright (C) 2014 Intel Corporation. All rights reserved.
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include <shared/hash.h>
|
|
#include <shared/util.h>
|
|
|
|
#include "testsuite.h"
|
|
|
|
static int freecount;
|
|
|
|
static void countfreecalls(void *v)
|
|
{
|
|
freecount++;
|
|
}
|
|
|
|
static int test_hash_new(const struct test *t)
|
|
{
|
|
struct hash *h = hash_new(8, NULL);
|
|
assert_return(h != NULL, EXIT_FAILURE);
|
|
hash_free(h);
|
|
return 0;
|
|
}
|
|
DEFINE_TEST(test_hash_new,
|
|
.description = "test hash_new");
|
|
|
|
|
|
static int test_hash_get_count(const struct test *t)
|
|
{
|
|
struct hash *h = hash_new(8, NULL);
|
|
const char *k1 = "k1", *k2 = "k2", *k3 = "k3";
|
|
const char *v1 = "v1", *v2 = "v2", *v3 = "v3";
|
|
|
|
hash_add(h, k1, v1);
|
|
hash_add(h, k2, v2);
|
|
hash_add(h, k3, v3);
|
|
|
|
assert_return(hash_get_count(h) == 3, EXIT_FAILURE);
|
|
|
|
hash_free(h);
|
|
return 0;
|
|
}
|
|
DEFINE_TEST(test_hash_get_count,
|
|
.description = "test hash_add / hash_get_count");
|
|
|
|
|
|
static int test_hash_replace(const struct test *t)
|
|
{
|
|
struct hash *h = hash_new(8, countfreecalls);
|
|
const char *k1 = "k1", *k2 = "k2", *k3 = "k3";
|
|
const char *v1 = "v1", *v2 = "v2", *v3 = "v3", *v4 = "v4";
|
|
const char *v;
|
|
int r = 0;
|
|
|
|
r |= hash_add(h, k1, v1);
|
|
r |= hash_add(h, k2, v2);
|
|
r |= hash_add(h, k3, v3);
|
|
|
|
/* replace v1 */
|
|
r |= hash_add(h, k1, v4);
|
|
|
|
assert_return(r == 0, EXIT_FAILURE);
|
|
assert_return(hash_get_count(h) == 3, EXIT_FAILURE);
|
|
|
|
v = hash_find(h, "k1");
|
|
assert_return(streq(v, v4), EXIT_FAILURE);
|
|
|
|
assert_return(freecount == 1, EXIT_FAILURE);
|
|
|
|
hash_free(h);
|
|
return 0;
|
|
}
|
|
DEFINE_TEST(test_hash_replace,
|
|
.description = "test hash_add replacing existing value");
|
|
|
|
|
|
static int test_hash_replace_failing(const struct test *t)
|
|
{
|
|
struct hash *h = hash_new(8, countfreecalls);
|
|
const char *k1 = "k1", *k2 = "k2", *k3 = "k3";
|
|
const char *v1 = "v1", *v2 = "v2", *v3 = "v3", *v4 = "v4";
|
|
const char *v;
|
|
int r = 0;
|
|
|
|
r |= hash_add(h, k1, v1);
|
|
r |= hash_add(h, k2, v2);
|
|
r |= hash_add(h, k3, v3);
|
|
|
|
assert_return(r == 0, EXIT_FAILURE);
|
|
|
|
/* replace v1 */
|
|
r = hash_add_unique(h, k1, v4);
|
|
assert_return(r != 0, EXIT_FAILURE);
|
|
assert_return(hash_get_count(h) == 3, EXIT_FAILURE);
|
|
|
|
v = hash_find(h, "k1");
|
|
assert_return(streq(v, v1), EXIT_FAILURE);
|
|
|
|
assert_return(freecount == 0, EXIT_FAILURE);
|
|
|
|
hash_free(h);
|
|
return 0;
|
|
}
|
|
DEFINE_TEST(test_hash_replace_failing,
|
|
.description = "test hash_add_unique failing to replace existing value");
|
|
|
|
|
|
static int test_hash_iter(const struct test *t)
|
|
{
|
|
struct hash *h = hash_new(8, NULL);
|
|
struct hash *h2 = hash_new(8, NULL);
|
|
const char *k1 = "k1", *k2 = "k2", *k3 = "k3";
|
|
const char *v1 = "v1", *v2 = "v2", *v3 = "v3";
|
|
struct hash_iter iter;
|
|
const char *k, *v;
|
|
|
|
hash_add(h, k1, v1);
|
|
hash_add(h2, k1, v1);
|
|
hash_add(h, k2, v2);
|
|
hash_add(h2, k2, v2);
|
|
hash_add(h, k3, v3);
|
|
hash_add(h2, k3, v3);
|
|
|
|
for (hash_iter_init(h, &iter);
|
|
hash_iter_next(&iter, &k, (const void **) &v);) {
|
|
v2 = hash_find(h2, k);
|
|
assert_return(v2 != NULL, EXIT_FAILURE);
|
|
hash_del(h2, k);
|
|
}
|
|
|
|
assert_return(hash_get_count(h) == 3, EXIT_FAILURE);
|
|
assert_return(hash_get_count(h2) == 0, EXIT_FAILURE);
|
|
|
|
hash_free(h);
|
|
hash_free(h2);
|
|
return 0;
|
|
}
|
|
DEFINE_TEST(test_hash_iter,
|
|
.description = "test hash_iter");
|
|
|
|
|
|
static int test_hash_iter_after_del(const struct test *t)
|
|
{
|
|
struct hash *h = hash_new(8, NULL);
|
|
struct hash *h2 = hash_new(8, NULL);
|
|
const char *k1 = "k1", *k2 = "k2", *k3 = "k3";
|
|
const char *v1 = "v1", *v2 = "v2", *v3 = "v3";
|
|
struct hash_iter iter;
|
|
const char *k, *v;
|
|
|
|
hash_add(h, k1, v1);
|
|
hash_add(h2, k1, v1);
|
|
hash_add(h, k2, v2);
|
|
hash_add(h2, k2, v2);
|
|
hash_add(h, k3, v3);
|
|
hash_add(h2, k3, v3);
|
|
|
|
hash_del(h, k1);
|
|
|
|
for (hash_iter_init(h, &iter);
|
|
hash_iter_next(&iter, &k, (const void **) &v);) {
|
|
v2 = hash_find(h2, k);
|
|
assert_return(v2 != NULL, EXIT_FAILURE);
|
|
hash_del(h2, k);
|
|
}
|
|
|
|
assert_return(hash_get_count(h) == 2, EXIT_FAILURE);
|
|
assert_return(hash_get_count(h2) == 1, EXIT_FAILURE);
|
|
|
|
hash_free(h);
|
|
hash_free(h2);
|
|
return 0;
|
|
}
|
|
DEFINE_TEST(test_hash_iter_after_del,
|
|
.description = "test hash_iter, after deleting element");
|
|
|
|
|
|
static int test_hash_free(const struct test *t)
|
|
{
|
|
struct hash *h = hash_new(8, countfreecalls);
|
|
const char *k1 = "k1", *k2 = "k2", *k3 = "k3";
|
|
const char *v1 = "v1", *v2 = "v2", *v3 = "v3";
|
|
|
|
hash_add(h, k1, v1);
|
|
hash_add(h, k2, v2);
|
|
hash_add(h, k3, v3);
|
|
|
|
hash_del(h, k1);
|
|
|
|
assert_return(freecount == 1, EXIT_FAILURE);
|
|
|
|
assert_return(hash_get_count(h) == 2, EXIT_FAILURE);
|
|
|
|
hash_free(h);
|
|
|
|
assert_return(freecount == 3, EXIT_FAILURE);
|
|
|
|
return 0;
|
|
}
|
|
DEFINE_TEST(test_hash_free,
|
|
.description = "test hash_free calling free function for all values");
|
|
|
|
|
|
static int test_hash_add_unique(const struct test *t)
|
|
{
|
|
const char *k[] = { "k1", "k2", "k3", "k4", "k5" };
|
|
const char *v[] = { "v1", "v2", "v3", "v4", "v5" };
|
|
unsigned int i, j, N;
|
|
|
|
N = ARRAY_SIZE(k);
|
|
for (i = 0; i < N; i++) {
|
|
/* With N - 1 buckets, there'll be a bucket with more than one key. */
|
|
struct hash *h = hash_new(N - 1, NULL);
|
|
|
|
/* Add the keys in different orders. */
|
|
for (j = 0; j < N; j++) {
|
|
unsigned int idx = (j + i) % N;
|
|
hash_add_unique(h, k[idx], v[idx]);
|
|
}
|
|
|
|
assert_return(hash_get_count(h) == N, EXIT_FAILURE);
|
|
hash_free(h);
|
|
}
|
|
return 0;
|
|
}
|
|
DEFINE_TEST(test_hash_add_unique,
|
|
.description = "test hash_add_unique with different key orders")
|
|
|
|
|
|
static int test_hash_massive_add_del(const struct test *t)
|
|
{
|
|
char buf[1024 * 8];
|
|
char *k;
|
|
struct hash *h;
|
|
unsigned int i, N = 1024;
|
|
|
|
h = hash_new(8, NULL);
|
|
|
|
k = &buf[0];
|
|
for (i = 0; i < N; i++) {
|
|
snprintf(k, 8, "k%d", i);
|
|
hash_add(h, k, k);
|
|
k += 8;
|
|
}
|
|
|
|
assert_return(hash_get_count(h) == N, EXIT_FAILURE);
|
|
|
|
k = &buf[0];
|
|
for (i = 0; i < N; i++) {
|
|
hash_del(h, k);
|
|
k += 8;
|
|
}
|
|
|
|
assert_return(hash_get_count(h) == 0, EXIT_FAILURE);
|
|
|
|
hash_free(h);
|
|
return 0;
|
|
}
|
|
DEFINE_TEST(test_hash_massive_add_del,
|
|
.description = "test multiple adds followed by multiple dels")
|
|
|
|
TESTSUITE_MAIN();
|