ARB
cb.cxx
Go to the documentation of this file.
1 // ============================================================== //
2 // //
3 // File : cb.cxx //
4 // Purpose : currently only a test sandbox //
5 // //
6 // Coded by Ralf Westram (coder@reallysoft.de) in August 2011 //
7 // Institute of Microbiology (Technical University Munich) //
8 // http://www.arb-home.de/ //
9 // //
10 // ============================================================== //
11 
12 #include <cb.h>
13 #include <string>
14 #include <stdint.h>
15 
16 using namespace std;
17 
18 STATIC_ASSERT(sizeof(int*) == sizeof(AW_CL)); // important for casted db-callback type (GB_CB vs GB_CB_wanted..)
19 
20 // --------------------------------------------------------------------------------
21 
22 #ifdef UNIT_TESTS
23 #include <test_unit.h>
24 
25 // ---------------------------------------------
26 // compile time test of type inspection
27 
28 #define COMPILE_ASSERT_POINTER_TO(ISTYPE,POINTER) \
29  STATIC_ASSERT(TypeT<POINTER>::IsPtrT && \
30  TypeT<CompountT<POINTER>::BaseT>::ISTYPE)
31 
32 typedef int (*somefun)(const char *);
33 static int myfun(const char *) { return 0; }
34 static somefun sfun = myfun;
35 
36 enum someenum { A, B };
37 
38 class someclass { public : int memfun() { return -1; } };
39 
40 
46 
48 COMPILE_ASSERT_POINTER_TO(IsFundaT, int*);
49 COMPILE_ASSERT_POINTER_TO(IsPtrT, int**);
51 
53 STATIC_ASSERT(IsFundaT<typeof(myfun)>::No);
55 
56 STATIC_ASSERT(IsFunctionT<typeof(myfun)>::Yes);
57 
58 STATIC_ASSERT(IsFunctionT<somefun>::No); // somefun is pointer to functiontype
59 COMPILE_ASSERT_POINTER_TO(IsFuncT, somefun);
60 STATIC_ASSERT(IsFunctionT<typeof(sfun)>::No); // sfun is pointer to functiontype
61 COMPILE_ASSERT_POINTER_TO(IsFuncT, typeof(sfun));
65 
68 
70 COMPILE_ASSERT_POINTER_TO(IsEnumT, someenum*);
71 
76 STATIC_ASSERT(IsEnumT<typeof(myfun)>::No);
77 
79 COMPILE_ASSERT_POINTER_TO(IsClassT, someclass*);
80 
86 STATIC_ASSERT(IsClassT<typeof(myfun)>::No);
87 
91 STATIC_ASSERT(TypeT<int[]>::IsArrayT);
92 STATIC_ASSERT(TypeT<int[7]>::IsArrayT);
93 STATIC_ASSERT(TypeT<typeof(myfun)>::IsFuncT);
94 STATIC_ASSERT(TypeT<typeof(&someclass::memfun)>::IsPtrMemT);
97 
98 // -----------------------
99 // test callbacks
100 
101 #define TRACE
102 
103 DECLARE_CBTYPE_VV_AND_BUILDERS(CustomCallback, void); // defines makeCustomCallback
104 
105 static uint32_t traceChecksum;
106 const int BUFFERSIZE = 100;
107 static char traceBuffer[BUFFERSIZE];
108 
109 __ATTR__FORMAT(1) static void tracef(const char *format, ...) {
110  va_list parg;
111  va_start(parg, format);
112  int printed = vsnprintf(traceBuffer, BUFFERSIZE, format, parg);
113  va_end(parg);
114 
115 #if defined(TRACE)
116  fputs(traceBuffer, stdout);
117 #endif
118  if (printed >= BUFFERSIZE) {
119  printf("\nprinted=%i\n", printed);
120  }
121  TEST_EXPECT(printed<BUFFERSIZE);
122 
123  traceChecksum = 0;
124  for (int p = 0; p<printed; ++p) {
125  traceChecksum = (traceChecksum<<1)^(traceChecksum>>31)^traceBuffer[p];
126  }
127 }
128 
129 static AW_root *fake_root = (AW_root*)1;
130 static AW_window *fake_win = (AW_window*)2;
131 static GBDATA *fake_gbd = (GBDATA*)3;
132 static AW_awar *fake_awar = (AW_awar*)4;
133 static bool fake_bool = false;
134 static GB_CB_TYPE fake_gbtype = GB_CB_CHANGED;
135 
136 static void rcb0(AW_root *r) {
137  TEST_EXPECT(r == fake_root);
138  tracef("rcb0()\n");
139 }
140 static void rcb1(AW_root *r, const char *name) {
141  TEST_EXPECT(r == fake_root);
142  tracef("rcb1(%s)\n", name);
143 }
144 static void rcb2(AW_root *r, const char *name, int val) {
145  TEST_EXPECT(r == fake_root);
146  tracef("rcb2(%s=%i) [int]\n", name, val);
147 }
148 static void rcb2(AW_root *r, const char *name, long val) {
149  TEST_EXPECT(r == fake_root);
150  tracef("rcb2(%s=%li) [long]\n", name, val);
151 }
152 
153 static void wcb0(AW_window *w) {
154  TEST_EXPECT(w == fake_win);
155  tracef("wcb0()\n");
156 }
157 static void wcb1(AW_window *w, const char *name) {
158  TEST_EXPECT(w == fake_win);
159  tracef("wcb1(%s)\n", name);
160 }
161 static void wcb1(AW_window *w, string *name) {
162  TEST_EXPECT(w == fake_win);
163  tracef("wcb1(%s) [string]\n", name->c_str());
164 }
165 static void wcb2(AW_window *w, const char *name, const char *val) {
166  TEST_EXPECT(w == fake_win);
167  tracef("wcb2(%s=%s) [const char/const char]\n", name, val);
168 }
169 static void wcb2(AW_window *w, const string *name, const string *val) {
170  TEST_EXPECT(w == fake_win);
171  tracef("wcb2(%s=%s) [string/string]\n", name->c_str(), val->c_str());
172 }
173 static void wcb2(AW_window *w, const char *name, int val) {
174  TEST_EXPECT(w == fake_win);
175  tracef("wcb2(%s=%i) [int]\n", name, val);
176 }
177 static void wcb2(AW_window *w, const char *name, long val) {
178  TEST_EXPECT(w == fake_win);
179  tracef("wcb2(%s=%li) [long]\n", name, val);
180 }
181 static void wcb2(AW_window *w, char c, long long val) {
182  TEST_EXPECT(w == fake_win);
183  tracef("wcb2(%c=%lli) [long long]\n", c, val);
184 }
185 
186 static void tacb0(AW_awar *a) {
187  TEST_EXPECT(a == fake_awar);
188  tracef("tacb0()\n");
189 }
190 static void tacb1(AW_awar *a, bool b) {
191  TEST_EXPECT(a == fake_awar);
192  TEST_EXPECT(b == fake_bool);
193  tracef("tacb1()\n");
194 }
195 static void tacb2(AW_awar *a, bool b, const char *name) {
196  TEST_EXPECT(a == fake_awar);
197  TEST_EXPECT(b == fake_bool);
198  tracef("tacb2(%s)\n", name);
199 }
200 static void tacb2(AW_awar *a, bool b, int val) {
201  TEST_EXPECT(a == fake_awar);
202  TEST_EXPECT(b == fake_bool);
203  tracef("tacb2(%i)\n", val);
204 }
205 
206 static void ucb0(UNFIXED) {
207  tracef("ucb0()\n");
208 }
209 static void ucb1(UNFIXED, const char *name) {
210  tracef("ucb1(%s)\n", name);
211 }
212 static void ucb2(UNFIXED, const char *name, int val) {
213  tracef("ucb2(%s=%i) [int]\n", name, val);
214 }
215 static void ucb2(UNFIXED, const char *name, long val) {
216  tracef("ucb2(%s=%li) [long]\n", name, val);
217 }
218 
219 static AW_window *cwcb0(AW_root *r) {
220  TEST_EXPECT(r == fake_root);
221  tracef("cwcb0()\n");
222  return fake_win;
223 }
224 static AW_window *cwcb1(AW_root *r, int x) {
225  TEST_EXPECT(r == fake_root);
226  tracef("cwcb1(%i)\n", x);
227  return fake_win;
228 }
229 static AW_window *cwcb1(AW_root *r, const long *lp) {
230  TEST_EXPECT(r == fake_root);
231  tracef("cwcb1(%li) [long ptr]\n", *lp);
232  return fake_win;
233 }
234 static AW_window *cwcb1(AW_root *r, const int *x) {
235  TEST_EXPECT(r == fake_root);
236  tracef("cwcb1(%i) [const ptr]\n", *x);
237  return fake_win;
238 }
239 static AW_window *cwcb1(AW_root *r, int *x) {
240  TEST_EXPECT(r == fake_root);
241  tracef("cwcb1(%i) [mutable ptr]\n", *x);
242  *x *= 2; // modify callback argument!
243  return fake_win;
244 }
245 static AW_window *cwcb1(AW_root *r, char* s) {
246  TEST_EXPECT(r == fake_root);
247  tracef("cwcb1(%s) [mutable]\n", s);
248  return fake_win;
249 }
250 static AW_window *cwcb1(AW_root *r, const char* s) {
251  TEST_EXPECT(r == fake_root);
252  tracef("cwcb1(%s) [const]\n", s);
253  return fake_win;
254 }
255 static AW_window *cwcb2(AW_root *r, const char *s1, const char *s2) {
256  TEST_EXPECT(r == fake_root);
257  tracef("cwcb2(%s,%s) [const const]\n", s1, s2);
258  return fake_win;
259 }
260 static AW_window *cwcb2(AW_root *r, const char *s1, char *s2) {
261  TEST_EXPECT(r == fake_root);
262  tracef("cwcb2(%s,%s) [const mutable]\n", s1, s2);
263  return fake_win;
264 }
265 
266 static AW_window *cwcb3(AW_root *r, const char *s1, const char *s2) {
267  TEST_EXPECT(r == fake_root);
268  tracef("cwcb3(%s,%s) [const const]\n", s1, s2);
269  return fake_win;
270 }
271 static AW_window *cwcb3(AW_root *r, const char *s1, char *s2) {
272  TEST_EXPECT(r == fake_root);
273  tracef("cwcb3(%s,%s) [const mutable]\n", s1, s2);
274  return fake_win;
275 }
276 static AW_window *cwcb3(AW_root *r, char *s1, const char *s2) {
277  TEST_EXPECT(r == fake_root);
278  tracef("cwcb3(%s,%s) [mutable const]\n", s1, s2);
279  return fake_win;
280 }
281 static AW_window *cwcb3(AW_root *r, char *s1, char *s2) {
282  TEST_EXPECT(r == fake_root);
283  tracef("cwcb3(%s,%s) [mutable mutable]\n", s1, s2);
284  return fake_win;
285 }
286 
287 static void dbcb01(GBDATA *gbd) {
288  TEST_EXPECT(gbd == fake_gbd);
289  tracef("dbcb01()\n");
290 }
291 static void dbcb012(GBDATA *gbd, GB_CB_TYPE t) {
292  TEST_EXPECT(gbd == fake_gbd && t == fake_gbtype);
293  tracef("dbcb012()\n");
294 }
295 static void dbcb02(GB_CB_TYPE t) {
296  tracef("dbcb02(%i)\n", int(t));
297 }
298 static void dbcb1(GBDATA *gbd, int x, GB_CB_TYPE t) {
299  TEST_EXPECT(gbd == fake_gbd && t == fake_gbtype);
300  tracef("dbcb1(%i) [int]\n", x);
301 }
302 static void dbcb1(GBDATA *gbd, const char *n, GB_CB_TYPE t) {
303  TEST_EXPECT(gbd == fake_gbd && t == fake_gbtype);
304  tracef("dbcb1(%s) [const char]\n", n);
305 }
306 
307 static void ccb11(const char *str) {
308  tracef("ccb11(%s)\n", str);
309 }
310 static void ccb12(int i) {
311  tracef("ccb12(%i)\n", i);
312 }
313 static void ccb2(int i, const char *str) {
314  tracef("ccb2(%i,%s)\n", i, str);
315 }
316 
317 static void plaincb() {
318  tracef("plaincb()\n");
319 }
320 static AW_window *cwcb_plain() {
321  tracef("cwcb_plain()\n");
322  return fake_win;
323 }
324 
325 inline void call(const RootCallback& rcb) { rcb(fake_root); }
326 inline void call(const WindowCallback& wcb) { wcb(fake_win); }
327 inline void call(const CreateWindowCallback& cwcb) { TEST_EXPECT(cwcb(fake_root) == fake_win); }
328 inline void call(const DatabaseCallback& dbcb) { dbcb(fake_gbd, fake_gbtype); }
329 inline void call(const TreeAwarCallback& tacb) { tacb(fake_awar, fake_bool); }
330 inline void call(const CustomCallback& ccb) { ccb(); }
331 
332 #define TEST_CB(cb,expectedChecksum) do { \
333  traceChecksum = -666; \
334  call(cb); \
335  TEST_EXPECT_EQUAL(traceChecksum, (uint32_t)expectedChecksum); \
336  } while(0)
337 
338 #define TEST_CB_TRACE(cb,expectedOutput) do { \
339  call(cb); \
340  TEST_EXPECT_EQUAL(traceBuffer, expectedOutput); \
341  } while(0)
342 
343 #define TEST_CB_TRACE__BROKEN(cb,expectedOutput) do { \
344  call(cb); \
345  TEST_EXPECT_EQUAL__BROKEN(traceBuffer, expectedOutput); \
346  } while(0)
347 
348 
349 static void freeCharp(char *str) { free(str); }
350 static void freeCharp(char *str1, char *str2) { free(str1); free(str2); }
351 static void deleteString(string *str) { delete str; }
352 static void deleteString(string *str1, string *str2) { delete str1; delete str2; }
353 
354 void TEST_cbs() {
355  // MISSING_TEST("please log");
356  // for (int i = 0; i<100000; ++i)
357  {
358  TEST_CB_TRACE(makeRootCallback(plaincb), "plaincb()\n");
359  TEST_CB_TRACE(makeRootCallback(rcb0), "rcb0()\n");
360  TEST_CB_TRACE(makeRootCallback(rcb1, "dispatched"), "rcb1(dispatched)\n");
361  TEST_CB_TRACE(makeRootCallback(rcb2, "age", 46), "rcb2(age=46) [int]\n");
362  TEST_CB_TRACE(makeRootCallback(rcb2, "size", 178L), "rcb2(size=178) [long]\n");
363 
364  TEST_CB_TRACE(makeWindowCallback(plaincb), "plaincb()\n");
365  TEST_CB_TRACE(makeWindowCallback(wcb0), "wcb0()\n");
366  TEST_CB_TRACE(makeWindowCallback(wcb1, "dispatched"), "wcb1(dispatched)\n");
367  TEST_CB_TRACE(makeWindowCallback(wcb2, "age", 46), "wcb2(age=46) [int]\n");
368  TEST_CB_TRACE(makeWindowCallback(wcb2, "size", 178L), "wcb2(size=178) [long]\n");
369 
370  TEST_CB_TRACE(makeTreeAwarCallback(plaincb), "plaincb()\n");
371  TEST_CB_TRACE(makeTreeAwarCallback(tacb0), "tacb0()\n");
372  TEST_CB_TRACE(makeTreeAwarCallback(tacb1), "tacb1()\n");
373  TEST_CB_TRACE(makeTreeAwarCallback(tacb2, "dispatched"), "tacb2(dispatched)\n");
374  TEST_CB_TRACE(makeTreeAwarCallback(tacb2, 46), "tacb2(46)\n");
375 
376  // declaring a cb with UNFIXED as fixed-argument allows to use callbacks as RootCallback AND as WindowCallback
377  // (when we use sigc++ in the future this should be changed to allowing functions w/o the UNFIXED-parameter)
378 
379  TEST_CB_TRACE(makeRootCallback(ucb0), "ucb0()\n");
380  TEST_CB_TRACE(makeRootCallback(ucb1, "dispatched"), "ucb1(dispatched)\n");
381  TEST_CB_TRACE(makeRootCallback(ucb2, "age", 46), "ucb2(age=46) [int]\n");
382  TEST_CB_TRACE(makeRootCallback(ucb2, "size", 178L), "ucb2(size=178) [long]\n");
383 
384  TEST_CB_TRACE(makeWindowCallback(ucb0), "ucb0()\n");
385  TEST_CB_TRACE(makeWindowCallback(ucb1, "dispatched"), "ucb1(dispatched)\n");
386  TEST_CB_TRACE(makeWindowCallback(ucb2, "age", 46), "ucb2(age=46) [int]\n");
387  TEST_CB_TRACE(makeWindowCallback(ucb2, "size", 178L), "ucb2(size=178) [long]\n");
388 
389 #if defined(ARB_64)
390  TEST_CB_TRACE(makeWindowCallback(wcb2, 'l', 49710827735915452LL), "wcb2(l=49710827735915452) [long long]\n");
391 #endif
392 
393  TEST_CB_TRACE(makeCreateWindowCallback(cwcb_plain), "cwcb_plain()\n");
394  TEST_CB_TRACE(makeCreateWindowCallback(cwcb0), "cwcb0()\n");
395  TEST_CB_TRACE(makeCreateWindowCallback(cwcb1, 77), "cwcb1(77)\n");
396 
397  // TEST_CB(makeDatabaseCallback(plaincb), 44760); // does not work (ambiguous due to 2 fixed arguments of DatabaseCallback)
398  TEST_CB_TRACE(makeDatabaseCallback(dbcb01), "dbcb01()\n");
399  TEST_CB_TRACE(makeDatabaseCallback(dbcb012), "dbcb012()\n");
400  TEST_CB_TRACE(makeDatabaseCallback(dbcb02), "dbcb02(2)\n"); // call dbcb02 with fixed argument (i.e. with argument normally passed by ARBDB)
401  TEST_CB_TRACE(makeDatabaseCallback(dbcb1, 77), "dbcb1(77) [int]\n");
402 
403  TEST_CB_TRACE(makeDatabaseCallback(dbcb1, freeCharp, strdup("test")), "dbcb1(test) [const char]\n");
404 
405  // callbacks with deallocator
406 
407  // TEST_CB(makeWindowCallback(wcb1, strdup("leak")), 0x163ac); // leaks
408  TEST_CB_TRACE(makeWindowCallback(wcb1, freeCharp, strdup("leak")), "wcb1(leak)\n");
409  // TEST_CB(makeWindowCallback(wcb1, freeCharp, "leak"), 0x163ac); // does not compile (can't call freeCharp with const char *)
410  TEST_CB_TRACE(makeWindowCallback(wcb1, deleteString, new string("leak")), "wcb1(leak) [string]\n");
411  // TEST_CB(makeWindowCallback(wcb2, strdup("hue"), strdup("hott")), 0xe09d7b1); // leaks
412  TEST_CB_TRACE(makeWindowCallback(wcb2, freeCharp, strdup("hue"), strdup("hott")), "wcb2(hue=hott) [const char/const char]\n");
413  TEST_CB_TRACE(makeWindowCallback(wcb2, deleteString, new string("hue"), new string("hott")), "wcb2(hue=hott) [string/string]\n");
414 
415  // test const vs non-const pointers:
416  char *mut = strdup("mut");
417  const char *con = "con";
418 
419  // if only const/const and const/mutable exists -> shall always select as much mutable as possible
420  TEST_CB_TRACE(makeCreateWindowCallback(cwcb2, con, con), "cwcb2(con,con) [const const]\n"); // exact match
421  TEST_CB_TRACE(makeCreateWindowCallback(cwcb2, mut, con), "cwcb2(mut,con) [const const]\n"); // fallback to const/const
422  TEST_CB_TRACE(makeCreateWindowCallback(cwcb2, con, mut), "cwcb2(con,mut) [const mutable]\n"); // exact match
423  TEST_CB_TRACE(makeCreateWindowCallback(cwcb2, mut, mut), "cwcb2(mut,mut) [const mutable]\n"); // fallback to const/mutable
424 
425  // if all const/nonconst combinations exist -> shall always pick exact match
426  TEST_CB_TRACE(makeCreateWindowCallback(cwcb3, con, con), "cwcb3(con,con) [const const]\n"); // exact match
427  TEST_CB_TRACE(makeCreateWindowCallback(cwcb3, mut, con), "cwcb3(mut,con) [mutable const]\n"); // exact match
428  TEST_CB_TRACE(makeCreateWindowCallback(cwcb3, con, mut), "cwcb3(con,mut) [const mutable]\n"); // exact match
429  TEST_CB_TRACE(makeCreateWindowCallback(cwcb3, mut, mut), "cwcb3(mut,mut) [mutable mutable]\n"); // exact match
430 
431  // test reference arguments
432  int imut = 17;
433  const int icon = 23;
434 
435  const long lcon = 775L;
436 
437  TEST_CB_TRACE(makeCreateWindowCallback(cwcb1, imut), "cwcb1(17)\n");
438  TEST_CB_TRACE(makeCreateWindowCallback(cwcb1, icon), "cwcb1(23)\n");
439  TEST_CB_TRACE(makeCreateWindowCallback(cwcb1, &lcon), "cwcb1(775) [long ptr]\n");
440 
441  TEST_CB_TRACE(makeCreateWindowCallback(cwcb1, &icon), "cwcb1(23) [const ptr]\n");
442  TEST_CB_TRACE(makeCreateWindowCallback(cwcb1, &icon), "cwcb1(23) [const ptr]\n");
443 
444  TEST_CB_TRACE(makeCreateWindowCallback(cwcb1, &imut), "cwcb1(17) [mutable ptr]\n"); // modifies 'imut'
445  TEST_CB_TRACE(makeCreateWindowCallback(cwcb1, &imut), "cwcb1(34) [mutable ptr]\n"); // modifies 'imut'
446  TEST_CB_TRACE(makeCreateWindowCallback(cwcb1, &imut), "cwcb1(68) [mutable ptr]\n"); // modifies 'imut'
447 
448  TEST_CB_TRACE(makeCreateWindowCallback(cwcb1, mut), "cwcb1(mut) [mutable]\n");
449  TEST_CB_TRACE(makeCreateWindowCallback(cwcb1, con), "cwcb1(con) [const]\n");
450 
451  free(mut);
452 
453  // test callbacks w/o fixed argument
454  TEST_CB_TRACE(makeCustomCallback(plaincb), "plaincb()\n");
455  TEST_CB_TRACE(makeCustomCallback(ccb11, "helo"), "ccb11(helo)\n");
456  TEST_CB_TRACE(makeCustomCallback(ccb12, 4711), "ccb12(4711)\n");
457  TEST_CB_TRACE(makeCustomCallback(ccb2, 4711, "helo"), "ccb2(4711,helo)\n");
458 
459  TEST_CB_TRACE(makeCustomCallback(ccb11, freeCharp, strdup("dup")), "ccb11(dup)\n");
460  }
461 
462 }
463 TEST_PUBLISH(TEST_cbs);
464 
465 #endif // UNIT_TESTS
466 
467 
AliDataPtr format(AliDataPtr data, const size_t wanted_len, GB_ERROR &error)
Definition: insdel.cxx:615
Definition: ttypes.h:198
Definition: trnsprob.h:20
#define __ATTR__FORMAT(pos)
Definition: attributes.h:60
STL namespace.
struct Unfixed_cb_parameter * UNFIXED
Definition: cb_base.h:15
#define TEST_PUBLISH(testfunction)
Definition: test_unit.h:1517
#define TEST_EXPECT(cond)
Definition: test_unit.h:1328
char * str
Definition: defines.h:20
va_end(argPtr)
fputs(TRACE_PREFIX, stderr)
long AW_CL
Definition: cb.h:21
const size_t BUFFERSIZE
va_start(argPtr, format)
STATIC_ASSERT(sizeof(int *)==sizeof(AW_CL))
DECLARE_CBTYPE_VV_AND_BUILDERS(StoreConfigCallback, char *)
GB_CB_TYPE
Definition: arbdb_base.h:46
GB_write_int const char s
Definition: AW_awar.cxx:154