testutil.h revision 299654
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/lib/libc/tests/nss/testutil.h 299654 2016-05-13 10:52:02Z 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{ \ 76292323Sngie ATF_REQUIRE(td != NULL); \ 77292323Sngie ATF_REQUIRE(clonef != NULL); \ 78292323Sngie ATF_REQUIRE(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 \ 97292323Sngie ATF_REQUIRE(td != NULL); \ 98292323Sngie ATF_REQUIRE(app_data != NULL); \ 99168754Sbushman \ 100168754Sbushman e = (struct ent##_entry *)malloc(sizeof(struct ent##_entry)); \ 101292323Sngie ATF_REQUIRE(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 \ 115292323Sngie ATF_REQUIRE(td != NULL); \ 116292323Sngie ATF_REQUIRE(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 \ 135292323Sngie ATF_REQUIRE(td1 != NULL); \ 136292323Sngie ATF_REQUIRE(td2 != NULL); \ 137292323Sngie ATF_REQUIRE(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 \ 166292323Sngie ATF_REQUIRE(td != NULL); \ 167292323Sngie ATF_REQUIRE(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; \ 185292323Sngie ATF_REQUIRE(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); \ 193292323Sngie e = NULL; \ 194168754Sbushman } \ 195291363Sngie} 196168754Sbushman 197168754Sbushman#define DECLARE_TEST_FILE_SNAPSHOT(ent) \ 198168754Sbushmanstruct ent##_snp_param { \ 199168754Sbushman FILE *fp; \ 200168754Sbushman void (*sdump_func)(struct ent *, char *, size_t); \ 201168754Sbushman}; \ 202168754Sbushman \ 203168754Sbushmanint __##ent##_snapshot_write_func(struct ent *, void *); \ 204168754Sbushmanint __##ent##_snapshot_write(char const *, struct ent##_test_data *, \ 205168754Sbushman void (*)(struct ent *, char *, size_t)); \ 206168754Sbushmanint __##ent##_snapshot_read(char const *, struct ent##_test_data *, \ 207291363Sngie int (*)(struct ent *, char *)); 208291363Sngie 209168754Sbushman#define TEST_SNAPSHOT_FILE_WRITE(ent, fname, td, f) \ 210168754Sbushman __##ent##_snapshot_write(fname, td, f) 211168754Sbushman#define TEST_SNAPSHOT_FILE_READ(ent, fname, td, f) \ 212168754Sbushman __##ent##_snapshot_read(fname, td, f) 213168754Sbushman 214168754Sbushman#define IMPLEMENT_TEST_FILE_SNAPSHOT(ent) \ 215168754Sbushmanint \ 216168754Sbushman__##ent##_snapshot_write_func(struct ent *data, void *mdata) \ 217168754Sbushman{ \ 218168754Sbushman char buffer[1024]; \ 219168754Sbushman struct ent##_snp_param *param; \ 220168754Sbushman \ 221292323Sngie ATF_REQUIRE(data != NULL); \ 222168754Sbushman \ 223168754Sbushman param = (struct ent##_snp_param *)mdata; \ 224168754Sbushman param->sdump_func(data, buffer, sizeof(buffer)); \ 225168754Sbushman fputs(buffer, param->fp); \ 226168754Sbushman fputc('\n', param->fp); \ 227168754Sbushman \ 228168754Sbushman return (0); \ 229168754Sbushman} \ 230168754Sbushman \ 231168754Sbushmanint \ 232168754Sbushman__##ent##_snapshot_write(char const *fname, struct ent##_test_data *td, \ 233168754Sbushman void (*sdump_func)(struct ent *, char *, size_t)) \ 234168754Sbushman{ \ 235168754Sbushman struct ent##_snp_param param; \ 236168754Sbushman \ 237292323Sngie ATF_REQUIRE(fname != NULL); \ 238292323Sngie ATF_REQUIRE(td != NULL); \ 239168754Sbushman \ 240168754Sbushman param.fp = fopen(fname, "w"); \ 241168754Sbushman if (param.fp == NULL) \ 242168754Sbushman return (-1); \ 243168754Sbushman \ 244168754Sbushman param.sdump_func = sdump_func; \ 245168754Sbushman __##ent##_test_data_foreach(td, __##ent##_snapshot_write_func, ¶m);\ 246168754Sbushman fclose(param.fp); \ 247168754Sbushman \ 248168754Sbushman return (0); \ 249168754Sbushman} \ 250168754Sbushman \ 251168754Sbushmanint \ 252168754Sbushman__##ent##_snapshot_read(char const *fname, struct ent##_test_data *td, \ 253168754Sbushman int (*read_func)(struct ent *, char *)) \ 254168754Sbushman{ \ 255168754Sbushman struct ent data; \ 256168754Sbushman FILE *fi; \ 257168754Sbushman size_t len; \ 258168754Sbushman int rv; \ 259168754Sbushman \ 260292323Sngie ATF_REQUIRE(fname != NULL); \ 261292323Sngie ATF_REQUIRE(td != NULL); \ 262168754Sbushman \ 263168754Sbushman fi = fopen(fname, "r"); \ 264168754Sbushman if (fi == NULL) \ 265168754Sbushman return (-1); \ 266168754Sbushman \ 267168754Sbushman rv = 0; \ 268168754Sbushman while (!feof(fi)) { \ 269299654Sngie char *buf = fgetln(fi, &len); \ 270299654Sngie if (buf == NULL || len <= 1) \ 271299654Sngie continue; \ 272299654Sngie if (buf[len - 1] == '\n') \ 273299654Sngie buf[len - 1] = '\0'; \ 274299654Sngie else \ 275299654Sngie buf[len] = '\0'; \ 276299654Sngie if (buf[0] == '#') \ 277299654Sngie continue; \ 278299654Sngie rv = read_func(&data, buf); \ 279299654Sngie if (rv == 0) { \ 280299654Sngie __##ent##_test_data_append(td, &data); \ 281299654Sngie td->free_func(&data); \ 282299654Sngie } else \ 283299654Sngie goto fin; \ 284168754Sbushman } \ 285168754Sbushman \ 286168754Sbushmanfin: \ 287168754Sbushman fclose(fi); \ 288168754Sbushman return (rv); \ 289168754Sbushman} 290168754Sbushman 291168754Sbushman#define DECLARE_1PASS_TEST(ent) \ 292168754Sbushmanint __##ent##_1pass_test(struct ent##_test_data *, \ 293168754Sbushman int (*)(struct ent *, void *), \ 294291363Sngie void *); 295291363Sngie 296168754Sbushman#define DO_1PASS_TEST(ent, td, f, mdata) \ 297168754Sbushman __##ent##_1pass_test(td, f, mdata) 298168754Sbushman 299168754Sbushman#define IMPLEMENT_1PASS_TEST(ent) \ 300168754Sbushmanint \ 301168754Sbushman__##ent##_1pass_test(struct ent##_test_data *td, \ 302168754Sbushman int (*tf)(struct ent *, void *), \ 303168754Sbushman void *mdata) \ 304168754Sbushman{ \ 305168754Sbushman int rv; \ 306168754Sbushman rv = __##ent##_test_data_foreach(td, tf, mdata); \ 307168754Sbushman \ 308168754Sbushman return (rv); \ 309168754Sbushman} 310168754Sbushman 311168754Sbushman#define DECLARE_2PASS_TEST(ent) \ 312168754Sbushmanint __##ent##_2pass_test(struct ent##_test_data *, \ 313168754Sbushman struct ent##_test_data *, \ 314168754Sbushman int (*)(struct ent *, struct ent *, void *), void *); 315168754Sbushman 316168754Sbushman#define DO_2PASS_TEST(ent, td1, td2, f, mdata) \ 317168754Sbushman __##ent##_2pass_test(td1, td2, f, mdata) 318291363Sngie 319168754Sbushman#define IMPLEMENT_2PASS_TEST(ent) \ 320168754Sbushmanint \ 321168754Sbushman__##ent##_2pass_test(struct ent##_test_data *td1, \ 322168754Sbushman struct ent##_test_data *td2, \ 323168754Sbushman int (*cmp_func)(struct ent *, struct ent *, void *), \ 324168754Sbushman void *cmp_mdata) \ 325168754Sbushman{ \ 326168754Sbushman int rv; \ 327168754Sbushman \ 328168754Sbushman rv = __##ent##_test_data_compare(td1, td2, cmp_func, cmp_mdata); \ 329168754Sbushman return (rv); \ 330168754Sbushman} 331