Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/lib/tests/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 8 kB image not shown  

Quelle  hashtable_test.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * KUnit test for the Kernel Hashtable structures.
 *
 * Copyright (C) 2022, Google LLC.
 * Author: Rae Moar <rmoar@google.com>
 */

#include <kunit/test.h>

#include <linux/hashtable.h>

struct hashtable_test_entry {
 int key;
 int data;
 struct hlist_node node;
 int visited;
};

static void hashtable_test_hash_init(struct kunit *test)
{
 /* Test the different ways of initialising a hashtable. */
 DEFINE_HASHTABLE(hash1, 2);
 DECLARE_HASHTABLE(hash2, 3);

 /* When using DECLARE_HASHTABLE, must use hash_init to
 * initialize the hashtable.
 */

 hash_init(hash2);

 KUNIT_EXPECT_TRUE(test, hash_empty(hash1));
 KUNIT_EXPECT_TRUE(test, hash_empty(hash2));
}

static void hashtable_test_hash_empty(struct kunit *test)
{
 struct hashtable_test_entry a;
 DEFINE_HASHTABLE(hash, 1);

 KUNIT_EXPECT_TRUE(test, hash_empty(hash));

 a.key = 1;
 a.data = 13;
 hash_add(hash, &a.node, a.key);

 /* Hashtable should no longer be empty. */
 KUNIT_EXPECT_FALSE(test, hash_empty(hash));
}

static void hashtable_test_hash_hashed(struct kunit *test)
{
 struct hashtable_test_entry a, b;
 DEFINE_HASHTABLE(hash, 4);

 a.key = 1;
 a.data = 13;
 hash_add(hash, &a.node, a.key);
 b.key = 1;
 b.data = 2;
 hash_add(hash, &b.node, b.key);

 KUNIT_EXPECT_TRUE(test, hash_hashed(&a.node));
 KUNIT_EXPECT_TRUE(test, hash_hashed(&b.node));
}

static void hashtable_test_hash_add(struct kunit *test)
{
 struct hashtable_test_entry a, b, *x;
 int bkt;
 DEFINE_HASHTABLE(hash, 3);

 a.key = 1;
 a.data = 13;
 a.visited = 0;
 hash_add(hash, &a.node, a.key);
 b.key = 2;
 b.data = 10;
 b.visited = 0;
 hash_add(hash, &b.node, b.key);

 hash_for_each(hash, bkt, x, node) {
  x->visited++;
  if (x->key == a.key)
   KUNIT_EXPECT_EQ(test, x->data, 13);
  else if (x->key == b.key)
   KUNIT_EXPECT_EQ(test, x->data, 10);
  else
   KUNIT_FAIL(test, "Unexpected key in hashtable.");
 }

 /* Both entries should have been visited exactly once. */
 KUNIT_EXPECT_EQ(test, a.visited, 1);
 KUNIT_EXPECT_EQ(test, b.visited, 1);
}

static void hashtable_test_hash_del(struct kunit *test)
{
 struct hashtable_test_entry a, b, *x;
 DEFINE_HASHTABLE(hash, 6);

 a.key = 1;
 a.data = 13;
 hash_add(hash, &a.node, a.key);
 b.key = 2;
 b.data = 10;
 b.visited = 0;
 hash_add(hash, &b.node, b.key);

 hash_del(&b.node);
 hash_for_each_possible(hash, x, node, b.key) {
  x->visited++;
  KUNIT_EXPECT_NE(test, x->key, b.key);
 }

 /* The deleted entry should not have been visited. */
 KUNIT_EXPECT_EQ(test, b.visited, 0);

 hash_del(&a.node);

 /* The hashtable should be empty. */
 KUNIT_EXPECT_TRUE(test, hash_empty(hash));
}

static void hashtable_test_hash_for_each(struct kunit *test)
{
 struct hashtable_test_entry entries[3];
 struct hashtable_test_entry *x;
 int bkt, i, j, count;
 DEFINE_HASHTABLE(hash, 3);

 /* Add three entries to the hashtable. */
 for (i = 0; i < 3; i++) {
  entries[i].key = i;
  entries[i].data = i + 10;
  entries[i].visited = 0;
  hash_add(hash, &entries[i].node, entries[i].key);
 }

 count = 0;
 hash_for_each(hash, bkt, x, node) {
  x->visited += 1;
  KUNIT_ASSERT_GE_MSG(test, x->key, 0, "Unexpected key in hashtable.");
  KUNIT_ASSERT_LT_MSG(test, x->key, 3, "Unexpected key in hashtable.");
  count++;
 }

 /* Should have visited each entry exactly once. */
 KUNIT_EXPECT_EQ(test, count, 3);
 for (j = 0; j < 3; j++)
  KUNIT_EXPECT_EQ(test, entries[j].visited, 1);
}

static void hashtable_test_hash_for_each_safe(struct kunit *test)
{
 struct hashtable_test_entry entries[3];
 struct hashtable_test_entry *x;
 struct hlist_node *tmp;
 int bkt, i, j, count;
 DEFINE_HASHTABLE(hash, 3);

 /* Add three entries to the hashtable. */
 for (i = 0; i < 3; i++) {
  entries[i].key = i;
  entries[i].data = i + 10;
  entries[i].visited = 0;
  hash_add(hash, &entries[i].node, entries[i].key);
 }

 count = 0;
 hash_for_each_safe(hash, bkt, tmp, x, node) {
  x->visited += 1;
  KUNIT_ASSERT_GE_MSG(test, x->key, 0, "Unexpected key in hashtable.");
  KUNIT_ASSERT_LT_MSG(test, x->key, 3, "Unexpected key in hashtable.");
  count++;

  /* Delete entry during loop. */
  hash_del(&x->node);
 }

 /* Should have visited each entry exactly once. */
 KUNIT_EXPECT_EQ(test, count, 3);
 for (j = 0; j < 3; j++)
  KUNIT_EXPECT_EQ(test, entries[j].visited, 1);
}

