xref: /netbsd-src/external/bsd/jemalloc/dist/test/unit/ql.c (revision 7bdf38e5b7a28439665f2fdeff81e36913eef7dd)
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