testutil.h revision 291363
1168754Sbushman/*- 2168754Sbushman * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> 3168754Sbushman * 4168754Sbushman * Redistribution and use in source and binary forms, with or without 5168754Sbushman * modification, are permitted provided that the following conditions 6168754Sbushman * are met: 7168754Sbushman * 1. Redistributions of source code must retain the above copyright 8168754Sbushman * notice, this list of conditions and the following disclaimer. 9168754Sbushman * 2. Redistributions in binary form must reproduce the above copyright 10168754Sbushman * notice, this list of conditions and the following disclaimer in the 11168754Sbushman * documentation and/or other materials provided with the distribution. 12168754Sbushman * 13168754Sbushman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14168754Sbushman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15168754Sbushman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16168754Sbushman * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17168754Sbushman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18168754Sbushman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19168754Sbushman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20168754Sbushman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21168754Sbushman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22168754Sbushman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23168754Sbushman * SUCH DAMAGE. 24168754Sbushman * 25168754Sbushman * $FreeBSD: head/tools/regression/lib/libc/nss/testutil.h 291363 2015-11-26 08:58:13Z ngie $ 26168754Sbushman */ 27168754Sbushman 28168754Sbushman#include <sys/queue.h> 29168754Sbushman 30168754Sbushman#define DECLARE_TEST_DATA(ent) \ 31168754Sbushmanstruct ent##_entry { \ 32168754Sbushman struct ent data; \ 33168754Sbushman STAILQ_ENTRY(ent##_entry) entries; \ 34168754Sbushman}; \ 35168754Sbushman \ 36168754Sbushmanstruct ent##_test_data { \ 37168754Sbushman void (*clone_func)(struct ent *, struct ent const *); \ 38168754Sbushman void (*free_func)(struct ent *); \ 39168754Sbushman \ 40168754Sbushman STAILQ_HEAD(ent_head, ent##_entry) snapshot_data; \ 41168754Sbushman}; \ 42168754Sbushman \ 43168754Sbushmanvoid __##ent##_test_data_init(struct ent##_test_data *, \ 44168754Sbushman void (*)(struct ent *, struct ent const *), \ 45168754Sbushman void (*freef)(struct ent *)); \ 46168754Sbushmanvoid __##ent##_test_data_destroy(struct ent##_test_data *); \ 47168754Sbushman \ 48168754Sbushmanvoid __##ent##_test_data_append(struct ent##_test_data *, struct ent *data);\ 49168754Sbushmanint __##ent##_test_data_foreach(struct ent##_test_data *, \ 50168754Sbushman int (*)(struct ent *, void *), void *); \ 51168754Sbushmanint __##ent##_test_data_compare(struct ent##_test_data *, \ 52168754Sbushman struct ent##_test_data *, int (*)(struct ent *, struct ent *, \ 53168754Sbushman void *), void *); \ 54168754Sbushmanstruct ent *__##ent##_test_data_find(struct ent##_test_data *, struct ent *,\ 55168754Sbushman int (*)(struct ent *, struct ent *, void *), void *); \ 56291363Sngievoid __##ent##_test_data_clear(struct ent##_test_data *); 57291363Sngie 58168754Sbushman#define TEST_DATA_INIT(ent, td, clonef, freef)\ 59168754Sbushman __##ent##_test_data_init(td, clonef, freef) 60168754Sbushman#define TEST_DATA_DESTROY(ent, td) __##ent##_test_data_destroy(td) 61168754Sbushman#define TEST_DATA_APPEND(ent, td, d) __##ent##_test_data_append(td, d) 62168754Sbushman#define TEST_DATA_FOREACH(ent, td, f, mdata)\ 63168754Sbushman __##ent##_test_data_foreach(td, f, mdata) 64168754Sbushman#define TEST_DATA_COMPARE(ent, td1, td2, fcmp, mdata)\ 65168754Sbushman __##ent##_test_data_compare(td1, td2, fcmp, mdata); 66168754Sbushman#define TEST_DATA_FIND(ent, td, d, fcmp, mdata)\ 67168754Sbushman __##ent##_test_data_find(td, d, fcmp, mdata) 68168754Sbushman#define TEST_DATA_CLEAR(ent, td) __##ent##_test_data_clear(td) 69168754Sbushman 70168754Sbushman#define IMPLEMENT_TEST_DATA(ent) \ 71168754Sbushmanvoid \ 72168754Sbushman__##ent##_test_data_init(struct ent##_test_data *td, \ 73168754Sbushman void (*clonef)(struct ent *, struct ent const *), \ 74168754Sbushman void (*freef)(struct ent *)) \ 75168754Sbushman{ \ 76168754Sbushman assert(td != NULL); \ 77168754Sbushman assert(clonef != NULL); \ 78168754Sbushman assert(freef != NULL); \ 79168754Sbushman \ 80168754Sbushman memset(td, 0, sizeof(*td)); \ 81168754Sbushman td->clone_func = clonef; \ 82168754Sbushman td->free_func = freef; \ 83168754Sbushman STAILQ_INIT(&td->snapshot_data); \ 84168754Sbushman} \ 85168754Sbushman \ 86168754Sbushmanvoid \ 87168754Sbushman__##ent##_test_data_destroy(struct ent##_test_data *td) \ 88168754Sbushman{ \ 89168754Sbushman __##ent##_test_data_clear(td); \ 90168754Sbushman} \ 91168754Sbushman \ 92168754Sbushmanvoid \ 93168754Sbushman__##ent##_test_data_append(struct ent##_test_data *td, struct ent *app_data)\ 94168754Sbushman{ \ 95168754Sbushman struct ent##_entry *e; \ 96168754Sbushman \ 97168754Sbushman assert(td != NULL); \ 98168754Sbushman assert(app_data != NULL); \ 99168754Sbushman \ 100168754Sbushman e = (struct ent##_entry *)malloc(sizeof(struct ent##_entry)); \ 101168754Sbushman assert(e != NULL); \ 102168754Sbushman memset(e, 0, sizeof(struct ent##_entry)); \ 103168754Sbushman \ 104168754Sbushman td->clone_func(&e->data, app_data); \ 105168754Sbushman STAILQ_INSERT_TAIL(&td->snapshot_data, e, entries); \ 106168754Sbushman} \ 107168754Sbushman \ 108168754Sbushmanint \ 109168754Sbushman__##ent##_test_data_foreach(struct ent##_test_data *td, \ 110168754Sbushman int (*forf)(struct ent *, void *), void *mdata) \ 111168754Sbushman{ \ 112168754Sbushman struct ent##_entry *e; \ 113168754Sbushman int rv; \ 114168754Sbushman \ 115168754Sbushman assert(td != NULL); \ 116168754Sbushman assert(forf != NULL); \ 117168754Sbushman \ 118168754Sbushman rv = 0; \ 119168754Sbushman STAILQ_FOREACH(e, &td->snapshot_data, entries) { \ 120168754Sbushman rv = forf(&e->data, mdata); \ 121168754Sbushman if (rv != 0) \ 122168754Sbushman break; \ 123168754Sbushman } \ 124168754Sbushman \ 125168754Sbushman return (rv); \ 126168754Sbushman} \ 127168754Sbushman \ 128168754Sbushmanint \ 129168754Sbushman__##ent##_test_data_compare(struct ent##_test_data *td1, struct ent##_test_data *td2,\ 130168754Sbushman int (*cmp_func)(struct ent *, struct ent *, void *), void *mdata)\ 131168754Sbushman{ \ 132168754Sbushman struct ent##_entry *e1, *e2; \ 133168754Sbushman int rv; \ 134168754Sbushman \ 135168754Sbushman assert(td1 != NULL); \ 136168754Sbushman assert(td2 != NULL); \ 137168754Sbushman assert(cmp_func != NULL); \ 138168754Sbushman \ 139168754Sbushman e1 = STAILQ_FIRST(&td1->snapshot_data); \ 140168754Sbushman e2 = STAILQ_FIRST(&td2->snapshot_data); \ 141168754Sbushman \ 142168754Sbushman rv = 0; \ 143168754Sbushman do { \ 144168754Sbushman if ((e1 == NULL) || (e2 == NULL)) { \ 145168754Sbushman if (e1 == e2) \ 146168754Sbushman return (0); \ 147168754Sbushman else \ 148168754Sbushman return (-1); \ 149168754Sbushman } \ 150168754Sbushman \ 151168754Sbushman rv = cmp_func(&e1->data, &e2->data, mdata); \ 152168754Sbushman e1 = STAILQ_NEXT(e1, entries); \ 153168754Sbushman e2 = STAILQ_NEXT(e2, entries); \ 154168754Sbushman } while (rv == 0); \ 155168754Sbushman \ 156168754Sbushman return (rv); \ 157168754Sbushman} \ 158168754Sbushman \ 159168754Sbushmanstruct ent * \ 160168754Sbushman__##ent##_test_data_find(struct ent##_test_data *td, struct ent *data, \ 161168754Sbushman int (*cmp)(struct ent *, struct ent *, void *), void *mdata) \ 162168754Sbushman{ \ 163168754Sbushman struct ent##_entry *e; \ 164168754Sbushman struct ent *result; \ 165168754Sbushman \ 166168754Sbushman assert(td != NULL); \ 167168754Sbushman assert(cmp != NULL); \ 168168754Sbushman \ 169168754Sbushman result = NULL; \ 170168754Sbushman STAILQ_FOREACH(e, &td->snapshot_data, entries) { \ 171168754Sbushman if (cmp(&e->data, data, mdata) == 0) { \ 172168754Sbushman result = &e->data; \ 173168754Sbushman break; \ 174168754Sbushman } \ 175168754Sbushman } \ 176168754Sbushman \ 177168754Sbushman return (result); \ 178168754Sbushman} \ 179168754Sbushman \ 180168754Sbushman \ 181168754Sbushmanvoid \ 182168754Sbushman__##ent##_test_data_clear(struct ent##_test_data *td) \ 183168754Sbushman{ \ 184168754Sbushman struct ent##_entry *e; \ 185168754Sbushman assert(td != NULL); \ 186168754Sbushman \ 187168754Sbushman while (!STAILQ_EMPTY(&td->snapshot_data)) { \ 188168754Sbushman e = STAILQ_FIRST(&td->snapshot_data); \ 189168754Sbushman STAILQ_REMOVE_HEAD(&td->snapshot_data, entries); \ 190168754Sbushman \ 191168754Sbushman td->free_func(&e->data); \ 192168754Sbushman free(e); \ 193168754Sbushman } \ 194291363Sngie} 195168754Sbushman 196168754Sbushman#define DECLARE_TEST_FILE_SNAPSHOT(ent) \ 197168754Sbushmanstruct ent##_snp_param { \ 198168754Sbushman FILE *fp; \ 199168754Sbushman void (*sdump_func)(struct ent *, char *, size_t); \ 200168754Sbushman}; \ 201168754Sbushman \ 202168754Sbushmanint __##ent##_snapshot_write_func(struct ent *, void *); \ 203168754Sbushmanint __##ent##_snapshot_write(char const *, struct ent##_test_data *, \ 204168754Sbushman void (*)(struct ent *, char *, size_t)); \ 205168754Sbushmanint __##ent##_snapshot_read(char const *, struct ent##_test_data *, \ 206291363Sngie int (*)(struct ent *, char *)); 207291363Sngie 208168754Sbushman#define TEST_SNAPSHOT_FILE_WRITE(ent, fname, td, f) \ 209168754Sbushman __##ent##_snapshot_write(fname, td, f) 210168754Sbushman#define TEST_SNAPSHOT_FILE_READ(ent, fname, td, f) \ 211168754Sbushman __##ent##_snapshot_read(fname, td, f) 212168754Sbushman 213168754Sbushman#define IMPLEMENT_TEST_FILE_SNAPSHOT(ent) \ 214168754Sbushmanint \ 215168754Sbushman__##ent##_snapshot_write_func(struct ent *data, void *mdata) \ 216168754Sbushman{ \ 217168754Sbushman char buffer[1024]; \ 218168754Sbushman struct ent##_snp_param *param; \ 219168754Sbushman \ 220168754Sbushman assert(data != NULL); \ 221168754Sbushman \ 222168754Sbushman param = (struct ent##_snp_param *)mdata; \ 223168754Sbushman param->sdump_func(data, buffer, sizeof(buffer)); \ 224168754Sbushman fputs(buffer, param->fp); \ 225168754Sbushman fputc('\n', param->fp); \ 226168754Sbushman \ 227168754Sbushman return (0); \ 228168754Sbushman} \ 229168754Sbushman \ 230168754Sbushmanint \ 231168754Sbushman__##ent##_snapshot_write(char const *fname, struct ent##_test_data *td, \ 232168754Sbushman void (*sdump_func)(struct ent *, char *, size_t)) \ 233168754Sbushman{ \ 234168754Sbushman struct ent##_snp_param param; \ 235168754Sbushman \ 236168754Sbushman assert(fname != NULL); \ 237168754Sbushman assert(td != NULL); \ 238168754Sbushman \ 239168754Sbushman param.fp = fopen(fname, "w"); \ 240168754Sbushman if (param.fp == NULL) \ 241168754Sbushman return (-1); \ 242168754Sbushman \ 243168754Sbushman param.sdump_func = sdump_func; \ 244168754Sbushman __##ent##_test_data_foreach(td, __##ent##_snapshot_write_func, ¶m);\ 245168754Sbushman fclose(param.fp); \ 246168754Sbushman \ 247168754Sbushman return (0); \ 248168754Sbushman} \ 249168754Sbushman \ 250168754Sbushmanint \ 251168754Sbushman__##ent##_snapshot_read(char const *fname, struct ent##_test_data *td, \ 252168754Sbushman int (*read_func)(struct ent *, char *)) \ 253168754Sbushman{ \ 254168754Sbushman char buffer[1024]; \ 255168754Sbushman struct ent data; \ 256168754Sbushman char *s; \ 257168754Sbushman FILE *fi; \ 258168754Sbushman size_t len; \ 259168754Sbushman int rv; \ 260168754Sbushman \ 261168754Sbushman assert(fname != NULL); \ 262168754Sbushman assert(td != NULL); \ 263168754Sbushman \ 264168754Sbushman fi = fopen(fname, "r"); \ 265168754Sbushman if (fi == NULL) \ 266168754Sbushman return (-1); \ 267168754Sbushman \ 268168754Sbushman rv = 0; \ 269168754Sbushman memset(buffer, 0, sizeof(buffer)); \ 270168754Sbushman while (!feof(fi)) { \ 271168754Sbushman s = fgets(buffer, sizeof(buffer), fi); \ 272168754Sbushman if (s != NULL && s[0] != '#') { \ 273168754Sbushman len = strlen(s); \ 274168754Sbushman if (len == 0) \ 275168754Sbushman continue; \ 276168754Sbushman if (buffer[len - 1] == '\n') \ 277168754Sbushman buffer[len -1] = '\0'; \ 278168754Sbushman \ 279168754Sbushman rv = read_func(&data, s); \ 280168754Sbushman if (rv == 0) { \ 281168754Sbushman __##ent##_test_data_append(td, &data); \ 282168754Sbushman td->free_func(&data); \ 283168754Sbushman } else \ 284168754Sbushman goto fin; \ 285168754Sbushman } \ 286168754Sbushman } \ 287168754Sbushman \ 288168754Sbushmanfin: \ 289168754Sbushman fclose(fi); \ 290168754Sbushman return (rv); \ 291168754Sbushman} 292168754Sbushman 293168754Sbushman#define DECLARE_1PASS_TEST(ent) \ 294168754Sbushmanint __##ent##_1pass_test(struct ent##_test_data *, \ 295168754Sbushman int (*)(struct ent *, void *), \ 296291363Sngie void *); 297291363Sngie 298168754Sbushman#define DO_1PASS_TEST(ent, td, f, mdata) \ 299168754Sbushman __##ent##_1pass_test(td, f, mdata) 300168754Sbushman 301168754Sbushman#define IMPLEMENT_1PASS_TEST(ent) \ 302168754Sbushmanint \ 303168754Sbushman__##ent##_1pass_test(struct ent##_test_data *td, \ 304168754Sbushman int (*tf)(struct ent *, void *), \ 305168754Sbushman void *mdata) \ 306168754Sbushman{ \ 307168754Sbushman int rv; \ 308168754Sbushman rv = __##ent##_test_data_foreach(td, tf, mdata); \ 309168754Sbushman \ 310168754Sbushman return (rv); \ 311168754Sbushman} 312168754Sbushman 313168754Sbushman#define DECLARE_2PASS_TEST(ent) \ 314168754Sbushmanint __##ent##_2pass_test(struct ent##_test_data *, \ 315168754Sbushman struct ent##_test_data *, \ 316168754Sbushman int (*)(struct ent *, struct ent *, void *), void *); 317168754Sbushman 318168754Sbushman#define DO_2PASS_TEST(ent, td1, td2, f, mdata) \ 319168754Sbushman __##ent##_2pass_test(td1, td2, f, mdata) 320291363Sngie 321168754Sbushman#define IMPLEMENT_2PASS_TEST(ent) \ 322168754Sbushmanint \ 323168754Sbushman__##ent##_2pass_test(struct ent##_test_data *td1, \ 324168754Sbushman struct ent##_test_data *td2, \ 325168754Sbushman int (*cmp_func)(struct ent *, struct ent *, void *), \ 326168754Sbushman void *cmp_mdata) \ 327168754Sbushman{ \ 328168754Sbushman int rv; \ 329168754Sbushman \ 330168754Sbushman rv = __##ent##_test_data_compare(td1, td2, cmp_func, cmp_mdata); \ 331168754Sbushman return (rv); \ 332168754Sbushman} 333