1 /*
2 * Copyright (c) 2019 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #include "qdf_ptr_hash.h"
21 #include "qdf_ptr_hash_test.h"
22 #include "qdf_trace.h"
23
24 #define qdf_ptr_hash_bits 4 /* 16 buckets */
25 #define qdf_ptr_hash_entry_count 10
26
27 struct qdf_ptr_hash_test_item {
28 uint32_t id;
29 struct qdf_ptr_hash_entry entry;
30 };
31
__qdf_ptr_hash_test_empty(struct qdf_ptr_hash * ht)32 static uint32_t __qdf_ptr_hash_test_empty(struct qdf_ptr_hash *ht)
33 {
34 struct qdf_ptr_hash_test_item *item;
35
36 /* a new ptr_hash should ... */
37
38 /* ... be empty */
39 QDF_BUG(qdf_ptr_hash_empty(ht));
40
41 /* ... return NULL with get()'d */
42 QDF_BUG(!qdf_ptr_hash_get(ht, NULL, item, entry));
43
44 return 0;
45 }
46
qdf_ptr_hash_test_empty(void)47 static uint32_t qdf_ptr_hash_test_empty(void)
48 {
49 qdf_ptr_hash_declare_ptr(ht, qdf_ptr_hash_bits);
50 int errors;
51
52 qdf_ptr_hash_init(ht);
53 errors = __qdf_ptr_hash_test_empty(ht);
54 qdf_ptr_hash_deinit(ht);
55
56 return errors;
57 }
58
__qdf_ptr_hash_test_add_remove(struct qdf_ptr_hash * ht)59 static uint32_t __qdf_ptr_hash_test_add_remove(struct qdf_ptr_hash *ht)
60 {
61 struct qdf_ptr_hash_test_item items[qdf_ptr_hash_entry_count];
62 struct qdf_ptr_hash_test_item *item;
63 int i;
64
65 /* a ptr_hash with items should ... */
66 for (i = 0; i < qdf_ptr_hash_entry_count; i++) {
67 items[i].id = i;
68 qdf_ptr_hash_add(ht, &items[i], &items[i], entry);
69 }
70
71 /* ... not be empty */
72 QDF_BUG(!qdf_ptr_hash_empty(ht));
73
74 /* ... be able to get() all items previously add()'d */
75 for (i = 0; i < qdf_ptr_hash_entry_count; i++) {
76 QDF_BUG(qdf_ptr_hash_get(ht, &items[i], item, entry));
77 QDF_BUG(item->id == items[i].id);
78 }
79
80 /* ... be able to remove() all items previously add()'d */
81 for (i = 0; i < qdf_ptr_hash_entry_count; i++) {
82 QDF_BUG(qdf_ptr_hash_remove(ht, &items[i], item, entry));
83 QDF_BUG(item->id == items[i].id);
84 }
85
86 /* ... be empty after remove()'ing all items */
87 QDF_BUG(qdf_ptr_hash_empty(ht));
88
89 return 0;
90 }
91
qdf_ptr_hash_test_add_remove(void)92 static uint32_t qdf_ptr_hash_test_add_remove(void)
93 {
94 qdf_ptr_hash_declare_ptr(ht, qdf_ptr_hash_bits);
95 int errors;
96
97 qdf_ptr_hash_init(ht);
98 errors = __qdf_ptr_hash_test_add_remove(ht);
99 qdf_ptr_hash_deinit(ht);
100
101 return errors;
102 }
103
__qdf_ptr_hash_test_for_each(struct qdf_ptr_hash * ht)104 static uint32_t __qdf_ptr_hash_test_for_each(struct qdf_ptr_hash *ht)
105 {
106 struct qdf_ptr_hash_bucket *bucket;
107 struct qdf_ptr_hash_test_item items[qdf_ptr_hash_entry_count];
108 struct qdf_ptr_hash_test_item *item;
109 int i;
110 int count;
111
112 /* a ptr_hash with items should ... */
113 for (i = 0; i < qdf_ptr_hash_entry_count; i++) {
114 items[i].id = i;
115 qdf_ptr_hash_add(ht, i, &items[i], entry);
116 }
117
118 /* ... be able to iterate over each item */
119 count = 0;
120 qdf_ptr_hash_for_each(ht, bucket, item, entry) {
121 QDF_BUG(item->id == items[item->id].id);
122 count++;
123 }
124 QDF_BUG(count == qdf_ptr_hash_entry_count);
125
126 /* ... be able to iterate by hash value */
127 count = 0;
128 for (i = 0; i < qdf_ptr_hash_entry_count; i++) {
129 qdf_ptr_hash_for_each_by_hash(ht, i, item, entry) {
130 QDF_BUG(item->id == items[item->id].id);
131 count++;
132 }
133 }
134 QDF_BUG(count >= qdf_ptr_hash_entry_count);
135
136 /* ... be able to iterate by key value */
137 for (i = 0; i < qdf_ptr_hash_entry_count; i++) {
138 count = 0;
139 qdf_ptr_hash_for_each_by_key(ht, i, item, entry) {
140 QDF_BUG(item->id == items[i].id);
141 count++;
142 }
143 QDF_BUG(count == 1);
144 }
145
146 /* ... be able to remove each item */
147 for (i = 0; i < qdf_ptr_hash_entry_count; i++) {
148 qdf_ptr_hash_remove(ht, i, item, entry);
149 QDF_BUG(item);
150 QDF_BUG(item->id == items[i].id);
151 }
152
153 /* ... be empty after all items are removed */
154 QDF_BUG(qdf_ptr_hash_empty(ht));
155
156 return 0;
157 }
158
qdf_ptr_hash_test_for_each(void)159 static uint32_t qdf_ptr_hash_test_for_each(void)
160 {
161 qdf_ptr_hash_declare_ptr(ht, qdf_ptr_hash_bits);
162 int errors;
163
164 qdf_ptr_hash_init(ht);
165 errors = __qdf_ptr_hash_test_for_each(ht);
166 qdf_ptr_hash_deinit(ht);
167
168 return errors;
169 }
170
qdf_ptr_hash_test_create_destroy(void)171 static uint32_t qdf_ptr_hash_test_create_destroy(void)
172 {
173 struct qdf_ptr_hash *ht = qdf_ptr_hash_create(qdf_ptr_hash_bits);
174 uint32_t errors = 0;
175
176 QDF_BUG(ht);
177 errors += __qdf_ptr_hash_test_empty(ht);
178 errors += __qdf_ptr_hash_test_add_remove(ht);
179 errors += __qdf_ptr_hash_test_for_each(ht);
180
181 qdf_ptr_hash_destroy(ht);
182
183 return errors;
184 }
185
qdf_ptr_hash_unit_test(void)186 uint32_t qdf_ptr_hash_unit_test(void)
187 {
188 uint32_t errors = 0;
189
190 errors += qdf_ptr_hash_test_empty();
191 errors += qdf_ptr_hash_test_add_remove();
192 errors += qdf_ptr_hash_test_for_each();
193 errors += qdf_ptr_hash_test_create_destroy();
194
195 return errors;
196 }
197
198