fixes for gcc 4
[dyninst.git] / testsuite / src / test00.mutatee.C
1 /*
2  * Copyright (c) 1996-2004 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 /* Test application (Mutatee) */
43
44 /* $Id: test00.mutatee.c,v  */
45
46 #include <stdio.h>
47 #include <assert.h>
48 #include <sys/types.h>
49 #include <signal.h>
50 #include <string.h>
51 #include <stdlib.h>
52
53 #include "../../common/h/serialize.h"
54 #include "../../symtabAPI/h/Symbol.h"
55 #include "../../symtabAPI/h/LineInformation.h"
56 #include "../../symtabAPI/h/symutil.h"
57 #include "../../symtabAPI/h/AddrLookup.h"
58 #include "../../symtabAPI/h/Symtab.h"
59 #include "../../symtabAPI/h/Type.h"
60 //  TODO:  move this file
61 #include "../../symtabAPI/src/Collections.h"
62
63 using namespace Dyninst;
64 using namespace Dyninst::SymtabAPI;
65 #include "mutatee_util.h"
66 #include "test0.h"
67
68 #if defined(i386_unknown_nt4_0) && !defined(__GNUC__)
69 #define WIN32_LEAN_AND_MEAN
70 #include <windows.h>
71 #include <process.h>
72 #define getpid _getpid
73 #else
74 #include <unistd.h>
75 #endif
76
77 #ifdef __cplusplus
78 int mutateeCplusplus = 1;
79 #else
80 #error
81 #endif
82
83 #ifndef FILE__
84 #define FILE__ strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__
85 #endif
86
87 #ifndef COMPILER
88 #define COMPILER ""
89 #endif
90 const char *Builder_id=COMPILER; /* defined on compile line */
91
92 /* control debug printf statements */
93 #define dprintf if (debugPrint) printf
94 int debugPrint = 0;
95 bool verbose = false;
96 const char *prog_name;
97
98 #define MAX_TEST 5
99
100
101 #if 0
102 bool runcmd(const char *file, std::vector<char *> &args)
103 {
104    int pid = fork();
105    if (pid == 0) {
106       // child -- exec command
107       char **new_argv = new char *[args.size()+ 2];
108       assert( new_argv );
109
110       // the first arg is always the filename
111       new_argv[0] = strdup(file);
112
113       for (unsigned int i = 0; i < args.size(); ++i) {
114          new_argv[i+1] = strdup(args[i]);
115       }
116       new_argv[args.size()+1] = NULL;
117
118       extern char **environ;
119       int res = execve(file, new_argv, environ);
120       fprintf(stderr, "%s[%d]:  exec returned code %d: %d:%s\n", 
121             __FILE__, __LINE__ , res, errno,strerror(errno));
122       abort();
123    }
124    else {
125       // parent, wait for child;
126       int status;
127       int res = waitpid(pid, &status, 0);
128       if (pid != res) {
129          fprintf(stderr, "%s[%d]:  waitpid: %s\n", __FILE__, __LINE__, strerror(errno));
130          return false;
131       }
132       if (!WIFEXITED(status)) {
133          fprintf(stderr, "%s[%d]:  process exited abnormally \n", __FILE__, __LINE__ );
134          if (WIFSIGNALED(status)) {
135             int signo = WTERMSIG(status);
136             fprintf(stderr, "%s[%d]:  process got signal %d \n", __FILE__, __LINE__, signo );
137          }
138          if (WIFSTOPPED(status)) {
139             int signo = WSTOPSIG(status);
140             fprintf(stderr, "%s[%d]:  weird, process is stopped with signal %d \n", __FILE__, __LINE__, signo );
141          }
142          return false;
143       }
144       int exit_status = WEXITSTATUS(status);
145       if (exit_status != 0) {
146          fprintf(stderr, "%s[%d]:  process returned code %d, not zero\n", __FILE__, __LINE__ , exit_status);
147          return false;
148       }
149       return true;
150    }
151 }
152 #endif
153
154
155 class ZeroOne;
156 class ZeroTwo;
157 class ZeroThree;
158 class ZeroFour;
159 class ZeroFive;
160 class ZeroSix;
161
162 bool test0()
163 {
164    //  some basic symtabAPI tests
165    //  here we just work with test1.mutatee_
166
167    SerializerBin::globalDisable();
168
169    bool err = false;
170    Symtab *test1_mutatee = NULL;
171    char cwdbuf[1024];
172    if (!getcwd(cwdbuf, 1024)) {
173       fprintf(stderr, "%s[%d]:  getcwd:  %s\n", FILE__, __LINE__, strerror(errno));
174       abort();
175    }
176
177    std::string cwd_str(cwdbuf);
178    std::string mutatee_short_name("test1.mutatee_gcc");
179    std::string mutatee_name = cwdbuf + std::string("/") + mutatee_short_name;
180
181    err = !Symtab::openFile(test1_mutatee, mutatee_name);
182
183    if (err) 
184    {
185       fprintf(stderr, "%s[%d]:  failed to create symtab for %s\n", 
186             FILE__, __LINE__, mutatee_name.c_str());
187       return false;
188    }
189    
190    if (NULL == test1_mutatee) 
191    {
192       fprintf(stderr, "%s[%d]:  failed to create symtab for %s\n", 
193             FILE__, __LINE__, mutatee_name.c_str());
194       return false;
195    }
196
197    if (!test1_mutatee->isExec()) 
198    {
199       fprintf(stderr, "%s[%d]:  symtab for %s is not an executable\n", 
200             FILE__, __LINE__, mutatee_name.c_str());
201       return false;
202    }
203
204    int aw = test1_mutatee->getAddressWidth();
205
206 #if defined (x86_64_unknown_linux2_4) \
207    || defined (ppc64_linux) \
208    || defined (ia64_unknown_linux2_4)
209    int expected_address_width = 8;
210 #else
211    int expected_address_width = 4;
212 #endif
213
214    if (aw != expected_address_width) 
215    {
216       fprintf(stderr, "%s[%d]:  symtab for %s: bad address width, %d, not %d\n", 
217             FILE__, __LINE__, mutatee_name.c_str(), aw, expected_address_width);
218       return false;
219    }
220
221    std::vector<Module *> mods;
222    if (!test1_mutatee->getAllModules(mods)) 
223    {
224       fprintf(stderr, "%s[%d]:  symtab for %s: failed to get modules\n", 
225             FILE__, __LINE__, mutatee_name.c_str());
226       return false;
227    }
228
229    if (!mods.size()) 
230    {
231       fprintf(stderr, "%s[%d]:  symtab for %s: failed to get modules\n", 
232             FILE__, __LINE__, mutatee_name.c_str());
233       return false;
234    }
235
236    if (mods.size() != 5) 
237    {
238       fprintf(stderr, "%s[%d]:  symtab for %s: wrong number of modules: %d, not 5\n", 
239             FILE__, __LINE__, mutatee_name.c_str(), mods.size());
240       return false;
241    }
242
243    std::vector<const char *> expected_modnames;
244    expected_modnames.push_back("DEFAULT_MODULE");
245    expected_modnames.push_back("test1.mutatee.c");
246    expected_modnames.push_back("mutatee_util.c");
247    expected_modnames.push_back("test1.mutateeCommon.c");
248
249 #if defined (os_linux)
250 #if defined (arch_x86)
251    expected_modnames.push_back("call35_1_x86_linux.s");
252 #elif defined (arch_x86_64)
253    expected_modnames.push_back("call35_1_x86_64_linux.s");
254 #endif
255 #elif defined (os_solaris)
256    expected_modnames.push_back("call35_1_sparc_solaris.s");
257 #else
258    expected_modnames.push_back("call35_1.c");
259 #endif
260
261    for (unsigned int i = 0; i < mods.size(); ++i) 
262    {
263       Module *m = mods[i];
264       std::string modname = m->fileName();
265       bool found = false;
266
267       for (unsigned int j = 0; j < expected_modnames.size(); ++j) 
268       {
269          std::string checkname(expected_modnames[i]);
270          if (modname == checkname) {
271             found = true;
272             break;
273          }
274       }
275
276       if (!found) 
277       {
278          fprintf(stderr, "%s[%d]:  symtab for %s: cannot find module %s\n", 
279                FILE__, __LINE__, mutatee_name.c_str(), modname.c_str());
280          return false;
281       }
282    }
283
284    //  It might seem redundant here, but now also verify that findModule also works
285
286    for (unsigned int i = 0; i <expected_modnames.size(); ++i) 
287    {
288       Module *m = NULL;
289       std::string modname(expected_modnames[i]);
290
291       if (!test1_mutatee->findModule(m, modname)) 
292       {
293          fprintf(stderr, "%s[%d]:  failed to find module %s\n", FILE__, __LINE__, 
294                expected_modnames[i]);
295
296          return false;
297       }
298
299       if (!m) 
300       {
301          fprintf(stderr, "%s[%d]:  failed to find module %s\n", FILE__, __LINE__, 
302                expected_modnames[i]);
303
304          return false;
305       }
306
307       std::string mod_filename = m->fileName();
308
309       if (mod_filename != modname) 
310       {
311          fprintf(stderr, "%s[%d]:  module name mismatch???  %s vs %s\n", FILE__, __LINE__, 
312                expected_modnames[i], mod_filename.c_str());
313
314          return false;
315       }
316    }
317
318    //  A cursory test for findAllSymbols...
319    std::vector<Symbol *> symbols;
320
321    std::vector<const char *> expected_functions;
322    expected_functions.push_back("func1_1");
323    expected_functions.push_back("func2_1");
324    expected_functions.push_back("func3_1");
325    expected_functions.push_back("func4_1");
326    expected_functions.push_back("func5_1");
327    expected_functions.push_back("func6_1");
328    expected_functions.push_back("func7_1");
329    expected_functions.push_back("func8_1");
330    expected_functions.push_back("func9_1");
331    expected_functions.push_back("func10_1");
332    expected_functions.push_back("func11_1");
333    expected_functions.push_back("func12_1");
334    expected_functions.push_back("func13_1");
335    expected_functions.push_back("func14_1");
336    expected_functions.push_back("func15_1");
337    expected_functions.push_back("func16_1");
338    expected_functions.push_back("func17_1");
339    expected_functions.push_back("func18_1");
340    expected_functions.push_back("func19_1");
341    expected_functions.push_back("func20_1");
342    expected_functions.push_back("func21_1");
343    expected_functions.push_back("func22_1");
344    expected_functions.push_back("func23_1");
345    expected_functions.push_back("func24_1");
346    expected_functions.push_back("func25_1");
347    expected_functions.push_back("func26_1");
348    expected_functions.push_back("func27_1");
349    expected_functions.push_back("func28_1");
350    expected_functions.push_back("func29_1");
351    expected_functions.push_back("func30_1");
352    
353    std::vector<const char *> expected_variables;
354    expected_variables.push_back("globalVariable1_1");
355    expected_variables.push_back("globalVariable3_1");
356    expected_variables.push_back("globalVariable4_1");
357    expected_variables.push_back("globalVariable5_1");
358    expected_variables.push_back("globalVariable5_2");
359    expected_variables.push_back("globalVariable6_1");
360    expected_variables.push_back("globalVariable6_2");
361    expected_variables.push_back("globalVariable6_3");
362    expected_variables.push_back("globalVariable6_4");
363    expected_variables.push_back("globalVariable6_5");
364    expected_variables.push_back("globalVariable6_6");
365    expected_variables.push_back("globalVariable7_1");
366    expected_variables.push_back("globalVariable7_2");
367    expected_variables.push_back("globalVariable7_3");
368    expected_variables.push_back("globalVariable7_4");
369    expected_variables.push_back("globalVariable7_5");
370    expected_variables.push_back("globalVariable7_6");
371    expected_variables.push_back("globalVariable7_7");
372    expected_variables.push_back("globalVariable7_8");
373    expected_variables.push_back("globalVariable7_9");
374    expected_variables.push_back("globalVariable7_10");
375    expected_variables.push_back("globalVariable7_11");
376    expected_variables.push_back("globalVariable7_12");
377    expected_variables.push_back("globalVariable7_13");
378    expected_variables.push_back("globalVariable7_14");
379
380    if (!test1_mutatee->getAllSymbolsByType(symbols, Symbol::ST_UNKNOWN)) 
381    {
382       fprintf(stderr, "%s[%d]:  failed to getAllSymbolsByType(... , ST_UNKNOWN)\n", 
383             FILE__, __LINE__);
384       return false;
385    }
386
387    if (!symbols.size())
388    {
389       fprintf(stderr, "%s[%d]:  failed to getAllSymbolsByType(... , ST_UNKNOWN)\n", 
390             FILE__, __LINE__);
391       return false;
392    }
393
394    //  with ST_UNKNOWN, all symbols should be returned, so look for both functions and variables
395
396    for (unsigned int i = 0; i < expected_functions.size(); ++i) 
397    {
398       std::string seekname(expected_functions[i]);
399
400       bool found = false;
401
402       for (unsigned int j = 0; j < symbols.size(); ++j) 
403       {
404          Symbol *sym = symbols[j];
405          if (!sym) 
406          {
407             fprintf(stderr, "%s[%d]:  NULL Symbol !!!\n", 
408                   FILE__, __LINE__);
409             return false;
410          }
411
412          std::string sname = sym->getName();
413
414          if (!sname.length()) 
415          {
416             fprintf(stderr, "%s[%d]:  Unnamed Symbol !!!\n", 
417                   FILE__, __LINE__);
418             return false;
419          }
420
421          if (seekname == sname) 
422          {
423             found = true;
424          }
425       }
426
427       if (!found) 
428       {
429          fprintf(stderr, "%s[%d]:  Cannot find symbol %s\n", 
430                FILE__, __LINE__, seekname.c_str());
431          return false;
432       }
433    }
434
435    for (unsigned int i = 0; i < expected_variables.size(); ++i) 
436    {
437       std::string seekname(expected_variables[i]);
438
439       bool found = false;
440
441       for (unsigned int j = 0; j < symbols.size(); ++j) 
442       {
443          Symbol *sym = symbols[j];
444          if (!sym) 
445          {
446             fprintf(stderr, "%s[%d]:  NULL Symbol !!!\n", 
447                   FILE__, __LINE__);
448             return false;
449          }
450
451          std::string sname = sym->getName();
452
453          if (!sname.length()) 
454          {
455             fprintf(stderr, "%s[%d]:  Unnamed Symbol !!!\n", 
456                   FILE__, __LINE__);
457             return false;
458          }
459
460          if (seekname == sname) 
461          {
462             found = true;
463          }
464       }
465
466       if (!found) 
467       {
468          fprintf(stderr, "%s[%d]:  Cannot find symbol %s\n", 
469                FILE__, __LINE__, seekname.c_str());
470          return false;
471       }
472    }
473
474    symbols.clear();
475
476    if (!test1_mutatee->getAllSymbolsByType(symbols, Symbol::ST_FUNCTION)) 
477    {
478       fprintf(stderr, "%s[%d]:  failed to getAllSymbolsByType(... , ST_FUNCTION)\n", 
479             FILE__, __LINE__);
480       return false;
481    }
482
483    if (!symbols.size())
484    {
485       fprintf(stderr, "%s[%d]:  failed to getAllSymbolsByType(... , ST_FUNCTION)\n", 
486             FILE__, __LINE__);
487       return false;
488    }
489
490    for (unsigned int i = 0; i < expected_functions.size(); ++i) 
491    {
492       std::string seekname(expected_functions[i]);
493
494       bool found = false;
495
496       for (unsigned int j = 0; j < symbols.size(); ++j) 
497       {
498          Symbol *sym = symbols[j];
499          if (!sym) 
500          {
501             fprintf(stderr, "%s[%d]:  NULL Symbol !!!\n", 
502                   FILE__, __LINE__);
503             return false;
504          }
505
506          std::string sname = sym->getName();
507
508          if (!sname.length()) 
509          {
510             fprintf(stderr, "%s[%d]:  Unnamed Symbol !!!\n", 
511                   FILE__, __LINE__);
512             return false;
513          }
514
515          if (seekname == sname) 
516          {
517             found = true;
518          }
519       }
520
521       if (!found) 
522       {
523          fprintf(stderr, "%s[%d]:  Cannot find symbol %s\n", 
524                FILE__, __LINE__, seekname.c_str());
525          return false;
526       }
527    }
528
529    symbols.clear();
530
531    if (!test1_mutatee->getAllSymbolsByType(symbols, Symbol::ST_OBJECT))
532    {
533       fprintf(stderr, "%s[%d]:  failed to getAllSymbolsByType(... , ST_OBJECT)\n", 
534             FILE__, __LINE__);
535       return false;
536    }
537
538    if (!symbols.size())
539    {
540       fprintf(stderr, "%s[%d]:  failed to getAllSymbolsByType(... , ST_OBJECT)\n", 
541             FILE__, __LINE__);
542       return false;
543    }
544
545    for (unsigned int i = 0; i < expected_variables.size(); ++i) 
546    {
547       std::string seekname(expected_variables[i]);
548
549       bool found = false;
550
551       for (unsigned int j = 0; j < symbols.size(); ++j) 
552       {
553          Symbol *sym = symbols[j];
554          if (!sym) 
555          {
556             fprintf(stderr, "%s[%d]:  NULL Symbol !!!\n", 
557                   FILE__, __LINE__);
558             return false;
559          }
560
561          std::string sname = sym->getName();
562
563          if (!sname.length()) 
564          {
565             fprintf(stderr, "%s[%d]:  Unnamed Symbol !!!\n", 
566                   FILE__, __LINE__);
567             return false;
568          }
569
570          if (seekname == sname) 
571          {
572             found = true;
573          }
574       }
575
576       if (!found) 
577       {
578          fprintf(stderr, "%s[%d]:  Cannot find symbol %s\n", 
579                FILE__, __LINE__, seekname.c_str());
580          return false;
581       }
582    }
583
584    symbols.clear();
585
586    for (unsigned int i = 0; i < expected_functions.size(); ++i) 
587    {
588       //  for each expected function, do 2 lookups, first by unknown
589       //  then by function
590       std::string search_str(expected_functions[i]);
591       bool ok = false;
592
593       ok = test1_mutatee->findSymbolByType(symbols, search_str, Symbol::ST_UNKNOWN);
594
595       if (!ok) 
596       {
597          fprintf(stderr, "%s[%d]:  Cannot find symbol %s\n", 
598                FILE__, __LINE__, search_str.c_str());
599          return false;
600       }
601       
602       if (!symbols.size()) 
603       {
604          fprintf(stderr, "%s[%d]:  Cannot find symbol %s\n", 
605                FILE__, __LINE__, search_str.c_str());
606          return false;
607       }
608
609       if (symbols.size() > 1) 
610       {
611          fprintf(stderr, "%s[%d]:  WARN:  found %d symbols called '%s'\n", 
612                FILE__, __LINE__, symbols.size(), search_str.c_str());
613          return false;
614       }
615
616       symbols.clear();
617
618       ok = test1_mutatee->findSymbolByType(symbols, search_str, Symbol::ST_FUNCTION);
619
620       if (!ok) 
621       {
622          fprintf(stderr, "%s[%d]:  Cannot find symbol %s\n", 
623                FILE__, __LINE__, search_str.c_str());
624          return false;
625       }
626       
627       if (!symbols.size()) 
628       {
629          fprintf(stderr, "%s[%d]:  Cannot find symbol %s\n", 
630                FILE__, __LINE__, search_str.c_str());
631          return false;
632       }
633
634       if (symbols.size() > 1) 
635       {
636          fprintf(stderr, "%s[%d]:  WARN:  found %d symbols called '%s'\n", 
637                FILE__, __LINE__, symbols.size(), search_str.c_str());
638          return false;
639       }
640
641       symbols.clear();
642    }
643
644    for (unsigned int i = 0; i < expected_variables.size(); ++i) 
645    {
646       //  for each expected variable, do 2 lookups, first by unknown
647       //  then by object
648       std::string search_str(expected_variables[i]);
649       bool ok = false;
650
651       ok = test1_mutatee->findSymbolByType(symbols, search_str, Symbol::ST_UNKNOWN);
652
653       if (!ok) 
654       {
655          fprintf(stderr, "%s[%d]:  Cannot find symbol %s\n", 
656                FILE__, __LINE__, search_str.c_str());
657          return false;
658       }
659       
660       if (!symbols.size()) 
661       {
662          fprintf(stderr, "%s[%d]:  Cannot find symbol %s\n", 
663                FILE__, __LINE__, search_str.c_str());
664          return false;
665       }
666
667       if (symbols.size() > 1) 
668       {
669          fprintf(stderr, "%s[%d]:  WARN:  found %d symbols called '%s'\n", 
670                FILE__, __LINE__, symbols.size(), search_str.c_str());
671          return false;
672       }
673
674       symbols.clear();
675
676       ok = test1_mutatee->findSymbolByType(symbols, search_str, Symbol::ST_OBJECT);
677
678       if (!ok) 
679       {
680          fprintf(stderr, "%s[%d]:  Cannot find symbol %s\n", 
681                FILE__, __LINE__, search_str.c_str());
682          return false;
683       }
684       
685       if (!symbols.size()) 
686       {
687          fprintf(stderr, "%s[%d]:  Cannot find symbol %s\n", 
688                FILE__, __LINE__, search_str.c_str());
689          return false;
690       }
691
692       if (symbols.size() > 1) 
693       {
694          fprintf(stderr, "%s[%d]:  WARN:  found %d symbols called '%s'\n", 
695                FILE__, __LINE__, symbols.size(), search_str.c_str());
696          return false;
697       }
698
699       symbols.clear();
700    }
701
702    fprintf(stderr, "\n%s[%d]:  Have modules:\n", FILE__, __LINE__);
703    for (unsigned int i = 0; i < mods.size(); ++i) 
704    {
705       Module *m = mods[i];
706       fprintf(stderr, "\t%s--%s\n", m->fileName().c_str(), m->fullName().c_str());
707    }
708
709    fprintf(stderr, "%s[%d]:  passed test0 so far\n", FILE__, __LINE__);
710
711    SerializerBin::globalEnable();
712
713    return true;
714 }
715
716 //////////////////////////////////////////////////////////////////
717 //////////////////////////////////////////////////////////////////
718 ///////////
719 ///////////  Test 1 --
720 ///////////
721 //////////////////////////////////////////////////////////////////
722 //////////////////////////////////////////////////////////////////
723
724 class ZeroOne : public Serializable{
725    public:
726       int zero_one_int;
727       unsigned int zero_one_unsigned_int;
728       long zero_one_long;
729       unsigned long zero_one_unsigned_long;
730 #if 0
731       short zero_one_short;
732 #endif
733       //unsigned short zero_two_unsigned_short;
734       char zero_one_char;
735       //unsigned char zero_two_unsigned_char;
736
737       bool operator==(const ZeroOne &cmp) {
738          if (zero_one_int != cmp.zero_one_int) return false;
739          if (zero_one_long != cmp.zero_one_long) return false;
740 #if 0
741          if (zero_one_short != cmp.zero_one_short) return false;
742 #endif
743          if (zero_one_char != cmp.zero_one_char) return false;
744          return true;
745       }
746       bool operator!=(const ZeroOne &cmp) {
747          return (! (*this == cmp));
748       }
749       void printcmp(const ZeroOne &cmp) 
750       {
751          fprintf(stderr, "%s[%d]: %d %s %d\n", __FILE__, __LINE__,
752                zero_one_int, 
753                (zero_one_int == cmp.zero_one_int) ? "==" : "!=", 
754                cmp.zero_one_int);
755
756          fprintf(stderr, "%s[%d]: %ld %s %ld\n", __FILE__, __LINE__,
757                zero_one_long, 
758                (zero_one_long == cmp.zero_one_long) ? "==" : "!=", 
759                cmp.zero_one_long);
760
761 #if 0
762          fprintf(stderr, "%s[%d]: %hu %s %hu\n", __FILE__, __LINE__, 
763                zero_one_short, 
764                zero_one_short == cmp.zero_one_short ? "==" : "!=", 
765                cmp.zero_one_short);
766 #endif
767          fprintf(stderr, "%s[%d]: %c %s %c\n", __FILE__, __LINE__,
768                zero_one_char, 
769                (zero_one_char == cmp.zero_one_char) ? "==" : "!=", 
770                cmp.zero_one_char);
771       }
772
773       void serialize(SerializerBase *sb, const char *) 
774       {
775          try {
776             gtranslate(sb, zero_one_int, NULL);
777             gtranslate(sb, zero_one_unsigned_int, NULL);
778             gtranslate(sb, zero_one_long, NULL);
779             gtranslate(sb, zero_one_unsigned_long, NULL);
780 #if 0
781             gtranslate(sb, zero_one_short, NULL);
782 #endif
783             gtranslate(sb, zero_one_char, NULL);
784          } SER_CATCH("ZeroOne");
785       }
786 };
787
788 bool setup_control(ZeroOne &zero1)
789 {
790    zero1.zero_one_int = -1237843;
791    zero1.zero_one_unsigned_int = 1237843;
792    zero1.zero_one_long = -12378434L;
793    zero1.zero_one_unsigned_long = 12378434L;
794 #if 0
795    zero1.zero_one_short = -12;
796    //zero1.zero_two_unsigned_char= 12;
797    zero1.zero_one_short = -1 * 'a';
798 #endif
799    //zero1.zero_two_unsigned_short = 'a';
800    return true;
801 }
802
803 bool test1b(const char *cachefile)
804 {
805    if (!cachefile) {
806       fprintf(stderr, "%s[%d]:  NULL param\n", FILE__, __LINE__);
807       abort();
808    }
809
810    bool res = deserialize_verify<ZeroOne>(cachefile);
811    if (!res) {
812       fprintf(stderr, "%s[%d]:  test1b failed\n", FILE__, __LINE__);
813    }
814    return res;
815 }
816
817
818 bool test1()
819 {
820 #if 0
821    bool res = serialize_test<ZeroOne>(1, prog_name);
822    if (!res) {
823       fprintf(stderr, "%s[%d]:  test1 failed\n", FILE__, __LINE__);
824    }
825
826    return res;
827 #endif
828    fprintf(stderr, "%s[%d]:  SHOULDN'T BE HERE\n", FILE__, __LINE__);
829    abort();
830 }
831
832
833 /* 
834  * Test #2 
835  */
836
837 class ZeroTwo : public Serializable {
838    public:
839    std::string zero_two_string1;
840    std::string zero_two_string2;
841    std::string zero_two_string3;
842    std::string zero_two_string4;
843    std::string zero_two_string5;
844    int zero_two_int1;
845    int zero_two_int2;
846    int zero_two_int3;
847    int zero_two_int4;
848    int zero_two_int5;
849    float zero_two_float1;
850    float zero_two_float2;
851    float zero_two_float3;
852    float zero_two_float4;
853    float zero_two_float5;
854
855    public:
856       bool operator==(const ZeroTwo &cmp) {
857          if (zero_two_int1 != cmp.zero_two_int1) return false;
858          if (zero_two_int2 != cmp.zero_two_int2) return false;
859          if (zero_two_int3 != cmp.zero_two_int3) return false;
860          if (zero_two_int4 != cmp.zero_two_int4) return false;
861          if (zero_two_int5 != cmp.zero_two_int5) return false;
862          if (zero_two_float1 != cmp.zero_two_float1) return false;
863          if (zero_two_float2 != cmp.zero_two_float2) return false;
864          if (zero_two_float3 != cmp.zero_two_float3) return false;
865          if (zero_two_float4 != cmp.zero_two_float4) return false;
866          if (zero_two_float5 != cmp.zero_two_float5) return false;
867          if (zero_two_string1 != cmp.zero_two_string1) return false;
868          if (zero_two_string2 != cmp.zero_two_string2) return false;
869          if (zero_two_string3 != cmp.zero_two_string3) return false;
870          if (zero_two_string4 != cmp.zero_two_string4) return false;
871          if (zero_two_string5 != cmp.zero_two_string5) return false;
872          return true;
873       }
874       bool operator!=(const ZeroTwo &cmp) {
875          return (! (*this == cmp));
876       }
877       void printcmp(const ZeroTwo &cmp) {
878          if (zero_two_int1 != cmp.zero_two_int1) 
879             fprintf(stderr, "%s[%d]: fail here\n", FILE__, __LINE__);
880          if (zero_two_int2 != cmp.zero_two_int2) 
881             fprintf(stderr, "%s[%d]: fail here\n", FILE__, __LINE__);
882          if (zero_two_int3 != cmp.zero_two_int3) 
883             fprintf(stderr, "%s[%d]: fail here\n", FILE__, __LINE__);
884          if (zero_two_int4 != cmp.zero_two_int4)
885             fprintf(stderr, "%s[%d]: fail here\n", FILE__, __LINE__);
886          if (zero_two_int5 != cmp.zero_two_int5) 
887             fprintf(stderr, "%s[%d]: fail here\n", FILE__, __LINE__);
888          if (zero_two_float1 != cmp.zero_two_float1) 
889             fprintf(stderr, "%s[%d]: fail here\n", FILE__, __LINE__);
890          if (zero_two_float2 != cmp.zero_two_float2)
891             fprintf(stderr, "%s[%d]: fail here\n", FILE__, __LINE__);
892          if (zero_two_float3 != cmp.zero_two_float3) 
893             fprintf(stderr, "%s[%d]: fail here\n", FILE__, __LINE__);
894          if (zero_two_float4 != cmp.zero_two_float4) 
895             fprintf(stderr, "%s[%d]: fail here\n", FILE__, __LINE__);
896          if (zero_two_float5 != cmp.zero_two_float5) 
897             fprintf(stderr, "%s[%d]: fail here\n", FILE__, __LINE__);
898          if (zero_two_string1 != cmp.zero_two_string1) 
899             fprintf(stderr, "%s[%d]: fail here\n", FILE__, __LINE__);
900          if (zero_two_string2 != cmp.zero_two_string2) 
901             fprintf(stderr, "%s[%d]: fail here\n", FILE__, __LINE__);
902          if (zero_two_string3 != cmp.zero_two_string3) 
903             fprintf(stderr, "%s[%d]: fail here\n", FILE__, __LINE__);
904          if (zero_two_string4 != cmp.zero_two_string4) 
905             fprintf(stderr, "%s[%d]: fail here\n", FILE__, __LINE__);
906          if (zero_two_string5 != cmp.zero_two_string5) 
907             fprintf(stderr, "%s[%d]: fail here\n", FILE__, __LINE__);
908       }
909
910       void serialize(SerializerBase *sb, const char *)
911       {
912          try {
913             gtranslate(sb, zero_two_int1);
914             gtranslate(sb, zero_two_int2);
915             gtranslate(sb, zero_two_int3);
916             gtranslate(sb, zero_two_int4);
917             gtranslate(sb, zero_two_int5);
918             gtranslate(sb, zero_two_float1);
919             gtranslate(sb, zero_two_float2);
920             gtranslate(sb, zero_two_float3);
921             gtranslate(sb, zero_two_float4);
922             gtranslate(sb, zero_two_float5);
923             gtranslate(sb, zero_two_string1);
924             gtranslate(sb, zero_two_string2);
925             gtranslate(sb, zero_two_string3);
926             gtranslate(sb, zero_two_string4);
927             gtranslate(sb, zero_two_string5);
928          } SER_CATCH("ZeroTwo");
929       }
930 };
931
932 bool setup_control(ZeroTwo &control)
933 {
934    control.zero_two_int1 = 0xdeadbeef;
935    control.zero_two_int2 = 0xbeeffeed;
936    control.zero_two_int3 = 0xdeadfeed;
937    control.zero_two_int4 = 0xfeedbeef;
938    control.zero_two_int5 = 0xdadabaca;
939    control.zero_two_float1 = 0.1;
940    control.zero_two_float2 = 1e23;
941    control.zero_two_float3 = 1.38742e5;
942    control.zero_two_float4 = 5.5;
943    control.zero_two_float5 = 6.6;
944    control.zero_two_string1 = std::string("hello world");
945    control.zero_two_string2 = std::string("This is not a test");
946    control.zero_two_string3 = std::string("This is a test");
947    control.zero_two_string4 = std::string("The world was beginning to flower into wounds");
948    control.zero_two_string5 = std::string("The aggressive stylization of this mass-produced cockpit, the exaggerated mouldings of the instrument binnacles emphasized my growing sense of a new junction between my own body and the automobile, closer than my feelings for Renata's broad hips and strong legs stowed out of sight beneath her red plastic raincoat");
949    return true;
950 }
951
952 bool test2()
953 {
954    bool res = serialize_test<ZeroTwo>(2, prog_name);
955    if (!res) {
956       fprintf(stderr, "%s[%d]:  test2 failed\n", FILE__, __LINE__);
957    }
958
959    return res;
960 }
961
962 bool test2b(const char *cachefile)
963 {
964    if (!cachefile) {
965       fprintf(stderr, "%s[%d]:  NULL param\n", FILE__, __LINE__);
966       abort();
967    }
968
969    bool res = deserialize_verify<ZeroTwo>(cachefile);
970    if (!res) {
971       fprintf(stderr, "%s[%d]:  test2b failed\n", FILE__, __LINE__);
972    }
973    return res;
974 }
975
976 /*
977  * Test #3 
978  */
979
980 class ZeroThree : public Serializable {
981    public:
982       std::vector<int> zero_three_ints;
983       bool operator==(const ZeroThree &cmp) {
984          if (zero_three_ints.size() != cmp.zero_three_ints.size()) {
985             return false;
986          }
987          for (unsigned int i = 0; i < cmp.zero_three_ints.size(); ++i) {
988             if ((zero_three_ints[i] != cmp.zero_three_ints[i])) 
989                   return false;
990          }
991          return true;
992       }
993
994       bool operator!=(const ZeroThree &cmp) {
995          return (! (*this == cmp));
996       }
997       void printcmp(const ZeroThree &cmp) {
998          if (zero_three_ints.size() != cmp.zero_three_ints.size()) {
999             fprintf(stderr, "%s[%d]:  vectors have sizes %d and %d\n", 
1000                   FILE__, __LINE__, cmp.zero_three_ints.size(), zero_three_ints.size());
1001          }
1002          for (unsigned int i = 0; i < cmp.zero_three_ints.size(); ++i) {
1003             if ((zero_three_ints[i] != cmp.zero_three_ints[i])) 
1004                fprintf(stderr, "elem %d: %d -- %d\n", i, zero_three_ints[i], 
1005                      cmp.zero_three_ints[i]);
1006          }
1007       }
1008
1009       void serialize(SerializerBase *sb, const char *)
1010       {
1011          try {
1012             gtranslate(sb, zero_three_ints);
1013          } SER_CATCH("ZeroThree");
1014       }
1015 };
1016
1017 bool setup_control(ZeroThree &param)
1018 {
1019    for (unsigned int i = 0; i < 50; ++i) {
1020       param.zero_three_ints.push_back(i*100 + 2077);
1021    }
1022    return true;
1023 }
1024
1025 bool test3()
1026 {
1027    bool res  = serialize_test<ZeroThree>(3, prog_name);
1028    if (!res) {
1029       fprintf(stderr, "%s[%d]:  test3 failed\n", FILE__, __LINE__);
1030    }
1031
1032    return res;
1033 }
1034
1035 bool test3b(const char *cachefile)
1036 {
1037    if (!cachefile) {
1038       fprintf(stderr, "%s[%d]:  NULL param\n", FILE__, __LINE__);
1039       abort();
1040    }
1041
1042    bool res = deserialize_verify<ZeroThree>(cachefile);
1043    if (!res) {
1044       fprintf(stderr, "%s[%d]:  test3b failed\n", FILE__, __LINE__);
1045    }
1046    return res;
1047 }
1048
1049 /*
1050  * Test #4 
1051  */
1052 class ZeroFour : public Serializable {
1053    public:
1054       std::vector<std::vector<int> > zero_four_ints;
1055       bool operator==(const ZeroFour &cmp) {
1056          if (zero_four_ints.size() != cmp.zero_four_ints.size()) {
1057             return false;
1058          }
1059          for (unsigned int i = 0; i < cmp.zero_four_ints.size(); ++i) {
1060             if ((zero_four_ints[i] != cmp.zero_four_ints[i])) 
1061                   return false;
1062          }
1063          return true;
1064       }
1065
1066       bool operator!=(const ZeroFour &cmp) {
1067          return (! (*this == cmp));
1068       }
1069       void printcmp(const ZeroFour &cmp) {
1070          if (zero_four_ints.size() != cmp.zero_four_ints.size()) {
1071             fprintf(stderr, "%s[%d]:  vectors have sizes %d and %d\n", 
1072                   FILE__, __LINE__, cmp.zero_four_ints.size(), zero_four_ints.size());
1073          }
1074          for (unsigned int i = 0; i < cmp.zero_four_ints.size(); ++i) {
1075             const std::vector<int> &v1 = cmp.zero_four_ints[i];
1076             const std::vector<int> &v2 = zero_four_ints[i];
1077
1078             for (unsigned int j = 0; j < v1.size(); ++j) {
1079
1080                if ((v1[j] != v2[j])) 
1081                   fprintf(stderr, "elem %d: %d -- %d\n", j, v1[j], v2[j]);
1082             }
1083          }
1084       }
1085       void serialize(SerializerBase *sb, const char *)
1086       {
1087          try {
1088             gtranslate(sb, zero_four_ints);
1089          } SER_CATCH("ZeroFour");
1090       }
1091
1092 };
1093
1094 bool setup_control(ZeroFour &param)
1095 {
1096
1097       //std::vector<std::vector<int> > zero_four_ints;
1098    param.zero_four_ints.resize(50);
1099    for (unsigned int i = 0; i < 50; ++i) {
1100       std::vector <int> &v  = param.zero_four_ints[i];
1101       v.resize(50);
1102       for (unsigned j = 0; j < 50; ++j) {
1103          v[j] = i*j + 2077;
1104       }
1105    }
1106    return true;
1107 }
1108
1109 bool test4()
1110 {
1111    bool res = serialize_test<ZeroFour>(4, prog_name);
1112    if (!res) {
1113       fprintf(stderr, "%s[%d]:  test4 failed\n", FILE__, __LINE__);
1114    }
1115
1116    return res;
1117 }
1118
1119 bool test4b(const char *cachefile)
1120 {
1121    if (!cachefile) {
1122       fprintf(stderr, "%s[%d]:  NULL param\n", FILE__, __LINE__);
1123       abort();
1124    }
1125
1126    bool res = deserialize_verify<ZeroFour>(cachefile);
1127    if (!res) {
1128       fprintf(stderr, "%s[%d]:  test4b failed\n", FILE__, __LINE__);
1129    }
1130    return res;
1131 }
1132
1133 /* 
1134  * Test #5 
1135  */
1136 class ZeroFive : public Serializable {
1137    public:
1138       std::vector<int *> zero_five_ints;
1139       bool operator==(const ZeroFive &cmp) {
1140          if (zero_five_ints.size() != cmp.zero_five_ints.size()) {
1141             return false;
1142          }
1143          for (unsigned int i = 0; i < cmp.zero_five_ints.size(); ++i) {
1144             assert(zero_five_ints[i]);
1145             assert(cmp.zero_five_ints[i]);
1146             if ((*zero_five_ints[i] != *cmp.zero_five_ints[i])) 
1147                   return false;
1148          }
1149          return true;
1150       }
1151
1152       bool operator!=(const ZeroFive &cmp) {
1153          return (! (*this == cmp));
1154       }
1155       void printcmp(const ZeroFive &cmp) {
1156          if (zero_five_ints.size() != cmp.zero_five_ints.size()) {
1157             fprintf(stderr, "%s[%d]:  vectors have sizes %d and %d\n", 
1158                   FILE__, __LINE__, cmp.zero_five_ints.size(), zero_five_ints.size());
1159          }
1160          for (unsigned int i = 0; i < cmp.zero_five_ints.size(); ++i) {
1161             assert(zero_five_ints[i]);
1162             if ((*zero_five_ints[i] != *cmp.zero_five_ints[i])) 
1163                fprintf(stderr, "elem %d: %d -- %d\n", i, *zero_five_ints[i], 
1164                      *cmp.zero_five_ints[i]);
1165          }
1166       }
1167
1168       void serialize(SerializerBase *sb, const char *)
1169       {
1170          try {
1171             gtranslate(sb,zero_five_ints);
1172          } SER_CATCH("ZeroFive");
1173       }
1174
1175 };
1176
1177 bool setup_control(ZeroFive &param)
1178 {
1179    for (unsigned int i = 0; i < 50; ++i) {
1180       int *newint = new int[1];
1181       assert(newint);
1182       *newint = i*100 + 2077;
1183       param.zero_five_ints.push_back(newint);
1184    }
1185    return true;
1186 }
1187
1188 bool test5()
1189 {
1190    bool res = serialize_test<ZeroFive>(5, prog_name);
1191    if (!res) {
1192       fprintf(stderr, "%s[%d]:  test5 failed\n", FILE__, __LINE__);
1193    }
1194
1195    return res;
1196 }
1197
1198 bool test5b(const char *cachefile)
1199 {
1200    if (!cachefile) {
1201       fprintf(stderr, "%s[%d]:  NULL param\n", FILE__, __LINE__);
1202       abort();
1203    }
1204
1205    bool res = deserialize_verify<ZeroFive>(cachefile);
1206    if (!res) {
1207       fprintf(stderr, "%s[%d]:  test5b failed\n", FILE__, __LINE__);
1208    }
1209    return res;
1210 }
1211
1212 /* 
1213  * Test #6 
1214  */
1215 class ZeroSix : public Serializable {
1216    public:
1217       hash_map<char, std::string> dictionary6;
1218       bool operator==(ZeroSix &cmp) {
1219          if (dictionary6.size() != cmp.dictionary6.size()) {
1220             return false;
1221          }
1222          hash_map<char, std::string>::iterator iter1 = dictionary6.begin();
1223          hash_map<char, std::string>::iterator iter2 = cmp.dictionary6.begin();
1224          while ((iter1 != dictionary6.end()) && (iter2 != cmp.dictionary6.end())) {
1225             char key1 = iter1->first;
1226             char key2 = iter2->first;
1227             std::string &val1 = iter1->second;
1228             std::string &val2 = iter2->second;
1229             if (key1 != key2) {
1230                fprintf(stderr, "%s[%d]: keys differ: %c != %c\n", 
1231                      FILE__, __LINE__, key1, key2);
1232                return false;
1233             }
1234             if (val1 != val2) {
1235                fprintf(stderr, "%s[%d]: vals differ: '%s' != '%s'\n", 
1236                      FILE__, __LINE__, val1.c_str(), val2.c_str());
1237                return false;
1238             }
1239             iter1++;
1240             iter2++;
1241          }
1242
1243          return true;
1244       }
1245
1246       bool operator!=(ZeroSix &cmp) {
1247          return (! (*this == cmp));
1248       }
1249       void printcmp(ZeroSix &cmp) {
1250          if (dictionary6.size() != cmp.dictionary6.size()) {
1251             fprintf(stderr, "%s[%d]:  hashes have sizes %d and %d\n", 
1252                   FILE__, __LINE__, cmp.dictionary6.size(), dictionary6.size());
1253          }
1254          hash_map<char, std::string>::iterator iter1 = dictionary6.begin();
1255          hash_map<char, std::string>::iterator iter2 = cmp.dictionary6.begin();
1256          while (iter1 != dictionary6.end() && iter2 != cmp.dictionary6.end()) {
1257             char key1 = iter1->first;
1258             char key2 = iter2->first;
1259             std::string val1 = iter1->second;
1260             std::string val2 = iter2->second;
1261             fprintf(stderr, "%s[%d]:  key1:  %c, val1: '%s'\n", FILE__, __LINE__, key1, val1.c_str());
1262             fprintf(stderr, "%s[%d]:  key2:  %c, val2: '%s'\n", FILE__, __LINE__, key2, val2.c_str());
1263             iter1++;
1264             iter2++;
1265          }
1266       }
1267
1268       void serialize(SerializerBase *sb, const char *) 
1269       {
1270          try {
1271             fprintf(stderr, "%s[%d]:  before gtranslate:  hash size = %d\n", 
1272                   FILE__, __LINE__, dictionary6.size());
1273             gtranslate(sb,dictionary6);
1274          } SER_CATCH("ZeroSix");
1275       }
1276
1277 };
1278
1279 bool setup_control(ZeroSix &param)
1280 {
1281    assert(param.dictionary6.size() == 0);
1282    param.dictionary6['a'] = "aardvark";
1283    param.dictionary6['b'] = "bollocks";
1284    param.dictionary6['c'] = "cro-magnon";
1285    param.dictionary6['d'] = "deadbeat";
1286    param.dictionary6['e'] = "elephant";
1287    param.dictionary6['f'] = "farce";
1288    param.dictionary6['g'] = "guardian";
1289    param.dictionary6['h'] = "heresy";
1290    param.dictionary6['i'] = "ipsedixit";
1291    param.dictionary6['j'] = "jovian";
1292    param.dictionary6['k'] = "killface";
1293    param.dictionary6['l'] = "lavatory";
1294    param.dictionary6['m'] = "masonic";
1295    param.dictionary6['n'] = "newbie";
1296    param.dictionary6['o'] = "oddity";
1297    param.dictionary6['p'] = "paternal";
1298    param.dictionary6['q'] = "quack";
1299    param.dictionary6['r'] = "restaurant";
1300    param.dictionary6['s'] = "salami";
1301    param.dictionary6['t'] = "twonky";
1302    param.dictionary6['u'] = "usurper";
1303    param.dictionary6['v'] = "velocity";
1304    param.dictionary6['w'] = "wherabouts";
1305    param.dictionary6['x'] = "xray-spex";
1306    param.dictionary6['y'] = "yosemite";
1307    param.dictionary6['z'] = "zeus";
1308    return true;
1309 }
1310
1311 bool test6()
1312 {
1313    bool res = serialize_test<ZeroSix>(6, prog_name);
1314    if (!res) {
1315       fprintf(stderr, "%s[%d]:  test6 failed\n", FILE__, __LINE__);
1316    }
1317
1318    return res;
1319 }
1320
1321 bool test6b(const char *cachefile)
1322 {
1323    if (!cachefile) {
1324       fprintf(stderr, "%s[%d]:  NULL param\n", FILE__, __LINE__);
1325       abort();
1326    }
1327
1328    bool res = deserialize_verify<ZeroSix>(cachefile);
1329    if (!res) {
1330       fprintf(stderr, "%s[%d]:  test6b failed\n", FILE__, __LINE__);
1331    }
1332    return res;
1333 }
1334
1335 int main(int iargc, char *argv[])
1336 {                                       /* despite different conventions */
1337    unsigned argc=(unsigned)iargc;      /* make argc consistently unsigned */
1338    unsigned int i;
1339    unsigned long testNum=0;
1340    char *modifier = NULL;
1341    char *aux_file_name = NULL;
1342    char *logfilename = NULL;
1343    prog_name = argv[0];
1344
1345    fprintf(stderr, "%s[%d]:  welcome to \"%s", __FILE__, __LINE__, argv[0]);
1346    for (unsigned int ii=1; ii < argc; ++ii) {
1347       fprintf(stderr, " %s", argv[ii]);
1348    }
1349    fprintf(stderr, "\"\n");
1350
1351    for (i=1; i < argc; i++) {
1352       if (!strcmp(argv[i], "-verbose")) {
1353          debugPrint = TRUE;
1354       } else if (!strcmp(argv[i], "-log")) {
1355          if ((i + 1) >= argc) {
1356             fprintf(stderr, "Missing log file name\n");
1357             exit(-1);
1358          }
1359          i += 1;
1360          logfilename = argv[i];
1361       } else if (!strcmp(argv[i], "-run")) {
1362          char *str_end_ptr = NULL;
1363          testNum = strtoul(argv[i+1], &str_end_ptr,10);
1364          if (*str_end_ptr != '\0') {
1365             //  catch subtests that are exec'd automatically (eg, 1b, 1c)
1366             modifier = str_end_ptr;
1367             aux_file_name = argv[i+2];
1368             fprintf(stderr, "%s[%d]:  have test modifier %s, testNum = %ld\n", 
1369                   FILE__, __LINE__, modifier, testNum);
1370             i += 1;
1371          }
1372           else {
1373             /* end of test list */
1374             break;
1375          }
1376          i++;
1377       } else {
1378          fprintf(stderr, "Usage: %s [-verbose] -run <num>\n", argv[0]);
1379          fprintf(stderr, "\n\nyou asked for:\n\t\"");
1380          for (unsigned int i = 0; i < argc; ++i) {
1381             fprintf(stderr, "%s ", argv[i]);
1382          }
1383          fprintf(stderr, "\"\n");
1384          exit(-1);
1385       }
1386    }
1387
1388    if ((logfilename != NULL) && (strcmp(logfilename, "-") != 0)) {
1389       outlog = fopen(logfilename, "a");
1390       if (NULL == outlog) {
1391          fprintf(stderr, "Error opening log file %s\n", logfilename);
1392          exit(-1);
1393       }
1394       errlog = outlog;
1395    } else {
1396       outlog = stdout;
1397       errlog = stderr;
1398    }
1399
1400    if ((argc==1) || debugPrint)
1401       logstatus("Mutatee %s [C++]:\"%s\"\n", argv[0], Builder_id);
1402    if (argc==1) exit(0);
1403
1404    bool test_ok = false;
1405    switch (testNum) {
1406       case 0:
1407          if (!modifier)
1408             test_ok = test0();
1409          else {
1410             fprintf(stderr, "%s[%d]:  ERROR:  modifier makes no sense here\n", FILE__, __LINE__);
1411          }
1412          break;
1413       case 1:
1414          if (!modifier)
1415             test_ok = test1();
1416          else {
1417             switch (*modifier) {
1418                case 'b':  
1419                   if (!aux_file_name) {
1420                      fprintf(stderr, "%s[%d]:  no aux file name\n", FILE__, __LINE__);
1421                      abort();
1422                   }
1423
1424                   fprintf(stderr, "%s[%d]:  process %d about to run test1b\n", 
1425                         FILE__, __LINE__, getpid());
1426                   test_ok = test1b(aux_file_name); 
1427                   fprintf(stderr, "%s[%d]:  process %d ran test1b\n", 
1428                         FILE__, __LINE__, getpid());
1429                   break;
1430                default:
1431                   fprintf(stderr, "%s[%d]:  bad modifier! %s\n", 
1432                         FILE__, __LINE__, modifier);
1433             };
1434          }
1435          break;
1436
1437       case 2:
1438          if (!modifier)
1439             test_ok = test2();
1440          else {
1441             switch (*modifier) {
1442                case 'b':  test_ok = test2b(aux_file_name); break;
1443                default:
1444                   fprintf(stderr, "%s[%d]:  bad modifier! %s\n", 
1445                         FILE__, __LINE__, modifier);
1446             };
1447          }
1448          break;
1449
1450       case 3:
1451          if (!modifier)
1452             test_ok = test3();
1453          else {
1454             switch (*modifier) {
1455                case 'b':  test_ok = test3b(aux_file_name); break;
1456                default:
1457                   fprintf(stderr, "%s[%d]:  bad modifier! %s\n", 
1458                         FILE__, __LINE__, modifier);
1459             };
1460          }
1461          break;
1462
1463       case 4:
1464          if (!modifier)
1465             test_ok = test4();
1466          else {
1467             switch (*modifier) {
1468                case 'b':  test_ok = test4b(aux_file_name); break;
1469                default:
1470                   fprintf(stderr, "%s[%d]:  bad modifier! %s\n", 
1471                         FILE__, __LINE__, modifier);
1472             };
1473          }
1474          break;
1475
1476       case 5:
1477          if (!modifier)
1478             test_ok = test5();
1479          else {
1480             switch (*modifier) {
1481                case 'b':  test_ok = test5b(aux_file_name); break;
1482                default:
1483                   fprintf(stderr, "%s[%d]:  bad modifier! %s\n", 
1484                         FILE__, __LINE__, modifier);
1485             };
1486          }
1487          break;
1488
1489       case 6:
1490          if (!modifier)
1491             test_ok = test6();
1492          else {
1493             switch (*modifier) {
1494                case 'b':  test_ok = test6b(aux_file_name); break;
1495                default:
1496                   fprintf(stderr, "%s[%d]:  bad modifier! %s\n", 
1497                         FILE__, __LINE__, modifier);
1498             };
1499          }
1500          break;
1501       default:
1502          fprintf(stderr, "%s[%d]: invalid test number %ld in mutatee\n", 
1503                FILE__, __LINE__, testNum);
1504          break;
1505    }
1506
1507    dprintf("Mutatee %s terminating.\n", argv[0]);
1508
1509    if ((outlog != NULL) && (outlog != stdout)) {
1510       fclose(outlog);
1511    }
1512
1513    if (test_ok) {
1514       return 0; /* true == no error, so return zero */
1515    }
1516
1517    return -1;
1518 }