static void hashtable_test_hash_for_each_possible(struct kunit *test)
{
 struct hashtable_test_entry entries[4];
 struct hashtable_test_entry *x, *y;
 int buckets[2];
 int bkt, i, j, count;
 DEFINE_HASHTABLE(hash, 5);

 /* Add three entries with key = 0 to the hashtable. */
 for (i = 0; i < 3; i++) {
  entries[i].key = 0;
  entries[i].data = i;
  entries[i].visited = 0;
  hash_add(hash, &entries[i].node, entries[i].key);
 }

 /* Add an entry with key = 1. */
 entries[3].key = 1;
 entries[3].data = 3;
 entries[3].visited = 0;
 hash_add(hash, &entries[3].node, entries[3].key);

 count = 0;
 hash_for_each_possible(hash, x, node, 0) {
  x->visited += 1;
  KUNIT_ASSERT_GE_MSG(test, x->data, 0, "Unexpected data in hashtable.");
  KUNIT_ASSERT_LT_MSG(test, x->data, 4, "Unexpected data in hashtable.");
  count++;
 }

 /* Should have visited each entry with key = 0 exactly once. */
 for (j = 0; j < 3; j++)
  KUNIT_EXPECT_EQ(test, entries[j].visited, 1);

 /* Save the buckets for the different keys. */
 hash_for_each(hash, bkt, y, node) {
  KUNIT_ASSERT_GE_MSG(test, y->key, 0, "Unexpected key in hashtable.");
  KUNIT_ASSERT_LE_MSG(test, y->key, 1, "Unexpected key in hashtable.");
  buckets[y->key] = bkt;
 }

 /* If entry with key = 1 is in the same bucket as the entries with
 * key = 0, check it was visited. Otherwise ensure that only three
 * entries were visited.
 */

 if (buckets[0] == buckets[1]) {
  KUNIT_EXPECT_EQ(test, count, 4);
  KUNIT_EXPECT_EQ(test, entries[3].visited, 1);
 } else {
  KUNIT_EXPECT_EQ(test, count, 3);
  KUNIT_EXPECT_EQ(test, entries[3].visited, 0);
 }
}

static void hashtable_test_hash_for_each_possible_safe(struct kunit *test)
{
 struct hashtable_test_entry entries[4];
 struct hashtable_test_entry *x, *y;
 struct hlist_node *tmp;
 int buckets[2];
 int bkt, i, j, count;
 DEFINE_HASHTABLE(hash, 5);

 /* Add three entries with key = 0 to the hashtable. */
 for (i = 0; i < 3; i++) {
  entries[i].key = 0;
  entries[i].data = i;
  entries[i].visited = 0;
  hash_add(hash, &entries[i].node, entries[i].key);
 }

 /* Add an entry with key = 1. */
 entries[3].key = 1;
 entries[3].data = 3;
 entries[3].visited = 0;
 hash_add(hash, &entries[3].node, entries[3].key);

 count = 0;
 hash_for_each_possible_safe(hash, x, tmp, node, 0) {
  x->visited += 1;
  KUNIT_ASSERT_GE_MSG(test, x->data, 0, "Unexpected data in hashtable.");
  KUNIT_ASSERT_LT_MSG(test, x->data, 4, "Unexpected data in hashtable.");
  count++;

  /* Delete entry during loop. */
  hash_del(&x->node);
 }

 /* Should have visited each entry with key = 0 exactly once. */
 for (j = 0; j < 3; j++)
  KUNIT_EXPECT_EQ(test, entries[j].visited, 1);

 /* Save the buckets for the different keys. */
 hash_for_each(hash, bkt, y, node) {
  KUNIT_ASSERT_GE_MSG(test, y->key, 0, "Unexpected key in hashtable.");
  KUNIT_ASSERT_LE_MSG(test, y->key, 1, "Unexpected key in hashtable.");
  buckets[y->key] = bkt;
 }

 /* If entry with key = 1 is in the same bucket as the entries with
 * key = 0, check it was visited. Otherwise ensure that only three
 * entries were visited.
 */

 if (buckets[0] == buckets[1]) {
  KUNIT_EXPECT_EQ(test, count, 4);
  KUNIT_EXPECT_EQ(test, entries[3].visited, 1);
 } else {
  KUNIT_EXPECT_EQ(test, count, 3);
  KUNIT_EXPECT_EQ(test, entries[3].visited, 0);
 }
}

static struct kunit_case hashtable_test_cases[] = {
 KUNIT_CASE(hashtable_test_hash_init),
 KUNIT_CASE(hashtable_test_hash_empty),
 KUNIT_CASE(hashtable_test_hash_hashed),
 KUNIT_CASE(hashtable_test_hash_add),
 KUNIT_CASE(hashtable_test_hash_del),
 KUNIT_CASE(hashtable_test_hash_for_each),
 KUNIT_CASE(hashtable_test_hash_for_each_safe),
 KUNIT_CASE(hashtable_test_hash_for_each_possible),
 KUNIT_CASE(hashtable_test_hash_for_each_possible_safe),
 {},
};

static struct kunit_suite hashtable_test_module = {
 .name = "hashtable",
 .test_cases = hashtable_test_cases,
};

kunit_test_suites(&hashtable_test_module);

MODULE_DESCRIPTION("KUnit test for the Kernel Hashtable structures");
MODULE_LICENSE("GPL");

Messung V0.5
C=94 H=93 G=93

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.