Mercurial > pub > dyncall > dyncall
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 |