the verifier shouldn't modify the IR.
[oota-llvm.git] / utils / NewNightlyTest.pl
1 #!/usr/bin/perl
2 use POSIX qw(strftime);
3 use File::Copy;
4 use File::Find;
5 use Socket;
6
7 #
8 # Program:  NewNightlyTest.pl
9 #
10 # Synopsis: Perform a series of tests which are designed to be run nightly.
11 #           This is used to keep track of the status of the LLVM tree, tracking
12 #           regressions and performance changes. Submits this information
13 #           to llvm.org where it is placed into the nightlytestresults database.
14 #
15 # Syntax:   NightlyTest.pl [OPTIONS] [CVSROOT BUILDDIR WEBDIR]
16 #   where
17 # OPTIONS may include one or more of the following:
18 #
19 # MAIN OPTIONS:
20 #  -config LLVMPATH If specified, use an existing LLVM build and only run and
21 #                   report the test information. The LLVMCONFIG argument should
22 #                   be the path to the llvm-config executable in the LLVM build.
23 #                   This should be the first argument if given. NOT YET
24 #                   IMPLEMENTED.
25 #  -nickname NAME   The NAME argument specifieds the nickname this script
26 #                   will submit to the nightlytest results repository.
27 #  -submit-server   Specifies a server to submit the test results too. If this
28 #                   option is not specified it defaults to
29 #                   llvm.org. This is basically just the address of the
30 #                   webserver
31 #  -submit-script   Specifies which script to call on the submit server. If
32 #                   this option is not specified it defaults to
33 #                   /nightlytest/NightlyTestAccept.php. This is basically
34 #                   everything after the www.yourserver.org.
35 #  -submit-aux      If specified, an auxiliary script to run in addition to the
36 #                   normal submit script. The script will be passed the path to
37 #                   the "sentdata.txt" file as its sole argument.
38 #  -nosubmit        Do not report the test results back to a submit server.
39 #
40 #
41 # BUILD OPTIONS (not used with -config):
42 #  -nocheckout      Do not create, checkout, update, or configure
43 #                   the source tree.
44 #  -noremove        Do not remove the BUILDDIR after it has been built.
45 #  -noremoveresults Do not remove the WEBDIR after it has been built.
46 #  -nobuild         Do not build llvm. If tests are enabled perform them
47 #                   on the llvm build specified in the build directory
48 #  -release         Build an LLVM Release version
49 #  -release-asserts Build an LLVM ReleaseAsserts version
50 #  -disable-bindings     Disable building LLVM bindings.
51 #  -with-clang      Checkout Clang source into tools/clang.
52 #  -compileflags    Next argument specifies extra options passed to make when
53 #                   building LLVM.
54 #  -use-gmake       Use gmake instead of the default make command to build
55 #                   llvm and run tests.
56 #
57 # TESTING OPTIONS:
58 #  -notest          Do not even attempt to run the test programs.
59 #  -nodejagnu       Do not run feature or regression tests
60 #  -enable-llcbeta  Enable testing of beta features in llc.
61 #  -enable-lli      Enable testing of lli (interpreter) features, default is off
62 #  -disable-pic     Disable building with Position Independent Code.
63 #  -disable-llc     Disable LLC tests in the nightly tester.
64 #  -disable-jit     Disable JIT tests in the nightly tester.
65 #  -disable-cbe     Disable C backend tests in the nightly tester.
66 #  -disable-lto     Disable link time optimization.
67 #  -test-cflags     Next argument specifies that C compilation options that
68 #                   override the default when running the testsuite.
69 #  -test-cxxflags   Next argument specifies that C++ compilation options that
70 #                   override the default when running the testsuite.
71 #  -extraflags      Next argument specifies extra options that are passed to
72 #                   compile the tests.
73 #  -noexternals     Do not run the external tests (for cases where povray
74 #                   or SPEC are not installed)
75 #  -with-externals  Specify a directory where the external tests are located.
76 #
77 # OTHER OPTIONS:
78 #  -parallel        Run parallel jobs with GNU Make (see -parallel-jobs).
79 #  -parallel-jobs   The number of parallel Make jobs to use (default is two).
80 #  -parallel-test   Allow parallel execution of llvm-test
81 #  -verbose         Turn on some debug output
82 #  -nice            Checkout/Configure/Build with "nice" to reduce impact
83 #                   on busy servers.
84 #  -f2c             Next argument specifies path to F2C utility
85 #  -gccpath         Path to gcc/g++ used to build LLVM
86 #  -target          Specify the target triplet
87 #  -cflags          Next argument specifies that C compilation options that
88 #                   override the default.
89 #  -cxxflags        Next argument specifies that C++ compilation options that
90 #                   override the default.
91 #  -ldflags         Next argument specifies that linker options that override
92 #                   the default.
93 #
94 # CVSROOT is ignored, it is passed for backwards compatibility.
95 # BUILDDIR is the directory where sources for this test run will be checked out
96 #  AND objects for this test run will be built. This directory MUST NOT
97 #  exist before the script is run; it will be created by the svn checkout
98 #  process and erased (unless -noremove is specified; see above.)
99 # WEBDIR is the directory into which the test results web page will be written,
100 #  AND in which the "index.html" is assumed to be a symlink to the most recent
101 #  copy of the results. This directory will be created if it does not exist.
102 # LLVMGCCDIR is the directory in which the LLVM GCC Front End is installed
103 #  to. This is the same as you would have for a normal LLVM build.
104 #
105 ##############################################################
106 #
107 # Getting environment variables
108 #
109 ##############################################################
110 my $HOME       = $ENV{'HOME'};
111 my $SVNURL     = $ENV{"SVNURL"};
112 $SVNURL        = 'http://llvm.org/svn/llvm-project' unless $SVNURL;
113 my $TestSVNURL = $ENV{"TestSVNURL"};
114 $TestSVNURL    = 'http://llvm.org/svn/llvm-project' unless $TestSVNURL;
115 my $BuildDir   = $ENV{'BUILDDIR'};
116 my $WebDir     = $ENV{'WEBDIR'};
117
118 my $LLVMSrcDir   = $ENV{'LLVMSRCDIR'};
119 $LLVMSrcDir    = "$BuildDir/llvm" unless $LLVMSrcDir;
120 my $LLVMObjDir   = $ENV{'LLVMOBJDIR'};
121 $LLVMObjDir    = "$BuildDir/llvm" unless $LLVMObjDir;
122 my $LLVMTestDir   = $ENV{'LLVMTESTDIR'};
123 $LLVMTestDir    = "$BuildDir/llvm/projects/llvm-test" unless $LLVMTestDir;
124
125 ##############################################################
126 #
127 # Calculate the date prefix...
128 #
129 ##############################################################
130 @TIME = localtime;
131 my $DATE = sprintf "%4d-%02d-%02d_%02d-%02d", $TIME[5]+1900, $TIME[4]+1, $TIME[3], $TIME[1], $TIME[0];
132
133 ##############################################################
134 #
135 # Parse arguments...
136 #
137 ##############################################################
138 $CONFIG_PATH="";
139 $CONFIGUREARGS="";
140 $nickname="";
141 $NOTEST=0;
142 $MAKECMD="make";
143 $SUBMITSERVER = "llvm.org";
144 $SUBMITSCRIPT = "/nightlytest/NightlyTestAccept.php";
145 $SUBMITAUX="";
146 $SUBMIT = 1;
147 $PARALLELJOBS = "2";
148 my $TESTFLAGS="";
149
150 while (scalar(@ARGV) and ($_ = $ARGV[0], /^[-+]/)) {
151   shift;
152   last if /^--$/;  # Stop processing arguments on --
153
154   # List command line options here...
155   if (/^-config$/)         { $CONFIG_PATH = "$ARGV[0]"; shift; next; }
156   if (/^-nocheckout$/)     { $NOCHECKOUT = 1; next; }
157   if (/^-noremove$/)       { $NOREMOVE = 1; next; }
158   if (/^-noremoveatend$/)  { $NOREMOVEATEND = 1; next; }
159   if (/^-noremoveresults$/){ $NOREMOVERESULTS = 1; next; }
160   if (/^-notest$/)         { $NOTEST = 1; next; }
161   if (/^-norunningtests$/) { next; } # Backward compatibility, ignored.
162   if (/^-parallel-jobs$/)  { $PARALLELJOBS = "$ARGV[0]"; shift; next;}
163   if (/^-parallel$/)       { $MAKEOPTS = "$MAKEOPTS -j$PARALLELJOBS"; next; }
164   if (/^-parallel-test$/)  { $PROGTESTOPTS .= " ENABLE_PARALLEL_REPORT=1"; next; }
165   if (/^-with-clang$/)     { $WITHCLANG = 1; next; }
166   if (/^-release$/)        { $MAKEOPTS = "$MAKEOPTS ENABLE_OPTIMIZED=1 ".
167                              "OPTIMIZE_OPTION=-O2"; next;}
168   if (/^-release-asserts$/){ $MAKEOPTS = "$MAKEOPTS ENABLE_OPTIMIZED=1 ".
169                              "DISABLE_ASSERTIONS=1 ".
170                              "OPTIMIZE_OPTION=-O2"; next;}
171   if (/^-enable-llcbeta$/) { $PROGTESTOPTS .= " ENABLE_LLCBETA=1"; next; }
172   if (/^-disable-pic$/)    { $CONFIGUREARGS .= " --enable-pic=no"; next; }
173   if (/^-enable-lli$/)     { $PROGTESTOPTS .= " ENABLE_LLI=1";
174                              $CONFIGUREARGS .= " --enable-lli"; next; }
175   if (/^-disable-llc$/)    { $PROGTESTOPTS .= " DISABLE_LLC=1";
176                              $CONFIGUREARGS .= " --disable-llc_diffs"; next; }
177   if (/^-disable-jit$/)    { $PROGTESTOPTS .= " DISABLE_JIT=1";
178                              $CONFIGUREARGS .= " --disable-jit"; next; }
179   if (/^-disable-bindings$/)    { $CONFIGUREARGS .= " --disable-bindings"; next; }
180   if (/^-disable-cbe$/)    { $PROGTESTOPTS .= " DISABLE_CBE=1"; next; }
181   if (/^-disable-lto$/)    { $PROGTESTOPTS .= " DISABLE_LTO=1"; next; }
182   if (/^-test-opts$/)      { $PROGTESTOPTS .= " $ARGV[0]"; shift; next; }
183   if (/^-verbose$/)        { $VERBOSE = 1; next; }
184   if (/^-teelogs$/)        { $TEELOGS = 1; next; }
185   if (/^-nice$/)           { $NICE = "nice "; next; }
186   if (/^-f2c$/)            { $CONFIGUREARGS .= " --with-f2c=$ARGV[0]";
187                              shift; next; }
188   if (/^-with-externals$/) { $CONFIGUREARGS .= " --with-externals=$ARGV[0]";
189                              shift; next; }
190   if (/^-configure-args$/) { $CONFIGUREARGS .= " $ARGV[0]";
191                              shift; next; }
192   if (/^-submit-server/)   { $SUBMITSERVER = "$ARGV[0]"; shift; next; }
193   if (/^-submit-script/)   { $SUBMITSCRIPT = "$ARGV[0]"; shift; next; }
194   if (/^-submit-aux/)      { $SUBMITAUX = "$ARGV[0]"; shift; next; }
195   if (/^-nosubmit$/)       { $SUBMIT = 0; next; }
196   if (/^-nickname$/)       { $nickname = "$ARGV[0]"; shift; next; }
197   if (/^-gccpath/)         { $CONFIGUREARGS .=
198                              " CC=$ARGV[0]/gcc CXX=$ARGV[0]/g++";
199                              $GCCPATH=$ARGV[0]; shift;  next; }
200   else                     { $GCCPATH=""; }
201   if (/^-target/)          { $CONFIGUREARGS .= " --target=$ARGV[0]";
202                              shift; next; }
203   if (/^-cflags/)          { $MAKEOPTS = "$MAKEOPTS C.Flags=\'$ARGV[0]\'";
204                              shift; next; }
205   if (/^-cxxflags/)        { $MAKEOPTS = "$MAKEOPTS CXX.Flags=\'$ARGV[0]\'";
206                              shift; next; }
207   if (/^-ldflags/)         { $MAKEOPTS = "$MAKEOPTS LD.Flags=\'$ARGV[0]\'";
208                              shift; next; }
209   if (/^-test-cflags/)     { $TESTFLAGS = "$TESTFLAGS CFLAGS=\'$ARGV[0]\'";
210                              shift; next; }
211   if (/^-test-cxxflags/)   { $TESTFLAGS = "$TESTFLAGS CXXFLAGS=\'$ARGV[0]\'";
212                              shift; next; }
213   if (/^-compileflags/)    { $MAKEOPTS = "$MAKEOPTS $ARGV[0]"; shift; next; }
214   if (/^-use-gmake/)       { $MAKECMD = "gmake"; shift; next; }
215   if (/^-extraflags/)      { $CONFIGUREARGS .=
216                              " --with-extra-options=\'$ARGV[0]\'"; shift; next;}
217   if (/^-noexternals$/)    { $NOEXTERNALS = 1; next; }
218   if (/^-nodejagnu$/)      { $NODEJAGNU = 1; next; }
219   if (/^-nobuild$/)        { $NOBUILD = 1; next; }
220   print "Unknown option: $_ : ignoring!\n";
221 }
222
223 if ($ENV{'LLVMGCCDIR'}) {
224   $CONFIGUREARGS .= " --with-llvmgccdir=" . $ENV{'LLVMGCCDIR'};
225   $LLVMGCCPATH = $ENV{'LLVMGCCDIR'} . '/bin';
226 }
227 else {
228   $LLVMGCCPATH = "";
229 }
230
231 if ($CONFIGUREARGS !~ /--disable-jit/) {
232   $CONFIGUREARGS .= " --enable-jit";
233 }
234
235 if (@ARGV != 0 and @ARGV != 3) {
236   die "error: must specify 0 or 3 options!";
237 }
238
239 if (@ARGV == 3) {
240   if ($CONFIG_PATH ne "") {
241       die "error: arguments are unsupported in -config mode,";
242   }
243
244   # ARGV[0] used to be the CVS root, ignored for backward compatibility.
245   $BuildDir   = $ARGV[1];
246   $WebDir     = $ARGV[2];
247 }
248
249 if ($CONFIG_PATH ne "") {
250   $BuildDir = "";
251   $SVNURL = $TestSVNURL = "";
252   if ($WebDir     eq "") {
253     die("please specify a web directory");
254   }
255 } else {
256   if ($BuildDir   eq "" or
257       $WebDir     eq "") {
258     die("please specify a build directory, and a web directory");
259   }
260 }
261
262 if ($nickname eq "") {
263   die ("Please invoke NewNightlyTest.pl with command line option " .
264        "\"-nickname <nickname>\"");
265 }
266
267 ##############################################################
268 #
269 # Define the file names we'll use
270 #
271 ##############################################################
272
273 my $Prefix = "$WebDir/$DATE";
274 my $SingleSourceLog = "$Prefix-SingleSource-ProgramTest.txt.gz";
275 my $MultiSourceLog = "$Prefix-MultiSource-ProgramTest.txt.gz";
276 my $ExternalLog = "$Prefix-External-ProgramTest.txt.gz";
277
278 # These are only valid in non-config mode.
279 my $ConfigureLog = "", $BuildLog = "", $COLog = "";
280 my $DejagnuLog = "", $DejagnuSum = "", $DejagnuLog = "";
281
282 # Are we in config mode?
283 my $ConfigMode = 0;
284
285 ##############################################################
286 #
287 # Helper functions
288 #
289 ##############################################################
290
291 sub GetDir {
292   my $Suffix = shift;
293   opendir DH, $WebDir;
294   my @Result = reverse sort grep !/$DATE/, grep /[-0-9]+$Suffix/, readdir DH;
295   closedir DH;
296   return @Result;
297 }
298
299 sub RunLoggedCommand {
300   my $Command = shift;
301   my $Log = shift;
302   my $Title = shift;
303   if ($TEELOGS) {
304       if ($VERBOSE) {
305           print "$Title\n";
306           print "$Command 2>&1 | tee $Log\n";
307       }
308       system "$Command 2>&1 | tee $Log";
309   } else {
310       if ($VERBOSE) {
311           print "$Title\n";
312           print "$Command 2>&1 > $Log\n";
313       }
314       system "$Command 2>&1 > $Log";
315   }
316 }
317
318 sub RunAppendingLoggedCommand {
319   my $Command = shift;
320   my $Log = shift;
321   my $Title = shift;
322   if ($TEELOGS) {
323       if ($VERBOSE) {
324           print "$Title\n";
325           print "$Command 2>&1 | tee -a $Log\n";
326       }
327       system "$Command 2>&1 | tee -a $Log";
328   } else {
329       if ($VERBOSE) {
330           print "$Title\n";
331           print "$Command 2>&1 > $Log\n";
332       }
333       system "$Command 2>&1 >> $Log";
334   }
335 }
336
337 sub GetRegex {   # (Regex with ()'s, value)
338   if ($_[1] =~ /$_[0]/m) {
339     return $1;
340   }
341   return "0";
342 }
343
344 sub ChangeDir { # directory, logical name
345   my ($dir,$name) = @_;
346   chomp($dir);
347   if ( $VERBOSE ) { print "Changing To: $name ($dir)\n"; }
348   $result = chdir($dir);
349   if (!$result) {
350     print "ERROR!!! Cannot change directory to: $name ($dir) because $!\n";
351     return false;
352   }
353   return true;
354 }
355
356 sub ReadFile {
357   if (open (FILE, $_[0])) {
358     undef $/;
359     my $Ret = <FILE>;
360     close FILE;
361     $/ = '\n';
362     return $Ret;
363   } else {
364     print "Could not open file '$_[0]' for reading!\n";
365     return "";
366   }
367 }
368
369 sub WriteFile {  # (filename, contents)
370   open (FILE, ">$_[0]") or die "Could not open file '$_[0]' for writing!\n";
371   print FILE $_[1];
372   close FILE;
373 }
374
375 sub CopyFile { #filename, newfile
376   my ($file, $newfile) = @_;
377   chomp($file);
378   if ($VERBOSE) { print "Copying $file to $newfile\n"; }
379   copy($file, $newfile);
380 }
381
382 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
383 #
384 # This function is meant to read in the dejagnu sum file and
385 # return a string with only the results (i.e. PASS/FAIL/XPASS/
386 # XFAIL).
387 #
388 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
389 sub GetDejagnuTestResults { # (filename, log)
390     my ($filename, $DejagnuLog) = @_;
391     my @lines;
392     $/ = "\n"; #Make sure we're going line at a time.
393
394     if( $VERBOSE) { print "DEJAGNU TEST RESULTS:\n"; }
395
396     if (open SRCHFILE, $filename) {
397         # Process test results
398         while ( <SRCHFILE> ) {
399             if ( length($_) > 1 ) {
400                 chomp($_);
401                 if ( m/^(PASS|XPASS|FAIL|XFAIL): .*\/llvm\/test\/(.*)$/ ) {
402                     push(@lines, "$1: test/$2");
403                 }
404             }
405         }
406     }
407     close SRCHFILE;
408
409     my $content = join("\n", @lines);
410     return $content;
411 }
412
413
414
415 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
416 #
417 # This function acts as a mini web browswer submitting data
418 # to our central server via the post method
419 #
420 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
421 sub SendData {
422     $host = $_[0];
423     $file = $_[1];
424     $variables = $_[2];
425
426     # Write out the "...-sentdata.txt" file.
427
428     my $sentdata="";
429     foreach $x (keys (%$variables)){
430         $value = $variables->{$x};
431         $sentdata.= "$x  => $value\n";
432     }
433     WriteFile "$Prefix-sentdata.txt", $sentdata;
434
435     if (!($SUBMITAUX eq "")) {
436         system "$SUBMITAUX \"$Prefix-sentdata.txt\"";
437     }
438
439     if (!$SUBMIT) {
440         return "Skipped standard submit.\n";
441     }
442
443     # Create the content to send to the server.
444
445     my $content;
446     foreach $key (keys (%$variables)){
447         $value = $variables->{$key};
448         $value =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg;
449         $content .= "$key=$value&";
450     }
451
452     # Send the data to the server.
453     #
454     # FIXME: This code should be more robust?
455
456     $port=80;
457     $socketaddr= sockaddr_in $port, inet_aton $host or die "Bad hostname\n";
458     socket SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp') or
459       die "Bad socket\n";
460     connect SOCK, $socketaddr or die "Bad connection\n";
461     select((select(SOCK), $| = 1)[0]);
462
463     $length = length($content);
464
465     my $send= "POST $file HTTP/1.0\n";
466     $send.= "Host: $host\n";
467     $send.= "Content-Type: application/x-www-form-urlencoded\n";
468     $send.= "Content-length: $length\n\n";
469     $send.= "$content";
470
471     print SOCK $send;
472     my $result;
473     while(<SOCK>){
474         $result  .= $_;
475     }
476     close(SOCK);
477
478     return $result;
479 }
480
481 ##############################################################
482 #
483 # Individual Build & Test Functions
484 #
485 ##############################################################
486
487 # Create the source repository directory.
488 sub CheckoutSource {
489   die "Invalid call!" unless $ConfigMode == 0;
490   if (-d $BuildDir) {
491     if (!$NOREMOVE) {
492       if ( $VERBOSE ) {
493         print "Build directory exists! Removing it\n";
494       }
495       system "rm -rf $BuildDir";
496       mkdir $BuildDir or die "Could not create checkout directory $BuildDir!";
497     } else {
498       if ( $VERBOSE ) {
499         print "Build directory exists!\n";
500       }
501     }
502   } else {
503     mkdir $BuildDir or die "Could not create checkout directory $BuildDir!";
504   }
505
506   ChangeDir( $BuildDir, "checkout directory" );
507   my $SVNCMD = "$NICE svn co --non-interactive";
508   RunLoggedCommand("( time -p $SVNCMD $SVNURL/llvm/trunk llvm; cd llvm/projects ; " .
509                    "  $SVNCMD $TestSVNURL/test-suite/trunk llvm-test )", $COLog,
510                    "CHECKOUT LLVM");
511   if ($WITHCLANG) {
512       RunLoggedCommand("( cd llvm/tools ; " .
513                        "  $SVNCMD $SVNURL/cfe/trunk clang )", $COLog,
514                        "CHECKOUT CLANG");
515   }
516 }
517
518 # Build the entire tree, saving build messages to the build log. Returns false
519 # on build failure.
520 sub BuildLLVM {
521   die "Invalid call!" unless $ConfigMode == 0;
522   my $EXTRAFLAGS = "--enable-spec --with-objroot=.";
523   RunLoggedCommand("(time -p $NICE ./configure $CONFIGUREARGS $EXTRAFLAGS) ",
524                    $ConfigureLog, "CONFIGURE");
525   # Build the entire tree, capturing the output into $BuildLog
526   RunAppendingLoggedCommand("($NICE $MAKECMD $MAKEOPTS clean)", $BuildLog, "BUILD CLEAN");
527   RunAppendingLoggedCommand("(time -p $NICE $MAKECMD $MAKEOPTS)", $BuildLog, "BUILD");
528
529   if (`grep '^$MAKECMD\[^:]*: .*Error' $BuildLog | wc -l` + 0 ||
530       `grep '^$MAKECMD: \*\*\*.*Stop.' $BuildLog | wc -l` + 0) {
531     return 0;
532   }
533
534   return 1;
535 }
536
537 # Running dejagnu tests and save results to log.
538 sub RunDejaGNUTests {
539   die "Invalid call!" unless $ConfigMode == 0;
540   # Run the feature and regression tests, results are put into testrun.sum and
541   # the full log in testrun.log.
542   system "rm -f test/testrun.log test/testrun.sum";
543   RunLoggedCommand("(time -p $MAKECMD $MAKEOPTS check)", $DejagnuLog, "DEJAGNU");
544
545   # Copy the testrun.log and testrun.sum to our webdir.
546   CopyFile("test/testrun.log", $DejagnuLog);
547   CopyFile("test/testrun.sum", $DejagnuSum);
548
549   return GetDejagnuTestResults($DejagnuSum, $DejagnuLog);
550 }
551
552 # Run the named tests (i.e. "SingleSource" "MultiSource" "External")
553 sub TestDirectory {
554   my $SubDir = shift;
555   ChangeDir( "$LLVMTestDir/$SubDir",
556              "Programs Test Subdirectory" ) || return ("", "");
557
558   my $ProgramTestLog = "$Prefix-$SubDir-ProgramTest.txt";
559
560   # Make sure to clean things if in non-config mode.
561   if ($ConfigMode == 1) {
562     RunLoggedCommand("$MAKECMD -k $MAKEOPTS $PROGTESTOPTS clean $TESTFLAGS",
563                      $ProgramTestLog, "TEST DIRECTORY $SubDir");
564   }
565
566   # Run the programs tests... creating a report.nightly.csv file.
567   my $LLCBetaOpts = "";
568   RunLoggedCommand("$MAKECMD -k $MAKEOPTS $PROGTESTOPTS report.nightly.csv ".
569                    "$TESTFLAGS TEST=nightly",
570                    $ProgramTestLog, "TEST DIRECTORY $SubDir");
571   $LLCBetaOpts = `$MAKECMD print-llcbeta-option`;
572
573   my $ProgramsTable;
574   if (`grep '^$MAKECMD\[^:]: .*Error' $ProgramTestLog | wc -l` + 0) {
575     $ProgramsTable="Error running test $SubDir\n";
576     print "ERROR TESTING\n";
577   } elsif (`grep '^$MAKECMD\[^:]: .*No rule to make target' $ProgramTestLog | wc -l` + 0) {
578     $ProgramsTable="Makefile error running tests $SubDir!\n";
579     print "ERROR TESTING\n";
580   } else {
581     # Create a list of the tests which were run...
582     system "egrep 'TEST-(PASS|FAIL)' < $ProgramTestLog ".
583            "| sort > $Prefix-$SubDir-Tests.txt";
584   }
585   $ProgramsTable = ReadFile "report.nightly.csv";
586
587   ChangeDir( "../../..", "Programs Test Parent Directory" );
588   return ($ProgramsTable, $LLCBetaOpts);
589 }
590
591 # Run all the nightly tests and return the program tables and the list of tests,
592 # passes, fails, and xfails.
593 sub RunNightlyTest() {
594   ($SSProgs, $llcbeta_options) = TestDirectory("SingleSource");
595   WriteFile "$Prefix-SingleSource-Performance.txt", $SSProgs;
596   ($MSProgs, $llcbeta_options) = TestDirectory("MultiSource");
597   WriteFile "$Prefix-MultiSource-Performance.txt", $MSProgs;
598   if ( ! $NOEXTERNALS ) {
599     ($ExtProgs, $llcbeta_options) = TestDirectory("External");
600     WriteFile "$Prefix-External-Performance.txt", $ExtProgs;
601     system "cat $Prefix-SingleSource-Tests.txt " .
602                "$Prefix-MultiSource-Tests.txt ".
603                "$Prefix-External-Tests.txt | sort > $Prefix-Tests.txt";
604     system "cat $Prefix-SingleSource-Performance.txt " .
605                "$Prefix-MultiSource-Performance.txt ".
606                "$Prefix-External-Performance.txt | sort > $Prefix-Performance.txt";
607   } else {
608     $ExtProgs = "External TEST STAGE SKIPPED\n";
609     if ( $VERBOSE ) {
610       print "External TEST STAGE SKIPPED\n";
611     }
612     system "cat $Prefix-SingleSource-Tests.txt " .
613                "$Prefix-MultiSource-Tests.txt ".
614                " | sort > $Prefix-Tests.txt";
615     system "cat $Prefix-SingleSource-Performance.txt " .
616                "$Prefix-MultiSource-Performance.txt ".
617                " | sort > $Prefix-Performance.txt";
618   }
619
620   # Compile passes, fails, xfails.
621   my $All = (ReadFile "$Prefix-Tests.txt");
622   my @TestSuiteResultLines = split "\n", $All;
623   my ($Passes, $Fails, $XFails) = "";
624
625   for ($x=0; $x < @TestSuiteResultLines; $x++) {
626     if (@TestSuiteResultLines[$x] =~ m/^PASS:/) {
627       $Passes .= "$TestSuiteResultLines[$x]\n";
628     }
629     elsif (@TestSuiteResultLines[$x] =~ m/^FAIL:/) {
630       $Fails .= "$TestSuiteResultLines[$x]\n";
631     }
632     elsif (@TestSuiteResultLines[$x] =~ m/^XFAIL:/) {
633       $XFails .= "$TestSuiteResultLines[$x]\n";
634     }
635   }
636
637   return ($SSProgs, $MSProgs, $ExtProgs, $All, $Passes, $Fails, $XFails);
638 }
639
640 ##############################################################
641 #
642 # Initialize filenames
643 #
644 ##############################################################
645
646 if (! -d $WebDir) {
647   mkdir $WebDir, 0777 or die "Unable to create web directory: '$WebDir'.";
648   if($VERBOSE){
649     warn "$WebDir did not exist; creating it.\n";
650   }
651 }
652
653 if ($CONFIG_PATH ne "") {
654   $ConfigMode = 1;
655   $LLVMSrcDir = GetRegex "^(.*)\\s+", `$CONFIG_PATH --src-root`;
656   $LLVMObjDir = GetRegex "^(.*)\\s+", `$CONFIG_PATH --obj-root`;
657   # FIXME: Add llvm-config hook for this?
658   $LLVMTestDir = $LLVMObjDir . "/projects/test-suite";
659 } else {
660   $ConfigureLog = "$Prefix-Configure-Log.txt";
661   $BuildLog = "$Prefix-Build-Log.txt";
662   $COLog = "$Prefix-CVS-Log.txt";
663   $DejagnuLog = "$Prefix-Dejagnu-testrun.log";
664   $DejagnuSum = "$Prefix-Dejagnu-testrun.sum";
665   $DejagnuLog = "$Prefix-DejagnuTests-Log.txt";
666 }
667
668 if ($VERBOSE) {
669   if ($CONFIG_PATH ne "") {
670     print "INITIALIZED (config mode)\n";
671     print "WebDir    = $WebDir\n";
672     print "Prefix    = $Prefix\n";
673     print "LLVM Src  = $LLVMSrcDir\n";
674     print "LLVM Obj  = $LLVMObjDir\n";
675     print "LLVM Test = $LLVMTestDir\n";
676   } else {
677     print "INITIALIZED\n";
678     print "SVN URL  = $SVNURL\n";
679     print "COLog    = $COLog\n";
680     print "BuildDir = $BuildDir\n";
681     print "WebDir   = $WebDir\n";
682     print "Prefix   = $Prefix\n";
683     print "BuildLog = $BuildLog\n";
684   }
685 }
686
687 ##############################################################
688 #
689 # The actual NewNightlyTest logic.
690 #
691 ##############################################################
692
693 $starttime = `date "+20%y-%m-%d %H:%M:%S"`;
694
695 my $BuildError = 0, $BuildStatus = "OK";
696 my $DejagnuTestResults = "Dejagnu skipped by user choice.";
697 if ($ConfigMode == 0) {
698   if (!$NOCHECKOUT) {
699     CheckoutSource();
700   }
701
702   # Build LLVM.
703   ChangeDir( $LLVMSrcDir , "llvm source directory") ;
704   if ($NOCHECKOUT || $NOBUILD) {
705     $BuildStatus = "Skipped by user";
706   } else {
707     if (!BuildLLVM()) {
708       if( $VERBOSE) { print  "\n***ERROR BUILDING TREE\n\n"; }
709       $BuildError = 1;
710       $BuildStatus = "Error: compilation aborted";
711       $NODEJAGNU=1;
712     }
713   }
714
715   # Run DejaGNU.
716   if (!$NODEJAGNU && !$BuildError) {
717     $DejagnuTestResults = RunDejaGNUTests();
718   }
719 }
720
721 # Run the llvm-test tests.
722 my ($SingleSourceProgramsTable, $MultiSourceProgramsTable, $ExternalProgramsTable,
723     $all_tests, $passes, $fails, $xfails) = "";
724 if (!$NOTEST && !$BuildError) {
725   ($SingleSourceProgramsTable, $MultiSourceProgramsTable, $ExternalProgramsTable,
726    $all_tests, $passes, $fails, $xfails) = RunNightlyTest();
727 }
728
729 $endtime = `date "+20%y-%m-%d %H:%M:%S"`;
730
731 # The last bit of logic is to remove the build and web dirs, after sending data
732 # to the server.
733
734 ##############################################################
735 #
736 # Accumulate the information to send to the server.
737 #
738 ##############################################################
739
740 if ( $VERBOSE ) { print "PREPARING LOGS TO BE SENT TO SERVER\n"; }
741
742 $machine_data = "uname: ".`uname -a`.
743                 "hardware: ".`uname -m`.
744                 "os: ".`uname -sr`.
745                 "name: ".`uname -n`.
746                 "date: ".`date \"+20%y-%m-%d\"`.
747                 "time: ".`date +\"%H:%M:%S\"`;
748
749 # Get gcc version.
750 my $gcc_version_long = "";
751 if ($GCCPATH ne "") {
752   $gcc_version_long = `$GCCPATH/gcc --version`;
753 } elsif ($ENV{"CC"}) {
754   $gcc_version_long = `$ENV{"CC"} --version`;
755 } else {
756   $gcc_version_long = `gcc --version`;
757 }
758 my $gcc_version = (split '\n', $gcc_version_long)[0];
759
760 # Get llvm-gcc target triple.
761 my $llvmgcc_version_long = "";
762 if ($LLVMGCCPATH ne "") {
763   $llvmgcc_version_long = `$LLVMGCCPATH/llvm-gcc -v 2>&1`;
764 } else {
765   $llvmgcc_version_long = `llvm-gcc -v 2>&1`;
766 }
767 (split '\n', $llvmgcc_version_long)[1] =~ /Target: (.+)/;
768 my $targetTriple = $1;
769
770 # Logs.
771 my ($ConfigureLogData, $BuildLogData, $DejagnuLogData, $CheckoutLogData) = "";
772 if ($ConfigMode == 0) {
773   $ConfigureLogData = ReadFile $ConfigureLog;
774   $BuildLogData = ReadFile $BuildLog;
775   $DejagnuLogData = ReadFile $DejagnuLog;
776   $CheckoutLogData = ReadFile $COLog;
777 }
778
779 # Checkout info.
780 my $CheckoutTime_Wall = GetRegex "^real ([0-9.]+)", $CheckoutLogData;
781 my $CheckoutTime_User = GetRegex "^user ([0-9.]+)", $CheckoutLogData;
782 my $CheckoutTime_Sys = GetRegex "^sys ([0-9.]+)", $CheckoutLogData;
783 my $CheckoutTime_CPU = $CVSCheckoutTime_User + $CVSCheckoutTime_Sys;
784
785 # Configure info.
786 my $ConfigTimeU = GetRegex "^user ([0-9.]+)", $ConfigureLogData;
787 my $ConfigTimeS = GetRegex "^sys ([0-9.]+)", $ConfigureLogData;
788 my $ConfigTime  = $ConfigTimeU+$ConfigTimeS;  # ConfigTime = User+System
789 my $ConfigWallTime = GetRegex "^real ([0-9.]+)",$ConfigureLogData;
790 $ConfigTime=-1 unless $ConfigTime;
791 $ConfigWallTime=-1 unless $ConfigWallTime;
792
793 # Build info.
794 my $BuildTimeU = GetRegex "^user ([0-9.]+)", $BuildLogData;
795 my $BuildTimeS = GetRegex "^sys ([0-9.]+)", $BuildLogData;
796 my $BuildTime  = $BuildTimeU+$BuildTimeS;  # BuildTime = User+System
797 my $BuildWallTime = GetRegex "^real ([0-9.]+)", $BuildLogData;
798 $BuildTime=-1 unless $BuildTime;
799 $BuildWallTime=-1 unless $BuildWallTime;
800
801 # DejaGNU info.
802 my $DejagnuTimeU = GetRegex "^user ([0-9.]+)", $DejagnuLogData;
803 my $DejagnuTimeS = GetRegex "^sys ([0-9.]+)", $DejagnuLogData;
804 $DejagnuTime  = $DejagnuTimeU+$DejagnuTimeS;  # DejagnuTime = User+System
805 $DejagnuWallTime = GetRegex "^real ([0-9.]+)", $DejagnuLogData;
806 $DejagnuTime     = "0.0" unless $DejagnuTime;
807 $DejagnuWallTime = "0.0" unless $DejagnuWallTime;
808
809 if ( $VERBOSE ) { print "SEND THE DATA VIA THE POST REQUEST\n"; }
810
811 my %hash_of_data = (
812   'machine_data' => $machine_data,
813   'build_data' => $ConfigureLogData . $BuildLogData,
814   'gcc_version' => $gcc_version,
815   'nickname' => $nickname,
816   'dejagnutime_wall' => $DejagnuWallTime,
817   'dejagnutime_cpu' => $DejagnuTime,
818   'cvscheckouttime_wall' => $CheckoutTime_Wall,
819   'cvscheckouttime_cpu' => $CheckoutTime_CPU,
820   'configtime_wall' => $ConfigWallTime,
821   'configtime_cpu'=> $ConfigTime,
822   'buildtime_wall' => $BuildWallTime,
823   'buildtime_cpu' => $BuildTime,
824   'buildstatus' => $BuildStatus,
825   'singlesource_programstable' => $SingleSourceProgramsTable,
826   'multisource_programstable' => $MultiSourceProgramsTable,
827   'externalsource_programstable' => $ExternalProgramsTable,
828   'llcbeta_options' => $llcbeta_options,
829   'passing_tests' => $passes,
830   'expfail_tests' => $xfails,
831   'unexpfail_tests' => $fails,
832   'all_tests' => $all_tests,
833   'dejagnutests_results' => $DejagnuTestResults,
834   'dejagnutests_log' => $DejagnuLogData,
835   'starttime' => $starttime,
836   'endtime' => $endtime,
837   'target_triple' => $targetTriple,
838
839   # Unused, but left around for backwards compatability.
840   'warnings' => "",
841   'cvsusercommitlist' => "",
842   'cvsuserupdatelist' => "",
843   'cvsaddedfiles' => "",
844   'cvsmodifiedfiles' => "",
845   'cvsremovedfiles' => "",
846   'lines_of_code' => "",
847   'cvs_file_count' => 0,
848   'cvs_dir_count' => 0,
849   'warnings_removed' => "",
850   'warnings_added' => "",
851   'new_tests' => "",
852   'removed_tests' => "",
853   'o_file_sizes' => "",
854   'a_file_sizes' => ""
855 );
856
857 if ($SUBMIT || !($SUBMITAUX eq "")) {
858   my $response = SendData $SUBMITSERVER,$SUBMITSCRIPT,\%hash_of_data;
859   if( $VERBOSE) { print "============================\n$response"; }
860 } else {
861   print "============================\n";
862   foreach $x(keys %hash_of_data){
863       print "$x  => $hash_of_data{$x}\n";
864   }
865 }
866
867 ##############################################################
868 #
869 # Remove the source tree...
870 #
871 ##############################################################
872 system ( "$NICE rm -rf $BuildDir")
873   if (!$NOCHECKOUT and !$NOREMOVE and !$NOREMOVEATEND);
874 system ( "$NICE rm -rf $WebDir")
875   if (!$NOCHECKOUT and !$NOREMOVE and !$NOREMOVERESULTS);