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