testutil.h revision 292323
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 292323 2015-12-16 08:09:03Z 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 char buffer[1024]; \ 256168754Sbushman struct ent data; \ 257168754Sbushman char *s; \ 258168754Sbushman FILE *fi; \ 259168754Sbushman size_t len; \ 260168754Sbushman int rv; \ 261168754Sbushman \ 262292323Sngie ATF_REQUIRE(fname != NULL); \ 263292323Sngie ATF_REQUIRE(td != NULL); \ 264168754Sbushman \ 265168754Sbushman fi = fopen(fname, "r"); \ 266168754Sbushman if (fi == NULL) \ 267168754Sbushman return (-1); \ 268168754Sbushman \ 269168754Sbushman rv = 0; \ 270168754Sbushman memset(buffer, 0, sizeof(buffer)); \ 271168754Sbushman while (!feof(fi)) { \ 272168754Sbushman s = fgets(buffer, sizeof(buffer), fi); \ 273168754Sbushman if (s != NULL && s[0] != '#') { \ 274168754Sbushman len = strlen(s); \ 275168754Sbushman if (len == 0) \ 276168754Sbushman continue; \ 277168754Sbushman if (buffer[len - 1] == '\n') \ 278168754Sbushman buffer[len -1] = '\0'; \ 279168754Sbushman \ 280168754Sbushman rv = read_func(&data, s); \ 281168754Sbushman if (rv == 0) { \ 282168754Sbushman __##ent##_test_data_append(td, &data); \ 283168754Sbushman td->free_func(&data); \ 284168754Sbushman } else \ 285168754Sbushman goto fin; \ 286168754Sbushman } \ 287168754Sbushman } \ 288168754Sbushman \ 289168754Sbushmanfin: \ 290168754Sbushman fclose(fi); \ 291168754Sbushman return (rv); \ 292168754Sbushman} 293168754Sbushman 294168754Sbushman#define DECLARE_1PASS_TEST(ent) \ 295168754Sbushmanint __##ent##_1pass_test(struct ent##_test_data *, \ 296168754Sbushman int (*)(struct ent *, void *), \ 297291363Sngie void *); 298291363Sngie 299168754Sbushman#define DO_1PASS_TEST(ent, td, f, mdata) \ 300168754Sbushman __##ent##_1pass_test(td, f, mdata) 301168754Sbushman 302168754Sbushman#define IMPLEMENT_1PASS_TEST(ent) \ 303168754Sbushmanint \ 304168754Sbushman__##ent##_1pass_test(struct ent##_test_data *td, \ 305168754Sbushman int (*tf)(struct ent *, void *), \ 306168754Sbushman void *mdata) \ 307168754Sbushman{ \ 308168754Sbushman int rv; \ 309168754Sbushman rv = __##ent##_test_data_foreach(td, tf, mdata); \ 310168754Sbushman \ 311168754Sbushman return (rv); \ 312168754Sbushman} 313168754Sbushman 314168754Sbushman#define DECLARE_2PASS_TEST(ent) \ 315168754Sbushmanint __##ent##_2pass_test(struct ent##_test_data *, \ 316168754Sbushman struct ent##_test_data *, \ 317168754Sbushman int (*)(struct ent *, struct ent *, void *), void *); 318168754Sbushman 319168754Sbushman#define DO_2PASS_TEST(ent, td1, td2, f, mdata) \ 320168754Sbushman __##ent##_2pass_test(td1, td2, f, mdata) 321291363Sngie 322168754Sbushman#define IMPLEMENT_2PASS_TEST(ent) \ 323168754Sbushmanint \ 324168754Sbushman__##ent##_2pass_test(struct ent##_test_data *td1, \ 325168754Sbushman struct ent##_test_data *td2, \ 326168754Sbushman int (*cmp_func)(struct ent *, struct ent *, void *), \ 327168754Sbushman void *cmp_mdata) \ 328168754Sbushman{ \ 329168754Sbushman int rv; \ 330168754Sbushman \ 331168754Sbushman rv = __##ent##_test_data_compare(td1, td2, cmp_func, cmp_mdata); \ 332168754Sbushman return (rv); \ 333168754Sbushman} 334