]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - tools/regression/lib/libc/nss/testutil.h
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / tools / regression / lib / libc / nss / testutil.h
1 /*-
2  * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  * $FreeBSD$
26  */
27
28 #include <sys/queue.h>
29
30 #define DECLARE_TEST_DATA(ent)                                          \
31 struct ent##_entry {                                                    \
32         struct ent data;                                                \
33         STAILQ_ENTRY(ent##_entry) entries;                              \
34 };                                                                      \
35                                                                         \
36 struct ent##_test_data {                                                \
37         void (*clone_func)(struct ent *, struct ent const *);           \
38         void (*free_func)(struct ent *);                                \
39                                                                         \
40         STAILQ_HEAD(ent_head, ent##_entry) snapshot_data;               \
41 };                                                                      \
42                                                                         \
43 void __##ent##_test_data_init(struct ent##_test_data *,                 \
44         void (*)(struct ent *, struct ent const *),                     \
45         void (*freef)(struct ent *));                                   \
46 void __##ent##_test_data_destroy(struct ent##_test_data *);             \
47                                                                         \
48 void __##ent##_test_data_append(struct ent##_test_data *, struct ent *data);\
49 int __##ent##_test_data_foreach(struct ent##_test_data *,               \
50         int (*)(struct ent *, void *), void *);                         \
51 int __##ent##_test_data_compare(struct ent##_test_data *,               \
52         struct ent##_test_data *, int (*)(struct ent *, struct ent *,   \
53         void *), void *);                                               \
54 struct ent *__##ent##_test_data_find(struct ent##_test_data *, struct ent *,\
55         int (*)(struct ent *, struct ent *, void *), void *);           \
56 void __##ent##_test_data_clear(struct ent##_test_data *);                       
57         
58 #define TEST_DATA_INIT(ent, td, clonef, freef)\
59         __##ent##_test_data_init(td, clonef, freef)
60 #define TEST_DATA_DESTROY(ent, td) __##ent##_test_data_destroy(td)
61 #define TEST_DATA_APPEND(ent, td, d) __##ent##_test_data_append(td, d)
62 #define TEST_DATA_FOREACH(ent, td, f, mdata)\
63         __##ent##_test_data_foreach(td, f, mdata)
64 #define TEST_DATA_COMPARE(ent, td1, td2, fcmp, mdata)\
65         __##ent##_test_data_compare(td1, td2, fcmp, mdata);
66 #define TEST_DATA_FIND(ent, td, d, fcmp, mdata)\
67         __##ent##_test_data_find(td, d, fcmp, mdata)
68 #define TEST_DATA_CLEAR(ent, td) __##ent##_test_data_clear(td)
69
70 #define IMPLEMENT_TEST_DATA(ent)                                        \
71 void                                                                    \
72 __##ent##_test_data_init(struct ent##_test_data *td,                    \
73         void (*clonef)(struct ent *, struct ent const *),               \
74         void (*freef)(struct ent *))                                    \
75 {                                                                       \
76         assert(td != NULL);                                             \
77         assert(clonef != NULL);                                         \
78         assert(freef != NULL);                                          \
79                                                                         \
80         memset(td, 0, sizeof(*td));                                     \
81         td->clone_func = clonef;                                        \
82         td->free_func = freef;                                          \
83         STAILQ_INIT(&td->snapshot_data);                                \
84 }                                                                       \
85                                                                         \
86 void                                                                    \
87 __##ent##_test_data_destroy(struct ent##_test_data *td)                 \
88 {                                                                       \
89         __##ent##_test_data_clear(td);                                  \
90 }                                                                       \
91                                                                         \
92 void                                                                    \
93 __##ent##_test_data_append(struct ent##_test_data *td, struct ent *app_data)\
94 {                                                                       \
95         struct ent##_entry *e;                                          \
96                                                                         \
97         assert(td != NULL);                                             \
98         assert(app_data != NULL);                                       \
99                                                                         \
100         e = (struct ent##_entry *)malloc(sizeof(struct ent##_entry));   \
101         assert(e != NULL);                                              \
102         memset(e, 0, sizeof(struct ent##_entry));                       \
103                                                                         \
104         td->clone_func(&e->data, app_data);                             \
105         STAILQ_INSERT_TAIL(&td->snapshot_data, e, entries);             \
106 }                                                                       \
107                                                                         \
108 int                                                                     \
109 __##ent##_test_data_foreach(struct ent##_test_data *td,                 \
110         int (*forf)(struct ent *, void *), void *mdata)                 \
111 {                                                                       \
112         struct ent##_entry *e;                                          \
113         int rv;                                                         \
114                                                                         \
115         assert(td != NULL);                                             \
116         assert(forf != NULL);                                           \
117                                                                         \
118         rv = 0;                                                         \
119         STAILQ_FOREACH(e, &td->snapshot_data, entries) {                \
120                 rv = forf(&e->data, mdata);                             \
121                 if (rv != 0)                                            \
122                         break;                                          \
123         }                                                               \
124                                                                         \
125         return (rv);                                                    \
126 }                                                                       \
127                                                                         \
128 int                                                                     \
129 __##ent##_test_data_compare(struct ent##_test_data *td1, struct ent##_test_data *td2,\
130         int (*cmp_func)(struct ent *, struct ent *, void *), void *mdata)\
131 {                                                                       \
132         struct ent##_entry *e1, *e2;                                    \
133         int rv;                                                         \
134                                                                         \
135         assert(td1 != NULL);                                            \
136         assert(td2 != NULL);                                            \
137         assert(cmp_func != NULL);                                       \
138                                                                         \
139         e1 = STAILQ_FIRST(&td1->snapshot_data);                         \
140         e2 = STAILQ_FIRST(&td2->snapshot_data);                         \
141                                                                         \
142         rv = 0;                                                         \
143         do {                                                            \
144                 if ((e1 == NULL) || (e2 == NULL)) {                     \
145                         if (e1 == e2)                                   \
146                                 return (0);                             \
147                         else                                            \
148                                 return (-1);                            \
149                 }                                                       \
150                                                                         \
151                 rv = cmp_func(&e1->data, &e2->data, mdata);             \
152                 e1 = STAILQ_NEXT(e1, entries);                          \
153                 e2 = STAILQ_NEXT(e2, entries);                          \
154         } while (rv == 0);                                              \
155                                                                         \
156         return (rv);                                                    \
157 }                                                                       \
158                                                                         \
159 struct ent *                                                            \
160 __##ent##_test_data_find(struct ent##_test_data *td, struct ent *data,  \
161         int (*cmp)(struct ent *, struct ent *, void *), void *mdata)    \
162 {                                                                       \
163         struct ent##_entry *e;                                          \
164         struct ent *result;                                             \
165                                                                         \
166         assert(td != NULL);                                             \
167         assert(cmp != NULL);                                            \
168                                                                         \
169         result = NULL;                                                  \
170         STAILQ_FOREACH(e, &td->snapshot_data, entries) {                \
171                 if (cmp(&e->data, data, mdata) == 0) {                  \
172                         result = &e->data;                              \
173                         break;                                          \
174                 }                                                       \
175         }                                                               \
176                                                                         \
177         return (result);                                                \
178 }                                                                       \
179                                                                         \
180                                                                         \
181 void                                                                    \
182 __##ent##_test_data_clear(struct ent##_test_data *td)                   \
183 {                                                                       \
184         struct ent##_entry *e;                                          \
185         assert(td != NULL);                                             \
186                                                                         \
187         while (!STAILQ_EMPTY(&td->snapshot_data)) {                     \
188                 e = STAILQ_FIRST(&td->snapshot_data);                   \
189                 STAILQ_REMOVE_HEAD(&td->snapshot_data, entries);        \
190                                                                         \
191                 td->free_func(&e->data);                                \
192                 free(e);                                                \
193         }                                                               \
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 }