1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2015 Joyent, Inc. 14 */ 15 16 /* 17 * mergeq testing routines 18 */ 19 20 #include <mergeq.h> 21 #include <stdio.h> 22 #include <errno.h> 23 #include <string.h> 24 #include <stdlib.h> 25 26 const char * 27 _umem_debug_init() 28 { 29 return ("default,verbose"); 30 } 31 32 const char * 33 _umem_logging_init(void) 34 { 35 return ("fail,contents"); 36 } 37 38 void * 39 mergeq_alloc(size_t size) 40 { 41 return (malloc(size)); 42 } 43 44 /*ARGSUSED*/ 45 void 46 mergeq_free(void *buf, size_t size) 47 { 48 free(buf); 49 } 50 51 static int 52 mqt_int(void *first, void *second, void **outp, void *arg) 53 { 54 uintptr_t a, b, c; 55 a = (uintptr_t)first; 56 b = (uintptr_t)second; 57 c = a + b; 58 *outp = (void *)c; 59 60 return (0); 61 } 62 63 static int 64 mqt_append(void *first, void *second, void **outp, void *arg) 65 { 66 char *out; 67 68 /* Yes, this leaks, don't worry about it for the test */ 69 if (asprintf(&out, "%s%s", first, second) != -1) { 70 *outp = out; 71 return (0); 72 } 73 return (-1); 74 } 75 76 static int 77 mqt_fatal(void *first, void *second, void **outp, void *arg) 78 { 79 return (-1); 80 } 81 82 /* 83 * Test structures and cases. We really want mq_args to be a flexible array 84 * member, but then we cant initialize it. Thus we set a fixed size number of 85 * entries. 86 */ 87 typedef struct mq_test { 88 const char *mq_desc; /* test description/name */ 89 mergeq_proc_f *mq_proc; /* processing function */ 90 int mq_rval; /* mergeq_merge return value */ 91 int mq_uerr; /* user error, if any */ 92 boolean_t mq_strcmp; /* use strcmp rather than == */ 93 void *mq_result; /* expected result */ 94 void **mq_args; /* argument array */ 95 } mq_test_t; 96 97 static void *mqt_empty_args[] = { NULL }; 98 static void *mqt_single_args[] = { (void *)42, NULL }; 99 static void *mqt_double_args[] = { (void *)42, (void *)27, NULL }; 100 static void *mqt_wrap_args[] = { 101 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 102 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 103 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 104 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 105 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 106 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 107 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 108 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 109 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 110 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 111 (void *)1, (void *)1, (void *)1, (void *)1, NULL 112 }; 113 static void *mqt_grow_args[] = { 114 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 115 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 116 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 117 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 118 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 119 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 120 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 121 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 122 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 123 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 124 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 125 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 126 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 127 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 128 (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, 129 (void *)1, (void *)1, NULL 130 }; 131 static void *mqt_order_args[] = { "l", "e", "g", "e", "n", "d", " ", "o", "f", 132 " ", "z", "e", "l", "d", "a", NULL }; 133 134 135 static mq_test_t mq_tests[] = { 136 { "empty", mqt_int, 0, 0, B_FALSE, NULL, mqt_empty_args }, 137 { "single", mqt_int, 0, 0, B_FALSE, (void *)42, mqt_single_args }, 138 { "double", mqt_int, 0, 0, B_FALSE, (void *)69, mqt_double_args }, 139 { "wrap", mqt_int, 0, 0, B_FALSE, (void *)64, mqt_wrap_args }, 140 { "grow", mqt_int, 0, 0, B_FALSE, (void *)92, mqt_grow_args }, 141 { "fatal", mqt_fatal, MERGEQ_UERROR, -1, B_FALSE, NULL, 142 mqt_double_args }, 143 { "order", mqt_append, 0, 0, B_TRUE, "alegend of zeld", mqt_order_args } 144 }; 145 146 #define NMQ_TESTS (sizeof (mq_tests) / sizeof (mq_test_t)) 147 148 static void 149 mq_test_run(mergeq_t *mqp, mq_test_t *mqt) 150 { 151 int ret, err; 152 void **itemp = mqt->mq_args; 153 void *out; 154 155 while (*itemp != NULL) { 156 if ((ret = mergeq_add(mqp, *itemp)) != 0) { 157 (void) fprintf(stderr, 158 "test %s: failed to add item: %s\n", 159 mqt->mq_desc, strerror(errno)); 160 exit(1); 161 } 162 itemp++; 163 } 164 165 ret = mergeq_merge(mqp, mqt->mq_proc, NULL, &out, &err); 166 if (ret != mqt->mq_rval) { 167 (void) fprintf(stderr, "test %s: got incorrect rval. " 168 "Expected %d, got %d\n", mqt->mq_desc, mqt->mq_rval, ret); 169 exit(1); 170 } 171 172 if (ret == MERGEQ_UERROR && err != mqt->mq_uerr) { 173 (void) fprintf(stderr, "test %s: got incorrect user error. " 174 "Expected %d, got %d\n", mqt->mq_desc, mqt->mq_uerr, err); 175 exit(1); 176 } 177 178 if (ret == 0) { 179 if (mqt->mq_strcmp == B_TRUE && 180 strcmp(out, mqt->mq_result) != 0) { 181 (void) fprintf(stderr, "test %s: got unexpected " 182 "result: %s, expected %s\n", mqt->mq_desc, out, 183 mqt->mq_result); 184 exit(1); 185 } else if (mqt->mq_strcmp == B_FALSE && out != mqt->mq_result) { 186 (void) fprintf(stderr, "test %s: got unexpected " 187 "result: %p, expected %p\n", mqt->mq_desc, out, 188 mqt->mq_result); 189 exit(1); 190 } 191 } 192 } 193 194 int 195 main(void) 196 { 197 int ret, i, t; 198 mergeq_t *mqp; 199 int nthreads[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, -1 }; 200 201 for (t = 0; nthreads[t] != -1; t++) { 202 printf("Beginning tests with %d threads\n", nthreads[t]); 203 if ((ret = mergeq_init(&mqp, nthreads[t])) != 0) { 204 fprintf(stderr, "failed to init mergeq: %s\n", 205 strerror(errno)); 206 return (1); 207 } 208 209 for (i = 0; i < NMQ_TESTS; i++) { 210 mq_test_run(mqp, &mq_tests[i]); 211 } 212 213 mergeq_fini(mqp); 214 } 215 216 return (0); 217 } 218