Accept topic changes from servers that do not send topic-set timestamps (fixes SF...
[ircu2.10.12-pk.git] / libs / dbprim / tests / t_ll_move.c
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$
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 }