comparison test/callback_suite_aggrs/main.c @ 523:cd46e111bc4c

- new test/callback_suite_aggrs (currently ahead of checked-in dyncall code and won't compile, though, as with call_suite_aggrs; dc code will be checked in, soon)
author Tassilo Philipp
date Wed, 13 Apr 2022 14:59:57 +0200
parents
children 71c884e610f0
comparison
equal deleted inserted replaced
522:f7fec6699e21 523:cd46e111bc4c
1 /*
2
3 Package: dyncall
4 Library: test
5 File: test/callback_suite_aggrs/main.c
6 Description:
7 License:
8
9 Copyright (c) 2022 Tassilo Philipp <tphilipp@potion-studios.com>
10
11 Permission to use, copy, modify, and distribute this software for any
12 purpose with or without fee is hereby granted, provided that the above
13 copyright notice and this permission notice appear in all copies.
14
15 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
16 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
18 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <assert.h>
28 #include <string.h>
29 #include "dyncall_callback.h"
30 #include "globals.h"
31 #include "../common/platformInit.h"
32 #include "../common/platformInit.c" /* Impl. for functions only used in this translation unit */
33
34
35
36
37 static void print_usage(const char* appName)
38 {
39 printf("usage:\n\
40 %s [ from [to] ]\n\
41 where\n\
42 from, to: test range (0-based, runs single test if \"to\" is omitted)\n\
43 options\n\
44 -h help on usage\n\
45 \n\
46 ", appName);
47 }
48
49
50 static int find_agg_idx(int* len, const char* sig)
51 {
52 int i;
53 for(i=0; i<G_naggs; ++i) {
54 const char* agg_sig = G_agg_sigs[i];
55 int l = strlen(agg_sig);
56 if(len)
57 *len = l;
58 if(strncmp(agg_sig, sig, l) == 0)
59 return i;
60 }
61 return -1;
62 }
63
64
65 static int cmp(const char* signature)
66 {
67 char atype;
68 const char* sig = signature;
69 int pos = 0;
70 int s = 0;
71 while ( (atype = *sig) != '\0') {
72 switch(atype) {
73 case '_': sig += 2; /* skip cconv prefix */ continue;
74 case ')': ++sig; /* skip ret type separator */ continue;
75 case 'v': s = (sig > signature) && sig[-1] == ')'; /* assure this was the return type */ break; /*TODO:check that no return-arg was touched.*/
76 case 'B': s = ( V_B[pos] == K_B[pos] ); if (!s) printf("'%c':%d: %d != %d ; ", atype, pos, V_B[pos], K_B[pos]); break;
77 case 'c': s = ( V_c[pos] == K_c[pos] ); if (!s) printf("'%c':%d: %d != %d ; ", atype, pos, V_c[pos], K_c[pos]); break;
78 case 's': s = ( V_s[pos] == K_s[pos] ); if (!s) printf("'%c':%d: %d != %d ; ", atype, pos, V_s[pos], K_s[pos]); break;
79 case 'i': s = ( V_i[pos] == K_i[pos] ); if (!s) printf("'%c':%d: %d != %d ; ", atype, pos, V_i[pos], K_i[pos]); break;
80 case 'j': s = ( V_j[pos] == K_j[pos] ); if (!s) printf("'%c':%d: %ld != %ld ; ", atype, pos, V_j[pos], K_j[pos]); break;
81 case 'l': s = ( V_l[pos] == K_l[pos] ); if (!s) printf("'%c':%d: %lld != %lld ; ", atype, pos, V_l[pos], K_l[pos]); break;
82 case 'C': s = ( V_C[pos] == K_C[pos] ); if (!s) printf("'%c':%d: %u != %u ; ", atype, pos, V_C[pos], K_C[pos]); break;
83 case 'S': s = ( V_S[pos] == K_S[pos] ); if (!s) printf("'%c':%d: %u != %u ; ", atype, pos, V_S[pos], K_S[pos]); break;
84 case 'I': s = ( V_I[pos] == K_I[pos] ); if (!s) printf("'%c':%d: %u != %u ; ", atype, pos, V_I[pos], K_I[pos]); break;
85 case 'J': s = ( V_J[pos] == K_J[pos] ); if (!s) printf("'%c':%d: %lu != %lu ; ", atype, pos, V_J[pos], K_J[pos]); break;
86 case 'L': s = ( V_L[pos] == K_L[pos] ); if (!s) printf("'%c':%d: %llu != %llu ; ", atype, pos, V_L[pos], K_L[pos]); break;
87 case 'p': s = ( V_p[pos] == K_p[pos] ); if (!s) printf("'%c':%d: %p != %p ; ", atype, pos, V_p[pos], K_p[pos]); break;
88 case 'f': s = ( V_f[pos] == K_f[pos] ); if (!s) printf("'%c':%d: %f != %f ; ", atype, pos, V_f[pos], K_f[pos]); break;
89 case 'd': s = ( V_d[pos] == K_d[pos] ); if (!s) printf("'%c':%d: %f != %f ; ", atype, pos, V_d[pos], K_d[pos]); break;
90 case '<': /* union */
91 case '{': /* struct */
92 {
93 /* no check: guaranteed to exist, or invoke func would've exited when passing args, above */
94 int len;
95 int i = find_agg_idx(&len, sig);
96 s = ((int(*)(const void*,const void*))G_agg_cmpfuncs[i])(V_a[pos], K_a[pos]);
97 if (!s) printf("'%c':%d: *%p != *%p ; ", atype, pos, V_a[pos], K_a[pos]);
98 sig += len-1; /* advance to next arg char; -1 to compensate for ++sig, below */
99 break;
100 }
101 default: printf("unknown atype '%c' ; ", atype); return 0;
102 }
103 if(!s) {
104 printf("arg mismatch at %d ; ", pos);
105 return 0;
106 }
107 ++sig;
108 ++pos;
109 }
110 return 1;
111 }
112
113
114 /* handler just copies all received args as well as return value into V_* */
115 static char handler(DCCallback* that, DCArgs* input, DCValue* output, void* userdata)
116 {
117 const char* signature = (const char*) userdata;
118 int pos = 0;
119 char ch;
120
121 for(;;) {
122 ch = *signature++;
123 if (!ch || ch == DC_SIGCHAR_ENDARG) break;
124 switch(ch) {
125 case DC_SIGCHAR_BOOL: V_B[pos] = dcbArgBool (input); break;
126 case DC_SIGCHAR_CHAR: V_c[pos] = dcbArgChar (input); break;
127 case DC_SIGCHAR_UCHAR: V_C[pos] = dcbArgUChar (input); break;
128 case DC_SIGCHAR_SHORT: V_s[pos] = dcbArgShort (input); break;
129 case DC_SIGCHAR_USHORT: V_S[pos] = dcbArgUShort (input); break;
130 case DC_SIGCHAR_INT: V_i[pos] = dcbArgInt (input); break;
131 case DC_SIGCHAR_UINT: V_I[pos] = dcbArgUInt (input); break;
132 case DC_SIGCHAR_LONG: V_j[pos] = dcbArgLong (input); break;
133 case DC_SIGCHAR_ULONG: V_J[pos] = dcbArgULong (input); break;
134 case DC_SIGCHAR_LONGLONG: V_l[pos] = dcbArgLongLong (input); break;
135 case DC_SIGCHAR_ULONGLONG: V_L[pos] = dcbArgULongLong(input); break;
136 case DC_SIGCHAR_FLOAT: V_f[pos] = dcbArgFloat (input); break;
137 case DC_SIGCHAR_DOUBLE: V_d[pos] = dcbArgDouble (input); break;
138 case DC_SIGCHAR_STRING:
139 case DC_SIGCHAR_POINTER: V_p[pos] = dcbArgPointer (input); break;
140 case DC_SIGCHAR_AGGREGATE: dcbArgAggr (input, V_a[pos]); break;
141 case DC_SIGCHAR_CC_PREFIX: ++signature; /* skip cconv prefix */ continue;
142 default: assert(0);
143 }
144 ++pos;
145 }
146
147 if(ch == DC_SIGCHAR_ENDARG)
148 ch = *signature;
149
150 /* write retval */
151 switch(ch) {
152 case DC_SIGCHAR_VOID: /* nothing to set */ break;
153 case DC_SIGCHAR_BOOL: output->B = K_B[pos]; break;
154 case DC_SIGCHAR_CHAR: output->c = K_c[pos]; break;
155 case DC_SIGCHAR_UCHAR: output->C = K_C[pos]; break;
156 case DC_SIGCHAR_SHORT: output->s = K_s[pos]; break;
157 case DC_SIGCHAR_USHORT: output->S = K_S[pos]; break;
158 case DC_SIGCHAR_INT: output->i = K_i[pos]; break;
159 case DC_SIGCHAR_UINT: output->I = K_I[pos]; break;
160 case DC_SIGCHAR_LONG: output->j = K_j[pos]; break;
161 case DC_SIGCHAR_ULONG: output->J = K_J[pos]; break;
162 case DC_SIGCHAR_LONGLONG: output->l = K_l[pos]; break;
163 case DC_SIGCHAR_ULONGLONG: output->L = K_L[pos]; break;
164 case DC_SIGCHAR_FLOAT: output->f = K_f[pos]; break;
165 case DC_SIGCHAR_DOUBLE: output->d = K_d[pos]; break;
166 case DC_SIGCHAR_STRING:
167 case DC_SIGCHAR_POINTER: output->p = K_p[pos]; break;
168 case DC_SIGCHAR_AGGREGATE: dcbReturnAggr(input, output, K_a[pos]); break;
169 default: assert(0);
170 }
171
172 /* return type info for dyncallback */
173 return ch;
174 }
175
176
177
178
179 static int run_test(int id)
180 {
181 const char* signature;
182 DCCallback* pcb;
183 int result;
184 int len_sig;
185 char *dc_sig;
186 DCaggr **dc_aggrs;
187 int n_aggrs = 0;
188
189 /* index range: [0,nsigs[ */
190 signature = G_sigtab[id];
191 printf("%d:%s", id, signature);
192
193 len_sig = strlen(signature);
194
195 /* prep dcbNewCallback() args: signature in dyncall format and array of
196 * DCaggr* descriptions; use len of verbose test-case sig, as always bigger
197 * than canonical/dyncall signature (where aggrs represented as single char)
198 * number of aggregates in sig and */
199 dc_sig = malloc(sizeof(char) *len_sig);
200 dc_aggrs = malloc(sizeof(DCaggr*)*len_sig);
201
202 len_sig = 0; /* len of canonical/dyncall sig */
203 while(*signature != '\0') {
204 switch(*signature) {
205 case '_': signature += 2; /* skip cconv prefix */ break;
206 case '<': /* union */
207 case '{': /* struct */
208 {
209 /* find aggregate sig */
210 int len;
211 int i = find_agg_idx(&len, signature);
212 if(i == -1) {
213 printf("unknown aggr sig at '%s' ;", signature);
214 return 0;
215 }
216 dc_sig[len_sig++] = 'A';
217 dc_aggrs[n_aggrs++] = ((DCaggr*(*)())G_agg_touchAfuncs[i])();
218 signature += len; /* advance to next arg char */
219 break;
220 }
221 default:
222 dc_sig[len_sig++] = *signature;
223 ++signature;
224 }
225 }
226 dc_sig[len_sig] = '\0';
227
228
229 pcb = dcbNewCallback(dc_sig, handler, (void*)dc_sig, dc_aggrs);
230 assert(pcb != NULL);
231
232 clear_V();
233
234 /* invoke call */
235 G_funtab[id]((void*)pcb);
236
237 result = cmp(G_sigtab[id]);
238
239 free(dc_sig);
240 free(dc_aggrs);
241
242 printf(":%d\n", result);
243
244 dcbFreeCallback(pcb);
245
246 return result;
247 }
248
249
250 static int run_all(int from, int to)
251 {
252 int i;
253 int failure = 0;
254 for(i=from; i<=to ;++i)
255 failure |= !( run_test(i) );
256
257 return !failure;
258 }
259
260
261 #define Error(X, Y, N) { fprintf(stderr, X, Y); print_usage(N); exit(1); }
262
263 int main(int argc, char* argv[])
264 {
265 int from = 0, to = G_ncases-1;
266 int i, pos = 0, total;
267
268 dcTest_initPlatform();
269
270
271 /* parse args */
272 for(i=1; i<argc; ++i)
273 {
274 if(argv[i][0] == '-')
275 {
276 switch(argv[i][1]) {
277 case 'h':
278 case '?':
279 print_usage(argv[0]);
280 return 0;
281 default:
282 Error("invalid option: %s\n\n", argv[i], argv[0]);
283 }
284 }
285 switch(pos++) {
286 case 0: from = to = atoi(argv[i]); break;
287 case 1: to = atoi(argv[i]); break;
288 default: Error("too many arguments (%d given, 2 allowed)\n\n", pos, argv[0]);
289 }
290 }
291 if(from < 0 || to >= G_ncases || from > to)
292 Error("invalid arguments (provided from or to not in order or outside of range [0,%d])\n\n", G_ncases-1, argv[0]);
293
294
295 init_test_data();
296 total = run_all(from, to);
297 deinit_test_data();
298
299 printf("result: callback_suite_aggrs: %d\n", total);
300
301 dcTest_deInitPlatform();
302
303 return !total;
304 }
305