]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - tools/regression/lib/libc/nss/testutil.h
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / tools / regression / lib / libc / nss / testutil.h
1 /*-
2  * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 #include <sys/queue.h>
30
31 #define DECLARE_TEST_DATA(ent)                                          \
32 struct ent##_entry {                                                    \
33         struct ent data;                                                \
34         STAILQ_ENTRY(ent##_entry) entries;                              \
35 };                                                                      \
36                                                                         \
37 struct ent##_test_data {                                                \
38         void (*clone_func)(struct ent *, struct ent const *);           \
39         void (*free_func)(struct ent *);                                \
40                                                                         \
41         STAILQ_HEAD(ent_head, ent##_entry) snapshot_data;               \
42 };                                                                      \
43                                                                         \
44 void __##ent##_test_data_init(struct ent##_test_data *,                 \
45         void (*)(struct ent *, struct ent const *),                     \
46         void (*freef)(struct ent *));                                   \
47 void __##ent##_test_data_destroy(struct ent##_test_data *);             \
48                                                                         \
49 void __##ent##_test_data_append(struct ent##_test_data *, struct ent *data);\
50 int __##ent##_test_data_foreach(struct ent##_test_data *,               \
51         int (*)(struct ent *, void *), void *);                         \
52 int __##ent##_test_data_compare(struct ent##_test_data *,               \
53         struct ent##_test_data *, int (*)(struct ent *, struct ent *,   \
54         void *), void *);                                               \
55 struct ent *__##ent##_test_data_find(struct ent##_test_data *, struct ent *,\
56         int (*)(struct ent *, struct ent *, void *), void *);           \
57 void __##ent##_test_data_clear(struct ent##_test_data *);                       
58         
59 #define TEST_DATA_INIT(ent, td, clonef, freef)\
60         __##ent##_test_data_init(td, clonef, freef)
61 #define TEST_DATA_DESTROY(ent, td) __##ent##_test_data_destroy(td)
62 #define TEST_DATA_APPEND(ent, td, d) __##ent##_test_data_append(td, d)
63 #define TEST_DATA_FOREACH(ent, td, f, mdata)\
64         __##ent##_test_data_foreach(td, f, mdata)
65 #define TEST_DATA_COMPARE(ent, td1, td2, fcmp, mdata)\
66         __##ent##_test_data_compare(td1, td2, fcmp, mdata);
67 #define TEST_DATA_FIND(ent, td, d, fcmp, mdata)\
68         __##ent##_test_data_find(td, d, fcmp, mdata)
69 #define TEST_DATA_CLEAR(ent, td) __##ent##_test_data_clear(td)
70
71 #define IMPLEMENT_TEST_DATA(ent)                                        \
72 void                                                                    \
73 __##ent##_test_data_init(struct ent##_test_data *td,                    \
74         void (*clonef)(struct ent *, struct ent const *),               \
75         void (*freef)(struct ent *))                                    \
76 {                                                                       \
77         assert(td != NULL);                                             \
78         assert(clonef != NULL);                                         \
79         assert(freef != NULL);                                          \
80                                                                         \
81         memset(td, 0, sizeof(*td));                                     \
82         td->clone_func = clonef;                                        \
83         td->free_func = freef;                                          \
84         STAILQ_INIT(&td->snapshot_data);                                \
85 }                                                                       \
86                                                                         \
87 void                                                                    \
88 __##ent##_test_data_destroy(struct ent##_test_data *td)                 \
89 {                                                                       \
90         __##ent##_test_data_clear(td);                                  \
91 }                                                                       \
92                                                                         \
93 void                                                                    \
94 __##ent##_test_data_append(struct ent##_test_data *td, struct ent *app_data)\
95 {                                                                       \
96         struct ent##_entry *e;                                          \
97                                                                         \
98         assert(td != NULL);                                             \
99         assert(app_data != NULL);                                       \
100                                                                         \
101         e = (struct ent##_entry *)malloc(sizeof(struct ent##_entry));   \
102         assert(e != NULL);                                              \
103         memset(e, 0, sizeof(struct ent##_entry));                       \
104                                                                         \
105         td->clone_func(&e->data, app_data);                             \
106         STAILQ_INSERT_TAIL(&td->snapshot_data, e, entries);             \
107 }                                                                       \
108                                                                         \
109 int                                                                     \
110 __##ent##_test_data_foreach(struct ent##_test_data *td,                 \
111         int (*forf)(struct ent *, void *), void *mdata)                 \
112 {                                                                       \
113         struct ent##_entry *e;                                          \
114         int rv;                                                         \
115                                                                         \
116         assert(td != NULL);                                             \
117         assert(forf != NULL);                                           \
118                                                                         \
119         rv = 0;                                                         \
120         STAILQ_FOREACH(e, &td->snapshot_data, entries) {                \
121                 rv = forf(&e->data, mdata);                             \
122                 if (rv != 0)                                            \
123                         break;                                          \
124         }                                                               \
125                                                                         \
126         return (rv);                                                    \
127 }                                                                       \
128                                                                         \
129 int                                                                     \
130 __##ent##_test_data_compare(struct ent##_test_data *td1, struct ent##_test_data *td2,\
131         int (*cmp_func)(struct ent *, struct ent *, void *), void *mdata)\
132 {                                                                       \
133         struct ent##_entry *e1, *e2;                                    \
134         int rv;                                                         \
135                                                                         \
136         assert(td1 != NULL);                                            \
137         assert(td2 != NULL);                                            \
138         assert(cmp_func != NULL);                                       \
139                                                                         \
140         e1 = STAILQ_FIRST(&td1->snapshot_data);                         \
141         e2 = STAILQ_FIRST(&td2->snapshot_data);                         \
142                                                                         \
143         rv = 0;                                                         \
144         do {                                                            \
145                 if ((e1 == NULL) || (e2 == NULL)) {                     \
146                         if (e1 == e2)                                   \
147                                 return (0);                             \
148                         else                                            \
149                                 return (-1);                            \
150                 }                                                       \
151                                                                         \
152                 rv = cmp_func(&e1->data, &e2->data, mdata);             \
153                 e1 = STAILQ_NEXT(e1, entries);                          \
154                 e2 = STAILQ_NEXT(e2, entries);                          \
155         } while (rv == 0);                                              \
156                                                                         \
157         return (rv);                                                    \
158 }                                                                       \
159                                                                         \
160 struct ent *                                                            \
161 __##ent##_test_data_find(struct ent##_test_data *td, struct ent *data,  \
162         int (*cmp)(struct ent *, struct ent *, void *), void *mdata)    \
163 {                                                                       \
164         struct ent##_entry *e;                                          \
165         struct ent *result;                                             \
166                                                                         \
167         assert(td != NULL);                                             \
168         assert(cmp != NULL);                                            \
169                                                                         \
170         result = NULL;                                                  \
171         STAILQ_FOREACH(e, &td->snapshot_data, entries) {                \
172                 if (cmp(&e->data, data, mdata) == 0) {                  \
173                         result = &e->data;                              \
174                         break;                                          \
175                 }                                                       \
176         }                                                               \
177                                                                         \
178         return (result);                                                \
179 }                                                                       \
180                                                                         \
181                                                                         \
182 void                                                                    \
183 __##ent##_test_data_clear(struct ent##_test_data *td)                   \
184 {                                                                       \
185         struct ent##_entry *e;                                          \
186         assert(td != NULL);                                             \
187                                                                         \
188         while (!STAILQ_EMPTY(&td->snapshot_data)) {                     \
189                 e = STAILQ_FIRST(&td->snapshot_data);                   \
190                 STAILQ_REMOVE_HEAD(&td->snapshot_data, entries);        \
191                                                                         \
192                 td->free_func(&e->data);                                \
193                 free(e);                                                \
194         }                                                               \
195 }                                                                       
196
197                                                                         \
198 #define DECLARE_TEST_FILE_SNAPSHOT(ent)                                 \
199 struct ent##_snp_param {                                                \
200         FILE *fp;                                                       \
201         void (*sdump_func)(struct ent *, char *, size_t);               \
202 };                                                                      \
203                                                                         \
204 int __##ent##_snapshot_write_func(struct ent *, void *);                \
205 int __##ent##_snapshot_write(char const *, struct ent##_test_data *,    \
206         void (*)(struct ent *, char *, size_t));                        \
207 int __##ent##_snapshot_read(char const *, struct ent##_test_data *,     \
208         int (*)(struct ent *, char *)); 
209                 
210 #define TEST_SNAPSHOT_FILE_WRITE(ent, fname, td, f)                     \
211         __##ent##_snapshot_write(fname, td, f)
212 #define TEST_SNAPSHOT_FILE_READ(ent, fname, td, f)                      \
213         __##ent##_snapshot_read(fname, td, f)
214
215 #define IMPLEMENT_TEST_FILE_SNAPSHOT(ent)                               \
216 int                                                                     \
217 __##ent##_snapshot_write_func(struct ent *data, void *mdata)            \
218 {                                                                       \
219         char buffer[1024];                                              \
220         struct ent##_snp_param *param;                                  \
221                                                                         \
222         assert(data != NULL);                                           \
223                                                                         \
224         param = (struct ent##_snp_param *)mdata;                        \
225         param->sdump_func(data, buffer, sizeof(buffer));                \
226         fputs(buffer, param->fp);                                       \
227         fputc('\n', param->fp);                                         \
228                                                                         \
229         return (0);                                                     \
230 }                                                                       \
231                                                                         \
232 int                                                                     \
233 __##ent##_snapshot_write(char const *fname, struct ent##_test_data *td, \
234         void (*sdump_func)(struct ent *, char *, size_t))               \
235 {                                                                       \
236         struct ent##_snp_param  param;                                  \
237                                                                         \
238         assert(fname != NULL);                                          \
239         assert(td != NULL);                                             \
240                                                                         \
241         param.fp = fopen(fname, "w");                                   \
242         if (param.fp == NULL)                                           \
243                 return (-1);                                            \
244                                                                         \
245         param.sdump_func = sdump_func;                                  \
246         __##ent##_test_data_foreach(td, __##ent##_snapshot_write_func, &param);\
247         fclose(param.fp);                                               \
248                                                                         \
249         return (0);                                                     \
250 }                                                                       \
251                                                                         \
252 int                                                                     \
253 __##ent##_snapshot_read(char const *fname, struct ent##_test_data *td,  \
254         int (*read_func)(struct ent *, char *))                         \
255 {                                                                       \
256         char buffer[1024];                                              \
257         struct ent data;                                                \
258         char *s;                                                        \
259         FILE *fi;                                                       \
260         size_t len;                                                     \
261         int rv;                                                         \
262                                                                         \
263         assert(fname != NULL);                                          \
264         assert(td != NULL);                                             \
265                                                                         \
266         fi = fopen(fname, "r");                                         \
267         if (fi == NULL)                                                 \
268                 return (-1);                                            \
269                                                                         \
270         rv = 0;                                                         \
271         memset(buffer, 0, sizeof(buffer));                              \
272         while (!feof(fi)) {                                             \
273                 s = fgets(buffer, sizeof(buffer), fi);                  \
274                 if (s != NULL && s[0] != '#') {                         \
275                         len = strlen(s);                                \
276                         if (len == 0)                                   \
277                                 continue;                               \
278                         if (buffer[len - 1] == '\n')                    \
279                                 buffer[len -1] = '\0';                  \
280                                                                         \
281                         rv = read_func(&data, s);                       \
282                         if (rv == 0) {                                  \
283                                 __##ent##_test_data_append(td, &data);  \
284                                 td->free_func(&data);                   \
285                         } else                                          \
286                                 goto fin;                               \
287                 }                                                       \
288         }                                                               \
289                                                                         \
290 fin:                                                                    \
291         fclose(fi);                                                     \
292         return (rv);                                                    \
293 }
294
295 #define DECLARE_1PASS_TEST(ent)                                         \
296 int __##ent##_1pass_test(struct ent##_test_data *,                      \
297         int (*)(struct ent *, void *),                                  \
298         void *);                                                        
299         
300 #define DO_1PASS_TEST(ent, td, f, mdata)                                \
301         __##ent##_1pass_test(td, f, mdata)
302
303 #define IMPLEMENT_1PASS_TEST(ent)                                       \
304 int                                                                     \
305 __##ent##_1pass_test(struct ent##_test_data *td,                        \
306         int (*tf)(struct ent *, void *),                                \
307         void *mdata)                                                    \
308 {                                                                       \
309         int rv;                                                         \
310         rv = __##ent##_test_data_foreach(td, tf, mdata);                \
311                                                                         \
312         return (rv);                                                    \
313 }
314
315 #define DECLARE_2PASS_TEST(ent)                                         \
316 int __##ent##_2pass_test(struct ent##_test_data *,                      \
317         struct ent##_test_data *,                                       \
318         int (*)(struct ent *, struct ent *, void *), void *);
319
320 #define DO_2PASS_TEST(ent, td1, td2, f, mdata)                          \
321         __##ent##_2pass_test(td1, td2, f, mdata)
322         
323 #define IMPLEMENT_2PASS_TEST(ent)                                       \
324 int                                                                     \
325 __##ent##_2pass_test(struct ent##_test_data *td1,                       \
326         struct ent##_test_data *td2,                                    \
327         int (*cmp_func)(struct ent *, struct ent *, void *),            \
328         void *cmp_mdata)                                                \
329 {                                                                       \
330         int rv;                                                         \
331                                                                         \
332         rv = __##ent##_test_data_compare(td1, td2, cmp_func, cmp_mdata);        \
333         return (rv);                                                    \
334 }