1 1.1 christos #include "test/jemalloc_test.h" 2 1.1 christos 3 1.1 christos #include "jemalloc/internal/ql.h" 4 1.1 christos 5 1.1 christos /* Number of ring entries, in [2..26]. */ 6 1.1 christos #define NENTRIES 9 7 1.1 christos 8 1.1 christos typedef struct list_s list_t; 9 1.1 christos typedef ql_head(list_t) list_head_t; 10 1.1 christos 11 1.1 christos struct list_s { 12 1.1 christos ql_elm(list_t) link; 13 1.1 christos char id; 14 1.1 christos }; 15 1.1 christos 16 1.1 christos static void 17 1.1 christos test_empty_list(list_head_t *head) { 18 1.1 christos list_t *t; 19 1.1 christos unsigned i; 20 1.1 christos 21 1.1.1.2 christos expect_true(ql_empty(head), "Unexpected element for empty list"); 22 1.1.1.2 christos expect_ptr_null(ql_first(head), "Unexpected element for empty list"); 23 1.1.1.2 christos expect_ptr_null(ql_last(head, link), 24 1.1 christos "Unexpected element for empty list"); 25 1.1 christos 26 1.1 christos i = 0; 27 1.1 christos ql_foreach(t, head, link) { 28 1.1 christos i++; 29 1.1 christos } 30 1.1.1.2 christos expect_u_eq(i, 0, "Unexpected element for empty list"); 31 1.1 christos 32 1.1 christos i = 0; 33 1.1 christos ql_reverse_foreach(t, head, link) { 34 1.1 christos i++; 35 1.1 christos } 36 1.1.1.2 christos expect_u_eq(i, 0, "Unexpected element for empty list"); 37 1.1 christos } 38 1.1 christos 39 1.1 christos TEST_BEGIN(test_ql_empty) { 40 1.1 christos list_head_t head; 41 1.1 christos 42 1.1 christos ql_new(&head); 43 1.1 christos test_empty_list(&head); 44 1.1 christos } 45 1.1 christos TEST_END 46 1.1 christos 47 1.1 christos static void 48 1.1 christos init_entries(list_t *entries, unsigned nentries) { 49 1.1 christos unsigned i; 50 1.1 christos 51 1.1 christos for (i = 0; i < nentries; i++) { 52 1.1 christos entries[i].id = 'a' + i; 53 1.1 christos ql_elm_new(&entries[i], link); 54 1.1 christos } 55 1.1 christos } 56 1.1 christos 57 1.1 christos static void 58 1.1 christos test_entries_list(list_head_t *head, list_t *entries, unsigned nentries) { 59 1.1 christos list_t *t; 60 1.1 christos unsigned i; 61 1.1 christos 62 1.1.1.2 christos expect_false(ql_empty(head), "List should not be empty"); 63 1.1.1.2 christos expect_c_eq(ql_first(head)->id, entries[0].id, "Element id mismatch"); 64 1.1.1.2 christos expect_c_eq(ql_last(head, link)->id, entries[nentries-1].id, 65 1.1 christos "Element id mismatch"); 66 1.1 christos 67 1.1 christos i = 0; 68 1.1 christos ql_foreach(t, head, link) { 69 1.1.1.2 christos expect_c_eq(t->id, entries[i].id, "Element id mismatch"); 70 1.1 christos i++; 71 1.1 christos } 72 1.1 christos 73 1.1 christos i = 0; 74 1.1 christos ql_reverse_foreach(t, head, link) { 75 1.1.1.2 christos expect_c_eq(t->id, entries[nentries-i-1].id, 76 1.1 christos "Element id mismatch"); 77 1.1 christos i++; 78 1.1 christos } 79 1.1 christos 80 1.1 christos for (i = 0; i < nentries-1; i++) { 81 1.1 christos t = ql_next(head, &entries[i], link); 82 1.1.1.2 christos expect_c_eq(t->id, entries[i+1].id, "Element id mismatch"); 83 1.1 christos } 84 1.1.1.2 christos expect_ptr_null(ql_next(head, &entries[nentries-1], link), 85 1.1 christos "Unexpected element"); 86 1.1 christos 87 1.1.1.2 christos expect_ptr_null(ql_prev(head, &entries[0], link), "Unexpected element"); 88 1.1 christos for (i = 1; i < nentries; i++) { 89 1.1 christos t = ql_prev(head, &entries[i], link); 90 1.1.1.2 christos expect_c_eq(t->id, entries[i-1].id, "Element id mismatch"); 91 1.1 christos } 92 1.1 christos } 93 1.1 christos 94 1.1 christos TEST_BEGIN(test_ql_tail_insert) { 95 1.1 christos list_head_t head; 96 1.1 christos list_t entries[NENTRIES]; 97 1.1 christos unsigned i; 98 1.1 christos 99 1.1 christos ql_new(&head); 100 1.1 christos init_entries(entries, sizeof(entries)/sizeof(list_t)); 101 1.1 christos for (i = 0; i < NENTRIES; i++) { 102 1.1 christos ql_tail_insert(&head, &entries[i], link); 103 1.1 christos } 104 1.1 christos 105 1.1 christos test_entries_list(&head, entries, NENTRIES); 106 1.1 christos } 107 1.1 christos TEST_END 108 1.1 christos 109 1.1 christos TEST_BEGIN(test_ql_tail_remove) { 110 1.1 christos list_head_t head; 111 1.1 christos list_t entries[NENTRIES]; 112 1.1 christos unsigned i; 113 1.1 christos 114 1.1 christos ql_new(&head); 115 1.1 christos init_entries(entries, sizeof(entries)/sizeof(list_t)); 116 1.1 christos for (i = 0; i < NENTRIES; i++) { 117 1.1 christos ql_tail_insert(&head, &entries[i], link); 118 1.1 christos } 119 1.1 christos 120 1.1 christos for (i = 0; i < NENTRIES; i++) { 121 1.1 christos test_entries_list(&head, entries, NENTRIES-i); 122 1.1 christos ql_tail_remove(&head, list_t, link); 123 1.1 christos } 124 1.1 christos test_empty_list(&head); 125 1.1 christos } 126 1.1 christos TEST_END 127 1.1 christos 128 1.1 christos TEST_BEGIN(test_ql_head_insert) { 129 1.1 christos list_head_t head; 130 1.1 christos list_t entries[NENTRIES]; 131 1.1 christos unsigned i; 132 1.1 christos 133 1.1 christos ql_new(&head); 134 1.1 christos init_entries(entries, sizeof(entries)/sizeof(list_t)); 135 1.1 christos for (i = 0; i < NENTRIES; i++) { 136 1.1 christos ql_head_insert(&head, &entries[NENTRIES-i-1], link); 137 1.1 christos } 138 1.1 christos 139 1.1 christos test_entries_list(&head, entries, NENTRIES); 140 1.1 christos } 141 1.1 christos TEST_END 142 1.1 christos 143 1.1 christos TEST_BEGIN(test_ql_head_remove) { 144 1.1 christos list_head_t head; 145 1.1 christos list_t entries[NENTRIES]; 146 1.1 christos unsigned i; 147 1.1 christos 148 1.1 christos ql_new(&head); 149 1.1 christos init_entries(entries, sizeof(entries)/sizeof(list_t)); 150 1.1 christos for (i = 0; i < NENTRIES; i++) { 151 1.1 christos ql_head_insert(&head, &entries[NENTRIES-i-1], link); 152 1.1 christos } 153 1.1 christos 154 1.1 christos for (i = 0; i < NENTRIES; i++) { 155 1.1 christos test_entries_list(&head, &entries[i], NENTRIES-i); 156 1.1 christos ql_head_remove(&head, list_t, link); 157 1.1 christos } 158 1.1 christos test_empty_list(&head); 159 1.1 christos } 160 1.1 christos TEST_END 161 1.1 christos 162 1.1 christos TEST_BEGIN(test_ql_insert) { 163 1.1 christos list_head_t head; 164 1.1 christos list_t entries[8]; 165 1.1 christos list_t *a, *b, *c, *d, *e, *f, *g, *h; 166 1.1 christos 167 1.1 christos ql_new(&head); 168 1.1 christos init_entries(entries, sizeof(entries)/sizeof(list_t)); 169 1.1 christos a = &entries[0]; 170 1.1 christos b = &entries[1]; 171 1.1 christos c = &entries[2]; 172 1.1 christos d = &entries[3]; 173 1.1 christos e = &entries[4]; 174 1.1 christos f = &entries[5]; 175 1.1 christos g = &entries[6]; 176 1.1 christos h = &entries[7]; 177 1.1 christos 178 1.1 christos /* 179 1.1 christos * ql_remove(), ql_before_insert(), and ql_after_insert() are used 180 1.1 christos * internally by other macros that are already tested, so there's no 181 1.1 christos * need to test them completely. However, insertion/deletion from the 182 1.1 christos * middle of lists is not otherwise tested; do so here. 183 1.1 christos */ 184 1.1 christos ql_tail_insert(&head, f, link); 185 1.1 christos ql_before_insert(&head, f, b, link); 186 1.1 christos ql_before_insert(&head, f, c, link); 187 1.1 christos ql_after_insert(f, h, link); 188 1.1 christos ql_after_insert(f, g, link); 189 1.1 christos ql_before_insert(&head, b, a, link); 190 1.1 christos ql_after_insert(c, d, link); 191 1.1 christos ql_before_insert(&head, f, e, link); 192 1.1 christos 193 1.1 christos test_entries_list(&head, entries, sizeof(entries)/sizeof(list_t)); 194 1.1 christos } 195 1.1 christos TEST_END 196 1.1 christos 197 1.1.1.2 christos static void 198 1.1.1.2 christos test_concat_split_entries(list_t *entries, unsigned nentries_a, 199 1.1.1.2 christos unsigned nentries_b) { 200 1.1.1.2 christos init_entries(entries, nentries_a + nentries_b); 201 1.1.1.2 christos 202 1.1.1.2 christos list_head_t head_a; 203 1.1.1.2 christos ql_new(&head_a); 204 1.1.1.2 christos for (unsigned i = 0; i < nentries_a; i++) { 205 1.1.1.2 christos ql_tail_insert(&head_a, &entries[i], link); 206 1.1.1.2 christos } 207 1.1.1.2 christos if (nentries_a == 0) { 208 1.1.1.2 christos test_empty_list(&head_a); 209 1.1.1.2 christos } else { 210 1.1.1.2 christos test_entries_list(&head_a, entries, nentries_a); 211 1.1.1.2 christos } 212 1.1.1.2 christos 213 1.1.1.2 christos list_head_t head_b; 214 1.1.1.2 christos ql_new(&head_b); 215 1.1.1.2 christos for (unsigned i = 0; i < nentries_b; i++) { 216 1.1.1.2 christos ql_tail_insert(&head_b, &entries[nentries_a + i], link); 217 1.1.1.2 christos } 218 1.1.1.2 christos if (nentries_b == 0) { 219 1.1.1.2 christos test_empty_list(&head_b); 220 1.1.1.2 christos } else { 221 1.1.1.2 christos test_entries_list(&head_b, entries + nentries_a, nentries_b); 222 1.1.1.2 christos } 223 1.1.1.2 christos 224 1.1.1.2 christos ql_concat(&head_a, &head_b, link); 225 1.1.1.2 christos if (nentries_a + nentries_b == 0) { 226 1.1.1.2 christos test_empty_list(&head_a); 227 1.1.1.2 christos } else { 228 1.1.1.2 christos test_entries_list(&head_a, entries, nentries_a + nentries_b); 229 1.1.1.2 christos } 230 1.1.1.2 christos test_empty_list(&head_b); 231 1.1.1.2 christos 232 1.1.1.2 christos if (nentries_b == 0) { 233 1.1.1.2 christos return; 234 1.1.1.2 christos } 235 1.1.1.2 christos 236 1.1.1.2 christos list_head_t head_c; 237 1.1.1.2 christos ql_split(&head_a, &entries[nentries_a], &head_c, link); 238 1.1.1.2 christos if (nentries_a == 0) { 239 1.1.1.2 christos test_empty_list(&head_a); 240 1.1.1.2 christos } else { 241 1.1.1.2 christos test_entries_list(&head_a, entries, nentries_a); 242 1.1.1.2 christos } 243 1.1.1.2 christos test_entries_list(&head_c, entries + nentries_a, nentries_b); 244 1.1.1.2 christos } 245 1.1.1.2 christos 246 1.1.1.2 christos TEST_BEGIN(test_ql_concat_split) { 247 1.1.1.2 christos list_t entries[NENTRIES]; 248 1.1.1.2 christos 249 1.1.1.2 christos test_concat_split_entries(entries, 0, 0); 250 1.1.1.2 christos 251 1.1.1.2 christos test_concat_split_entries(entries, 0, 1); 252 1.1.1.2 christos test_concat_split_entries(entries, 1, 0); 253 1.1.1.2 christos 254 1.1.1.2 christos test_concat_split_entries(entries, 0, NENTRIES); 255 1.1.1.2 christos test_concat_split_entries(entries, 1, NENTRIES - 1); 256 1.1.1.2 christos test_concat_split_entries(entries, NENTRIES / 2, 257 1.1.1.2 christos NENTRIES - NENTRIES / 2); 258 1.1.1.2 christos test_concat_split_entries(entries, NENTRIES - 1, 1); 259 1.1.1.2 christos test_concat_split_entries(entries, NENTRIES, 0); 260 1.1.1.2 christos } 261 1.1.1.2 christos TEST_END 262 1.1.1.2 christos 263 1.1.1.2 christos TEST_BEGIN(test_ql_rotate) { 264 1.1.1.2 christos list_head_t head; 265 1.1.1.2 christos list_t entries[NENTRIES]; 266 1.1.1.2 christos unsigned i; 267 1.1.1.2 christos 268 1.1.1.2 christos ql_new(&head); 269 1.1.1.2 christos init_entries(entries, sizeof(entries)/sizeof(list_t)); 270 1.1.1.2 christos for (i = 0; i < NENTRIES; i++) { 271 1.1.1.2 christos ql_tail_insert(&head, &entries[i], link); 272 1.1.1.2 christos } 273 1.1.1.2 christos 274 1.1.1.2 christos char head_id = ql_first(&head)->id; 275 1.1.1.2 christos for (i = 0; i < NENTRIES; i++) { 276 1.1.1.2 christos assert_c_eq(ql_first(&head)->id, head_id, ""); 277 1.1.1.2 christos ql_rotate(&head, link); 278 1.1.1.2 christos assert_c_eq(ql_last(&head, link)->id, head_id, ""); 279 1.1.1.2 christos head_id++; 280 1.1.1.2 christos } 281 1.1.1.2 christos test_entries_list(&head, entries, NENTRIES); 282 1.1.1.2 christos } 283 1.1.1.2 christos TEST_END 284 1.1.1.2 christos 285 1.1.1.2 christos TEST_BEGIN(test_ql_move) { 286 1.1.1.2 christos list_head_t head_dest, head_src; 287 1.1.1.2 christos list_t entries[NENTRIES]; 288 1.1.1.2 christos unsigned i; 289 1.1.1.2 christos 290 1.1.1.2 christos ql_new(&head_src); 291 1.1.1.2 christos ql_move(&head_dest, &head_src); 292 1.1.1.2 christos test_empty_list(&head_src); 293 1.1.1.2 christos test_empty_list(&head_dest); 294 1.1.1.2 christos 295 1.1.1.2 christos init_entries(entries, sizeof(entries)/sizeof(list_t)); 296 1.1.1.2 christos for (i = 0; i < NENTRIES; i++) { 297 1.1.1.2 christos ql_tail_insert(&head_src, &entries[i], link); 298 1.1.1.2 christos } 299 1.1.1.2 christos ql_move(&head_dest, &head_src); 300 1.1.1.2 christos test_empty_list(&head_src); 301 1.1.1.2 christos test_entries_list(&head_dest, entries, NENTRIES); 302 1.1.1.2 christos } 303 1.1.1.2 christos TEST_END 304 1.1.1.2 christos 305 1.1 christos int 306 1.1 christos main(void) { 307 1.1 christos return test( 308 1.1 christos test_ql_empty, 309 1.1 christos test_ql_tail_insert, 310 1.1 christos test_ql_tail_remove, 311 1.1 christos test_ql_head_insert, 312 1.1 christos test_ql_head_remove, 313 1.1.1.2 christos test_ql_insert, 314 1.1.1.2 christos test_ql_concat_split, 315 1.1.1.2 christos test_ql_rotate, 316 1.1.1.2 christos test_ql_move); 317 1.1 christos } 318