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 *
_umem_debug_init()27 _umem_debug_init()
28 {
29 return ("default,verbose");
30 }
31
32 const char *
_umem_logging_init(void)33 _umem_logging_init(void)
34 {
35 return ("fail,contents");
36 }
37
38 void *
mergeq_alloc(size_t size)39 mergeq_alloc(size_t size)
40 {
41 return (malloc(size));
42 }
43
44 /*ARGSUSED*/
45 void
mergeq_free(void * buf,size_t size)46 mergeq_free(void *buf, size_t size)
47 {
48 free(buf);
49 }
50
51 static int
mqt_int(void * first,void * second,void ** outp,void * arg)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
mqt_append(void * first,void * second,void ** outp,void * arg)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
mqt_fatal(void * first,void * second,void ** outp,void * arg)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
mq_test_run(mergeq_t * mqp,mq_test_t * mqt)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
main(void)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