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