Mercurial > pub > dyncall > dyncall
annotate test/callback_suite/main.c @ 509:f3d44195dbdf
callback_suite:
- further, big refactoring to make the test data setup be a lot more in line with call_suite and call_suite_aggrs
- added support to test void return values (was missing in prev version)
author | Tassilo Philipp |
---|---|
date | Sat, 09 Apr 2022 23:00:24 +0200 |
parents | 5a3c07a0f376 |
children | 71c884e610f0 |
rev | line source |
---|---|
0 | 1 /* |
2 | |
3 Package: dyncall | |
4 Library: test | |
5 File: test/callback_suite/main.c | |
6 Description: | |
7 License: | |
8 | |
505 | 9 Copyright (c) 2011-2022 Daniel Adler <dadler@uni-goettingen.de>, |
0 | 10 Tassilo Philipp <tphilipp@potion-studios.com> |
11 | |
12 Permission to use, copy, modify, and distribute this software for any | |
13 purpose with or without fee is hereby granted, provided that the above | |
14 copyright notice and this permission notice appear in all copies. | |
15 | |
16 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
17 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
18 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
19 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
21 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
22 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
23 | |
24 */ | |
25 | |
487 | 26 #include <stdio.h> |
0 | 27 #include <stdlib.h> |
505 | 28 #include <assert.h> |
29 #include "dyncall_callback.h" | |
30 #include "globals.h" | |
0 | 31 #include "../common/platformInit.h" |
32 #include "../common/platformInit.c" /* Impl. for functions only used in this translation unit */ | |
33 | |
34 | |
505 | 35 |
36 | |
37 static void print_usage(const char* appName) | |
410
7608e34098b0
- cleanups, simplifications, some api clarification, ...
Tassilo Philipp
parents:
281
diff
changeset
|
38 { |
7608e34098b0
- cleanups, simplifications, some api clarification, ...
Tassilo Philipp
parents:
281
diff
changeset
|
39 printf("usage:\n\ |
505 | 40 %s [ from [to] ]\n\ |
410
7608e34098b0
- cleanups, simplifications, some api clarification, ...
Tassilo Philipp
parents:
281
diff
changeset
|
41 where\n\ |
505 | 42 from, to: test range (0-based, runs single test if \"to\" is omitted)\n\ |
410
7608e34098b0
- cleanups, simplifications, some api clarification, ...
Tassilo Philipp
parents:
281
diff
changeset
|
43 options\n\ |
7608e34098b0
- cleanups, simplifications, some api clarification, ...
Tassilo Philipp
parents:
281
diff
changeset
|
44 -h help on usage\n\ |
7608e34098b0
- cleanups, simplifications, some api clarification, ...
Tassilo Philipp
parents:
281
diff
changeset
|
45 \n\ |
7608e34098b0
- cleanups, simplifications, some api clarification, ...
Tassilo Philipp
parents:
281
diff
changeset
|
46 ", appName); |
7608e34098b0
- cleanups, simplifications, some api clarification, ...
Tassilo Philipp
parents:
281
diff
changeset
|
47 } |
7608e34098b0
- cleanups, simplifications, some api clarification, ...
Tassilo Philipp
parents:
281
diff
changeset
|
48 |
7608e34098b0
- cleanups, simplifications, some api clarification, ...
Tassilo Philipp
parents:
281
diff
changeset
|
49 |
509 | 50 static int cmp(const char* signature) |
505 | 51 { |
509 | 52 char atype; |
53 const char* sig = signature; | |
54 int pos = 0; | |
55 int s = 0; | |
56 while ( (atype = *sig++) != '\0') { | |
57 switch(atype) { | |
58 case ')': /* skip cconv prefix or ret type separator */ continue; | |
59 case 'v': s = (sig > signature+1) && sig[-2] == ')'; /* assure this was the return type */ break; /*TODO:check that no return-arg was touched.*/ | |
60 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; | |
61 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; | |
62 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; | |
63 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; | |
64 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; | |
65 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; | |
66 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; | |
67 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; | |
68 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; | |
69 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; | |
70 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; | |
71 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; | |
72 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; | |
73 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; | |
74 default: printf("unknown atype '%c' ; ", atype); return 0; | |
75 } | |
76 if (!s) { | |
77 printf("arg mismatch at %d ; ", pos); | |
78 return 0; | |
79 } | |
80 pos++; | |
505 | 81 } |
509 | 82 return 1; |
505 | 83 } |
84 | |
85 | |
509 | 86 /* handler just copies all received args as well as return value into V_* */ |
505 | 87 static char handler(DCCallback* that, DCArgs* input, DCValue* output, void* userdata) |
88 { | |
89 const char* signature = (const char*) userdata; | |
90 int pos = 0; | |
91 char ch; | |
0 | 92 |
505 | 93 for(;;) { |
94 ch = *signature++; | |
95 if (!ch || ch == DC_SIGCHAR_ENDARG) break; | |
96 switch(ch) { | |
509 | 97 case DC_SIGCHAR_BOOL: V_B[pos] = dcbArgBool (input); break; |
98 case DC_SIGCHAR_CHAR: V_c[pos] = dcbArgChar (input); break; | |
99 case DC_SIGCHAR_UCHAR: V_C[pos] = dcbArgUChar (input); break; | |
100 case DC_SIGCHAR_SHORT: V_s[pos] = dcbArgShort (input); break; | |
101 case DC_SIGCHAR_USHORT: V_S[pos] = dcbArgUShort (input); break; | |
102 case DC_SIGCHAR_INT: V_i[pos] = dcbArgInt (input); break; | |
103 case DC_SIGCHAR_UINT: V_I[pos] = dcbArgUInt (input); break; | |
104 case DC_SIGCHAR_LONG: V_j[pos] = dcbArgLong (input); break; | |
105 case DC_SIGCHAR_ULONG: V_J[pos] = dcbArgULong (input); break; | |
106 case DC_SIGCHAR_LONGLONG: V_l[pos] = dcbArgLongLong (input); break; | |
107 case DC_SIGCHAR_ULONGLONG:V_L[pos] = dcbArgULongLong(input); break; | |
108 case DC_SIGCHAR_FLOAT: V_f[pos] = dcbArgFloat (input); break; | |
109 case DC_SIGCHAR_DOUBLE: V_d[pos] = dcbArgDouble (input); break; | |
505 | 110 case DC_SIGCHAR_STRING: |
509 | 111 case DC_SIGCHAR_POINTER: V_p[pos] = dcbArgPointer (input); break; |
505 | 112 case DC_SIGCHAR_CC_PREFIX: ++signature; /* skip cconv prefix */ continue; |
509 | 113 default: assert(0); |
505 | 114 } |
115 ++pos; | |
116 } | |
117 | |
118 if(ch == DC_SIGCHAR_ENDARG) | |
119 ch = *signature; | |
120 | |
509 | 121 /* write retval */ |
505 | 122 switch(ch) { |
509 | 123 case DC_SIGCHAR_VOID: /* nothing to set */ break; |
124 case DC_SIGCHAR_BOOL: output->B = K_B[pos]; break; | |
125 case DC_SIGCHAR_CHAR: output->c = K_c[pos]; break; | |
126 case DC_SIGCHAR_UCHAR: output->C = K_C[pos]; break; | |
127 case DC_SIGCHAR_SHORT: output->s = K_s[pos]; break; | |
128 case DC_SIGCHAR_USHORT: output->S = K_S[pos]; break; | |
129 case DC_SIGCHAR_INT: output->i = K_i[pos]; break; | |
130 case DC_SIGCHAR_UINT: output->I = K_I[pos]; break; | |
131 case DC_SIGCHAR_LONG: output->j = K_j[pos]; break; | |
132 case DC_SIGCHAR_ULONG: output->J = K_J[pos]; break; | |
133 case DC_SIGCHAR_LONGLONG: output->l = K_l[pos]; break; | |
134 case DC_SIGCHAR_ULONGLONG:output->L = K_L[pos]; break; | |
135 case DC_SIGCHAR_FLOAT: output->f = K_f[pos]; break; | |
136 case DC_SIGCHAR_DOUBLE: output->d = K_d[pos]; break; | |
505 | 137 case DC_SIGCHAR_STRING: |
509 | 138 case DC_SIGCHAR_POINTER: output->p = K_p[pos]; break; |
139 default: assert(0); | |
505 | 140 } |
141 | |
509 | 142 /* return type info for dyncallback */ |
505 | 143 return ch; |
144 } | |
145 | |
146 | |
147 | |
148 | |
149 static int run_test(int id) | |
150 { | |
151 const char* signature; | |
152 DCCallback* pcb; | |
153 int result; | |
154 | |
155 /* index range: [0,nsigs[ */ | |
156 signature = G_sigtab[id]; | |
157 printf("%d:%s", id, signature); | |
158 | |
159 pcb = dcbNewCallback(signature, handler, (void*)signature, NULL); | |
160 assert(pcb != NULL); | |
161 | |
509 | 162 clear_V(); |
163 | |
505 | 164 /* invoke call */ |
165 G_funtab[id]((void*)pcb); | |
166 | |
167 result = cmp(signature); | |
509 | 168 |
505 | 169 printf(":%d\n", result); |
509 | 170 |
505 | 171 dcbFreeCallback(pcb); |
172 | |
173 return result; | |
174 } | |
175 | |
176 | |
177 static int run_all(int from, int to) | |
178 { | |
179 int i; | |
180 int failure = 0; | |
181 for(i=from; i<=to ;++i) | |
182 failure |= !( run_test(i) ); | |
183 | |
184 return !failure; | |
185 } | |
0 | 186 |
187 | |
505 | 188 #define Error(X, Y, N) { fprintf(stderr, X, Y); print_usage(N); exit(1); } |
0 | 189 |
487 | 190 int main(int argc, char* argv[]) |
0 | 191 { |
505 | 192 int from = 0, to = G_ncases-1; |
193 int i, pos = 0, total; | |
487 | 194 |
0 | 195 dcTest_initPlatform(); |
196 | |
197 | |
505 | 198 /* parse args */ |
199 for(i=1; i<argc; ++i) | |
487 | 200 { |
201 if(argv[i][0] == '-') | |
495
45ac093ca822
- test/callback_suite: make it use shared random sig generator from call_suite and call_suite_aggrs
Tassilo Philipp
parents:
487
diff
changeset
|
202 { |
0 | 203 switch(argv[i][1]) { |
487 | 204 case 'h': |
205 case '?': | |
505 | 206 print_usage(argv[0]); |
495
45ac093ca822
- test/callback_suite: make it use shared random sig generator from call_suite and call_suite_aggrs
Tassilo Philipp
parents:
487
diff
changeset
|
207 return 0; |
505 | 208 default: |
209 Error("invalid option: %s\n\n", argv[i], argv[0]); | |
0 | 210 } |
211 } | |
487 | 212 switch(pos++) { |
505 | 213 case 0: from = to = atoi(argv[i]); break; |
214 case 1: to = atoi(argv[i]); break; | |
487 | 215 default: Error("too many arguments (%d given, 2 allowed)\n\n", pos, argv[0]); |
0 | 216 } |
217 } | |
505 | 218 if(from < 0 || to >= G_ncases || from > to) |
219 Error("invalid arguments (provided from or to not in order or outside of range [0,%d])\n\n", G_ncases-1, argv[0]); | |
0 | 220 |
221 | |
505 | 222 init_test_data(); |
223 total = run_all(from, to); | |
224 deinit_test_data(); | |
487 | 225 |
505 | 226 printf("result: callback_suite: %d\n", total); |
0 | 227 |
228 dcTest_deInitPlatform(); | |
229 | |
505 | 230 return !total; |
0 | 231 } |
232 |