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 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 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 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 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 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 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 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 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