2 ** Copyright (C) 2002 by Kevin L. Mitchell <klmitch@mit.edu>
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Library General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2 of the License, or (at your option) any later version.
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Library General Public License for more details.
14 ** You should have received a copy of the GNU Library General Public
15 ** License along with this library; if not, write to the Free
16 ** Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
26 #define OBJECT0 (void *)0x01234567
27 #define OBJECT1 (void *)0x12345678
28 #define OBJECT2 (void *)0x23456789
29 #define OBJECT3 (void *)0x3456789a
30 #define OBJECT4 (void *)0x456789ab
32 #define OBJECT5 (void *)0x56789abc
33 #define OBJECT6 (void *)0x6789abcd
34 #define OBJECT7 (void *)0x789abcde
35 #define OBJECT8 (void *)0x89abcdef
36 #define OBJECT9 (void *)0x9abcdef0
38 #define OBJECTA (void *)0xabcdef01
40 #define DEADINT 0xdeadbeef
41 #define DEADPTR (void *)0xdeadbeef
43 /* Check return value of add operation and report PASS/FAIL */
45 check_result(unsigned long result, unsigned long expected, char *test,
48 if (result != expected) {
49 printf("FAIL/%s:%s incorrectly returned %lu (expected %lu)\n", test, info,
54 printf("PASS/%s:%s correctly returned %lu\n", test, info, result);
57 /* Check that a list head matches expectations */
59 check_list(link_head_t *list, unsigned int count, link_elem_t *head,
60 link_elem_t *tail, int idx, char *test, char *info)
62 if (list->lh_count != count) { /* Check count first */
63 printf("FAIL/%s_%d_count:%s: Count mismatch\n", test, idx, info);
66 printf("PASS/%s_%d_count:%s: Counts match\n", test, idx, info);
68 if (list->lh_first != head) { /* then check the head pointer */
69 printf("FAIL/%s_%d_first:%s: Head pointer mismatch\n", test, idx, info);
72 printf("PASS/%s_%d_first:%s: Head pointers match\n", test, idx, info);
74 if (list->lh_last != tail) { /* finally check the tail pointer */
75 printf("FAIL/%s_%d_last:%s: Tail pointer mismatch\n", test, idx, info);
78 printf("PASS/%s_%d_last:%s: Tail pointers match\n", test, idx, info);
81 /* Check that a list element matches expectations */
83 check_elem(link_elem_t *elem, link_elem_t *prev, link_elem_t *next,
84 link_head_t *head, int l_idx, int e_idx, char *test, char *info)
86 if (elem->le_next != next) { /* check next pointer first */
87 printf("FAIL/%s_%d/%d_next:%s: Next pointer mismatch\n", test, l_idx,
91 printf("PASS/%s_%d/%d_next:%s: Next pointers match\n", test, l_idx, e_idx,
94 if (elem->le_prev != prev) { /* then check prev pointer */
95 printf("FAIL/%s_%d/%d_prev:%s: Prev pointer mismatch\n", test, l_idx,
99 printf("PASS/%s_%d/%d_prev:%s: Prev pointers match\n", test, l_idx, e_idx,
102 if (elem->le_head != head) { /* finally check list head pointer */
103 printf("FAIL/%s_%d/%d_head:%s: Head pointer mismatch\n", test, l_idx,
107 printf("PASS/%s_%d/%d_head:%s: Head pointers match\n", test, l_idx, e_idx,
111 /* Check the status of the list */
113 check_list_order(link_head_t *lists, int list_idx, link_elem_t *elems,
114 int elem1_idx, int elem2_idx, int elem3_idx, int elem4_idx,
115 int elem5_idx, char *test, char *info)
117 /* Check that the list head looks correct first */
118 check_list(&lists[list_idx], 5, &elems[elem1_idx], &elems[elem5_idx],
119 list_idx, test, info);
120 /* Now check that all elements are there and are in the proper order */
121 check_elem(&elems[elem1_idx], 0, &elems[elem2_idx], &lists[list_idx],
122 list_idx, elem1_idx, test, info);
123 check_elem(&elems[elem2_idx], &elems[elem1_idx], &elems[elem3_idx],
124 &lists[list_idx], list_idx, elem2_idx, test, info);
125 check_elem(&elems[elem3_idx], &elems[elem2_idx], &elems[elem4_idx],
126 &lists[list_idx], list_idx, elem3_idx, test, info);
127 check_elem(&elems[elem4_idx], &elems[elem3_idx], &elems[elem5_idx],
128 &lists[list_idx], list_idx, elem4_idx, test, info);
129 check_elem(&elems[elem5_idx], &elems[elem4_idx], 0, &lists[list_idx],
130 list_idx, elem5_idx, test, info);
134 main(int argc, char **argv)
137 link_head_t list[] = { /* some lists to operate on */
140 { DEADINT, DEADINT, DEADPTR, DEADPTR, 0 } /* list[2] is a bad list */
142 link_elem_t elem[] = { /* some elements to operate on */
143 LINK_ELEM_INIT(OBJECT0),
144 LINK_ELEM_INIT(OBJECT1),
145 LINK_ELEM_INIT(OBJECT2),
146 LINK_ELEM_INIT(OBJECT3),
147 LINK_ELEM_INIT(OBJECT4),
148 LINK_ELEM_INIT(OBJECT5),
149 LINK_ELEM_INIT(OBJECT6),
150 LINK_ELEM_INIT(OBJECT7),
151 LINK_ELEM_INIT(OBJECT8),
152 LINK_ELEM_INIT(OBJECT9),
153 LINK_ELEM_INIT(OBJECTA),
154 { DEADINT, DEADPTR, DEADPTR, DEADPTR, DEADPTR, DEADINT } /* elem[11] */
157 /* First, build the lists */
158 for (i = 0; i < 5; i++)
159 if (ll_add(&list[0], &elem[i], LINK_LOC_TAIL, 0) ||
160 ll_add(&list[1], &elem[i + 5], LINK_LOC_TAIL, 0))
161 return -1; /* failed to initialize test */
163 /* Baseline--verify that the lists are in proper order */
164 check_list_order(list, 0, elem, 0, 1, 2, 3, 4, "ll_move_baseline",
165 "Verify baseline list[0] ordering");
166 check_list_order(list, 1, elem, 5, 6, 7, 8, 9, "ll_move_baseline",
167 "Verify baseline list[1] ordering");
169 /* OK, now check to see if ll_move verifies its arguments correctly */
170 check_result(ll_move(0, 0, LINK_LOC_HEAD, 0), DB_ERR_BADARGS,
171 "ll_move_noargs", "ll_move() with no arguments", 0);
172 check_result(ll_move(&list[2], &elem[0], LINK_LOC_HEAD, 0), DB_ERR_BADARGS,
173 "ll_move_badlist", "ll_move() with bad list", 1);
174 check_result(ll_move(&list[0], &elem[11], LINK_LOC_HEAD, 0),
175 DB_ERR_BADARGS, "ll_move_badnew",
176 "ll_move() with bad new element", 1);
177 check_result(ll_move(&list[0], &elem[0], LINK_LOC_TAIL, &elem[11]),
178 DB_ERR_BADARGS, "ll_move_badelem",
179 "ll_move() with bad element", 1);
180 check_result(ll_move(&list[0], &elem[0], LINK_LOC_BEFORE, 0),
181 DB_ERR_BADARGS, "ll_move_before_noelem",
182 "ll_move() before with no element", 1);
183 check_result(ll_move(&list[0], &elem[0], LINK_LOC_AFTER, 0),
184 DB_ERR_BADARGS, "ll_move_after_noelem",
185 "ll_move() after with no element", 1);
187 /* Make sure movement of object around itself is rejected */
188 check_result(ll_move(&list[0], &elem[0], LINK_LOC_BEFORE, &elem[0]),
189 DB_ERR_BUSY, "ll_move_neweqelem",
190 "ll_move() with new == element", 1);
192 /* Check to see if unused elements are detected correctly */
193 check_result(ll_move(&list[0], &elem[10], LINK_LOC_HEAD, 0),
194 DB_ERR_UNUSED, "ll_move_newunused",
195 "ll_move() with unused new element", 1);
196 check_result(ll_move(&list[0], &elem[4], LINK_LOC_HEAD, &elem[10]),
197 DB_ERR_UNUSED, "ll_move_elemunused",
198 "ll_move() with unused original element", 1);
200 /* Next check to see if list mismatches are handled properly */
201 check_result(ll_move(&list[0], &elem[5], LINK_LOC_HEAD, 0),
202 DB_ERR_WRONGTABLE, "ll_move_newwronglist",
203 "ll_move() with new element in wrong list", 1);
204 check_result(ll_move(&list[0], &elem[4], LINK_LOC_HEAD, &elem[5]),
205 DB_ERR_WRONGTABLE, "ll_move_elemwronglist",
206 "ll_move() with original element in wrong list", 1);
208 /* OK, now let's actually do something */
210 /* Start off with moving the tail element to the head of the list */
211 check_result(ll_move(&list[0], &elem[4], LINK_LOC_HEAD, 0), 0,
212 "ll_move_l0e4h", "Move tail element to head of list", 1);
213 check_list_order(list, 0, elem, 4, 0, 1, 2, 3, "ll_move_l0e4h",
214 "Test movement of tail element to head of list");
216 /* Now try the head element back to the tail of the list */
217 check_result(ll_move(&list[0], &elem[4], LINK_LOC_TAIL, 0), 0,
218 "ll_move_l0e4t", "Move head element to tail of list", 1);
219 check_list_order(list, 0, elem, 0, 1, 2, 3, 4, "ll_move_l0e4t",
220 "Test movement of head element to tail of list");
222 /* Let's now move the tail element to *after* the head of the list */
223 check_result(ll_move(&list[0], &elem[4], LINK_LOC_AFTER, &elem[0]), 0,
224 "ll_move_l0e4a0", "Move tail element to after head of list", 1);
225 check_list_order(list, 0, elem, 0, 4, 1, 2, 3, "ll_move_l0e4a0",
226 "Test movement of tail to after head of list");
228 /* How about moving the head element to *before* the tail of the list? */
229 check_result(ll_move(&list[0], &elem[0], LINK_LOC_BEFORE, &elem[3]), 0,
230 "ll_move_l0e0b3", "Move head element to before tail of list",
232 check_list_order(list, 0, elem, 4, 1, 2, 0, 3, "ll_move_l0e0b3",
233 "Test movement of head to before tail of list");
235 /* OK, now do some dancing element checks */
236 check_result(ll_move(&list[0], &elem[4], LINK_LOC_AFTER, &elem[1]), 0,
237 "ll_move_l0e4a1", "Swap elements with LINK_LOC_AFTER", 1);
238 check_list_order(list, 0, elem, 1, 4, 2, 0, 3, "ll_move_l0e4a1",
239 "Swap elements with LINK_LOC_AFTER");
240 check_result(ll_move(&list[0], &elem[3], LINK_LOC_BEFORE, &elem[0]), 0,
241 "ll_move_l0e3b0", "Swap elements with LINK_LOC_BEFORE", 1);
242 check_list_order(list, 0, elem, 1, 4, 2, 3, 0, "ll_move_l0e3b0",
243 "Swap elements with LINK_LOC_BEFORE");
245 /* Finally, verify that moving heads/tails to the head/tail (respectively)
248 check_result(ll_move(&list[0], &elem[1], LINK_LOC_HEAD, 0), 0,
249 "ll_move_l0e1h", "Move head element to head", 1);
250 check_list_order(list, 0, elem, 1, 4, 2, 3, 0, "ll_move_l0e1h",
251 "Move head element to head");
252 check_result(ll_move(&list[0], &elem[0], LINK_LOC_TAIL, 0), 0,
253 "ll_move_l0e0t", "Move tail element to tail", 1);
254 check_list_order(list, 0, elem, 1, 4, 2, 3, 0, "ll_move_l0e0t",
255 "Move tail element to tail");