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_add.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 |
#define OBJECT5 (void *)0x56789abc |
32 |
|
33 |
#define DEADINT 0xdeadbeef |
34 |
#define DEADPTR (void *)0xdeadbeef |
35 |
|
36 |
/* Check return value of add operation and report PASS/FAIL */ |
37 |
static void |
38 |
check_result(unsigned long result, unsigned long expected, char *test, |
39 |
char *info, int die) |
40 |
{ |
41 |
if (result != expected) { |
42 |
printf("FAIL/%s:%s incorrectly returned %lu (expected %lu)\n", test, info, |
43 |
result, expected); |
44 |
if (die) |
45 |
exit(0); |
46 |
} else |
47 |
printf("PASS/%s:%s correctly returned %lu\n", test, info, result); |
48 |
} |
49 |
|
50 |
/* Check that a list head matches expectations */ |
51 |
static void |
52 |
check_list(link_head_t *list, unsigned int count, link_elem_t *head, |
53 |
link_elem_t *tail, char *test, char *info) |
54 |
{ |
55 |
if (list->lh_count != count) { /* Check count first */ |
56 |
printf("FAIL/%s_count:%s: Count mismatch\n", test, info); |
57 |
exit(0); |
58 |
} else |
59 |
printf("PASS/%s_count:%s: Counts match\n", test, info); |
60 |
|
61 |
if (list->lh_first != head) { /* then check the head pointer */ |
62 |
printf("FAIL/%s_first:%s: Head pointer mismatch\n", test, info); |
63 |
exit(0); |
64 |
} else |
65 |
printf("PASS/%s_first:%s: Head pointers match\n", test, info); |
66 |
|
67 |
if (list->lh_last != tail) { /* finally check the tail pointer */ |
68 |
printf("FAIL/%s_last:%s: Tail pointer mismatch\n", test, info); |
69 |
exit(0); |
70 |
} else |
71 |
printf("PASS/%s_last:%s: Tail pointers match\n", test, info); |
72 |
} |
73 |
|
74 |
/* Check that a list element matches expectations */ |
75 |
static void |
76 |
check_elem(link_elem_t *elem, link_elem_t *prev, link_elem_t *next, |
77 |
link_head_t *head, char *test, char *info) |
78 |
{ |
79 |
if (elem->le_next != next) { /* check next pointer first */ |
80 |
printf("FAIL/%s_next:%s: Next pointer mismatch\n", test, info); |
81 |
exit(0); |
82 |
} else |
83 |
printf("PASS/%s_next:%s: Next pointers match\n", test, info); |
84 |
|
85 |
if (elem->le_prev != prev) { /* then check prev pointer */ |
86 |
printf("FAIL/%s_prev:%s: Prev pointer mismatch\n", test, info); |
87 |
exit(0); |
88 |
} else |
89 |
printf("PASS/%s_prev:%s: Prev pointers match\n", test, info); |
90 |
|
91 |
if (elem->le_head != head) { /* finally check list head pointer */ |
92 |
printf("FAIL/%s_head:%s: Head pointer mismatch\n", test, info); |
93 |
exit(0); |
94 |
} else |
95 |
printf("PASS/%s_head:%s: Head pointers match\n", test, info); |
96 |
} |
97 |
|
98 |
int |
99 |
main(int argc, char **argv) |
100 |
{ |
101 |
link_head_t list[] = { /* some lists to operate on */ |
102 |
LINK_HEAD_INIT(0), |
103 |
LINK_HEAD_INIT(0), |
104 |
{ DEADINT, DEADINT, DEADPTR, DEADPTR, 0 } /* list[2] is a bad list */ |
105 |
}; |
106 |
link_elem_t elem[] = { /* some elements to operate on */ |
107 |
LINK_ELEM_INIT(OBJECT0), |
108 |
LINK_ELEM_INIT(OBJECT1), |
109 |
LINK_ELEM_INIT(OBJECT2), |
110 |
LINK_ELEM_INIT(OBJECT3), |
111 |
LINK_ELEM_INIT(OBJECT4), |
112 |
LINK_ELEM_INIT(OBJECT5), |
113 |
{ DEADINT, DEADPTR, DEADPTR, DEADPTR, DEADPTR, DEADINT } /* elem[6] */ |
114 |
}; |
115 |
|
116 |
/* Check the cases that yield "BADARGS" */ |
117 |
check_result(ll_add(0, 0, LINK_LOC_HEAD, 0), DB_ERR_BADARGS, |
118 |
"ll_add_noargs", "ll_add() with no arguments", 0); |
119 |
check_result(ll_add(&list[2], &elem[0], LINK_LOC_HEAD, 0), DB_ERR_BADARGS, |
120 |
"ll_add_badlist", "ll_add() with bad list", 0); |
121 |
check_result(ll_add(&list[0], &elem[6], LINK_LOC_HEAD, 0), DB_ERR_BADARGS, |
122 |
"ll_add_badnew", "ll_add() with bad new element", 0); |
123 |
check_result(ll_add(&list[0], &elem[0], LINK_LOC_HEAD, &elem[6]), |
124 |
DB_ERR_BADARGS, "ll_add_badelem", "ll_add() with bad element", |
125 |
0); |
126 |
check_result(ll_add(&list[0], &elem[0], LINK_LOC_BEFORE, 0), |
127 |
DB_ERR_BADARGS, "ll_add_before_noelem", |
128 |
"ll_add() before with no element", 0); |
129 |
check_result(ll_add(&list[0], &elem[0], LINK_LOC_AFTER, 0), DB_ERR_BADARGS, |
130 |
"ll_add_after_noelem", "ll_add() after with no element", 0); |
131 |
|
132 |
/* OK, now add an element to one list */ |
133 |
check_result(ll_add(&list[0], &elem[0], LINK_LOC_HEAD, 0), 0, |
134 |
"ll_add_l0e0", "ll_add() head list[0] elem[0]", 1); |
135 |
|
136 |
/* Verify that it added correctly */ |
137 |
check_list(&list[0], 1, &elem[0], &elem[0], "list_l0e0", |
138 |
"List 0 head after first insert"); |
139 |
check_elem(&elem[0], 0, 0, &list[0], "elem_l0e0", |
140 |
"Element 0 after first insert"); |
141 |
|
142 |
/* Now try to add it to a second list */ |
143 |
check_result(ll_add(&list[1], &elem[0], LINK_LOC_HEAD, 0), DB_ERR_BUSY, |
144 |
"ll_add_l1e0", "ll_add() head list[1] elem[0]", 1); |
145 |
|
146 |
/* OK, now try adding another element to a second list, using TAIL */ |
147 |
check_result(ll_add(&list[1], &elem[1], LINK_LOC_TAIL, 0), 0, |
148 |
"ll_add_l1e1", "ll_add() tail list[1] elem[1]", 1); |
149 |
|
150 |
/* Verify that it added correctly */ |
151 |
check_list(&list[1], 1, &elem[1], &elem[1], "list_l1e1", |
152 |
"List 1 head after second insert"); |
153 |
check_elem(&elem[1], 0, 0, &list[1], "elem_l1e1", |
154 |
"Element 1 after second insert"); |
155 |
|
156 |
/* Now try adding an element to list[0] after an element in list[1] */ |
157 |
check_result(ll_add(&list[0], &elem[2], LINK_LOC_AFTER, &elem[1]), |
158 |
DB_ERR_WRONGTABLE, "ll_add_l0e2a1", |
159 |
"ll_add() list[0] elem[2] after elem[1] (list[1])", 1); |
160 |
|
161 |
/* Now try adding after an element that hasn't been inserted anywhere */ |
162 |
check_result(ll_add(&list[0], &elem[2], LINK_LOC_AFTER, &elem[3]), |
163 |
DB_ERR_UNUSED, "ll_add_l0e2a3", |
164 |
"ll_add() list[0] elem[2] after elem[3] (no list)", 1); |
165 |
|
166 |
/* Let's now try adding to the head of a list */ |
167 |
check_result(ll_add(&list[0], &elem[2], LINK_LOC_TAIL, 0), 0, "ll_add_l0e2t", |
168 |
"ll_add() tail list[0] elem[2]", 1); |
169 |
|
170 |
/* Verify that it added correctly */ |
171 |
check_list(&list[0], 2, &elem[0], &elem[2], "list_l0e0e2", |
172 |
"List 0 head after third insert"); |
173 |
check_elem(&elem[0], 0, &elem[2], &list[0], "elem_l0e0e2_0", |
174 |
"Element 0 after third insert"); |
175 |
check_elem(&elem[2], &elem[0], 0, &list[0], "elem_l0e0e2_2", |
176 |
"Element 2 after third insert"); |
177 |
|
178 |
/* Now try for the head */ |
179 |
check_result(ll_add(&list[1], &elem[3], LINK_LOC_HEAD, 0), 0, "ll_add_l1e3h", |
180 |
"ll_add() head list[1] elem[3]", 1); |
181 |
|
182 |
/* Verify that it added correctly */ |
183 |
check_list(&list[1], 2, &elem[3], &elem[1], "list_l1e3e1", |
184 |
"List 1 head after fourth insert"); |
185 |
check_elem(&elem[1], &elem[3], 0, &list[1], "elem_l1e3e1_1", |
186 |
"Element 1 after fourth insert"); |
187 |
check_elem(&elem[3], 0, &elem[1], &list[1], "elem_l1e3e1_3", |
188 |
"Element 3 after fourth insert"); |
189 |
|
190 |
/* Let's try adding an element in the middle by inserting before last */ |
191 |
check_result(ll_add(&list[0], &elem[4], LINK_LOC_BEFORE, ll_last(&list[0])), |
192 |
0, "ll_add_l0e4b2", "ll_add() list[0] elem[4] before elem[2]", |
193 |
1); |
194 |
|
195 |
/* Verify that it added correctly */ |
196 |
check_list(&list[0], 3, &elem[0], &elem[2], "list_l0e0e4e2", |
197 |
"List 0 head after fifth insert"); |
198 |
check_elem(&elem[0], 0, &elem[4], &list[0], "elem_l0e0e4e2_0", |
199 |
"Element 0 after fifth insert"); |
200 |
check_elem(&elem[2], &elem[4], 0, &list[0], "elem_l0e0e4e2_2", |
201 |
"Element 2 after fifth insert"); |
202 |
check_elem(&elem[4], &elem[0], &elem[2], &list[0], "elem_l0e0e4e2_4", |
203 |
"Element 4 after fifth insert"); |
204 |
|
205 |
/* OK, now try inserting after first */ |
206 |
check_result(ll_add(&list[1], &elem[5], LINK_LOC_AFTER, ll_first(&list[1])), |
207 |
0, "ll_add_l1e5a3", "ll_add() list[1] elem[5] after elem[3]", |
208 |
1); |
209 |
|
210 |
/* Verify that it added correctly */ |
211 |
check_list(&list[1], 3, &elem[3], &elem[1], "list_l1e3e5e1", |
212 |
"List 1 head after sixth insert"); |
213 |
check_elem(&elem[1], &elem[5], 0, &list[1], "elem_l1e3e5e1_1", |
214 |
"Element 1 after sixth insert"); |
215 |
check_elem(&elem[3], 0, &elem[5], &list[1], "elem_l1e3e5e1_3", |
216 |
"Element 3 after sixth insert"); |
217 |
check_elem(&elem[5], &elem[3], &elem[1], &list[1], "elem_l1e3e5e1_5", |
218 |
"Element 5 after sixth insert"); |
219 |
|
220 |
return 0; |
221 |
} |