~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/lib/hashtable_test.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * KUnit test for the Kernel Hashtable structures.
  4  *
  5  * Copyright (C) 2022, Google LLC.
  6  * Author: Rae Moar <rmoar@google.com>
  7  */
  8 #include <kunit/test.h>
  9 
 10 #include <linux/hashtable.h>
 11 
 12 struct hashtable_test_entry {
 13         int key;
 14         int data;
 15         struct hlist_node node;
 16         int visited;
 17 };
 18 
 19 static void hashtable_test_hash_init(struct kunit *test)
 20 {
 21         /* Test the different ways of initialising a hashtable. */
 22         DEFINE_HASHTABLE(hash1, 2);
 23         DECLARE_HASHTABLE(hash2, 3);
 24 
 25         /* When using DECLARE_HASHTABLE, must use hash_init to
 26          * initialize the hashtable.
 27          */
 28         hash_init(hash2);
 29 
 30         KUNIT_EXPECT_TRUE(test, hash_empty(hash1));
 31         KUNIT_EXPECT_TRUE(test, hash_empty(hash2));
 32 }
 33 
 34 static void hashtable_test_hash_empty(struct kunit *test)
 35 {
 36         struct hashtable_test_entry a;
 37         DEFINE_HASHTABLE(hash, 1);
 38 
 39         KUNIT_EXPECT_TRUE(test, hash_empty(hash));
 40 
 41         a.key = 1;
 42         a.data = 13;
 43         hash_add(hash, &a.node, a.key);
 44 
 45         /* Hashtable should no longer be empty. */
 46         KUNIT_EXPECT_FALSE(test, hash_empty(hash));
 47 }
 48 
 49 static void hashtable_test_hash_hashed(struct kunit *test)
 50 {
 51         struct hashtable_test_entry a, b;
 52         DEFINE_HASHTABLE(hash, 4);
 53 
 54         a.key = 1;
 55         a.data = 13;
 56         hash_add(hash, &a.node, a.key);
 57         b.key = 1;
 58         b.data = 2;
 59         hash_add(hash, &b.node, b.key);
 60 
 61         KUNIT_EXPECT_TRUE(test, hash_hashed(&a.node));
 62         KUNIT_EXPECT_TRUE(test, hash_hashed(&b.node));
 63 }
 64 
 65 static void hashtable_test_hash_add(struct kunit *test)
 66 {
 67         struct hashtable_test_entry a, b, *x;
 68         int bkt;
 69         DEFINE_HASHTABLE(hash, 3);
 70 
 71         a.key = 1;
 72         a.data = 13;
 73         a.visited = 0;
 74         hash_add(hash, &a.node, a.key);
 75         b.key = 2;
 76         b.data = 10;
 77         b.visited = 0;
 78         hash_add(hash, &b.node, b.key);
 79 
 80         hash_for_each(hash, bkt, x, node) {
 81                 x->visited++;
 82                 if (x->key == a.key)
 83                         KUNIT_EXPECT_EQ(test, x->data, 13);
 84                 else if (x->key == b.key)
 85                         KUNIT_EXPECT_EQ(test, x->data, 10);
 86                 else
 87                         KUNIT_FAIL(test, "Unexpected key in hashtable.");
 88         }
 89 
 90         /* Both entries should have been visited exactly once. */
 91         KUNIT_EXPECT_EQ(test, a.visited, 1);
 92         KUNIT_EXPECT_EQ(test, b.visited, 1);
 93 }
 94 
 95 static void hashtable_test_hash_del(struct kunit *test)
 96 {
 97         struct hashtable_test_entry a, b, *x;
 98         DEFINE_HASHTABLE(hash, 6);
 99 
100         a.key = 1;
101         a.data = 13;
102         hash_add(hash, &a.node, a.key);
103         b.key = 2;
104         b.data = 10;
105         b.visited = 0;
106         hash_add(hash, &b.node, b.key);
107 
108         hash_del(&b.node);
109         hash_for_each_possible(hash, x, node, b.key) {
110                 x->visited++;
111                 KUNIT_EXPECT_NE(test, x->key, b.key);
112         }
113 
114         /* The deleted entry should not have been visited. */
115         KUNIT_EXPECT_EQ(test, b.visited, 0);
116 
117         hash_del(&a.node);
118 
119         /* The hashtable should be empty. */
120         KUNIT_EXPECT_TRUE(test, hash_empty(hash));
121 }
122 
123 static void hashtable_test_hash_for_each(struct kunit *test)
124 {
125         struct hashtable_test_entry entries[3];
126         struct hashtable_test_entry *x;
127         int bkt, i, j, count;
128         DEFINE_HASHTABLE(hash, 3);
129 
130         /* Add three entries to the hashtable. */
131         for (i = 0; i < 3; i++) {
132                 entries[i].key = i;
133                 entries[i].data = i + 10;
134                 entries[i].visited = 0;
135                 hash_add(hash, &entries[i].node, entries[i].key);
136         }
137 
138         count = 0;
139         hash_for_each(hash, bkt, x, node) {
140                 x->visited += 1;
141                 KUNIT_ASSERT_GE_MSG(test, x->key, 0, "Unexpected key in hashtable.");
142                 KUNIT_ASSERT_LT_MSG(test, x->key, 3, "Unexpected key in hashtable.");
143                 count++;
144         }
145 
146         /* Should have visited each entry exactly once. */
147         KUNIT_EXPECT_EQ(test, count, 3);
148         for (j = 0; j < 3; j++)
149                 KUNIT_EXPECT_EQ(test, entries[j].visited, 1);
150 }
151 
152 static void hashtable_test_hash_for_each_safe(struct kunit *test)
153 {
154         struct hashtable_test_entry entries[3];
155         struct hashtable_test_entry *x;
156         struct hlist_node *tmp;
157         int bkt, i, j, count;
158         DEFINE_HASHTABLE(hash, 3);
159 
160         /* Add three entries to the hashtable. */
161         for (i = 0; i < 3; i++) {
162                 entries[i].key = i;
163                 entries[i].data = i + 10;
164                 entries[i].visited = 0;
165                 hash_add(hash, &entries[i].node, entries[i].key);
166         }
167 
168         count = 0;
169         hash_for_each_safe(hash, bkt, tmp, x, node) {
170                 x->visited += 1;
171                 KUNIT_ASSERT_GE_MSG(test, x->key, 0, "Unexpected key in hashtable.");
172                 KUNIT_ASSERT_LT_MSG(test, x->key, 3, "Unexpected key in hashtable.");
173                 count++;
174 
175                 /* Delete entry during loop. */
176                 hash_del(&x->node);
177         }
178 
179         /* Should have visited each entry exactly once. */
180         KUNIT_EXPECT_EQ(test, count, 3);
181         for (j = 0; j < 3; j++)
182                 KUNIT_EXPECT_EQ(test, entries[j].visited, 1);
183 }
184 
185 static void hashtable_test_hash_for_each_possible(struct kunit *test)
186 {
187         struct hashtable_test_entry entries[4];
188         struct hashtable_test_entry *x, *y;
189         int buckets[2];
190         int bkt, i, j, count;
191         DEFINE_HASHTABLE(hash, 5);
192 
193         /* Add three entries with key = 0 to the hashtable. */
194         for (i = 0; i < 3; i++) {
195                 entries[i].key = 0;
196                 entries[i].data = i;
197                 entries[i].visited = 0;
198                 hash_add(hash, &entries[i].node, entries[i].key);
199         }
200 
201         /* Add an entry with key = 1. */
202         entries[3].key = 1;
203         entries[3].data = 3;
204         entries[3].visited = 0;
205         hash_add(hash, &entries[3].node, entries[3].key);
206 
207         count = 0;
208         hash_for_each_possible(hash, x, node, 0) {
209                 x->visited += 1;
210                 KUNIT_ASSERT_GE_MSG(test, x->data, 0, "Unexpected data in hashtable.");
211                 KUNIT_ASSERT_LT_MSG(test, x->data, 4, "Unexpected data in hashtable.");
212                 count++;
213         }
214 
215         /* Should have visited each entry with key = 0 exactly once. */
216         for (j = 0; j < 3; j++)
217                 KUNIT_EXPECT_EQ(test, entries[j].visited, 1);
218 
219         /* Save the buckets for the different keys. */
220         hash_for_each(hash, bkt, y, node) {
221                 KUNIT_ASSERT_GE_MSG(test, y->key, 0, "Unexpected key in hashtable.");
222                 KUNIT_ASSERT_LE_MSG(test, y->key, 1, "Unexpected key in hashtable.");
223                 buckets[y->key] = bkt;
224         }
225 
226         /* If entry with key = 1 is in the same bucket as the entries with
227          * key = 0, check it was visited. Otherwise ensure that only three
228          * entries were visited.
229          */
230         if (buckets[0] == buckets[1]) {
231                 KUNIT_EXPECT_EQ(test, count, 4);
232                 KUNIT_EXPECT_EQ(test, entries[3].visited, 1);
233         } else {
234                 KUNIT_EXPECT_EQ(test, count, 3);
235                 KUNIT_EXPECT_EQ(test, entries[3].visited, 0);
236         }
237 }
238 
239 static void hashtable_test_hash_for_each_possible_safe(struct kunit *test)
240 {
241         struct hashtable_test_entry entries[4];
242         struct hashtable_test_entry *x, *y;
243         struct hlist_node *tmp;
244         int buckets[2];
245         int bkt, i, j, count;
246         DEFINE_HASHTABLE(hash, 5);
247 
248         /* Add three entries with key = 0 to the hashtable. */
249         for (i = 0; i < 3; i++) {
250                 entries[i].key = 0;
251                 entries[i].data = i;
252                 entries[i].visited = 0;
253                 hash_add(hash, &entries[i].node, entries[i].key);
254         }
255 
256         /* Add an entry with key = 1. */
257         entries[3].key = 1;
258         entries[3].data = 3;
259         entries[3].visited = 0;
260         hash_add(hash, &entries[3].node, entries[3].key);
261 
262         count = 0;
263         hash_for_each_possible_safe(hash, x, tmp, node, 0) {
264                 x->visited += 1;
265                 KUNIT_ASSERT_GE_MSG(test, x->data, 0, "Unexpected data in hashtable.");
266                 KUNIT_ASSERT_LT_MSG(test, x->data, 4, "Unexpected data in hashtable.");
267                 count++;
268 
269                 /* Delete entry during loop. */
270                 hash_del(&x->node);
271         }
272 
273         /* Should have visited each entry with key = 0 exactly once. */
274         for (j = 0; j < 3; j++)
275                 KUNIT_EXPECT_EQ(test, entries[j].visited, 1);
276 
277         /* Save the buckets for the different keys. */
278         hash_for_each(hash, bkt, y, node) {
279                 KUNIT_ASSERT_GE_MSG(test, y->key, 0, "Unexpected key in hashtable.");
280                 KUNIT_ASSERT_LE_MSG(test, y->key, 1, "Unexpected key in hashtable.");
281                 buckets[y->key] = bkt;
282         }
283 
284         /* If entry with key = 1 is in the same bucket as the entries with
285          * key = 0, check it was visited. Otherwise ensure that only three
286          * entries were visited.
287          */
288         if (buckets[0] == buckets[1]) {
289                 KUNIT_EXPECT_EQ(test, count, 4);
290                 KUNIT_EXPECT_EQ(test, entries[3].visited, 1);
291         } else {
292                 KUNIT_EXPECT_EQ(test, count, 3);
293                 KUNIT_EXPECT_EQ(test, entries[3].visited, 0);
294         }
295 }
296 
297 static struct kunit_case hashtable_test_cases[] = {
298         KUNIT_CASE(hashtable_test_hash_init),
299         KUNIT_CASE(hashtable_test_hash_empty),
300         KUNIT_CASE(hashtable_test_hash_hashed),
301         KUNIT_CASE(hashtable_test_hash_add),
302         KUNIT_CASE(hashtable_test_hash_del),
303         KUNIT_CASE(hashtable_test_hash_for_each),
304         KUNIT_CASE(hashtable_test_hash_for_each_safe),
305         KUNIT_CASE(hashtable_test_hash_for_each_possible),
306         KUNIT_CASE(hashtable_test_hash_for_each_possible_safe),
307         {},
308 };
309 
310 static struct kunit_suite hashtable_test_module = {
311         .name = "hashtable",
312         .test_cases = hashtable_test_cases,
313 };
314 
315 kunit_test_suites(&hashtable_test_module);
316 
317 MODULE_DESCRIPTION("KUnit test for the Kernel Hashtable structures");
318 MODULE_LICENSE("GPL");
319 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php