]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - tools/regression/lib/libc/nss/testutil.h
MFstable/10 r291759:
[FreeBSD/stable/9.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 #define DECLARE_TEST_FILE_SNAPSHOT(ent)                                 \
198 struct ent##_snp_param {                                                \
199         FILE *fp;                                                       \
200         void (*sdump_func)(struct ent *, char *, size_t);               \
201 };                                                                      \
202                                                                         \
203 int __##ent##_snapshot_write_func(struct ent *, void *);                \
204 int __##ent##_snapshot_write(char const *, struct ent##_test_data *,    \
205         void (*)(struct ent *, char *, size_t));                        \
206 int __##ent##_snapshot_read(char const *, struct ent##_test_data *,     \
207         int (*)(struct ent *, char *));
208
209 #define TEST_SNAPSHOT_FILE_WRITE(ent, fname, td, f)                     \
210         __##ent##_snapshot_write(fname, td, f)
211 #define TEST_SNAPSHOT_FILE_READ(ent, fname, td, f)                      \
212         __##ent##_snapshot_read(fname, td, f)
213
214 #define IMPLEMENT_TEST_FILE_SNAPSHOT(ent)                               \
215 int                                                                     \
216 __##ent##_snapshot_write_func(struct ent *data, void *mdata)            \
217 {                                                                       \
218         char buffer[1024];                                              \
219         struct ent##_snp_param *param;                                  \
220                                                                         \
221         assert(data != NULL);                                           \
222                                                                         \
223         param = (struct ent##_snp_param *)mdata;                        \
224         param->sdump_func(data, buffer, sizeof(buffer));                \
225         fputs(buffer, param->fp);                                       \
226         fputc('\n', param->fp);                                         \
227                                                                         \
228         return (0);                                                     \
229 }                                                                       \
230                                                                         \
231 int                                                                     \
232 __##ent##_snapshot_write(char const *fname, struct ent##_test_data *td, \
233         void (*sdump_func)(struct ent *, char *, size_t))               \
234 {                                                                       \
235         struct ent##_snp_param  param;                                  \
236                                                                         \
237         assert(fname != NULL);                                          \
238         assert(td != NULL);                                             \
239                                                                         \
240         param.fp = fopen(fname, "w");                                   \
241         if (param.fp == NULL)                                           \
242                 return (-1);                                            \
243                                                                         \
244         param.sdump_func = sdump_func;                                  \
245         __##ent##_test_data_foreach(td, __##ent##_snapshot_write_func, &param);\
246         fclose(param.fp);                                               \
247                                                                         \
248         return (0);                                                     \
249 }                                                                       \
250                                                                         \
251 int                                                                     \
252 __##ent##_snapshot_read(char const *fname, struct ent##_test_data *td,  \
253         int (*read_func)(struct ent *, char *))                         \
254 {                                                                       \
255         char buffer[1024];                                              \
256         struct ent data;                                                \
257         char *s;                                                        \
258         FILE *fi;                                                       \
259         size_t len;                                                     \
260         int rv;                                                         \
261                                                                         \
262         assert(fname != NULL);                                          \
263         assert(td != NULL);                                             \
264                                                                         \
265         fi = fopen(fname, "r");                                         \
266         if (fi == NULL)                                                 \
267                 return (-1);                                            \
268                                                                         \
269         rv = 0;                                                         \
270         memset(buffer, 0, sizeof(buffer));                              \
271         while (!feof(fi)) {                                             \
272                 s = fgets(buffer, sizeof(buffer), fi);                  \
273                 if (s != NULL && s[0] != '#') {                         \
274                         len = strlen(s);                                \
275                         if (len == 0)                                   \
276                                 continue;                               \
277                         if (buffer[len - 1] == '\n')                    \
278                                 buffer[len -1] = '\0';                  \
279                                                                         \
280                         rv = read_func(&data, s);                       \
281                         if (rv == 0) {                                  \
282                                 __##ent##_test_data_append(td, &data);  \
283                                 td->free_func(&data);                   \
284                         } else                                          \
285                                 goto fin;                               \
286                 }                                                       \
287         }                                                               \
288                                                                         \
289 fin:                                                                    \
290         fclose(fi);                                                     \
291         return (rv);                                                    \
292 }
293
294 #define DECLARE_1PASS_TEST(ent)                                         \
295 int __##ent##_1pass_test(struct ent##_test_data *,                      \
296         int (*)(struct ent *, void *),                                  \
297         void *);
298
299 #define DO_1PASS_TEST(ent, td, f, mdata)                                \
300         __##ent##_1pass_test(td, f, mdata)
301
302 #define IMPLEMENT_1PASS_TEST(ent)                                       \
303 int                                                                     \
304 __##ent##_1pass_test(struct ent##_test_data *td,                        \
305         int (*tf)(struct ent *, void *),                                \
306         void *mdata)                                                    \
307 {                                                                       \
308         int rv;                                                         \
309         rv = __##ent##_test_data_foreach(td, tf, mdata);                \
310                                                                         \
311         return (rv);                                                    \
312 }
313
314 #define DECLARE_2PASS_TEST(ent)                                         \
315 int __##ent##_2pass_test(struct ent##_test_data *,                      \
316         struct ent##_test_data *,                                       \
317         int (*)(struct ent *, struct ent *, void *), void *);
318
319 #define DO_2PASS_TEST(ent, td1, td2, f, mdata)                          \
320         __##ent##_2pass_test(td1, td2, f, mdata)
321
322 #define IMPLEMENT_2PASS_TEST(ent)                                       \
323 int                                                                     \
324 __##ent##_2pass_test(struct ent##_test_data *td1,                       \
325         struct ent##_test_data *td2,                                    \
326         int (*cmp_func)(struct ent *, struct ent *, void *),            \
327         void *cmp_mdata)                                                \
328 {                                                                       \
329         int rv;                                                         \
330                                                                         \
331         rv = __##ent##_test_data_compare(td1, td2, cmp_func, cmp_mdata);        \
332         return (rv);                                                    \
333 }