Bluegene testsuite fixes
[dyninst.git] / testsuite / src / test_driver.C
1 /*
2  * Copyright (c) 1996-2009 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  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 // $Id: test_driver.C,v 1.7 2008/10/30 19:16:50 legendre Exp $
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <stdarg.h>
36 #include <string.h>
37 #include <string>
38 #include <errno.h>
39 #include <vector>
40 #include <iostream>
41 #include <sstream>
42 #include <assert.h>
43 #include <algorithm>
44 #include <sys/stat.h>
45 #include <time.h>
46 #include <limits.h>
47
48 #if defined(os_windows_test)
49 #define vsnprintf _vsnprintf
50 #define snprintf _snprintf
51 #pragma warning(disable:4786)
52 #include <direct.h>
53 #else
54 #include <fnmatch.h>
55 #include <dirent.h>
56 #include <unistd.h>
57 #include <sys/times.h>
58 #include <sys/time.h>
59 #include <sys/resource.h>
60 #include <strings.h>
61 #endif
62
63 #include "ParameterDict.h"
64 #include "test_lib.h"
65 #include "error.h"
66 #include "ResumeLog.h"
67 #include "TestOutputDriver.h"
68 #include "StdOutputDriver.h"
69 #include "comptester.h"
70 #include "help.h"
71
72 #define opt_none 1<<0
73 #define opt_low 1<<1
74 #define opt_high 1<<2
75 #define opt_max 1<<3
76 #define opt_all (opt_none|opt_low|opt_high|opt_max)
77
78 struct compiler_t {
79    const char *option;
80    const char *mutatee_str;
81    bool enabled;
82 };
83
84 #define NUM_COMPILERS 21
85 compiler_t compilers[] = {
86    { "-gcc", "gcc", false },
87    { "-g++", "g++", true },
88    { "-gfortran", "gfortran", true },
89    { "-icc", "icc", false },
90    { "-icpc", "iCC", false },
91    { "-pgcc", "pgcc", false },
92    { "-pgCC", "pgCC", false },
93    { "-cc", "cc", false },
94    { "-CC", "CC", false },
95    { "-cxx", "cxx", false },
96    { "-VC", "VC", false },
97    { "-VC++", "VC++", true },
98    { "-suncc", "suncc", false },
99    { "-xlc", "xlc", false },
100    { "-xlC", "xlC", false },
101    { "-bgxlc", "bgxlc", true },
102    { "-bgxlc++", "bgxlc++", true },
103    { "-ibmas", "ibmas", false },
104    { "-masm", "masm", false },
105    { "-nasm", "nasm", false },
106    { "-nocompiler", "nocompiler", true }
107 };
108    
109 // These determine the defaults when test driver is invoked with no options
110 int optLevel = opt_none;
111 bool runDefaultOpts = true;
112 bool runAllTests = true;
113 bool runAllMutatees = true;
114 bool runDefaultCompilers = true;
115 bool runAllCompilers = false;
116 bool runDefaultStarts = true;
117 bool runCreate = true;
118 bool runAttach = false;
119 bool runRewriter = false;
120 bool runDeserialize = false;
121 bool useHumanLog = true;
122 bool enableLogging = true;
123 bool printLabels = false;
124 bool shouldDebugBreak = false;
125 bool called_from_runTests = false;
126 bool quietFormat = false;
127 bool runDyninst = false;
128 bool runSymtab = false;
129 bool runInstruction = false;
130 bool runAllComps = true;
131 bool printMutateeLogHeader = false;
132 bool measureMEMCPU = false;
133 bool runAllABIs = true;
134 bool runABI_32 = false;
135 bool runABI_64 = false;
136 bool limitSkippedTests = false;
137 bool noclean = false;
138 bool runMT = true;
139 bool runST = true;
140 bool setT = false;
141 bool runMP = true;
142 bool runSP = true;
143 bool setP = false;
144 bool runProcControl = false;
145 bool runDynamicLink = false;
146 bool runStaticLink = false;
147 bool runAllLinks = true;
148 bool runPic = false;
149 bool runNonPic = true;
150
151 int limitResumeGroup = -1;
152 int limitResumeTest = -1;
153 int skipToTest = 0;
154 int skipToMutatee = 0;
155 int skipToOption = 0;
156 int testLimit = 0;
157 int testsRun = 0;
158 int errorPrint = 0;
159 int debugPrint = 0;
160 int unique_id = 0;
161 int max_unique_id = 0;
162 char *humanlog_name = "-";
163 char *crashlog_name = "crashlog";
164 char *measureFileName = "-";
165 std::vector<char *> mutatee_list;
166 std::vector<char *> test_list;
167
168 #if defined(os_windows_test)
169 char *logfilename = "NUL";
170 #else
171 char *logfilename = "/dev/null";
172 #endif
173 FILE *outlog = NULL;
174 FILE *errlog = NULL;
175
176 char *pdscrdir = NULL;
177 char *uw_pdscrdir = "/scratch/paradyn/builds/scripts";
178 char *umd_pdscrdir = "/fs/dyninst/dyninst/current/scripts";
179
180 int parseArgs(int argc, char *argv[]);
181 int setupLogs();
182
183 // Include test setup data
184 #include "test_info_new.h"
185
186 #if !defined(os_windows_test)
187 int runScript(const char *name, ...)
188 {
189    char test[1024];
190    int result;
191    va_list ap;
192    va_start(ap, name);
193    vsnprintf(test, 1024, name, ap);
194    va_end(ap);
195
196    char test2[1024];
197    if ((outlog != NULL) && (outlog != stdout)) {
198       snprintf(test2, 1024, "sh -c \"%s\" >>%s 2>&1", test, logfilename);
199    } else {
200       snprintf(test2, 1024, "%s", test);
201    }
202
203    // Flush before/after script run
204    flushOutputLog();
205    flushErrorLog();
206    result = system(test2);
207    flushOutputLog();
208    flushErrorLog();
209
210    return result;
211 }
212 #else
213 int runScript(const char *name, ...) {
214    getOutput()->log(STDERR, "runScript not implemented on Windows\n");
215    assert(0);
216    return -1;
217 }
218 #endif
219
220 #if !defined(os_windows_test)
221 //static void *mem_start;
222 //static struct tms start_time;
223
224 #include <unistd.h>
225 #include <fcntl.h>
226 #include <sys/time.h>
227
228 #ifndef timersub
229 #define timersub(b, a, r) \
230 do { \
231     (r)->tv_sec = (b)->tv_sec - (a)->tv_sec;\
232     (r)->tv_usec = (b)->tv_usec -(a)->tv_usec;\
233     if((r)->tv_usec < 0) {\
234         (r)->tv_sec--;\
235         (r)->tv_usec += 1000000;\
236     } \
237 } while(0)
238 #endif
239
240 class testMetrics
241 {
242     public:
243     testMetrics(TestOutputDriver* d)
244     : driver(d)
245     {
246         if (!measureMEMCPU || !d)
247             return;
248
249         getrusage(RUSAGE_SELF, &start_time);
250     }
251     ~testMetrics()
252     {
253         if (!measureMEMCPU || !driver)
254             return;
255
256         //unsigned long mem_end = get_mem_usage();
257         struct rusage end_time;
258         getrusage(RUSAGE_SELF, &end_time);
259
260         //signed long mem_diff = mem_end - mem_start;
261         timeval utime, stime;
262         timersub(&end_time.ru_utime, &start_time.ru_utime, &utime);
263         timersub(&end_time.ru_stime, &start_time.ru_stime, &stime);
264         double ut, st;
265         ut = (double)(utime.tv_sec) + (double)(utime.tv_usec)/1000000;
266         st = (double)(stime.tv_sec) + (double)(stime.tv_usec)/1000000;
267         // If Linux ever fills out the full rusage structure, we'll capture the difference in high-water mark here.
268         // Right now, this should log zeroes for our memory usage...we're still getting the framework in at least.
269         // Note that RSS is measured in kB, so we'll scale...
270         driver->logMemory(1024 * (end_time.ru_maxrss - start_time.ru_maxrss));  
271         driver->logTime(ut + st);
272     }
273     private:
274         TestOutputDriver* driver;
275         struct rusage start_time;
276 };
277
278 void setupProcessGroup()
279 {
280    if (!called_from_runTests)
281       return;
282
283    /* This is used over setpgrp() for portability reasons */
284    setpgid(0,0);
285 }
286
287 #else
288
289 class testMetrics
290 {
291     public:
292         testMetrics(TestOutputDriver*) {}
293 };
294
295 void setupProcessGroup()
296 {
297 }
298
299 #endif
300
301 void printLogMutateeHeader(const char *mutatee, test_linktype_t linktype)
302 {
303    if (!enableLogging)
304       return;
305    flushOutputLog();
306    flushErrorLog();
307    // Mutatee Description
308    // Mutatee Info
309    if ( (mutatee != NULL) && (strcmp(mutatee, "") != 0) ) {
310       getOutput()->log(LOGINFO, "[Tests with %s]\n", mutatee);
311 #if !defined(os_windows_test)
312       if ( pdscrdir ) {
313          runScript("ls -lLF %s", mutatee);
314          if( linktype == DynamicLink ) 
315             runScript("%s/ldd_PD %s", pdscrdir, mutatee);
316          else
317             getOutput()->log(LOGINFO, "%s: statically linked\n", mutatee);
318       }
319 #endif
320    } else {
321       getOutput()->log(LOGINFO, "[Tests with none]\n");
322    }
323
324    getOutput()->log(LOGINFO, "\n");
325    flushOutputLog();
326    flushErrorLog();
327 }
328
329 void printLogOptionHeader(TestInfo *tinfo)
330 {
331    if (!printMutateeLogHeader)
332       return;
333    flushOutputLog();
334    flushErrorLog();
335    // Full test description
336    getOutput()->log(LOGINFO, "test-info: %s\n", tinfo->label);
337    flushOutputLog();
338    flushErrorLog();
339 }
340
341 void printHumanTestHeader(test_data_t &test, char *mutatee, bool useAttach)
342 {
343    flushOutputLog();
344    flushErrorLog();
345    // Test Header
346    getOutput()->log(LOGINFO, "Running: %s", test.name);
347    if ( strcmp(mutatee, "") != 0 )
348    {
349       getOutput()->log(LOGINFO, " with mutatee: %s", mutatee);
350    }
351    if ( useAttach )
352    {
353       getOutput()->log(LOGINFO, " in attach mode");
354    }
355    getOutput()->log(LOGINFO, ".\n");
356
357
358    flushOutputLog();
359    flushErrorLog();
360 }
361
362 struct formatStrings
363 {
364    formatStrings(const std::string& pass, const std::string& skip, const std::string& fail, const std::string& crash, 
365                  const std::string& create, const std::string& attach, const std::string& testNameFormat) :
366       passStr(pass), skipStr(skip), failStr(fail), crashStr(crash), createStr(create), attachStr(attach), testNameFormatStr(testNameFormat) 
367    {
368    }
369    formatStrings() 
370    {
371    }
372   
373    std::string passStr;
374    std::string skipStr;
375    std::string failStr;
376    std::string crashStr;
377    std::string createStr;
378    std::string attachStr;
379    std::string testNameFormatStr;
380 };
381
382 static formatStrings verboseStrings("PASSED\n", "SKIPPED\n", "FAILED\n", "CRASHED\n", "create\tresult: ", "attach\tresult: ", "%s: mutatee: %s create_mode: ");
383 static formatStrings compactStrings(".", "S", "F", "C", "", "", "");
384
385 struct failureInfo
386 {
387    std::string testName;
388    bool createMode;
389    bool wasCrash;
390 };
391
392 // Performs a wildcard string match on Unix-like systems, and a standard string
393 // match on Windows
394 // Returns true for match found, false for no match
395 bool nameMatches(const char *wcname, const char *tomatch) {
396 #if defined(os_windows_test)
397    // Sadly, we can't assume the presence of fnmatch on Windows
398    return (strcmp(wcname, tomatch) == 0);
399 #else
400    // The other systems we support are unix-based and should provide fnmatch (?)
401    return (fnmatch(wcname, tomatch, 0) == 0);
402 #endif
403 }
404
405 // Returns true if the vector mutatee_list contains the string mutatee, and
406 // returns false if it does not
407 bool mutateeListContains(std::vector<char *> mutatee_list, const char *mutatee) {
408    if (NULL == mutatee) {
409       return false;
410    }
411    for (size_t i = 0; i < mutatee_list.size(); i++) {
412       if (nameMatches(mutatee_list[i], mutatee)) {
413          return true;
414       }
415    }
416    return false;
417 }
418
419 // Runs through all the test names in testsn, and enables any matching tests
420 // in testsv.  If any tests matched, returns true.  If there were no matching
421 // tests, returns false
422 // Okay, we don't actually enable any tests here; we just disable tests that
423 // don't match.  All tests start out enabled, and we previously disabled any
424 // that are crashing while we were parsing the resume log.
425 bool testListContains(TestInfo * test,
426                       std::vector<char *> &testsn) {
427    bool match_found = false;
428
429    for (size_t i = 0; i < testsn.size(); i++) {
430       if (nameMatches(testsn[i], test->name))
431          return true;
432    }
433    return false;
434 }
435
436 int numUnreportedTests(RunGroup *group)
437 {
438    int num_unreported = 0;
439
440    for (unsigned i=0; i<group->tests.size(); i++)
441    {
442       if (shouldRunTest(group, group->tests[i]))
443       {
444         num_unreported++;
445       }
446    }
447
448    return num_unreported;
449 }
450
451 void executeTest(ComponentTester *tester,
452                  RunGroup *group, TestInfo *test, 
453                  ParameterDict param)
454 {
455     std::map<std::string, std::string> attrs;
456     TestOutputDriver::getAttributesMap(test, group, attrs);
457
458     std::vector<ParamString*> new_params;
459     int group_num = group->index;
460     int test_num = test->index;
461
462     std::map<std::string, std::string>::iterator i = attrs.begin();
463     for (; i != attrs.end(); i++)
464     {
465         ParamString *pstr = new ParamString((*i).second.c_str());
466         param[(*i).first] = pstr;
467         new_params.push_back(pstr);
468     }
469
470     {
471         testMetrics m(getOutput());
472
473         if(shouldRunTest(group, test))
474         {
475             log_teststart(group_num, test_num, test_setup_rs);
476             test->results[test_setup_rs] = tester->test_setup(test, param);
477             log_testresult(test->results[test_setup_rs]);
478         }
479         if(shouldRunTest(group, test))
480         {
481             log_teststart(group_num, test_num, test_execute_rs);
482             test->results[test_execute_rs] = test->mutator->executeTest();
483             log_testresult(test->results[test_execute_rs]);
484         }
485         if(shouldRunTest(group, test))
486         {
487             log_teststart(group_num, test_num, test_teardown_rs);
488             test->results[test_teardown_rs] = tester->test_teardown(test, param);
489             log_testresult(test->results[test_teardown_rs]);
490         }
491     }
492         
493     
494
495    for (unsigned j=0; j<new_params.size(); j++)
496       delete new_params[j];
497 }
498
499 void disableUnwantedTests(std::vector<RunGroup *> groups)
500 {
501    if (!runCreate || !runAttach || !runRewriter || !runDeserialize) {
502       for (unsigned  i = 0; i < groups.size(); i++) {
503          if (((groups[i]->useAttach == CREATE) && !runCreate) ||
504              ((groups[i]->useAttach == USEATTACH) && !runAttach) ||
505              ((groups[i]->useAttach == DISK) && !runRewriter) ||
506              ((groups[i]->useAttach == DESERIALIZE) && !runDeserialize))
507          {
508             for (unsigned j=0; j<groups[i]->tests.size(); j++)
509                groups[i]->tests[j]->disabled = true;
510             groups[i]->disabled = true;
511          }
512       }
513    }
514    if (!runAllTests)
515    {
516       for (unsigned  i = 0; i < groups.size(); i++) {
517          for (unsigned j=0; j<groups[i]->tests.size(); j++) {
518             if (!testListContains(groups[i]->tests[j], test_list)) {
519                groups[i]->tests[j]->disabled = true;
520             }
521          }
522       }
523    }
524    if (!runAllMutatees)
525    {
526       for (unsigned  i = 0; i < groups.size(); i++) {
527          if (!mutateeListContains(mutatee_list, groups[i]->mutatee))
528          {
529             for (unsigned j=0; j<groups[i]->tests.size(); j++)
530                groups[i]->tests[j]->disabled = true;
531             groups[i]->disabled = true;
532          }
533       }
534    }
535    if (!runAllComps && runAllMutatees)
536    {
537       for (unsigned  i = 0; i < groups.size(); i++) {
538          if (!groups[i]->mod || 
539              (!runDyninst && groups[i]->mod->name == std::string("dyninst")) ||
540              (!runSymtab && groups[i]->mod->name == std::string("symtab")) ||
541              (!runInstruction && groups[i]->mod->name == std::string("instruction")) ||
542              (!runProcControl && groups[i]->mod->name == std::string("proccontrol")))
543          {
544             groups[i]->disabled = true;
545          }
546       }
547    }
548    else 
549    {
550       for (unsigned  i = 0; i < groups.size(); i++) {
551          if (!groups[i]->mod)
552             groups[i]->disabled = true;
553       }
554    }
555    if (!runAllCompilers && runAllMutatees)
556    {
557       for (unsigned i=0; i<groups.size(); i++)
558       {
559          if (groups[i]->disabled)
560             continue;
561          bool compiler_enabled = false;
562          const char *compiler_name;
563          if (!groups[i]->mutatee || strlen(groups[i]->mutatee) == 0)
564             compiler_name = "nocompiler";
565          else {
566             compiler_name = groups[i]->compiler;
567          }
568          for (unsigned j=0; j<NUM_COMPILERS; j++)
569          {
570             if (strcmp(compiler_name, compilers[j].mutatee_str) == 0)
571             {
572                compiler_enabled = compilers[j].enabled;
573                break;
574             }
575          }
576          if (!compiler_enabled)
577             groups[i]->disabled = true;
578       }
579    }
580    if (optLevel != opt_all && runAllMutatees)
581    {
582       for (unsigned  i = 0; i < groups.size(); i++) {
583          if (groups[i]->disabled)
584             continue;
585          if (!groups[i]->optlevel)
586             continue;
587          if ((optLevel&opt_none) && (strcmp(groups[i]->optlevel, "none")==0))
588             continue;
589          if ((optLevel&opt_low) && (strcmp(groups[i]->optlevel, "low")==0))
590             continue;
591          if ((optLevel&opt_high) && (strcmp(groups[i]->optlevel, "high")==0))
592             continue;
593          if ((optLevel&opt_max) && (strcmp(groups[i]->optlevel, "max")==0))
594             continue;
595          groups[i]->disabled = true;
596       }      
597    }
598    if (!runMT) {
599       for (unsigned  i = 0; i < groups.size(); i++) {
600          if (groups[i]->threadmode == MultiThreaded) {
601             groups[i]->disabled = true;
602          }
603       }
604    }
605    if (!runST) {
606       for (unsigned  i = 0; i < groups.size(); i++) {
607          if (groups[i]->threadmode == SingleThreaded) {
608             groups[i]->disabled = true;
609          }
610       }
611    }
612    if (!runMP) {
613       for (unsigned  i = 0; i < groups.size(); i++) {
614          if (groups[i]->procmode == MultiProcess) {
615             groups[i]->disabled = true;
616          }
617       }
618    }
619    if (!runSP) {
620       for (unsigned  i = 0; i < groups.size(); i++) {
621          if (groups[i]->procmode == SingleProcess) {
622             groups[i]->disabled = true;
623          }
624       }
625    }
626    if( !runAllLinks && (!runDynamicLink || !runStaticLink) ) {
627        for (unsigned i = 0; i < groups.size(); i++) {
628            if( (!runStaticLink && (groups[i]->linktype == StaticLink)) ||
629                  (!runDynamicLink && (groups[i]->linktype == DynamicLink)) )
630            {
631                groups[i]->disabled = true;
632            }
633        }
634    }
635
636 #if defined(cap_32_64_test)
637    if (!runAllABIs && runAllMutatees)
638    {
639       for (unsigned  i = 0; i < groups.size(); i++) 
640       {
641          if (groups[i]->disabled)
642             continue;
643          if (runABI_32 && strcmp(groups[i]->abi, "32") == 0)
644             continue;
645          if (runABI_64 && strcmp(groups[i]->abi, "64") == 0)
646             continue;
647          groups[i]->disabled = true;            
648       }
649    }
650 #endif
651    if(!runPic || !runNonPic)
652    {
653        for (unsigned  i = 0; i < groups.size(); i++)
654        {
655            if (groups[i]->disabled)
656                continue;
657            if (groups[i]->pic == nonPIC && runNonPic)
658                continue;
659            if (groups[i]->pic == PIC && runPic)
660                continue;
661            groups[i]->disabled = true;
662        }
663    }
664    if (unique_id && max_unique_id) {
665       unsigned cur_test = 0;
666       unsigned cur_test_limitgroup = 0;
667       for (unsigned i=0; i < groups.size(); i++) 
668       {
669          if (groups[i]->disabled) continue;
670          for (unsigned j=0; j<groups[i]->tests.size(); j++) 
671          {
672             if (groups[i]->tests[j]->disabled) {
673                continue;
674             }
675             if (cur_test && cur_test % testLimit == 0) {
676                cur_test_limitgroup++;
677             }
678             cur_test++;
679
680             if (cur_test_limitgroup % max_unique_id != (unique_id-1)) {
681                groups[i]->tests[j]->disabled = true;
682             }
683          }       
684       }
685    }
686
687    parse_resumelog(groups);
688
689    if (testLimit) {
690       int test_run = 0;
691       for (unsigned  i = 0; i < groups.size(); i++) 
692       {
693          if (groups[i]->disabled)
694             continue;
695          for (unsigned j=0; j<groups[i]->tests.size(); j++) 
696          {
697             if (groups[i]->tests[j]->disabled)
698                continue;
699             if (test_run < testLimit) {
700                test_run++;
701                continue;
702             }
703
704             groups[i]->tests[j]->disabled = true;
705             if (!limitSkippedTests) {
706                limitSkippedTests = true;
707                limitResumeGroup = i;
708                limitResumeTest = j;
709             }
710          }      
711       }
712    }
713
714    for (unsigned  i = 0; i < groups.size(); i++) {
715       if (groups[i]->disabled)
716          continue;
717       groups[i]->disabled = true;
718       if (groups[i]->mod) {
719          for (unsigned j=0; j<groups[i]->tests.size(); j++) {
720             if (!groups[i]->tests[j]->disabled)
721                groups[i]->disabled = false;
722          }
723       }
724    }
725 }
726
727 void setIndexes(std::vector<RunGroup *> groups)
728 {
729    int maxlen = 0;
730    for (unsigned  i = 0; i < groups.size(); i++) {
731       groups[i]->index = i;
732       for (unsigned j=0; j<groups[i]->tests.size(); j++) {
733          groups[i]->tests[j]->index = j;
734          int namelen = strlen(groups[i]->tests[j]->name);
735                  if (namelen > maxlen)
736                          maxlen = namelen;
737       }
738    }
739    TestInfo::setMaxTestNameLength(maxlen);
740 }   
741
742 volatile int dont_optimize = 0;
743 void tests_breakpoint()
744 {
745   dont_optimize++;
746   //Breakpoint here to get a binary with test libraries loaded.
747 }
748
749 void executeGroup(ComponentTester *tester, RunGroup *group, 
750                   ParameterDict param)
751 {
752    test_results_t result;
753    // setupMutatorsForRunGroup creates TestMutator objects and
754    // sets a pointer in the TestInfo object to point to the TestMutator for
755    // each test.
756    int tests_found = setupMutatorsForRunGroup(group);
757    if (tests_found <= 0)
758       return;
759    tests_breakpoint();
760
761    int groupnum = group->index;
762
763    ParamString mutatee_prm(group->mutatee);
764    ParamInt startstate_prm((int) group->state);
765    ParamInt createmode_prm((int) group->useAttach);
766    ParamInt customexecution_prm((int) group->customExecution);
767    ParamInt selfstart_prm((int) group->selfStart);
768    ParamInt threadmode_prm((int) group->threadmode);
769    ParamInt procmode_prm((int) group->procmode);
770
771    param["pathname"] = &mutatee_prm;
772    param["startState"] = &startstate_prm;
773    param["useAttach"] = &createmode_prm;
774    param["customExecution"] = &customexecution_prm;
775    param["selfStart"] = &selfstart_prm;
776    param["threadMode"] = &threadmode_prm;
777    param["processMode"] = &procmode_prm;
778
779    for (unsigned i=0; i<group->tests.size(); i++)
780    {
781       if (shouldRunTest(group, group->tests[i]))
782          testsRun++;
783    }
784
785    log_teststart(groupnum, 0, group_setup_rs);
786    result = tester->group_setup(group, param);
787    log_testresult(result);
788    if (result != PASSED && result != SKIPPED && result != UNKNOWN) {
789       getOutput()->log(LOGERR, "Group setup failed: %s\n", 
790                        tester->getLastErrorMsg().c_str());
791    }
792    if (result != UNKNOWN) {
793       for (unsigned int i = 0; i < group->tests.size(); i++) {
794          group->tests[i]->results[group_setup_rs] = result;
795       }
796    }
797
798    for(unsigned i = 0; i < group->tests.size(); i++)
799    {
800       // Print mutator log header
801           assert(group->tests[i]);
802       printLogOptionHeader(group->tests[i]);
803
804       if (shouldRunTest(group, group->tests[i])) {
805          log_teststart(groupnum, i, test_init_rs);
806          if(group->tests[i]->mutator)
807          {
808             test_results_t setup_res = group->tests[i]->mutator->setup(param);
809             group->tests[i]->results[test_init_rs] = setup_res;
810             if (setup_res != PASSED)
811             {
812                logerror("%s[%d]:  setup failed (%d) for test %s\n", 
813                         FILE__, __LINE__, (int) setup_res, group->tests[i]->name);
814             }
815          }
816          else
817          {
818             logerror("No mutator object found for test: %s\n", group->tests[i]->name);
819             group->tests[i]->results[test_init_rs] = FAILED;
820          }
821          log_testresult(group->tests[i]->results[test_init_rs]);
822       }
823    }
824       
825    for (size_t i = 0; i < group->tests.size(); i++) {
826       executeTest(tester, group, group->tests[i], param);
827    }
828
829    log_teststart(groupnum, 0, group_teardown_rs);
830    result = tester->group_teardown(group, param);
831    log_testresult(result);
832    if (result != PASSED && result != SKIPPED && result != UNKNOWN) {
833       getOutput()->log(LOGERR, "Group teardown failed: %s\n", 
834                        tester->getLastErrorMsg().c_str());
835    }
836    if (result != UNKNOWN) {
837       for (unsigned int i = 0; i < group->tests.size(); i++) {
838          group->tests[i]->results[group_teardown_rs] = result;
839       }
840    }
841
842    for (int i = 0; i < group->tests.size(); i++) {
843       reportTestResult(group, group->tests[i]);
844    }
845 }
846
847 #define is_int(x) (x >= '0' && x <= '9')
848 bool strint_lt(const char *lv, const char *rv)
849 {
850    int i = 0;
851    while (lv[i] != '\0' && rv[i] != '\0')
852    {
853       if (lv[i] == rv[i]) {
854          i++;
855          continue;
856       }
857
858       bool lint = is_int(lv[i]);
859       bool rint = is_int(rv[i]);
860
861       if (lint && !rint)
862          return true;
863       else if (!lint && rint)
864          return false;
865       else if (!lint && !rint)
866          return (lv[i] < rv[i]);
867       else {
868          return atoi(lv+i) < atoi(rv+i);
869       }
870    }
871    if (lv[i] == '\0' && rv[i] != '\0')
872       return true;
873    return false;
874 }
875
876 struct groupcmp 
877 {
878    bool operator()(const RunGroup* lv, const RunGroup* rv)
879    {
880       if (!lv->mod)
881          return false;
882       if (!rv->mod)
883          return true;
884       if (lv->useAttach == DESERIALIZE && rv->useAttach != DESERIALIZE)
885          return false;
886       if (rv->useAttach == DESERIALIZE && lv->useAttach != DESERIALIZE)
887          return true;
888       if (lv->mod == rv->mod)
889       {
890          return strint_lt(lv->mutatee, rv->mutatee);
891       }
892       return std::string(lv->mod->name).compare(rv->mod->name) == -1;
893    }
894 };
895
896 struct testcmp 
897 {
898    bool operator()(const TestInfo* lv, const TestInfo* rv)
899    {
900       return strint_lt(lv->name, rv->name);
901    }
902 };
903
904 void initModuleIfNecessary(RunGroup *group, std::vector<RunGroup *> &groups, 
905                            ParameterDict &params)
906 {
907    bool initModule = false;
908    if (group->disabled)
909       return;
910    for (unsigned j=0; j<group->tests.size(); j++)
911    {
912       if (group->mod && !group->mod->setupRun() && !group->tests[j]->disabled)
913          initModule = true;
914    }
915    if (!initModule)
916       return;
917
918    log_teststart(group->index, 0, program_setup_rs);
919    test_results_t result = group->mod->tester->program_setup(params);
920    log_testresult(result);
921
922    group->mod->setSetupRun(true);
923
924    for (unsigned i=0; i<groups.size(); i++) {
925       if (groups[i]->disabled || groups[i]->mod != group->mod)
926          continue;
927       for (unsigned j=0; j<groups[i]->tests.size(); j++) {
928          if (groups[i]->tests[j]->disabled)
929             continue;
930          groups[i]->tests[j]->results[program_setup_rs] = result;
931          if (result != PASSED)
932             reportTestResult(groups[i], groups[i]->tests[j]);
933       }
934    }
935 }
936          
937
938 void startAllTests(std::vector<RunGroup *> &groups,
939                    std::vector<char *> mutatee_list)
940 {
941    // Begin setting up test parameters
942    ParameterDict param;
943    unsigned i;
944    bool aborted_group = false;
945
946    ParamString logfile_p(logfilename);
947    ParamInt verbose_p((int) !quietFormat);
948    ParamInt usehuman_p((int) useHumanLog);
949    ParamInt printlabels_p((int) printLabels);
950    ParamInt debugprint_p((int) debugPrint);
951    ParamInt noclean_p((int) noclean);
952    ParamInt uniqueid_p((int) unique_id);
953    ParamString humanname_p(humanlog_name);
954    std::string mutateeresume_name = std::string("mutatee_") + get_resumelog_name();
955    ParamString resumelog_p(mutateeresume_name.c_str());
956
957    param["logfilename"] = &logfile_p;
958    param["verbose"] = &verbose_p;
959    param["usehumanlog"] = &usehuman_p;
960    param["humanlogname"] = &humanname_p;
961    param["printlabels"] = &printlabels_p;
962    param["debugPrint"] = &debugprint_p;
963    param["noClean"] = &noclean_p;
964    param["mutatee_resumelog"] = &resumelog_p;
965    param["unique_id"] = &uniqueid_p;
966
967    // Print Test Log Header
968    getOutput()->log(LOGINFO, "Commencing test(s) ...\n");
969 #if !defined(os_windows_test)
970    if ( pdscrdir )
971    {
972       runScript("date");
973       runScript("uname -a");
974    }
975    getOutput()->log(LOGINFO, "TESTDIR=%s\n", getenv("PWD"));
976 #else
977         char* cwd = _getcwd(NULL, 0);
978         if(cwd) {
979            getOutput()->log(LOGINFO, "TESTDIR=%s\n", cwd);
980         } else {
981                 getOutput()->log(LOGERR, "Couldn't get working directory!\n");
982         }
983         free(cwd);
984 #endif
985    // Sets the disable flag on groups and tests that weren't selected by
986    // options or have alread been passed according to the resumelog
987    std::sort(groups.begin(), groups.end(), groupcmp());
988    for (i=0; i<groups.size(); i++)
989       std::sort(groups[i]->tests.begin(), groups[i]->tests.end(), testcmp());
990
991    setIndexes(groups);
992    disableUnwantedTests(groups);
993
994    std::vector<Module *> modules;
995    Module::getAllModules(modules);
996
997    //measureStart();
998
999    for (i = 0; i < groups.size(); i++) {
1000         if (groups[i]->disabled)
1001          continue;
1002
1003       //If we fail then have the log resume us at this group
1004       log_resumepoint(i, 0);
1005
1006       initModuleIfNecessary(groups[i], groups, param);
1007
1008       // Print mutatee (run group) header
1009       printLogMutateeHeader(groups[i]->mutatee, groups[i]->linktype);
1010
1011       int before_group = numUnreportedTests(groups[i]);
1012       if (!before_group)
1013          continue;
1014
1015       executeGroup(groups[i]->mod->tester, groups[i], param);
1016       int after_group = numUnreportedTests(groups[i]);
1017    
1018       if (after_group) {
1019          if (before_group == after_group) {
1020             //This should be uncommon.  We made no forward progress
1021             // running tests in the group, and we have tests that didn't run.
1022             // Mark the group as failed, as we don't want to just spin here.
1023             for (unsigned j=0; j<groups[i]->tests.size(); j++) {
1024                if (!shouldRunTest(groups[i], groups[i]->tests[j]))
1025                   continue;
1026                groups[i]->tests[j]->results[group_teardown_rs] = FAILED;
1027                reportTestResult(groups[i], groups[i]->tests[j]);
1028             }
1029          }
1030          else {
1031             aborted_group = true;
1032             break;
1033          }
1034       }
1035    }
1036
1037    unsigned final_group = i;
1038    
1039    for (i = 0; i < final_group; i++) {
1040        Module *mod = groups[i]->mod;
1041      if (!mod || !mod->isInitialized() || groups[i]->disabled)
1042        continue;
1043      
1044      log_teststart(groups[i]->index, 0, program_teardown_rs);
1045      test_results_t result = mod->tester->program_teardown(param);
1046      log_testresult(result);
1047
1048      for (unsigned j=0; j < groups[i]->tests.size(); j++)
1049      {
1050        if (!groups[i]->tests[j]->disabled) {
1051           groups[i]->tests[j]->results[program_teardown_rs] = result;
1052        }
1053        reportTestResult(groups[i], groups[i]->tests[j]);
1054      }
1055      mod->setInitialized(false);
1056    }
1057
1058    if (!aborted_group) {
1059      if (limitSkippedTests) {
1060        log_resumepoint(limitResumeGroup, limitResumeTest);
1061      } else {
1062        log_clear();
1063      }
1064    }
1065       
1066    //measureEnd();
1067    cleanPIDFile();
1068    return;
1069 } // startAllTests()
1070
1071 void DebugPause() {
1072    getOutput()->log(STDERR, "Waiting for attach by debugger\n");
1073 #if defined(os_windows_test)
1074    DebugBreak();
1075 #else
1076    static volatile int set_me = 0;
1077    while (!set_me)
1078      P_sleep(1);
1079 #endif
1080 }
1081
1082 // Find the paradyn scripts directory.  It can be specified in the environment
1083 // variable 'PDSCRDIR', or we pick up a default location for the UW and UMD
1084 // sites, or we generate a default based on the DYNINST_ROOT directory, or
1085 // we use a default '../../../scripts'.
1086 void setPDScriptDir(bool skip_warning)
1087 {
1088    pdscrdir = getenv("PDSCRDIR");
1089    if ( pdscrdir == NULL )
1090    {
1091 #if !defined(os_windows_test)
1092       // Environment variable not set, try default wisc/umd directories
1093       DIR *dir;
1094       dir = opendir(uw_pdscrdir);
1095       if ( dir != NULL ) {
1096          closedir(dir);
1097          pdscrdir = uw_pdscrdir;
1098          return;
1099       }
1100       dir = opendir(umd_pdscrdir);
1101       if ( dir != NULL ) {
1102          closedir(dir);
1103          pdscrdir = umd_pdscrdir;
1104          return;
1105       }
1106
1107       // Environment variable not set and default UW/UMD directories missing.
1108       // Derive default from DYNINST_ROOT
1109       char *basedir = getenv("DYNINST_ROOT");
1110       if (NULL == basedir) {
1111          // DYNINST_ROOT not set.  Print a warning, and default it to "../../.."
1112          if (!skip_warning) {
1113             getOutput()->log(STDERR, "** WARNING: DYNINST_ROOT not set.  Please set the environment variable\n");
1114             getOutput()->log(STDERR, "\tto the path for the top of the Dyninst library installation.\n");
1115             getOutput()->log(STDERR, "\tUsing default: '../../..'\n");
1116          }
1117          basedir = "../../..";
1118       }
1119       int basedir_len = strlen(basedir);
1120       int pdscrdir_len = basedir_len + strlen("/scripts") + 1;
1121       // BUG This allocated array lasts for the lifetime of the program, so it's
1122       // currently not worth worrying about freeing the memory.
1123       pdscrdir = new char[pdscrdir_len];
1124       strncpy(pdscrdir, basedir, basedir_len + 1);
1125       strcat(pdscrdir, "/scripts");
1126
1127       dir = opendir(pdscrdir);
1128       if (!dir) {
1129          pdscrdir = NULL;
1130       } else {
1131          closedir(dir);
1132       }
1133
1134 #endif
1135    }
1136 }
1137    
1138 void updateSearchPaths(const char *filename) {
1139 #if !defined(os_windows_test)
1140    // First, find the directory we reside in
1141
1142     bool include_cwd_always = false;
1143 #if defined(os_aix_test)
1144     // AIX strips a ./ from the start of argv[0], so
1145     // we will execute ./test_driver and see test_driver
1146
1147     include_cwd_always = true;
1148 #endif
1149
1150    char *execpath;
1151    char pathname[PATH_MAX];
1152    getcwd(pathname, PATH_MAX);
1153
1154    if (filename[0] == '/') {
1155       // If it begins with a slash, it's an absolute path
1156       execpath = strdup(filename);
1157    } else if (strchr(filename,'/') || include_cwd_always) {
1158       // If it contains slashes, it's a relative path
1159       char *filename_copy = strdup(filename);
1160       
1161       execpath = (char *) ::malloc(strlen(pathname) + strlen(filename_copy) + 2);
1162       strcpy(execpath,pathname);
1163       strcat(execpath,"/");
1164       strcat(execpath,filename_copy);
1165       ::free(filename_copy);
1166    } else {
1167       // If it's just a name, it was found in PATH. 
1168       // Add current directory to the search path
1169       const char *pathenv = getenv("PATH");
1170       char *newpath = (char *) malloc (strlen(pathenv)+3);
1171       strcat(newpath, pathenv);
1172       strcat(newpath, ":.");
1173       execpath = searchPath(newpath, filename);
1174       if(execpath == NULL) {
1175          //  Not found in PATH - we'll assume it should be in CWD
1176          return;
1177       }
1178    }
1179
1180    *strrchr(execpath, '/') = '\0';
1181    // Now update PATH and LD_LIBRARY_PATH/LIBPATH
1182
1183    char *envCopy;
1184
1185    char *envPath = getenv("PATH");
1186    envCopy = (char *) ::malloc(((envPath && strlen(envPath)) ? strlen(envPath) + 1 : 0) + strlen(execpath) + 6);
1187    strcpy(envCopy, "PATH=");
1188    if (envPath && strlen(envPath)) {
1189       strcat(envCopy, envPath);
1190       strcat(envCopy, ":");
1191    }
1192    strcat(envCopy, execpath);
1193    assert(!putenv(envCopy));
1194     
1195    char *envLibPath;
1196 #if defined(os_aix_test)
1197    envLibPath = getenv("LIBPATH");
1198 #else
1199    envLibPath = getenv("LD_LIBRARY_PATH");
1200 #endif
1201     
1202    envCopy = (char *) ::malloc(((envLibPath && strlen(envLibPath)) ? strlen(envLibPath) + 1 : 0) + strlen(execpath) + 17);
1203 #if defined(os_aix_test)
1204    strcpy(envCopy, "LIBPATH=");
1205 #else
1206    strcpy(envCopy, "LD_LIBRARY_PATH=");
1207 #endif
1208    if (envLibPath && strlen(envLibPath)) {
1209       strcat(envCopy, envLibPath);
1210       strcat(envCopy, ":");
1211    }
1212    strcat(envCopy, execpath);
1213    assert(!putenv(envCopy));
1214
1215    //fprintf(stderr, "%s[%d]:  set LD_LIBRARY_PATH to %s\n", FILE__, __LINE__, getenv("LD_LIBRARY_PATH"));
1216    ::free(execpath);
1217 #endif
1218 }
1219
1220 bool testsRemain(std::vector<RunGroup *> &groups)
1221 {
1222    for (unsigned  i = 0; i < groups.size(); i++) {
1223       if (groups[i]->disabled)
1224          continue;
1225       for (unsigned j=0; j<groups[i]->tests.size(); j++) {
1226          if (shouldRunTest(groups[i], groups[i]->tests[j]))
1227             return true;
1228       }
1229    }
1230    return false;
1231 }
1232
1233 int main(int argc, char *argv[]) {
1234    updateSearchPaths(argv[0]);
1235
1236    setOutput(new StdOutputDriver(NULL));
1237    
1238    int result = parseArgs(argc, argv);
1239    if (result)
1240       exit(result);
1241
1242    if (unique_id) {
1243       char id_string[32];
1244       snprintf(id_string, 32, "%d", unique_id);
1245       std::string newname = std::string(get_resumelog_name()) + std::string(".") + std::string(id_string);
1246       set_resumelog_name(strdup(newname.c_str()));
1247    }
1248
1249    // Fill in tests vector with lists of test to run
1250    std::vector<RunGroup *> tests;
1251    initialize_mutatees(tests);  
1252
1253    result = setupLogs();
1254    if (result)
1255       exit(result);
1256
1257    setupProcessGroup();
1258
1259    // Set the resume log name
1260    if ( getenv("RESUMELOG") ) {
1261       set_resumelog_name(getenv("RESUMELOG"));
1262    }
1263
1264    if ( shouldDebugBreak ) {
1265       DebugPause();
1266    }
1267
1268     startAllTests(tests, mutatee_list);
1269
1270    if ((outlog != NULL) && (outlog != stdout)) {
1271       fclose(outlog);
1272    }
1273    fflush(stdout);
1274
1275    if (!testsRemain(tests) && !limitSkippedTests)
1276       return NOTESTS;
1277    return 0;
1278 }
1279
1280 int setupLogs()
1281 {
1282    // Set the script dir if we require scripts
1283    if ( enableLogging )
1284    {
1285      setPDScriptDir(true);
1286    }
1287
1288    // Set up the logging file..
1289    if ((logfilename != NULL) && (strcmp(logfilename, "-") != 0)) {
1290       outlog = fopen(logfilename, "a");
1291       if (NULL == outlog) {
1292          getOutput()->log(STDERR, "Error opening log file '%s'\n", logfilename);
1293          return NOTESTS;
1294       }
1295       errlog = outlog;
1296    } else {
1297       outlog = stdout;
1298       errlog = stderr;
1299    }
1300    setOutputLog(outlog);
1301    setErrorLog(errlog);
1302    setOutputLogFilename(logfilename);
1303    setErrorLogFilename(logfilename);
1304
1305    if ((logfilename != NULL) && (strcmp(logfilename, "-") != 0)) {
1306       getOutput()->redirectStream(LOGINFO, logfilename);
1307       getOutput()->redirectStream(LOGERR, logfilename);
1308    }
1309    if (useHumanLog) {
1310       getOutput()->redirectStream(HUMAN, humanlog_name);
1311    } else {
1312       getOutput()->redirectStream(HUMAN, NULL);
1313    }
1314    return 0;
1315 }
1316
1317 int parseArgs(int argc, char *argv[])
1318 {
1319    for (unsigned i=1; i < argc; i++ )
1320    {
1321       if (strncmp(argv[i], "-v+", 3) == 0)
1322          errorPrint++;
1323       if (strncmp(argv[i], "-v++", 4) == 0)
1324          errorPrint++;
1325       if (strncmp(argv[i], "-verbose", 2) == 0)
1326          debugPrint = 1;
1327       else if (strcmp(argv[i], "-q") == 0)
1328       {
1329          getOutput()->log(STDERR, "[%s:%u] - Quiet format not yet enabled\n");
1330          quietFormat = true;
1331       }
1332       else if ( strcmp(argv[i], "-skipTo")==0)
1333       {
1334          // skip to test i+1
1335          skipToTest = atoi(argv[++i]);
1336       }
1337       else if ( strcmp(argv[i], "-log")==0)
1338       {
1339          logfilename = "-";
1340          if ((i + 1) < argc) {
1341             if ((argv[i + 1][0] != '-') || (argv[i + 1][1] == '\0')) {
1342                i += 1;
1343                logfilename = argv[i];
1344             }
1345          }
1346       }
1347       else if ( strcmp(argv[i], "-logfile") == 0) {
1348          getOutput()->log(STDERR, "WARNING: -logfile is a deprecated option; use -log instead\n");
1349          /* Store the log file name */
1350          if ((i + 1) >= argc) {
1351             getOutput()->log(STDERR, "Missing log file name\n");
1352             return NOTESTS;
1353          }
1354          i += 1;
1355          logfilename = argv[i];
1356       }
1357       else if ( strcmp(argv[i], "-debug")==0)
1358       {
1359          shouldDebugBreak = true;
1360       }
1361       else if ( strcmp(argv[i], "-test") == 0)
1362       {
1363          char *tests;
1364          char *name;
1365
1366          runAllTests = false;
1367          if ( i + 1 >= argc )
1368          {
1369             getOutput()->log(STDERR, "-test must be followed by a testname\n");
1370             return NOTESTS;
1371          }
1372
1373          tests = strdup(argv[++i]);
1374
1375          name = strtok(tests, ","); // FIXME Use strtok_r()
1376          test_list.push_back(name);
1377          while ( name != NULL )
1378          {
1379             name = strtok(NULL, ",");
1380             if ( name != NULL )
1381             {
1382                test_list.push_back(name);
1383             }
1384          }
1385       }
1386       else if ( strcmp(argv[i], "-mutatee") == 0)
1387       {
1388          char *mutatees;
1389          char *name;
1390
1391          runAllMutatees = false;
1392          if ( i + 1 >= argc )
1393          {
1394             getOutput()->log(STDERR, "-mutatee must be followed by mutatee names\n");
1395             return NOTESTS;
1396          }
1397
1398          mutatees = strdup(argv[++i]);
1399
1400          name = strtok(mutatees, ","); // FIXME Use strtok_r()
1401          if (NULL == name) {
1402             // Special handling for a "" mutatee specified on the command line
1403             mutatee_list.push_back("");
1404          } else {
1405             mutatee_list.push_back(name);
1406          }
1407          while ( name != NULL )
1408          {
1409             name = strtok(NULL, ","); // FIXME Use strtok_r()
1410             if ( name != NULL )
1411             {
1412                mutatee_list.push_back(name);
1413             }
1414          }
1415       }
1416       // TODO: Remove the -run option, it is replaced by the -test option
1417       else if ( strcmp(argv[i], "-run") == 0)
1418       {
1419          unsigned int j;
1420          runAllTests = false;
1421          for ( j = i+1; j < argc; j++ )
1422          {
1423             if ( argv[j][0] == '-' )
1424             {
1425                // end of test list
1426                break;
1427             }
1428             else
1429             {
1430                test_list.push_back(argv[j]);
1431             }
1432          }
1433          i = j - 1;
1434       }
1435       // TODO -attach and -create are DyninstAPI specific
1436       else if ( strcmp(argv[i], "-attach") == 0 )
1437       {
1438          if (runDefaultStarts)
1439          {
1440             runCreate = false;
1441             runRewriter = false;
1442          }
1443          runAttach = true;
1444          runDefaultStarts = false;
1445       }
1446       else if ( strcmp(argv[i], "-create") == 0 )
1447       {
1448          if (runDefaultStarts)
1449          {
1450             runAttach = false;
1451             runRewriter = false;
1452          }
1453          runCreate = true;
1454          runDefaultStarts = false;
1455       }
1456       else if ( strcmp(argv[i], "-rewriter") == 0 )
1457       {
1458          if (runDefaultStarts)
1459          {
1460             runCreate = false;
1461             runAttach = false;
1462          }
1463          runRewriter = true;
1464          runDefaultStarts = false;
1465       }
1466       else if ( strcmp(argv[i], "-noclean") == 0 )
1467       {
1468          noclean = true;
1469       }
1470       else if ( strcmp(argv[i], "-serialize") == 0 )
1471       {
1472          runDefaultStarts = false;
1473          runCreate = true;
1474          runAttach = false;
1475          runDeserialize = true;
1476       }
1477       else if (strcmp(argv[i], "-allmode") == 0)
1478       {
1479          runCreate = true;
1480          runAttach = true;
1481          runDeserialize = true;
1482          runRewriter = false;
1483          runDefaultStarts = false;
1484       }
1485       else if (strcmp(argv[i], "-all") == 0)
1486       {
1487          runCreate = true;
1488          runAttach = true;
1489          runDeserialize = true;
1490          runRewriter = true;
1491          runAllLinks = true;
1492          runAllCompilers = true;
1493          runAllComps = true;
1494          runPic = true;
1495          runNonPic = true;
1496       }
1497       else if (strcmp(argv[i], "-full") == 0)
1498       {
1499          //Like -all, but with full optimization levels
1500          runCreate = true;
1501          runAttach = true;
1502          runDeserialize = true;
1503          runRewriter = true;
1504          runAllLinks = true;
1505          runAllCompilers = true;
1506          runAllComps = true;
1507          runPic = true;
1508          runNonPic = true;
1509          optLevel = opt_all;
1510       }
1511       else if ( strcmp(argv[i], "-dyninst") == 0)
1512       {
1513          runDyninst = true;
1514          runAllComps = false;
1515       }
1516       else if ( strcmp(argv[i], "-symtab") == 0)
1517       {
1518          runSymtab = true;
1519          runAllComps = false;
1520       }
1521       else if (strcmp(argv[i], "-instruction") == 0)
1522       {
1523          runInstruction = true;
1524          runAllComps = false;
1525       }
1526       else if (strcmp(argv[i], "-proccontrol") == 0)
1527       {
1528          runProcControl = true;
1529          runAllComps = false;
1530       }
1531       else if (strcmp(argv[i], "-allcomp") == 0)
1532       {
1533          runSymtab = true;
1534          runDyninst = true;
1535          runInstruction = true;
1536          runAllComps = true;
1537       }
1538       else if (strcmp(argv[i], "-max") == 0)
1539       {
1540          if (runDefaultOpts)
1541             optLevel = 0;
1542          runDefaultOpts = false;
1543          optLevel |= opt_max;
1544       }
1545       else if (strcmp(argv[i], "-high") == 0)
1546       {
1547          if (runDefaultOpts)
1548             optLevel = 0;
1549          runDefaultOpts = false;
1550          optLevel |= opt_high;
1551       }
1552       else if (strcmp(argv[i], "-low") == 0)
1553       {
1554          if (runDefaultOpts)
1555             optLevel = 0;
1556          runDefaultOpts = false;
1557          optLevel |= opt_low;
1558       }
1559       else if (strcmp(argv[i], "-none") == 0)
1560       {
1561          if (runDefaultOpts)
1562             optLevel = 0;
1563          runDefaultOpts = false;
1564          optLevel |= opt_none;
1565       }
1566       else if (strcmp(argv[i], "-allopt") == 0)
1567       {
1568          runDefaultOpts = false;
1569          optLevel |= opt_all;
1570       }
1571       else if (strcmp(argv[i], "-32") == 0)
1572       {
1573          runAllABIs = false;
1574          runABI_32 = true;
1575       }
1576       else if (strcmp(argv[i], "-64") == 0)
1577       {
1578          runAllABIs = false;
1579          runABI_64 = true;
1580       }
1581       else if (strcmp(argv[i], "-pic") == 0)
1582       {
1583           runPic = true;
1584           runNonPic = false;
1585       }
1586       else if ((strcmp(argv[i], "-cpumem") == 0) ||
1587                (strcmp(argv[i], "-memcpu") == 0))
1588       {
1589          measureMEMCPU = true;
1590          if (i+1 < argc)
1591          {
1592             if (argv[i+1][0] != '-')
1593             {
1594                i++;
1595                measureFileName = argv[i];
1596             }
1597             else if (argv[i+1][1] == '\0')
1598             {
1599                i++;
1600                measureFileName = "-";
1601             }
1602          }
1603       }
1604       else if ((strcmp(argv[i], "-enable-resume") == 0) ||
1605                (strcmp(argv[i], "-use-resume") == 0)) {
1606          enableResumeLog();
1607       } else if ( strcmp(argv[i], "-header") == 0 ) {
1608          printMutateeLogHeader = true;
1609       } else if ( strcmp(argv[i], "-limit") == 0 ) {
1610          if ( i + 1 >= argc ) {
1611             getOutput()->log(STDERR, "-limit must be followed by an integer limit\n");
1612             return NOTESTS;
1613          }
1614          testLimit = strtol(argv[++i], NULL, 10);
1615          if ((0 == testLimit) && (EINVAL == errno)) {
1616             getOutput()->log(STDERR, "-limit must be followed by an integer limit\n");
1617             return NOTESTS;
1618          }
1619       }
1620       else if (strcmp(argv[i], "-resumelog-name") == 0)
1621       {
1622          if (i + 1 >= argc) {
1623             getOutput()->log(STDERR, "-resumelog-name must be followed by a filename\n");
1624             return NOTESTS;
1625          }
1626          set_resumelog_name(argv[++i]);
1627       }
1628       else if (strcmp(argv[i], "-unique") == 0) {
1629          if (i + 1 < argc) {
1630             unique_id = atoi(argv[++i]);
1631          }
1632          if (!unique_id) {
1633             getOutput()->log(STDERR, "-unique must be followed by a non-zero integer\n");
1634             return NOTESTS;
1635          }
1636       }
1637       else if (strcmp(argv[i], "-max-unique") == 0) {
1638          if (i + 1 < argc) {
1639             max_unique_id = atoi(argv[++i]);
1640          }
1641          if (!max_unique_id) {
1642             getOutput()->log(STDERR, "-max_unique must be followed by a non-zero integer\n");
1643             return NOTESTS;
1644          }
1645       }
1646       else if ( strcmp(argv[i], "-humanlog") == 0 ) {
1647          // Verify that the following argument exists
1648          if ( i + 1 >= argc )
1649          {
1650             getOutput()->log(STDERR, "-humanlog must by followed by a filename\n");
1651             return NOTESTS;
1652          }
1653
1654          useHumanLog = true;
1655          humanlog_name = argv[++i];
1656       } else if (strcmp(argv[i], "-under-runtests") == 0) {
1657          called_from_runTests = true;
1658       }
1659       else if ((strcmp(argv[i], "-help") == 0) ||
1660                (strcmp(argv[i], "--help") == 0)) {
1661          print_help();
1662          exit(-5);
1663       }
1664       else if (strcmp(argv[i], "-pidfile") == 0) {
1665          char *pidFilename = NULL;
1666          if (i + 1 >= argc) {
1667             getOutput()->log(STDERR, "-pidfile must be followed by a filename\n");
1668             return NOTESTS;
1669          }
1670          i += 1;
1671          pidFilename = argv[i];
1672          setPIDFilename(pidFilename);
1673       }
1674       else if (strcmp(argv[i], "-dboutput") == 0) {
1675          char * failedOutputFile = NULL;
1676          //check if a failed output file is specified
1677          if ((i + 1) < argc) {
1678             if (argv[i+1][0] != '-' || argv[i+1][1] == '\0') {
1679                //either it doesn't start with - or it's exactly -
1680                i++;
1681                failedOutputFile = argv[i];
1682             }
1683          }
1684
1685          if (NULL == failedOutputFile) {
1686             //TODO insert proper value
1687             time_t rawtime;
1688             struct tm * timeinfo = (tm *)malloc(sizeof(struct tm));
1689
1690             time(&rawtime);
1691             timeinfo = localtime(&rawtime);
1692
1693             failedOutputFile = (char*)malloc(sizeof(char) * strlen("sql_dblog-xxxx-xx-xx0"));
1694             if (failedOutputFile == NULL) {
1695                fprintf(stderr, "[%s:%u] - Out of memory!\n", __FILE__, __LINE__);
1696                // TODO Handle error;
1697             }
1698             sprintf(failedOutputFile, "sql_dblog-%4d-%02d-%02d",
1699                     timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday);
1700
1701             getOutput()->log(STDERR, "No 'SQL log file' found, using default %s\n", failedOutputFile);
1702          }
1703
1704          std::string s_failedOutputFile (failedOutputFile);
1705          TestOutputDriver *newoutput = loadOutputDriver("DatabaseOutputDriver", &s_failedOutputFile);
1706
1707          //make sure it loaded correctly before replacing default output
1708          if (newoutput != NULL) {
1709             setOutput(newoutput);
1710          }
1711       }
1712       else if (strcmp(argv[i], "-allcompilers") == 0)
1713       {
1714          runDefaultCompilers = false;
1715          runAllCompilers = true;
1716       }
1717       else if (strcmp(argv[i], "-mt") == 0)
1718       {
1719          runMT = true;
1720          if (!setT)
1721             runST = false;
1722          setT = true;
1723       }
1724       else if (strcmp(argv[i], "-st") == 0)
1725       {
1726          runST = true;
1727          if (!setT)
1728             runMT = false;
1729          setT = true;
1730       }
1731       else if (strcmp(argv[i], "-mp") == 0)
1732       {
1733          runMP = true;
1734          if (!setP)
1735             runSP = false;
1736          setP = true;
1737       }
1738       else if (strcmp(argv[i], "-sp") == 0)
1739       {
1740          runSP = true;
1741          if (!setP)
1742             runMP = false;
1743          setP = true;
1744       }
1745       else if( strcmp(argv[i], "-dynamiclink") == 0) {
1746           runDynamicLink = true;
1747           runAllLinks = false;
1748       }
1749       else if( strcmp(argv[i], "-staticlink") == 0) {
1750           runStaticLink = true;
1751           runAllLinks = false;
1752       }
1753       else
1754       {
1755          bool found_compiler_option = false;
1756          for (unsigned j=0; j<NUM_COMPILERS; j++)
1757          {
1758             if (runDefaultCompilers)
1759             {
1760                //The first time we see a compiler option, disable the
1761                // ones that are default on.
1762                compilers[j].enabled = false;
1763             }
1764             if (strcmp(argv[i], compilers[j].option) == 0)
1765             {
1766                compilers[j].enabled = true;
1767                found_compiler_option = true;
1768             }
1769          }
1770          runDefaultCompilers = false;
1771
1772          if (!found_compiler_option) {
1773             getOutput()->log(STDOUT, "Unrecognized option: '%s'\n", argv[i]);
1774             return NOTESTS;
1775          }
1776       }
1777    }
1778    return 0;
1779 }
1780