Home | History | Annotate | Line # | Download | only in unit
      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