1 |
/* |
2 |
** Copyright (C) 2002 by Kevin L. Mitchell <klmitch@mit.edu> |
3 |
** |
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. |
8 |
** |
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. |
13 |
** |
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, |
17 |
** MA 02111-1307, USA |
18 |
** |
19 |
** @(#)$Id: t_ll_move.c,v 1.2 2003/06/12 01:10:11 klmitch Exp $ |
20 |
*/ |
21 |
#include <stdio.h> |
22 |
#include <stdlib.h> |
23 |
|
24 |
#include "dbprim.h" |
25 |
|
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 |
31 |
|
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 |
37 |
|
38 |
#define OBJECTA (void *)0xabcdef01 |
39 |
|
40 |
#define DEADINT 0xdeadbeef |
41 |
#define DEADPTR (void *)0xdeadbeef |
42 |
|
43 |
/* Check return value of add operation and report PASS/FAIL */ |
44 |
static void |
45 |
check_result(unsigned long result, unsigned long expected, char *test, |
46 |
char *info, int die) |
47 |
{ |
48 |
if (result != expected) { |
49 |
printf("FAIL/%s:%s incorrectly returned %lu (expected %lu)\n", test, info, |
50 |
result, expected); |
51 |
if (die) |
52 |
exit(0); |
53 |
} else |
54 |
printf("PASS/%s:%s correctly returned %lu\n", test, info, result); |
55 |
} |
56 |
|
57 |
/* Check that a list head matches expectations */ |
58 |
static void |
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) |
61 |
{ |
62 |
if (list->lh_count != count) { /* Check count first */ |
63 |
printf("FAIL/%s_%d_count:%s: Count mismatch\n", test, idx, info); |
64 |
exit(0); |
65 |
} else |
66 |
printf("PASS/%s_%d_count:%s: Counts match\n", test, idx, info); |
67 |
|
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); |
70 |
exit(0); |
71 |
} else |
72 |
printf("PASS/%s_%d_first:%s: Head pointers match\n", test, idx, info); |
73 |
|
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); |
76 |
exit(0); |
77 |
} else |
78 |
printf("PASS/%s_%d_last:%s: Tail pointers match\n", test, idx, info); |
79 |
} |
80 |
|
81 |
/* Check that a list element matches expectations */ |
82 |
static void |
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) |
85 |
{ |
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, |
88 |
e_idx, info); |
89 |
exit(0); |
90 |
} else |
91 |
printf("PASS/%s_%d/%d_next:%s: Next pointers match\n", test, l_idx, e_idx, |
92 |
info); |
93 |
|
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, |
96 |
e_idx, info); |
97 |
exit(0); |
98 |
} else |
99 |
printf("PASS/%s_%d/%d_prev:%s: Prev pointers match\n", test, l_idx, e_idx, |
100 |
info); |
101 |
|
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, |
104 |
e_idx, info); |
105 |
exit(0); |
106 |
} else |
107 |
printf("PASS/%s_%d/%d_head:%s: Head pointers match\n", test, l_idx, e_idx, |
108 |
info); |
109 |
} |
110 |
|
111 |
/* Check the status of the list */ |
112 |
static void |
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) |
116 |
{ |
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); |
131 |
} |
132 |
|
133 |
int |
134 |
main(int argc, char **argv) |
135 |
{ |
136 |
int i; |
137 |
link_head_t list[] = { /* some lists to operate on */ |
138 |
LINK_HEAD_INIT(0), |
139 |
LINK_HEAD_INIT(0), |
140 |
{ DEADINT, DEADINT, DEADPTR, DEADPTR, 0 } /* list[2] is a bad list */ |
141 |
}; |
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] */ |
155 |
}; |
156 |
|
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 */ |
162 |
|
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"); |
168 |
|
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); |
186 |
|
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); |
191 |
|
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); |
199 |
|
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); |
207 |
|
208 |
/* OK, now let's actually do something */ |
209 |
|
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"); |
215 |
|
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"); |
221 |
|
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"); |
227 |
|
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", |
231 |
1); |
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"); |
234 |
|
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"); |
244 |
|
245 |
/* Finally, verify that moving heads/tails to the head/tail (respectively) |
246 |
* works properly. |
247 |
*/ |
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"); |
256 |
|
257 |
return 0; |
258 |
} |