Initial add of defaria.com
[clearscm.git] / defaria.com / GD / rantest
1 #!/usr/bin/perl\r
2 ##############################################################################\r
3 #\r
4 # Name:         rantest\r
5 #\r
6 # Description:  This script is a test driver script capable of running tests\r
7 #               individually or from a file. There are many facilities for\r
8 #               specifying input and options to this program - see the usage\r
9 #               and help subroutines for clues. Basically you can run rantest\r
10 #               by itself and it will interactively prompt you for what to do\r
11 #               and what information or options it needs. Additionally you can\r
12 #               set options in the environment such as RANTEST_VIEW or\r
13 #               RANTEST_UNIT to serve as defaults. Or you can use -view or\r
14 #               -type, for example, at the command line to supply such parms.\r
15 #               If rantest still doesn't have all it needs it will prompts.\r
16 #\r
17 #               Note that options and/or test cases can be specified in config\r
18 #               files specified by RANTEST_FILE or -file. Embedded in the\r
19 #               config file can be additional options in the form of:\r
20 #\r
21 #               b2_l3_rnc_irt_001.test:\r
22 #               ----------------------\r
23 #               view:   p6258c_SIMCQ00000100_intview\r
24 #               type:   rnc\r
25 #               unit:   4\r
26 #               exec: tc CN_SIM/TC_CN_Simulation_RANAP_Setup.profile -timeout 60\r
27 #               exec: tc CN_SIM/TC_CN_Simulation.profile -timeout -1 -pause 5\r
28 #               exec: tc RBS_SIM/TC_RBS_Sim_Cell_Setup.profile -timeout 180\r
29 #               exec: tc l3_rnc/irt/TC_b2_l3_rnc_irt_001.profile -timeout 180\r
30 #\r
31 #               Above we've set view, type and unit for the test run\r
32 #               and defined test steps of tc\r
33 #               CN_SIM/TC_CN_Simulation_RANAP_Setup.profile,\r
34 #               CN_SIM/TC_CN_Simulation.profile,\r
35 #               RBS_SIM/TC_RBS_Sim_Cell_Setup.profile and\r
36 #               l3_rnc/irt/TC_b2_l3_rnc_irt_001.profile\r
37 #\r
38 #               Note that you can specify optional additional\r
39 #               parameters after the test name like -timeout and a\r
40 #               bunch of other parameters as described in the "Command\r
41 #               Line in East" document.\r
42 #\r
43 #               This would be run as so:\r
44 #\r
45 #               $ rantest -file b2_l3_rnc_irt_001.test\r
46 #\r
47 #               Suite files, those ending in .suite, are different\r
48 #               from .test files in that they merely contain a list of\r
49 #               .test files (relative to <view>/vobs/simdev/test) to\r
50 #               execute for this suite. Note that parameters can be\r
51 #               added after the suite file name:\r
52 #\r
53 #               nightly.suite:\r
54 #               --------------\r
55 #               # RNC IRT tests\r
56 #               b2_l3_rnc_irt_007.test -unit 4\r
57 #               b2_l3_rnc_irt_014.test\r
58 #\r
59 #               # RNC SCH tests\r
60 #               b2_l3_rnc_sch_001.test -view official_view\r
61 #               b2_l3_rnc_sch_003a.test\r
62 #\r
63 # Author:       Andrew@ClearSCM.com\r
64 #\r
65 # Copyright (c) 2008, 2009 General Dynamics\r
66 #\r
67 # All rights reserved except as subject to DFARS 252.227-7014 of contract\r
68 # number CP02H8901N issued under prime contract N00039-04-C-2009.\r
69 #\r
70 # Warning: This document contains technical data whose export is restricted\r
71 # by the Arms Export Control Act (Title 22, U.S.C., Sec 2751, et seq.) or the\r
72 # Export Administration Act of 1979, as amended, Title, 50, U.S.C., App. 2401\r
73 # et seq. Violations of these export laws are subject to severe criminal\r
74 # penalties. Disseminate in accordance with provisions of DoD Directive\r
75 # 5230.25.\r
76 #\r
77 ##############################################################################\r
78 use strict;\r
79 use warnings;\r
80 \r
81 use File::Basename;\r
82 use File::Glob ':glob';\r
83 use File::Path;\r
84 use FindBin;\r
85 use Getopt::Long;\r
86 use Net::Domain qw (hostname);\r
87 use Term::ANSIColor qw (:constants);\r
88 use Term::ReadLine;\r
89 use Term::ReadLine::Gnu;\r
90 \r
91 # Use the SDE Tools libraries. Sorry for this long path. I didn't come\r
92 # up with it!\r
93 use lib "/cleartrig/ent/SNSD/muos/ccadm_tools/vobs/ranccadm/scripts/lib";\r
94 \r
95 use DateUtils;\r
96 use Display;\r
97 use Utils;\r
98 use GetConfig;\r
99 use Logger;\r
100 \r
101 error "$FindBin::Script only runs on seast1", 1\r
102   unless hostname eq "seast1";\r
103 \r
104 use lib "$FindBin::Bin/../lib";\r
105 \r
106 use GD::RantestDB;\r
107 use GD::Nethawk::East;\r
108 \r
109 use constant VERSION_NBR=> "1.2.5";\r
110 use constant VERSION    => BOLD GREEN   VERSION_NBR;\r
111 use constant PROMPT     => BOLD YELLOW  "$FindBin::Script>";\r
112 use constant DESC       => BOLD RED     "$FindBin::Script",\r
113                            RESET        "Version", VERSION\r
114                          . RESET        ": "\r
115                          . BOLD CYAN    "RAN T"\r
116                          . RESET        "ool for "\r
117                          . BOLD CYAN    "E"\r
118                          . RESET        "xecution of "\r
119                          . BOLD CYAN    "S"\r
120                          . RESET        "ystem "\r
121                          . BOLD CYAN    "T"\r
122                          . RESET        "ests";\r
123 \r
124 use constant HISTORY_FILE => "$ENV{HOME}/.rantest_hist";\r
125 use constant LOGBASE      => "$ENV{MNT_DIR}/testlogs";\r
126 \r
127 ############################################################################\r
128 # Globals\r
129 ############################################################################\r
130 my $_east;\r
131 my $_connected          = 0;\r
132 my $_debugging;\r
133 my $_log;\r
134 my $_term;\r
135 my $_rantestdb;\r
136 my $_testNbr            = 0;\r
137 my $_validationNbr      = 0;\r
138 \r
139 my %_stats;\r
140 \r
141 my %_executionResults;\r
142 \r
143 my (%_opts, %_cmdline_opts);\r
144 \r
145 # Seed opts from the environment.\r
146 $_opts{eastview}        = $ENV{RANTEST_EASTVIEW}        if $ENV{RANTEST_EASTVIEW};\r
147 $_opts{eastview}        = $ENV{RANTEST_VIEW}            if $ENV{RANTEST_VIEW} && !$_opts{eastview};\r
148 $_opts{tm500view}       = $ENV{RANTEST_TM500VIEW}       if $ENV{RANTEST_TM500VIEW};\r
149 $_opts{nmsview}         = $ENV{RANTEST_NMSVIEW}         if $ENV{RANTEST_NMSVIEW};\r
150 $_opts{type}            = $ENV{RANTEST_TYPE}            if $ENV{RANTEST_TYPE};\r
151 $_opts{class}           = $ENV{RANTEST_CLASS}           if $ENV{RANTEST_CLASS};\r
152 $_opts{unit}            = $ENV{RANTEST_UNIT}            if $ENV{RANTEST_UNIT};\r
153 $_opts{test}            = $ENV{RANTEST_TEST}            if $ENV{RANTEST_TEST};\r
154 $_opts{file}            = $ENV{RANTEST_FILE}            if $ENV{RANTEST_FILE};\r
155 $_opts{rfr}             = $ENV{RANTEST_RFR}             if $ENV{RANTEST_RFR};\r
156 $_opts{checkin_on_error}= $ENV{CHECKIN_ON_ERROR}        if $ENV{CHECKIN_ON_ERROR};\r
157 $_opts{feature}         = $ENV{RANTEST_FEATURE}         if $ENV{RANTEST_FEATURE};\r
158 $_opts{regression}      = $ENV{RANTEST_REGRESSION}      if $ENV{RANTEST_REGRESSION};\r
159 $_opts{secure}          = $ENV{RANTEST_SECURE}          if $ENV{RANTEST_SECURE};\r
160 \r
161 # Explicitly default secure to either $ENV{RANTEST_SECURE}, if defined, otherwise 1\r
162 $_opts{secure} = $ENV{RANTEST_SECURE} ? $ENV{RANTEST_SECURE} : 1;\r
163 \r
164 sub usage (;$) {\r
165   my ($msg) = @_;\r
166 \r
167   my $usage = "ERROR: $msg\n\n" if $msg;\r
168 \r
169   $usage .= <<END;\r
170 Usage: $FindBin::Script\t[-us|age] [-v|erbose] [-d|ebug]\r
171   [-view|-eastview <view>] [-tm500view <view>] [-nmsview <view>]\r
172   [-type <type>] [-class <class>] [-rfr <testcase ID>] [-checkin_on_error]\r
173   [-unit <unit #>] [-test <test>] [-file <file>] [-feature <feature>]\r
174   [-[no]s|ecure]\r
175 \r
176 Where:\r
177 \r
178   -us|age:           Display usage\r
179   -ve|rbose:         Turn on verbose mode\r
180   -d|ebug:           Turn on debug mode\r
181   -[ea|st]view <tag> View tag to run test(s) under\r
182   -tm|500view <tag>  TM 500 view to set into the environment for\r
183                      test\r
184   -nm|sview <tag>    NMS view to set into the environment for\r
185                      test\r
186   -ty|pe <type>      Type of unit to test (i.e. rbs | rnc)\r
187   -c|lass <class>    Class of test (i.e. one of the following):\r
188 \r
189       Load           LoadTCRunner\r
190       Pool           RegressionLoadRunner\r
191       TC             RegressionRunner\r
192       TS             RegressionTSRunner\r
193       Manual         Manual test\r
194 \r
195   -un|it <unit #>    Unit number to test on\r
196   -te|st <test>      Name of test (Optional: If not specific you will\r
197                      be prompted for test case names)\r
198   -f|ile <file>      File containing a list of tests to execute (Optional:\r
199                      Contains a file of test classes and names to test)\r
200   -rfr <testcase ID> Run for record: ID is the test case ID to store\r
201                      results under\r
202   -checkin_on_error  Checks in rfr log files even if a test(s) fails\r
203   -regression        Run regression tests. These tests will log there\r
204                      results.\r
205   -feature <feature> If specified then FEATURE will be set into the\r
206                      environment on the blade before calling\r
207                      start_east_auto.\r
208   -[no]s|ecure       Indicates whether or not to secure the node before\r
209                      attempting to connect to it. (Default: secure).\r
210 \r
211 NOTE: Set ANSI_COLORS_DISABLED to turn off colors\r
212 \r
213 If you specify -file you cannot specify -test nor -class. -class'es are\r
214 read from -file.\r
215 \r
216 Additionally, options above can be specified in the environment by\r
217 preceeding the environment variable with \"RANTEST_\". For example,\r
218 \r
219   \$ export RANTEST_TYPE=rbs\r
220   \$ export RANTEST_UNIT=2\r
221   \$ rantest\r
222 \r
223 Also such options can be specified in the -file:\r
224 \r
225   unit: 5\r
226   executionlevel: 2\r
227   ts ts1.profile -timeout -1 -pause 5\r
228   ts ts2.profile -displaylevel 3\r
229   ts ts3.profile -activecalls 10\r
230 \r
231 Options after test profile name are passed directory to EAST's command\r
232 line. The exceptions are -timeout and -pause:\r
233 \r
234   -timeout <n>          Specifies the timeout for this test's execution.\r
235                         If negative the test will be placed in the\r
236                         background. No result is recovered from\r
237                         background tests nor are any logfiles analysed\r
238                         or stored. If positive then this sets the\r
239                         timeout period for this test in seconds.\r
240 \r
241   -pause <n>            Used in conjunction with -timeout. If test is\r
242                         backgrounded then $FindBin::Script will wait\r
243                         pause seconds before returning control from\r
244                         this test. This allows the backgrounded test\r
245                         time to start.\r
246 \r
247   -name <name>          Names a test. Used in conditional execution.\r
248 \r
249   -if (<name> <status>) Run this test if the named test returned <status>\r
250                         where <status> is one of\r
251 \r
252                           . Success\r
253                           . Failure\r
254                           . In Progress\r
255                           . Timed out\r
256                           . Failed to execute\r
257                           . Rendezvous\r
258                           . Failed to rendezvous\r
259 \r
260 Note: Required options not supplied will be prompted for.\r
261 END\r
262 \r
263   my $pager = $ENV{PAGER} ? $ENV{PAGER} : "more";\r
264 \r
265   system "echo \"$usage\" | $pager";\r
266 \r
267   exit 1 if $msg;\r
268 } # usage\r
269 \r
270 sub help () {\r
271   display DESC . RESET;\r
272   display <<END;\r
273 \r
274 Valid commands are:\r
275 \r
276 help:                   This display\r
277 usage:                  Displays command line usage\r
278 version:                Displays version of $FindBin::Script\r
279 exit|quit:              Exits $FindBin::Script\r
280 source <file>           Execute the contents of <file>\r
281 set <option>=<value>    Set <option> to <value>\r
282 get <option>            Displays <option> (if set)\r
283 elock <pattern>         Display elock status (default all units)\r
284 \r
285 Running tests:\r
286 \r
287 load <test profile> <options> Run a test case by profile (LoadTCRunner)\r
288 pool <test profile> <options> Run a regression load (RegressionLoadRunner)\r
289 tc   <test profile> <options> Run a regression (RegressionRunner)\r
290 ts   <test profile> <options> Run a regression test suite (RegressionTSRunner)\r
291 manual\r
292 \r
293 Note: ReadLine is supported thus you can edit previous commands.\r
294 Try the up arrow!\r
295 END\r
296 } # Help\r
297 \r
298 sub getParm ($) {\r
299   my ($prompt) = @_;\r
300 \r
301   my $value;\r
302 \r
303   while (!$value or $value eq "") {\r
304     display_nolf BOLD YELLOW . "$FindBin::Script needs the following parameter - $prompt" . RESET;\r
305 \r
306     $value = <STDIN>;\r
307 \r
308     chomp $value;\r
309   } # while\r
310 \r
311   return $value;\r
312 } # getParm\r
313 \r
314 sub eLock (;$) {\r
315   my ($unit) = @_;\r
316 \r
317   my ($status, @locks) = Execute "ls $ENV{MNT_DIR}/$ENV{EAST_REL}/DUT/*/desktop.lock 2> /dev/null";\r
318 \r
319   $status >>= 8;\r
320 \r
321   foreach (@locks) {\r
322     my $unit_found;\r
323 \r
324     if (/.*DUT\/(\w+)\/desktop/) {\r
325       $unit_found = $1;\r
326 \r
327       next if $unit && $unit_found !~ /$unit/i;\r
328     } # if\r
329 \r
330     my @fields  = split /\//, $_;\r
331     my $uid     = (stat $_)[4];\r
332     my $mtime   = (stat $_)[9];\r
333     my $userid  = (getpwuid ($uid))[0];\r
334     my $name    = (getpwuid ($uid))[6];\r
335 \r
336     display BOLD CYAN   "$fields[5]\t"\r
337           . RESET       "locked since "\r
338           . BOLD YELLOW localtime ((stat $_)[9])\r
339           . RESET       " by "\r
340           . MAGENTA     $name\r
341           . RESET       " ("\r
342           . GREEN       $userid\r
343           . RESET       ")";\r
344   } # foreach\r
345 } # eLock\r
346 \r
347 sub displaySummary () {\r
348   my $msg = "Summary:";\r
349 \r
350   foreach (sort keys %_stats) {\r
351     $msg .= " $_stats{$_} $_";\r
352   } # foreach\r
353 \r
354   $_log->msg ($msg) if $_log;\r
355 } # displaySummary\r
356 \r
357 sub announceTestrun ($) {\r
358   my ($testname) = @_;\r
359 \r
360   my $user = $ENV{USER}         ? $ENV{USER}\r
361            : $ENV{LOGNAME}      ? $ENV{LOGNAME}\r
362            : "Unknown";\r
363   my $timestamp = YMDHMS;\r
364 \r
365   $_testNbr++;\r
366 \r
367   verbose BOLD YELLOW   "Test #" . $_testNbr . "\t"\r
368         . RESET CYAN    $testname\r
369         . RESET         " run on $timestamp by "\r
370         . YELLOW        $user\r
371         . RESET         " on "\r
372         . MAGENTA       $_opts{type}\r
373         . RESET         " unit "\r
374         . CYAN          $_opts{unit}\r
375         . RESET;\r
376 \r
377   $_log->log ("Test #$_testNbr $testname run on: $timestamp by $user on $_opts{type} unit $_opts{unit}");\r
378 } # announceTestrun\r
379 \r
380 sub saveHistory {\r
381   $_term->WriteHistory (HISTORY_FILE) if $_term;\r
382 } # saveHistory\r
383 \r
384 sub executeTestStep () {\r
385   if (!$_connected) {\r
386     # Get required parameters if not specified in the command line or environment\r
387     $_opts{eastview}    = getParm "View:"  unless $_opts{eastview};\r
388     $_opts{type}        = getParm "Type:"  unless $_opts{type};\r
389     $_opts{class}       = getParm "Class:" unless $_opts{class};\r
390     $_opts{unit}        = getParm "Unit:"  unless $_opts{unit};\r
391 \r
392     # Connect to it\r
393     my $msg = $_east->connect (\r
394       $_opts{eastview},\r
395       $_opts{type},\r
396       $_opts{unit},\r
397       $_opts{tm500view},\r
398       $_opts{nmsview},\r
399       $_opts{feature},\r
400       $_opts{secure}\r
401     );\r
402 \r
403     if ($msg) {\r
404       $_log->err ("Unable to connect to EAST\n$msg");\r
405       verbose RED "Skipping renaming test steps" . RESET;\r
406       $_stats{Failed}++;\r
407       return -1;\r
408     } else {\r
409       $_connected = 1;\r
410     } # if\r
411   } # if\r
412 \r
413   my ($status, $msg) = Nethawk::East::validTestType ($_opts{class});\r
414 \r
415   if ($status != 0) {\r
416     $_log->err ($msg);\r
417     return $status;\r
418   } # if\r
419 \r
420   if (!$_opts{test}) {\r
421     # Manual tests only have classes\r
422     unless ($_opts{class} eq 'manual') {\r
423       $_log->err ("No test specified");\r
424       return 1;\r
425     } # unless\r
426   } # if\r
427 \r
428   $_east->setCollectLogFiles (1);\r
429 \r
430   verbose_nolf $_stats{Run} . ": " . CYAN "$_opts{class}\t" . BOLD YELLOW $_opts{test} . RESET;\r
431 \r
432   my $testStepResult;\r
433 \r
434   my $startTime = time;\r
435   my $stepName  = "Unknown";\r
436 \r
437   if ($_opts{test} =~ /(.*)\.profile/) {\r
438     $stepName = $1;\r
439   } elsif ($_opts{class} eq "manual") {\r
440     $stepName = "Manual";\r
441   } elsif ($_opts{class} eq "shell") {\r
442     $stepName = $_opts{test};\r
443   } elsif ($_opts{test} =~ /^rantvl/) {\r
444     $stepName = $_opts{test};\r
445 \r
446     $_east->setRantvlStartTime (time);\r
447   } # if\r
448 \r
449   my ($stepID, $errMsg) = $_rantestdb->startSteprun ($stepName);\r
450 \r
451   ($status, $testStepResult) = $_east->exec (\%_opts, \%_executionResults);\r
452 \r
453   # Collect any extended logs\r
454   if ((!defined $_opts{timeout} or $_opts{timeout} > 0) and\r
455       ($_east->{class} eq "load" or\r
456        $_east->{class} eq "tc"   or\r
457        $_east->{class} eq "ts"   or\r
458        $_east->{class} eq "pool")) {\r
459     $_east->collectExtendedLogFiles;\r
460   } # if\r
461 \r
462   my $endTime = time;\r
463 \r
464   if ($status == 0) {\r
465     if ($testStepResult eq "Success") {\r
466       verbose GREEN " $testStepResult" . RESET;\r
467       $_stats{Passed}++;\r
468     } elsif ($testStepResult eq "In progress" or\r
469              $testStepResult eq "Logging started") {\r
470       verbose MAGENTA " $testStepResult" . RESET;\r
471       $_stats{Concurrent}++;\r
472     } elsif ($testStepResult eq "Rendezvous") {\r
473       verbose BOLD . " $testStepResult" . RESET;\r
474       $_stats{Rendezvous}++;\r
475     } else {\r
476       verbose RED " $testStepResult" . RESET;\r
477       $status = 1;\r
478       $_stats{Failed}++;\r
479     } # if\r
480   } else {\r
481     if ($testStepResult eq "Skipped") {\r
482       verbose BOLD . " $testStepResult" . RESET;\r
483       $_stats{Skipped}++;\r
484     } elsif ($testStepResult eq "Timed out") {\r
485       verbose CYAN " $testStepResult" . RESET;\r
486       $status = 1;\r
487       $_stats{Timedout}++;\r
488     } else {\r
489       verbose RED " $testStepResult" . RESET;\r
490       $status = 1;\r
491       $_stats{Failed}++;\r
492     } # if\r
493   } # if\r
494 \r
495   # Log test step result\r
496   $_log->log ("$_stats{Run}: $_opts{class}\t$_opts{test} $testStepResult");\r
497 \r
498   my ($dbErrNbr, $dbErrMsg) = $_rantestdb->endSteprun (\r
499     runID       => $_east->{runID},\r
500     stepID      => $stepID,\r
501     start       => UnixDatetime2SQLDatetime (scalar (localtime ($startTime))),\r
502     end         => UnixDatetime2SQLDatetime (scalar (localtime ($endTime))),\r
503     result      => $testStepResult,\r
504   );\r
505 \r
506   error $dbErrMsg if $dbErrNbr != 0;\r
507 \r
508   return $status;\r
509 } # executeTestStep\r
510 \r
511 sub testTimeout {\r
512   error "Test timed out ($_opts{testtimeout}) seconds passed)";\r
513 \r
514   $_east->disconnect;\r
515 \r
516   # Collect logfiles\r
517   $_east->collectLogFiles;\r
518 } # testTimeout\r
519 \r
520 sub interrupted {\r
521   use Term::ReadKey;\r
522 \r
523   display BLUE "\nInterrupted" . RESET;\r
524 \r
525   displaySummary;\r
526 \r
527   display_nolf\r
528     CYAN        . BOLD "C" . RESET CYAN         "ontinue"       . RESET . " or " .\r
529     MAGENTA     . BOLD "A" . RESET MAGENTA      "bort run"      . RESET . " (" .\r
530     CYAN        . BOLD "C" . RESET "/" .\r
531     MAGENTA     . BOLD "a" . RESET ")?";\r
532 \r
533   ReadMode ("cbreak");\r
534   my $answer = ReadKey (0);\r
535   ReadMode ("normal");\r
536 \r
537   if ($answer eq "\n") {\r
538     display "c";\r
539   } else {\r
540     display $answer;\r
541   } # if\r
542 \r
543   $answer = lc $answer;\r
544 \r
545   if ($answer eq "c") {\r
546     display "Continuing...";\r
547   } elsif ($answer eq "a") {\r
548     display RED "Aborting run" . RESET;\r
549     $_east->setCollectLogFiles (0);\r
550     saveHistory;\r
551     exit;\r
552   } # if\r
553 } # interrupted\r
554 \r
555 sub interpolate ($) {\r
556   my ($str) = @_;\r
557 \r
558   # Perform psuedo variable interpolation. The following psuedo\r
559   # variables are supported:\r
560   #\r
561   # view:         Absolute path to your view\r
562   my $view      = "$ENV{MNT_DIR}/snapshot_views/$_east->{userdir}/$_east->{view}";\r
563   my $simdev    = "$view/vobs/simdev";\r
564 \r
565   # msgdefs:      Absolute path to msgdefs\r
566   my $msgdefs   = "$simdev/msgdefs";\r
567 \r
568   # validation:  Absolute path to validation\r
569   my $validation        = "$simdev/validation";\r
570 \r
571   # logpath:      Absolute path into the "testlogs" area where\r
572   #               logfiles are written\r
573   my $logpath   = LOGBASE . "/" . $_east->getSaveTo;\r
574 \r
575   while ($str =~ /\$/) {\r
576     my ($var, $slice);\r
577 \r
578     if ($str =~ /\$(\w+)/) {    \r
579       # Regular $var\r
580       $var      = $1;\r
581     } elsif ($str =~ /\$(\[.+?\])\[(.+?)\]/) {\r
582       # A $[fileset][slice] reference\r
583       $var      = $1;\r
584       $slice    = $2;\r
585     } elsif ($str =~ /\$(\[.+?\])/) {   \r
586       # A $[fileset] reference\r
587       $var      = $1;\r
588     } # if\r
589 \r
590     if ($var eq "logpath") {\r
591       $str =~ s/\$$var/$logpath/;\r
592     } elsif ($var eq "msgdefs") {\r
593       $str =~ s/\$$var/$msgdefs/;\r
594     } elsif ($var eq "validation") {\r
595       $str =~ s/\$$var/$validation/;\r
596     } elsif ($var eq "view") {\r
597       $str =~ s/\$$var/$view/;\r
598     } elsif ($var =~ /\[(.+)\]/) {\r
599       my $fileset = $1;\r
600 \r
601       my @fileset = glob $fileset;\r
602       my $list;\r
603 \r
604       if (defined $slice) {\r
605         $fileset = quotemeta $fileset;\r
606 \r
607         # Here we handle a slice, but if the slice is of the form x..y\r
608         # then we need to handled it differently\r
609         if ($slice =~ /(\d+)\.\.(\d+)/) {\r
610           # Need to turn off warnings for this next construct of\r
611           # @array[$1..$2]. Otherwise it complains. If we use\r
612           # $array[$1..$2] then it doesn't work! Also take on the\r
613           # base fileset defined above.\r
614           #\r
615           # Adjust bounds\r
616           $2 = $#fileset if $2 > $#fileset;\r
617 \r
618           no warnings;\r
619           $list = join ",", @fileset[$1..$2];\r
620           use warnings;\r
621         } else {\r
622           # Not a slice really but an array reference\r
623           $list = "$fileset[$slice]";\r
624         } # if\r
625 \r
626         $str =~ s/\$\[$fileset\]\[$slice\]/$list/;\r
627       } else {\r
628         $list = join ",", @fileset;\r
629         $str =~ s/\$\[$fileset\]/$list/;\r
630       } # if\r
631 \r
632       if (defined $slice) {\r
633         $str =~ s/\$\[$fileset\]\[$slice\]//;\r
634       } else {\r
635         $str =~ s/\$\[$fileset\]//;\r
636       } # if\r
637     } else {\r
638       error "Unknown variable ($var) encountered in val line:\n$str", 1;\r
639     } # if\r
640   } # while\r
641 \r
642   return $str;\r
643 } # interpolate\r
644 \r
645 sub runValidation ($$) {\r
646   my ($cmd, $logfile) = @_;\r
647 \r
648   my $origCmd = $cmd;\r
649 \r
650   my ($stepID, $errMsg);\r
651 \r
652   ($stepID, $errMsg) = $_rantestdb->startSteprun ($origCmd);\r
653 \r
654   if ($stepID == 0) {\r
655     error "Unable to startSteprun\n$errMsg";\r
656     return 1;\r
657   } # if\r
658 \r
659   my $startTime = time;\r
660 \r
661   $cmd = interpolate ($cmd);\r
662 \r
663   my ($status, @lines) = Execute ("$cmd >> $logfile 2>&1");\r
664 \r
665   $status >>= 8;\r
666 \r
667   my $endTime = time;\r
668 \r
669   my ($dbErrNbr, $dbErrMsg) = $_rantestdb->endSteprun (\r
670     runID       => $_east->{runID},\r
671     stepID      => $stepID,\r
672     start       => UnixDatetime2SQLDatetime (scalar (localtime ($startTime))),\r
673     end         => UnixDatetime2SQLDatetime (scalar (localtime ($endTime))),\r
674     result      => $status ? "Failure" : "Success",\r
675   );\r
676 \r
677   error $dbErrMsg if $dbErrNbr != 0;\r
678 \r
679   # Output lines to stdout\r
680   if (-e $logfile) {\r
681     verbose "$_\n" foreach (ReadFile $logfile);\r
682   } else {\r
683     verbose "Unable to read $logfile";\r
684     $status++;\r
685   } # if\r
686 \r
687   $_validationNbr++;\r
688 \r
689   verbose BOLD YELLOW . "Test #$_testNbr validation #$_validationNbr \t" . RESET CYAN $origCmd\r
690     . (($status == 0) ? GREEN " Success" : RED " Failure") . RESET;\r
691 \r
692   $_log->log ("Test #$_testNbr validation #$_validationNbr\t$origCmd " . (($status == 0) ? "Success" : "Failure"));\r
693 \r
694   return $status;\r
695 } # runValidation\r
696 \r
697 sub runValidations (@) {\r
698   my @validations = @_;\r
699 \r
700   my $validationErrs = 0;\r
701 \r
702   # Make Validation log directory\r
703   my $validationDir = LOGBASE . "/" . $_east->getSaveTo . "/Validations";\r
704 \r
705   eval { mkpath $validationDir };\r
706 \r
707   error "Unable to create Validation directory - $validationDir\n$@", 1 if $@;\r
708 \r
709   chmod 0775, $validationDir;\r
710 \r
711   my $viewPath  = "$ENV{MNT_DIR}/snapshot_views/$_east->{userdir}/$_east->{view}";\r
712   my $vobPath   = "vobs/simdev";\r
713 \r
714   foreach (@validations) {\r
715     my @tokens  = split;\r
716     my $outfile = $tokens[0] . ".log";\r
717 \r
718     $validationErrs += runValidation $_, "$validationDir/$outfile";\r
719   } # foreach\r
720 \r
721   $_stats{Failed} += $validationErrs;\r
722 \r
723   return $validationErrs;\r
724 } # runValidations\r
725 \r
726 sub runTestFile ($) {\r
727   my ($file) = @_;\r
728 \r
729   my $testName = fileparse $file, ".test";\r
730 \r
731   my $testID = $_rantestdb->startTest ($testName);\r
732 \r
733   my %fileopts = GetConfig ($file);\r
734 \r
735   # GetConfig leaves keys %fileopts as case sensitive but we want them\r
736   # case insentive so fix that here.\r
737   foreach (keys (%fileopts)) {\r
738     my $key = lc $_;\r
739 \r
740     # Make "view" an alias for "eastview" but only if there is no\r
741     # eastview already defined\r
742     if ($key eq "view") {\r
743       if (!$fileopts{eastview}) {\r
744         $fileopts{eastview} = delete $fileopts{view};\r
745         $_ = $key = "eastview";\r
746       } # if\r
747     } # if\r
748 \r
749     # Set into %_opts only if that key doesn't exist already. This\r
750     # allows command line options to override options specified in the\r
751     # file. The exception to this is the exec array. This gets\r
752     # replaced in suite runs.\r
753     if ($key eq "exec" || !$_opts{$key}) {\r
754       $_opts{$key} = $fileopts{$_};\r
755     } # if\r
756   } # foreach\r
757 \r
758   my $testStartTime = time;\r
759 \r
760   $_east->setSaveTo ("$testName/$_opts{type}$_opts{unit}/" . YMDHMS ($testStartTime));\r
761 \r
762   eval { mkpath LOGBASE . "/" . $_east->getSaveTo };\r
763 \r
764   error "Unable to create log directory\n$@", 1 if $@;\r
765 \r
766   chmod 0775, LOGBASE . "/" . $_east->getSaveTo;\r
767 \r
768   unless ($_log) {\r
769     $_log = new Logger (\r
770       name      => $testName,\r
771       path      => LOGBASE . "/" . $_east->getSaveTo,\r
772       append    => "yes",\r
773     );\r
774 \r
775     $_log->log ("$FindBin::Script Version " . VERSION_NBR . "\nUsing view: $_opts{eastview}");\r
776   } # unless\r
777 \r
778   verbose BOLD CYAN "Using view: " . RESET $_opts{eastview};\r
779 \r
780   announceTestrun $testName;\r
781 \r
782   my @tokens;\r
783 \r
784   my $testFailures      = 0;\r
785   my $result            = 0;\r
786   my $errMsg;\r
787 \r
788   # Set testTimer if specified\r
789   if ($_opts{testtimeout}) {\r
790     $SIG{ALRM} = \&testTimeout;\r
791     alarm $_opts{testtimeout};\r
792   } # if\r
793 \r
794   ($_east->{runID}, $errMsg) = $_rantestdb->startTestrun (UnixDatetime2SQLDatetime localtime $testStartTime);\r
795 \r
796   return ($_east->{runID}, $errMsg) if $_east->{runID} == 0;\r
797 \r
798   $_validationNbr = 0;\r
799 \r
800   if (ref $_opts{exec} eq "ARRAY") {\r
801     foreach (@{$_opts{exec}}) {\r
802       @tokens = split;\r
803 \r
804       $_opts{class} = shift @tokens;\r
805       $_opts{test}  = join " ", @tokens;\r
806 \r
807       $_stats{Run}++;\r
808 \r
809       $result = executeTestStep;\r
810 \r
811       if ($result == -1) {\r
812         $testFailures++;\r
813         last;\r
814       } else {\r
815         $testFailures += $result;\r
816       } # if\r
817     } # foreach\r
818   } else {\r
819     if ($_opts{exec}) {\r
820       @tokens = split /\s+/, $_opts{exec};\r
821 \r
822       $_opts{class} = shift @tokens;\r
823       $_opts{test}  = join " ", @tokens;\r
824 \r
825       $_stats{Run}++;\r
826 \r
827       $result = executeTestStep;\r
828 \r
829       if ($result == -1) {\r
830         $testFailures++;\r
831       } else {\r
832         $testFailures += $result;\r
833       } # if\r
834     } # if\r
835   } # if\r
836 \r
837   my $execType = $_opts{rfr}            ? "Run for Record"\r
838                : $_opts{regression}     ? "Regression" : "Normal";\r
839 \r
840   return 1 if $result == -1;\r
841 \r
842   # Disconnect from EAST\r
843   $_east->disconnect;\r
844 \r
845   # Assign 'Failed' and 'Timedout' 0 if they are not initialized\r
846   $_stats{Failed}   ||= 0;\r
847   $_stats{Timedout} ||= 0;\r
848 \r
849   my $testErrors = $_stats{Failed} + $_stats{Timedout};\r
850 \r
851   # Collect log files and check them in based on checkin_on_error option\r
852   $_east->collectLogFiles($testErrors, $_opts{checkin_on_error});\r
853 \r
854   if ($testFailures == 0 and $_opts{val}) {\r
855     my @validations = ref $_opts{val} eq "ARRAY"\r
856                     ? @{$_opts{val}}\r
857                     : ($_opts{val});\r
858 \r
859     $testFailures += runValidations @validations;\r
860   } # if\r
861 \r
862   # Log test results\r
863   verbose BOLD YELLOW . "Test #$_testNbr\t" . RESET CYAN $testName\r
864     . (($testFailures == 0) ? GREEN " Success" : RED " Failure") . RESET;\r
865 \r
866   $_log->log ("Test #$_testNbr\t$testName " . (($testFailures == 0) ? "Success" : "Failure"));\r
867 \r
868   my ($_runID, $dbErrMsg) = $_rantestdb->endTestrun (\r
869     runID               => $_east->{runID},\r
870     suiteID             => $_east->{suiteID} ? $_east->{suiteID} : 0,\r
871     name                => fileparse ($file, ".test"),\r
872     execType            => $execType,\r
873     start               => UnixDatetime2SQLDatetime (scalar (localtime ($testStartTime))),\r
874     result              => $testFailures == 0 ? "Success" : "Failure",\r
875     unit                => "$_east->{unitType}$_east->{unitNbr}",\r
876     rantest_version     => VERSION_NBR,\r
877     east_version        => $ENV{EAST_REL},\r
878     ran_version         => $_east->{ran_version},\r
879     tm500_version       => $_east->{tm500_version},\r
880     nms_version         => $_east->{nms_version},\r
881     eastlogs            => LOGBASE . "/" . $_east->getSaveTo,\r
882   );\r
883 \r
884   error $dbErrMsg if $_runID == 0;\r
885 \r
886   return $testFailures;\r
887 } # runTestFile\r
888 \r
889 sub setPath ($) {\r
890   my ($view) = @_;\r
891 \r
892   return if $ENV{PATH} =~ /$view/;\r
893 \r
894   my $userdir;\r
895 \r
896   if ($view =~ /(\S+)_SIM/) {\r
897     $userdir = $1;\r
898   } else {\r
899     error "Unable to find userdir", 1;\r
900   } # if\r
901 \r
902   my @paths = (\r
903     "$ENV{MNT_DIR}/snapshot_views/$userdir/$view/vobs/simdev/sbin",\r
904     "$ENV{MNT_DIR}/snapshot_views/$userdir/$view/vobs/simdev/bin",\r
905     "$ENV{MNT_DIR}/snapshot_views/$userdir/$view/vobs/gdtools/rantest_auto/bin",\r
906   );\r
907 \r
908   $ENV{PATH} = join (":", @paths) . ":" . $ENV{PATH};\r
909 } # setPath\r
910 \r
911 sub runSuiteFile ($) {\r
912   my ($file) = @_;\r
913 \r
914   error "View must be specified when running in suite mode", 1 unless $_opts{eastview};\r
915 \r
916   setPath $_opts{eastview};\r
917 \r
918   my $userdir;\r
919 \r
920   if ($_opts{eastview} =~ /(\S+)_SIM/) {\r
921     $userdir = $1;\r
922   } else {\r
923     error "Unable to find userdir", 1;\r
924   } # if\r
925 \r
926   unless (open FILE, $file) {\r
927     error "Unable to open file $file - $!";\r
928     return 1\r
929   } # unless\r
930 \r
931   my @lines = <FILE>;\r
932 \r
933   chomp @lines;\r
934 \r
935   close FILE;\r
936 \r
937   my $i                 = 0;\r
938   my $suiteStartTime    = time;\r
939   my $suiteFailures     = 0;\r
940   my $suiteName         = fileparse ($file, ".suite");\r
941 \r
942   $_log = new Logger (\r
943     name        => $suiteName,\r
944     path        => LOGBASE,\r
945     append      => "yes",\r
946   );\r
947 \r
948   $_log->log ("$FindBin::Script Version " . VERSION_NBR);\r
949 \r
950   ($_east->{suiteID}) = $_rantestdb->startSuiterun ($suiteName);\r
951 \r
952   verbose BOLD MAGENTA "Suite\t" . RESET GREEN $suiteName . RESET;\r
953 \r
954   $_log->log ("Suite\t$suiteName");\r
955 \r
956   foreach (@lines) {\r
957     $i++;\r
958     next if /(^#|^$)/;\r
959 \r
960     my @components = split;\r
961 \r
962 \r
963     my $viewPath = "$ENV{MNT_DIR}/snapshot_views/$userdir/$_opts{eastview}/vobs/simdev/test/";\r
964     my $testFile = "$viewPath/" . shift @components;\r
965 \r
966     unless (-e $testFile) {\r
967       error "Unable to find test file $testFile (Line: $i)";\r
968       next;\r
969     } # unless\r
970 \r
971     unless (/\.test/) {\r
972       error "Not a .test file: $testFile (Line: $i)";\r
973       next;\r
974     } # unless\r
975 \r
976     # Get test options. It seems GetOptions doesn't support taking\r
977     # input from anything but @ARGV so we'll have to save a copy and\r
978     # restore it.\r
979     my @savedOptions = @ARGV;\r
980 \r
981     @ARGV = split;\r
982 \r
983     my %suiteOptions;\r
984 \r
985     my $status = GetOptions (\r
986       \%suiteOptions,\r
987       "eastview=s",\r
988       "tm500view=s",\r
989       "nmsview=s",\r
990       "type=s",\r
991       "class=s",\r
992       "unit=s",\r
993       "test=s",\r
994       "file=s",\r
995       "rfr=s",\r
996       "regression",\r
997     ) || usage "Invalid parameter";\r
998 \r
999     # Restore @ARGV\r
1000     @ARGV = @savedOptions;\r
1001 \r
1002     # Restore the original command line options:\r
1003     %_opts = %_cmdline_opts;\r
1004 \r
1005     # Merge in %suiteOptions: Set into %_opts only if that key doesn't\r
1006     # exist already. This allows command line options to override\r
1007     # options specified on the .test line in the .suite file\r
1008     foreach (keys %suiteOptions) {\r
1009       $_opts{$_} = $suiteOptions{$_} unless $_opts{$_};\r
1010     } # foreach\r
1011 \r
1012     $suiteFailures += runTestFile $testFile;\r
1013 \r
1014     # Need to disconnect $_east to shut down the previous run\r
1015     my $savedSuiteID = $_east->{suiteID};\r
1016 \r
1017     $_east->disconnect;\r
1018 \r
1019     # Collect logfiles\r
1020     $_east->collectLogFiles;\r
1021 \r
1022     if ($suiteFailures == 0 and $_opts{val}) {\r
1023       my @validations = ref $_opts{val} eq "ARRAY"\r
1024                       ? @{$_opts{val}}\r
1025                       : ($_opts{val});\r
1026 \r
1027       $suiteFailures += runValidations @validations;\r
1028     } # if\r
1029 \r
1030     $_east = new Nethawk::East;\r
1031 \r
1032     $_east->{suiteID} = $savedSuiteID;\r
1033 \r
1034     $_connected = 0;\r
1035   } # foreach\r
1036 \r
1037   # Log suite results\r
1038   verbose BOLD MAGENTA "Suite\t" . RESET GREEN $suiteName\r
1039     . (($suiteFailures == 0) ? GREEN " Success" : RED " Failure") . RESET;\r
1040 \r
1041   $_log->log ("Suite\t$suiteName" . ($suiteFailures == 0) ? "Success" : "Failure");\r
1042 \r
1043   my $errMsg;\r
1044 \r
1045   ($_east->{suiteID}, $errMsg) = $_rantestdb->endSuiterun (\r
1046     name        => fileparse ($file, ".suite"),\r
1047     start       => UnixDatetime2SQLDatetime (scalar (localtime ($suiteStartTime))),\r
1048     result      => $suiteFailures ? "Failure" : "Success",\r
1049   );\r
1050 \r
1051   error $errMsg if $_east->{suiteID} != 0;\r
1052 \r
1053   return $suiteFailures;\r
1054 } # runSuiteFile\r
1055 \r
1056 sub runFile ($) {\r
1057   my ($file) = @_;\r
1058 \r
1059   unless (-e $file) {\r
1060     error "File $file does not exist";\r
1061     return;\r
1062   } # if\r
1063 \r
1064   $_term->AddHistory ("source $file")\r
1065     unless $_debugging or !-t STDIN;\r
1066 \r
1067   $SIG{INT} = \&interrupted;\r
1068 \r
1069   # Determine file type\r
1070   if ($file =~ /\.test$/) {\r
1071     runTestFile $file;\r
1072   } elsif ($file =~ /\.suite$/) {\r
1073     return runSuiteFile $file\r
1074   } else {\r
1075     error "File $file is not a .suite or .test file", 1;\r
1076   } # if\r
1077 } # runFile\r
1078 \r
1079 $SIG{TERM}      =\r
1080 $SIG{QUIT}      = \&saveHistory;\r
1081 \r
1082 # Set a more friendly umask\r
1083 umask 002;\r
1084 \r
1085 GetOptions (\r
1086   \%_opts,\r
1087   verbose       => sub { set_verbose },\r
1088   debug         => sub { set_debug },\r
1089   usage         => sub { usage; exit 0 },\r
1090   "eastview:s",\r
1091   "view:s",\r
1092   "tm500view:s",\r
1093   "nmsview:s",\r
1094   "type:s",\r
1095   "class:s",\r
1096   "unit:s",\r
1097   "test:s",\r
1098   "file:s",\r
1099   "rfr:s",\r
1100   "checkin_on_error",\r
1101   "feature:s",\r
1102   "secure!",\r
1103   "regression",\r
1104 ) || usage "Invalid parameter";\r
1105 \r
1106 # Special case elock command\r
1107 if (scalar @ARGV > 0 and $ARGV[0] =~ /elock/i) {\r
1108   eLock ($ARGV[1]);\r
1109   exit;\r
1110 } # if\r
1111 \r
1112 usage "Extraneous parameters: " . join " ", @ARGV if scalar @ARGV > 0;\r
1113 \r
1114 # Check for mutually exclusive options\r
1115 if ($_opts{file}) {\r
1116   my $suffix = $ENV{RANTEST_FILE} ? "\nNote: The environment variable RANTEST_FILE is set" : "";\r
1117 \r
1118   if ($_opts{test}) {\r
1119     $suffix .= $ENV{RANTEST_TEST} ? "\nNote: The environment variable RANTEST_TEST is set" : "";\r
1120   } elsif ($_opts{class}) {\r
1121     $suffix .= $ENV{RANTEST_CLASS} ? "\nNote: The environment variable RANTEST_CLASS is set" : "";\r
1122   } # if\r
1123 \r
1124   usage "<test> and <file> are mutually exclusive$suffix"  if $_opts{test};\r
1125   usage "<class> and <file> are mutually exclusive$suffix" if $_opts{class};\r
1126 } # if\r
1127 \r
1128 if ($_opts{eastview}) {\r
1129   my $suffix = $ENV{RANTEST_VIEW} ? "\nNote: The environment variable RANTEST_VIEW is set" : "";\r
1130   $suffix .= $ENV{RANTEST_EASTVIEW} ? "\nNote: The environment variable RANTEST_EASTVIEW is set" : "";\r
1131 \r
1132   usage "<eastview> and <view> are mutually exclusive$suffix" if $_opts{view};\r
1133 } # if\r
1134 \r
1135 usage "-rfr and -regression are mutually exclusive" if $_opts{rfr} && $_opts{regression};\r
1136 \r
1137 # Make "view" an alias for "eastview" but only if there is no eastview\r
1138 # already defined\r
1139 $_opts{eastview} = delete $_opts{view} if $_opts{view} && !$_opts{eastview};\r
1140 \r
1141 # Check for required parameters\r
1142 usage "-view or -eastview specified but no view given"\r
1143   if defined $_opts{view} and $_opts{view} eq "";\r
1144 usage "-tm500view specified but no view given"\r
1145   if defined $_opts{tm500view} and $_opts{tm500view} eq "";\r
1146 usage "-nmsview specified but no view given"\r
1147   if defined $_opts{nmsview} and $_opts{nmsview} eq "";\r
1148 usage "-type specified but no type given"\r
1149   if defined $_opts{type} and $_opts{type} eq "";\r
1150 usage "-class specified but no class given"\r
1151   if defined $_opts{class} and $_opts{class} eq "";\r
1152 usage "-unit specified but no unit # given"\r
1153   if defined $_opts{unit} and $_opts{unit} eq "";\r
1154 usage "-test specified but no test given"\r
1155   if defined $_opts{test} and $_opts{test} eq "";\r
1156 usage "-file specified but no file given"\r
1157   if defined $_opts{file} and $_opts{file} eq "";\r
1158 usage "-rfr specified but no testcase ID given"\r
1159   if defined $_opts{rfr} and $_opts{rfr} eq "";\r
1160 \r
1161 # Save these original command line options. If we are in suite mode\r
1162 # then we must allow the individual .test options override these\r
1163 # original command line options.  If -rfr is on then we are by default\r
1164 # verbose\r
1165 %_cmdline_opts = %_opts;\r
1166 \r
1167 set_verbose if $_opts{rfr};\r
1168 \r
1169 # Instantiate a new East object\r
1170 $_east = new Nethawk::East;\r
1171 \r
1172 # Set testcase ID into East object\r
1173 $_east->setTestCaseID ($_opts{rfr});\r
1174 \r
1175 $_debugging = get_debug;\r
1176 \r
1177 # If we are debugging (and thus STDIN gets confused between the debugger's\r
1178 # STDIN and rantest's STDIN) or if we don't have a tty (-t - we would not \r
1179 # have a tty if run from say cron(1m), then do not perform these actions\r
1180 # on $_term.\r
1181 unless ($_debugging or !-t STDIN) {\r
1182   $_term = new Term::ReadLine $FindBin::Script;\r
1183 \r
1184   $_term->{AUTORESET} = 1;\r
1185 \r
1186   # Restore previous history, if any\r
1187   $_term->ReadHistory (HISTORY_FILE);\r
1188 } # unless\r
1189 \r
1190 # Announce ourselves\r
1191 verbose DESC . RESET;\r
1192 \r
1193 # Open Rantest Database\r
1194 $_rantestdb = new RantestDB ("pswit", "!qaz2w3e");\r
1195 \r
1196 if ($_opts{test}) {\r
1197   $SIG{INT} = \&interrupted;\r
1198 \r
1199   $_stats{Run}++;\r
1200 \r
1201   # Separate off options\r
1202   my $testName = $_opts{test};\r
1203 \r
1204   if ($_opts{test} =~ /(\S+)\s+\-.*$/) {\r
1205     $testName = $1;\r
1206  } # if\r
1207 \r
1208   $testName = fileparse ($testName, "\.profile");\r
1209 \r
1210   $_east->setSaveTo ("$testName/$_opts{type}$_opts{unit}/" . YMDHMS);\r
1211 \r
1212   eval { mkpath LOGBASE . "/" . $_east->getSaveTo };\r
1213 \r
1214   return (1, $@) if $@;\r
1215 \r
1216   chmod 0775, LOGBASE . "/" . $_east->getSaveTo;\r
1217 \r
1218   $_log = new Logger (\r
1219     name        => $testName,\r
1220     path        => LOGBASE . "/" . $_east->getSaveTo,\r
1221     append      => "yes",\r
1222   );\r
1223 \r
1224   $_log->log ("$FindBin::Script Version " . VERSION_NBR . "\nUsing view: $_opts{eastview}");\r
1225 \r
1226   executeTestStep;\r
1227 \r
1228   $_term->AddHistory ("$_opts{class} $_opts{test}") unless $_debugging && -t STDIN;\r
1229 \r
1230   # Disconnect from EAST\r
1231   $_east->disconnect;\r
1232 \r
1233   # Collect logfiles\r
1234   $_east->collectLogFiles;\r
1235 } elsif ($_opts{file}) {\r
1236   runFile $_opts{file};\r
1237 } else {\r
1238   $_east->setSaveTo ("rantest/" . YMDHMS);\r
1239 \r
1240   eval { mkpath LOGBASE . "/" . $_east->getSaveTo };\r
1241 \r
1242   return (1, $@) if $@;\r
1243 \r
1244   chmod 0777, LOGBASE . "/" . $_east->getSaveTo;\r
1245 \r
1246   $_log = new Logger (\r
1247     path        => LOGBASE . "/" . $_east->getSaveTo,\r
1248     append      => "yes"\r
1249   );\r
1250 \r
1251   display DESC if !get_verbose;\r
1252 \r
1253   if ($_opts{eastview}) {\r
1254     $_log->log ("$FindBin::Script Version " . VERSION_NBR . "\nUsing view: $_opts{eastview}");\r
1255   } else {\r
1256     $_log->log ("$FindBin::Script Version " . VERSION_NBR);\r
1257   } # if\r
1258 \r
1259   set_verbose;\r
1260 \r
1261   while () {\r
1262     my $cmd;\r
1263 \r
1264     unless ($_debugging) {\r
1265       $cmd = $_term->readline (PROMPT . RESET);\r
1266     } else {\r
1267       display_nolf PROMPT . RESET;\r
1268 \r
1269       $cmd = <STDIN>;\r
1270     } # if\r
1271 \r
1272     # Handle Control-d\r
1273     unless (defined $cmd) {\r
1274       display "";\r
1275       saveHistory;\r
1276       exit 0;\r
1277     } # if\r
1278 \r
1279     chomp $cmd;\r
1280 \r
1281     next if $cmd eq "";\r
1282 \r
1283     if ($cmd =~ /exit|quit/i) {\r
1284       $_term->remove_history ($_term->where_history);\r
1285       saveHistory;\r
1286       exit 0;\r
1287     } # if\r
1288 \r
1289     if ($cmd =~ /^elock/i) {\r
1290       if ($cmd =~ /^elock\s+(\w+)/i) {\r
1291         eLock $1;\r
1292       } else {\r
1293         eLock;\r
1294       } # if\r
1295 \r
1296       next;\r
1297     } # if\r
1298 \r
1299     my @tokens = split /\s+/, $cmd;\r
1300 \r
1301     $_opts{class}       = shift @tokens;\r
1302     $_opts{test}        = join " ", @tokens;\r
1303 \r
1304     $cmd = lc $_opts{class};\r
1305 \r
1306     if ($cmd eq "help") {\r
1307       help;\r
1308       $_term->remove_history ($_term->where_history) unless $_debugging;\r
1309       next;\r
1310     } elsif ($cmd eq "usage") {\r
1311       usage;\r
1312       $_term->remove_history ($_term->where_history) unless $_debugging;\r
1313       next;\r
1314     } elsif ($cmd eq "version") {\r
1315       display DESC;\r
1316       $_term->remove_history ($_term->where_history) unless $_debugging;\r
1317       next;\r
1318     } elsif ($cmd eq "source") {\r
1319       runFile $tokens[0];\r
1320     } elsif ($cmd eq "set") {\r
1321       if ($_opts{test} =~ /\s*(\w+)\s*=\s*(.+)/) {\r
1322         my $optionName  = $1;\r
1323         my $value       = $2;\r
1324 \r
1325         # Remove quotes, if any. Note no check for balancing.\r
1326         $value =~ s/[\"\']//g;\r
1327 \r
1328         # Set option\r
1329         $_opts{$optionName} = $value;\r
1330       } # if\r
1331     } elsif ($cmd eq "get") {\r
1332       if ($_opts{$tokens[0]}) {\r
1333         display "$tokens[0] = $_opts{$tokens[0]}";\r
1334       } else {\r
1335         display "$tokens[0] is not set";\r
1336       } # if\r
1337     } else {\r
1338       $_stats{Run}++;\r
1339       $_opts{class} = lc $_opts{class};\r
1340 \r
1341       if ( $_opts{class} eq "manual" ) {\r
1342         $_opts{test} = " ";\r
1343       } # if\r
1344 \r
1345       executeTestStep;\r
1346     } # if\r
1347   } # while\r
1348 \r
1349   # Disconnect from EAST\r
1350   $_east->disconnect;\r
1351 \r
1352   # Assign 'Failed' and 'Timedout' 0 if they are not initialized\r
1353   $_stats{Failed}   ||= 0;\r
1354   $_stats{Timedout} ||= 0;\r
1355 \r
1356   my $testErrors = $_stats{Failed} + $_stats{Timedout};\r
1357 \r
1358   # Collect log files and check them in based on checkin_on_error option\r
1359   $_east->collectLogFiles($testErrors, $_opts{checkin_on_error});\r
1360 \r
1361 } # if\r
1362 \r
1363 saveHistory;\r
1364 displaySummary;\r
1365 \r
1366 # The combination of Failed and Timedout represents our exit\r
1367 # status. If either or both of them is defined then they will be\r
1368 # non-zero and thus we exit with a non-zero status. Only if both are\r
1369 # undefined, and thus set to 0 by the code below, will we exit 0.\r
1370 $_stats{Failed}         = 0 unless $_stats{Failed};\r
1371 $_stats{Timedout}       = 0 unless $_stats{Timedout};\r
1372 \r
1373 # Now exit with the correct status\r
1374 exit ($_stats{Failed} + $_stats{Timedout});\r