]> git.proxmox.com Git - mirror_spl.git/blame - modules/splat/splat-list.c
Add 5 splat tests for list handling
[mirror_spl.git] / modules / splat / splat-list.c
CommitLineData
d702c04f
BB
1/*
2 * This file is part of the SPL: Solaris Porting Layer.
3 *
4 * Copyright (c) 2008 Lawrence Livermore National Security, LLC.
5 * Produced at Lawrence Livermore National Laboratory
6 * Written by:
7 * Brian Behlendorf <behlendorf1@llnl.gov>,
8 * Herb Wartens <wartens2@llnl.gov>,
9 * Jim Garlick <garlick@llnl.gov>
10 * UCRL-CODE-235197
11 *
12 * This is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 */
26
27#include "splat-internal.h"
28
29#define SPLAT_SUBSYSTEM_LIST 0x0c00
30#define SPLAT_LIST_NAME "list"
31#define SPLAT_LIST_DESC "Kernel List Tests"
32
33#define SPLAT_LIST_TEST1_ID 0x0c01
34#define SPLAT_LIST_TEST1_NAME "create/destroy"
35#define SPLAT_LIST_TEST1_DESC "Create/destroy Test"
36
37#define SPLAT_LIST_TEST2_ID 0x0c02
38#define SPLAT_LIST_TEST2_NAME "insert/remove head"
39#define SPLAT_LIST_TEST2_DESC "Insert/remove head Test"
40
41#define SPLAT_LIST_TEST3_ID 0x0c03
42#define SPLAT_LIST_TEST3_NAME "insert/remove tail"
43#define SPLAT_LIST_TEST3_DESC "Insert/remove tail Test"
44
45#define SPLAT_LIST_TEST4_ID 0x0c04
46#define SPLAT_LIST_TEST4_NAME "insert_after"
47#define SPLAT_LIST_TEST4_DESC "Insert_after Test"
48
49#define SPLAT_LIST_TEST5_ID 0x0c05
50#define SPLAT_LIST_TEST5_NAME "insert_before"
51#define SPLAT_LIST_TEST5_DESC "Insert_before Test"
52
53#define SPLAT_LIST_TEST6_ID 0x0c06
54#define SPLAT_LIST_TEST6_NAME "remove"
55#define SPLAT_LIST_TEST6_DESC "Remove Test"
56
57
58/* It is important that li_node is not the first element, this
59 * ensures the list_d2l/list_object macros are working correctly. */
60typedef struct list_item {
61 int li_data;
62 list_node_t li_node;
63} list_item_t;
64
65#define LIST_ORDER_STACK 0
66#define LIST_ORDER_QUEUE 1
67
68static int
69splat_list_test1(struct file *file, void *arg)
70{
71 list_t list;
72
73 splat_vprint(file, SPLAT_LIST_TEST1_NAME, "Creating list\n%s", "");
74 list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
75
76 if (!list_is_empty(&list)) {
77 splat_vprint(file, SPLAT_LIST_TEST1_NAME,
78 "New list NOT empty%s\n", "");
79 /* list_destroy() intentionally skipped to avoid assert */
80 return -EEXIST;
81 }
82
83 splat_vprint(file, SPLAT_LIST_TEST1_NAME, "Destroying list\n%s", "");
84 list_destroy(&list);
85
86 /* Validate the list has been destroyed */
87 if (list_link_active(&list.list_head)) {
88 splat_vprint(file, SPLAT_LIST_TEST1_NAME,
89 "Destroyed list still active%s", "");
90 return -EIO;
91 }
92
93 return 0;
94}
95
96static int
97splat_list_validate(list_t *list, int size, int order, int mult)
98{
99 list_item_t *li;
100 int i;
101
102 /* Walk all items in list from head to verify stack or queue
103 * ordering. We bound the for loop by size+1 to ensure that
104 * we still terminate if there is list corruption. We also
105 * intentionally make things a little more complex than they
106 * need to be by using list_head/list_next for queues, and
107 * list_tail/list_prev for stacks. This is simply done for
108 * coverage and to ensure these function are working right.
109 */
110 for (i = 0, li = (order ? list_head(list) : list_tail(list));
111 i < size + 1 && li != NULL;
112 i++, li = (order ? list_next(list, li) : list_prev(list, li)))
113 if (li->li_data != i * mult)
114 return -EIDRM;
115
116 if (i != size)
117 return -E2BIG;
118
119 return 0;
120}
121
122static int
123splat_list_test2(struct file *file, void *arg)
124{
125 list_t list;
126 list_item_t *li;
127 int i, list_size = 8, rc = 0;
128
129 splat_vprint(file, SPLAT_LIST_TEST2_NAME, "Creating list\n%s", "");
130 list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
131
132 /* Insert all items at the list head to form a stack */
133 splat_vprint(file, SPLAT_LIST_TEST2_NAME,
134 "Adding %d items to list head\n", list_size);
135 for (i = 0; i < list_size; i++) {
136 li = kmem_alloc(sizeof(list_item_t), KM_SLEEP);
137 if (li == NULL) {
138 rc = -ENOMEM;
139 goto out;
140 }
141
142 list_link_init(&li->li_node);
143 li->li_data = i;
144 list_insert_head(&list, li);
145 }
146
147 splat_vprint(file, SPLAT_LIST_TEST2_NAME,
148 "Validating %d item list is a stack\n", list_size);
149 rc = splat_list_validate(&list, list_size, LIST_ORDER_STACK, 1);
150 if (rc)
151 splat_vprint(file, SPLAT_LIST_TEST2_NAME,
152 "List validation failed, %d\n", rc);
153out:
154 /* Remove all items */
155 splat_vprint(file, SPLAT_LIST_TEST2_NAME,
156 "Removing %d items from list head\n", list_size);
157 while ((li = list_remove_head(&list)))
158 kmem_free(li, sizeof(list_item_t));
159
160 splat_vprint(file, SPLAT_LIST_TEST2_NAME, "Destroying list\n%s", "");
161 list_destroy(&list);
162
163 return rc;
164}
165
166static int
167splat_list_test3(struct file *file, void *arg)
168{
169 list_t list;
170 list_item_t *li;
171 int i, list_size = 8, rc = 0;
172
173 splat_vprint(file, SPLAT_LIST_TEST3_NAME, "Creating list\n%s", "");
174 list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
175
176 /* Insert all items at the list tail to form a queue */
177 splat_vprint(file, SPLAT_LIST_TEST3_NAME,
178 "Adding %d items to list tail\n", list_size);
179 for (i = 0; i < list_size; i++) {
180 li = kmem_alloc(sizeof(list_item_t), KM_SLEEP);
181 if (li == NULL) {
182 rc = -ENOMEM;
183 goto out;
184 }
185
186 list_link_init(&li->li_node);
187 li->li_data = i;
188 list_insert_tail(&list, li);
189 }
190
191 splat_vprint(file, SPLAT_LIST_TEST3_NAME,
192 "Validating %d item list is a queue\n", list_size);
193 rc = splat_list_validate(&list, list_size, LIST_ORDER_QUEUE, 1);
194 if (rc)
195 splat_vprint(file, SPLAT_LIST_TEST3_NAME,
196 "List validation failed, %d\n", rc);
197out:
198 /* Remove all items */
199 splat_vprint(file, SPLAT_LIST_TEST3_NAME,
200 "Removing %d items from list tail\n", list_size);
201 while ((li = list_remove_tail(&list)))
202 kmem_free(li, sizeof(list_item_t));
203
204 splat_vprint(file, SPLAT_LIST_TEST3_NAME, "Destroying list\n%s", "");
205 list_destroy(&list);
206
207 return rc;
208}
209
210static int
211splat_list_test4(struct file *file, void *arg)
212{
213 list_t list;
214 list_item_t *li_new, *li_last = NULL;
215 int i, list_size = 8, rc = 0;
216
217 splat_vprint(file, SPLAT_LIST_TEST4_NAME, "Creating list\n%s", "");
218 list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
219
220 /* Insert all items after the last item to form a queue */
221 splat_vprint(file, SPLAT_LIST_TEST4_NAME,
222 "Adding %d items each after the last item\n", list_size);
223 for (i = 0; i < list_size; i++) {
224 li_new = kmem_alloc(sizeof(list_item_t), KM_SLEEP);
225 if (li_new == NULL) {
226 rc = -ENOMEM;
227 goto out;
228 }
229
230 list_link_init(&li_new->li_node);
231 li_new->li_data = i;
232 list_insert_after(&list, li_last, li_new);
233 li_last = li_new;
234 }
235
236 splat_vprint(file, SPLAT_LIST_TEST4_NAME,
237 "Validating %d item list is a queue\n", list_size);
238 rc = splat_list_validate(&list, list_size, LIST_ORDER_QUEUE, 1);
239 if (rc)
240 splat_vprint(file, SPLAT_LIST_TEST4_NAME,
241 "List validation failed, %d\n", rc);
242out:
243 /* Remove all items */
244 splat_vprint(file, SPLAT_LIST_TEST4_NAME,
245 "Removing %d items from list tail\n", list_size);
246 while ((li_new = list_remove_head(&list)))
247 kmem_free(li_new, sizeof(list_item_t));
248
249 splat_vprint(file, SPLAT_LIST_TEST4_NAME, "Destroying list\n%s", "");
250 list_destroy(&list);
251
252 return rc;
253}
254
255static int
256splat_list_test5(struct file *file, void *arg)
257{
258 list_t list;
259 list_item_t *li_new, *li_last = NULL;
260 int i, list_size = 8, rc = 0;
261
262 splat_vprint(file, SPLAT_LIST_TEST5_NAME, "Creating list\n%s", "");
263 list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
264
265 /* Insert all items before the last item to form a stack */
266 splat_vprint(file, SPLAT_LIST_TEST5_NAME,
267 "Adding %d items each before the last item\n", list_size);
268 for (i = 0; i < list_size; i++) {
269 li_new = kmem_alloc(sizeof(list_item_t), KM_SLEEP);
270 if (li_new == NULL) {
271 rc = -ENOMEM;
272 goto out;
273 }
274
275 list_link_init(&li_new->li_node);
276 li_new->li_data = i;
277 list_insert_before(&list, li_last, li_new);
278 li_last = li_new;
279 }
280
281 splat_vprint(file, SPLAT_LIST_TEST5_NAME,
282 "Validating %d item list is a queue\n", list_size);
283 rc = splat_list_validate(&list, list_size, LIST_ORDER_STACK, 1);
284 if (rc)
285 splat_vprint(file, SPLAT_LIST_TEST5_NAME,
286 "List validation failed, %d\n", rc);
287out:
288 /* Remove all items */
289 splat_vprint(file, SPLAT_LIST_TEST5_NAME,
290 "Removing %d items from list tail\n", list_size);
291 while ((li_new = list_remove_tail(&list)))
292 kmem_free(li_new, sizeof(list_item_t));
293
294 splat_vprint(file, SPLAT_LIST_TEST5_NAME, "Destroying list\n%s", "");
295 list_destroy(&list);
296
297 return rc;
298}
299
300static int
301splat_list_test6(struct file *file, void *arg)
302{
303 list_t list;
304 list_item_t *li, *li_prev;
305 int i, list_size = 8, rc = 0;
306
307 splat_vprint(file, SPLAT_LIST_TEST6_NAME, "Creating list\n%s", "");
308 list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
309
310 /* Insert all items at the list tail to form a queue */
311 splat_vprint(file, SPLAT_LIST_TEST6_NAME,
312 "Adding %d items to list tail\n", list_size);
313 for (i = 0; i < list_size; i++) {
314 li = kmem_alloc(sizeof(list_item_t), KM_SLEEP);
315 if (li == NULL) {
316 rc = -ENOMEM;
317 goto out;
318 }
319
320 list_link_init(&li->li_node);
321 li->li_data = i;
322 list_insert_tail(&list, li);
323 }
324
325 /* Remove all odd items from the queue */
326 splat_vprint(file, SPLAT_LIST_TEST6_NAME,
327 "Removing %d odd items from the list\n", list_size / 2);
328 for (li = list_head(&list); li != NULL; li = list_next(&list, li)) {
329 if (li->li_data % 2 == 1) {
330 li_prev = list_prev(&list, li);
331 list_remove(&list, li);
332 li = li_prev;
333 }
334 }
335
336 splat_vprint(file, SPLAT_LIST_TEST6_NAME, "Validating %d item "
337 "list is a queue of only even elements\n", list_size / 2);
338 rc = splat_list_validate(&list, list_size / 2, LIST_ORDER_QUEUE, 2);
339 if (rc)
340 splat_vprint(file, SPLAT_LIST_TEST6_NAME,
341 "List validation failed, %d\n", rc);
342out:
343 /* Remove all items */
344 splat_vprint(file, SPLAT_LIST_TEST6_NAME,
345 "Removing %d items from list tail\n", list_size / 2);
346 while ((li = list_remove_tail(&list)))
347 kmem_free(li, sizeof(list_item_t));
348
349 splat_vprint(file, SPLAT_LIST_TEST6_NAME, "Destroying list\n%s", "");
350 list_destroy(&list);
351
352 return rc;
353}
354
355splat_subsystem_t *
356splat_list_init(void)
357{
358 splat_subsystem_t *sub;
359
360 sub = kmalloc(sizeof(*sub), GFP_KERNEL);
361 if (sub == NULL)
362 return NULL;
363
364 memset(sub, 0, sizeof(*sub));
365 strncpy(sub->desc.name, SPLAT_LIST_NAME, SPLAT_NAME_SIZE);
366 strncpy(sub->desc.desc, SPLAT_LIST_DESC, SPLAT_DESC_SIZE);
367 INIT_LIST_HEAD(&sub->subsystem_list);
368 INIT_LIST_HEAD(&sub->test_list);
369 spin_lock_init(&sub->test_lock);
370 sub->desc.id = SPLAT_SUBSYSTEM_LIST;
371
372 SPLAT_TEST_INIT(sub, SPLAT_LIST_TEST1_NAME, SPLAT_LIST_TEST1_DESC,
373 SPLAT_LIST_TEST1_ID, splat_list_test1);
374 SPLAT_TEST_INIT(sub, SPLAT_LIST_TEST2_NAME, SPLAT_LIST_TEST2_DESC,
375 SPLAT_LIST_TEST2_ID, splat_list_test2);
376 SPLAT_TEST_INIT(sub, SPLAT_LIST_TEST3_NAME, SPLAT_LIST_TEST3_DESC,
377 SPLAT_LIST_TEST3_ID, splat_list_test3);
378 SPLAT_TEST_INIT(sub, SPLAT_LIST_TEST4_NAME, SPLAT_LIST_TEST4_DESC,
379 SPLAT_LIST_TEST4_ID, splat_list_test4);
380 SPLAT_TEST_INIT(sub, SPLAT_LIST_TEST5_NAME, SPLAT_LIST_TEST5_DESC,
381 SPLAT_LIST_TEST5_ID, splat_list_test5);
382 SPLAT_TEST_INIT(sub, SPLAT_LIST_TEST6_NAME, SPLAT_LIST_TEST6_DESC,
383 SPLAT_LIST_TEST6_ID, splat_list_test6);
384
385 return sub;
386}
387
388void
389splat_list_fini(splat_subsystem_t *sub)
390{
391 ASSERT(sub);
392
393 SPLAT_TEST_FINI(sub, SPLAT_LIST_TEST6_ID);
394 SPLAT_TEST_FINI(sub, SPLAT_LIST_TEST5_ID);
395 SPLAT_TEST_FINI(sub, SPLAT_LIST_TEST4_ID);
396 SPLAT_TEST_FINI(sub, SPLAT_LIST_TEST3_ID);
397 SPLAT_TEST_FINI(sub, SPLAT_LIST_TEST2_ID);
398 SPLAT_TEST_FINI(sub, SPLAT_LIST_TEST1_ID);
399
400 kfree(sub);
401}
402
403int
404splat_list_id(void)
405{
406 return SPLAT_SUBSYSTEM_LIST;
407}