2 ##############################################################################
\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
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
21 # b2_l3_rnc_irt_001.test:
\r
22 # ----------------------
\r
23 # view: p6258c_SIMCQ00000100_intview
\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
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
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
43 # This would be run as so:
\r
45 # $ rantest -file b2_l3_rnc_irt_001.test
\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
56 # b2_l3_rnc_irt_007.test -unit 4
\r
57 # b2_l3_rnc_irt_014.test
\r
60 # b2_l3_rnc_sch_001.test -view official_view
\r
61 # b2_l3_rnc_sch_003a.test
\r
63 # Author: Andrew@ClearSCM.com
\r
65 # Copyright (c) 2008, 2009 General Dynamics
\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
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
77 ##############################################################################
\r
82 use File::Glob ':glob';
\r
86 use Net::Domain qw (hostname);
\r
87 use Term::ANSIColor qw (:constants);
\r
89 use Term::ReadLine::Gnu;
\r
91 # Use the SDE Tools libraries. Sorry for this long path. I didn't come
\r
93 use lib "/cleartrig/ent/SNSD/muos/ccadm_tools/vobs/ranccadm/scripts/lib";
\r
101 error "$FindBin::Script only runs on seast1", 1
\r
102 unless hostname eq "seast1";
\r
104 use lib "$FindBin::Bin/../lib";
\r
107 use GD::Nethawk::East;
\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
115 . BOLD CYAN "RAN T"
\r
118 . RESET "xecution of "
\r
124 use constant HISTORY_FILE => "$ENV{HOME}/.rantest_hist";
\r
125 use constant LOGBASE => "$ENV{MNT_DIR}/testlogs";
\r
127 ############################################################################
\r
129 ############################################################################
\r
131 my $_connected = 0;
\r
137 my $_validationNbr = 0;
\r
141 my %_executionResults;
\r
143 my (%_opts, %_cmdline_opts);
\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
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
167 my $usage = "ERROR: $msg\n\n" if $msg;
\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
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
184 -nm|sview <tag> NMS view to set into the environment for
\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
190 Pool RegressionLoadRunner
\r
191 TC RegressionRunner
\r
192 TS RegressionTSRunner
\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
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
205 -feature <feature> If specified then FEATURE will be set into the
\r
206 environment on the blade before calling
\r
208 -[no]s|ecure Indicates whether or not to secure the node before
\r
209 attempting to connect to it. (Default: secure).
\r
211 NOTE: Set ANSI_COLORS_DISABLED to turn off colors
\r
213 If you specify -file you cannot specify -test nor -class. -class'es are
\r
216 Additionally, options above can be specified in the environment by
\r
217 preceeding the environment variable with \"RANTEST_\". For example,
\r
219 \$ export RANTEST_TYPE=rbs
\r
220 \$ export RANTEST_UNIT=2
\r
223 Also such options can be specified in the -file:
\r
227 ts ts1.profile -timeout -1 -pause 5
\r
228 ts ts2.profile -displaylevel 3
\r
229 ts ts3.profile -activecalls 10
\r
231 Options after test profile name are passed directory to EAST's command
\r
232 line. The exceptions are -timeout and -pause:
\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
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
247 -name <name> Names a test. Used in conditional execution.
\r
249 -if (<name> <status>) Run this test if the named test returned <status>
\r
250 where <status> is one of
\r
256 . Failed to execute
\r
258 . Failed to rendezvous
\r
260 Note: Required options not supplied will be prompted for.
\r
263 my $pager = $ENV{PAGER} ? $ENV{PAGER} : "more";
\r
265 system "echo \"$usage\" | $pager";
\r
271 display DESC . RESET;
\r
274 Valid commands are:
\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
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
293 Note: ReadLine is supported thus you can edit previous commands.
\r
303 while (!$value or $value eq "") {
\r
304 display_nolf BOLD YELLOW . "$FindBin::Script needs the following parameter - $prompt" . RESET;
\r
317 my ($status, @locks) = Execute "ls $ENV{MNT_DIR}/$ENV{EAST_REL}/DUT/*/desktop.lock 2> /dev/null";
\r
324 if (/.*DUT\/(\w+)\/desktop/) {
\r
327 next if $unit && $unit_found !~ /$unit/i;
\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
336 display BOLD CYAN "$fields[5]\t"
\r
337 . RESET "locked since "
\r
338 . BOLD YELLOW localtime ((stat $_)[9])
\r
347 sub displaySummary () {
\r
348 my $msg = "Summary:";
\r
350 foreach (sort keys %_stats) {
\r
351 $msg .= " $_stats{$_} $_";
\r
354 $_log->msg ($msg) if $_log;
\r
357 sub announceTestrun ($) {
\r
358 my ($testname) = @_;
\r
360 my $user = $ENV{USER} ? $ENV{USER}
\r
361 : $ENV{LOGNAME} ? $ENV{LOGNAME}
\r
363 my $timestamp = YMDHMS;
\r
367 verbose BOLD YELLOW "Test #" . $_testNbr . "\t"
\r
368 . RESET CYAN $testname
\r
369 . RESET " run on $timestamp by "
\r
372 . MAGENTA $_opts{type}
\r
374 . CYAN $_opts{unit}
\r
377 $_log->log ("Test #$_testNbr $testname run on: $timestamp by $user on $_opts{type} unit $_opts{unit}");
\r
378 } # announceTestrun
\r
381 $_term->WriteHistory (HISTORY_FILE) if $_term;
\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
393 my $msg = $_east->connect (
\r
404 $_log->err ("Unable to connect to EAST\n$msg");
\r
405 verbose RED "Skipping renaming test steps" . RESET;
\r
413 my ($status, $msg) = Nethawk::East::validTestType ($_opts{class});
\r
415 if ($status != 0) {
\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
428 $_east->setCollectLogFiles (1);
\r
430 verbose_nolf $_stats{Run} . ": " . CYAN "$_opts{class}\t" . BOLD YELLOW $_opts{test} . RESET;
\r
432 my $testStepResult;
\r
434 my $startTime = time;
\r
435 my $stepName = "Unknown";
\r
437 if ($_opts{test} =~ /(.*)\.profile/) {
\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
446 $_east->setRantvlStartTime (time);
\r
449 my ($stepID, $errMsg) = $_rantestdb->startSteprun ($stepName);
\r
451 ($status, $testStepResult) = $_east->exec (\%_opts, \%_executionResults);
\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
462 my $endTime = time;
\r
464 if ($status == 0) {
\r
465 if ($testStepResult eq "Success") {
\r
466 verbose GREEN " $testStepResult" . RESET;
\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
476 verbose RED " $testStepResult" . RESET;
\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
487 $_stats{Timedout}++;
\r
489 verbose RED " $testStepResult" . RESET;
\r
495 # Log test step result
\r
496 $_log->log ("$_stats{Run}: $_opts{class}\t$_opts{test} $testStepResult");
\r
498 my ($dbErrNbr, $dbErrMsg) = $_rantestdb->endSteprun (
\r
499 runID => $_east->{runID},
\r
501 start => UnixDatetime2SQLDatetime (scalar (localtime ($startTime))),
\r
502 end => UnixDatetime2SQLDatetime (scalar (localtime ($endTime))),
\r
503 result => $testStepResult,
\r
506 error $dbErrMsg if $dbErrNbr != 0;
\r
509 } # executeTestStep
\r
512 error "Test timed out ($_opts{testtimeout}) seconds passed)";
\r
514 $_east->disconnect;
\r
517 $_east->collectLogFiles;
\r
523 display BLUE "\nInterrupted" . RESET;
\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
533 ReadMode ("cbreak");
\r
534 my $answer = ReadKey (0);
\r
535 ReadMode ("normal");
\r
537 if ($answer eq "\n") {
\r
543 $answer = lc $answer;
\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
555 sub interpolate ($) {
\r
558 # Perform psuedo variable interpolation. The following psuedo
\r
559 # variables are supported:
\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
565 # msgdefs: Absolute path to msgdefs
\r
566 my $msgdefs = "$simdev/msgdefs";
\r
568 # validation: Absolute path to validation
\r
569 my $validation = "$simdev/validation";
\r
571 # logpath: Absolute path into the "testlogs" area where
\r
572 # logfiles are written
\r
573 my $logpath = LOGBASE . "/" . $_east->getSaveTo;
\r
575 while ($str =~ /\$/) {
\r
578 if ($str =~ /\$(\w+)/) {
\r
581 } elsif ($str =~ /\$(\[.+?\])\[(.+?)\]/) {
\r
582 # A $[fileset][slice] reference
\r
585 } elsif ($str =~ /\$(\[.+?\])/) {
\r
586 # A $[fileset] reference
\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
601 my @fileset = glob $fileset;
\r
604 if (defined $slice) {
\r
605 $fileset = quotemeta $fileset;
\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
616 $2 = $#fileset if $2 > $#fileset;
\r
619 $list = join ",", @fileset[$1..$2];
\r
622 # Not a slice really but an array reference
\r
623 $list = "$fileset[$slice]";
\r
626 $str =~ s/\$\[$fileset\]\[$slice\]/$list/;
\r
628 $list = join ",", @fileset;
\r
629 $str =~ s/\$\[$fileset\]/$list/;
\r
632 if (defined $slice) {
\r
633 $str =~ s/\$\[$fileset\]\[$slice\]//;
\r
635 $str =~ s/\$\[$fileset\]//;
\r
638 error "Unknown variable ($var) encountered in val line:\n$str", 1;
\r
645 sub runValidation ($$) {
\r
646 my ($cmd, $logfile) = @_;
\r
648 my $origCmd = $cmd;
\r
650 my ($stepID, $errMsg);
\r
652 ($stepID, $errMsg) = $_rantestdb->startSteprun ($origCmd);
\r
654 if ($stepID == 0) {
\r
655 error "Unable to startSteprun\n$errMsg";
\r
659 my $startTime = time;
\r
661 $cmd = interpolate ($cmd);
\r
663 my ($status, @lines) = Execute ("$cmd >> $logfile 2>&1");
\r
667 my $endTime = time;
\r
669 my ($dbErrNbr, $dbErrMsg) = $_rantestdb->endSteprun (
\r
670 runID => $_east->{runID},
\r
672 start => UnixDatetime2SQLDatetime (scalar (localtime ($startTime))),
\r
673 end => UnixDatetime2SQLDatetime (scalar (localtime ($endTime))),
\r
674 result => $status ? "Failure" : "Success",
\r
677 error $dbErrMsg if $dbErrNbr != 0;
\r
679 # Output lines to stdout
\r
681 verbose "$_\n" foreach (ReadFile $logfile);
\r
683 verbose "Unable to read $logfile";
\r
689 verbose BOLD YELLOW . "Test #$_testNbr validation #$_validationNbr \t" . RESET CYAN $origCmd
\r
690 . (($status == 0) ? GREEN " Success" : RED " Failure") . RESET;
\r
692 $_log->log ("Test #$_testNbr validation #$_validationNbr\t$origCmd " . (($status == 0) ? "Success" : "Failure"));
\r
697 sub runValidations (@) {
\r
698 my @validations = @_;
\r
700 my $validationErrs = 0;
\r
702 # Make Validation log directory
\r
703 my $validationDir = LOGBASE . "/" . $_east->getSaveTo . "/Validations";
\r
705 eval { mkpath $validationDir };
\r
707 error "Unable to create Validation directory - $validationDir\n$@", 1 if $@;
\r
709 chmod 0775, $validationDir;
\r
711 my $viewPath = "$ENV{MNT_DIR}/snapshot_views/$_east->{userdir}/$_east->{view}";
\r
712 my $vobPath = "vobs/simdev";
\r
714 foreach (@validations) {
\r
715 my @tokens = split;
\r
716 my $outfile = $tokens[0] . ".log";
\r
718 $validationErrs += runValidation $_, "$validationDir/$outfile";
\r
721 $_stats{Failed} += $validationErrs;
\r
723 return $validationErrs;
\r
726 sub runTestFile ($) {
\r
729 my $testName = fileparse $file, ".test";
\r
731 my $testID = $_rantestdb->startTest ($testName);
\r
733 my %fileopts = GetConfig ($file);
\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
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
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
758 my $testStartTime = time;
\r
760 $_east->setSaveTo ("$testName/$_opts{type}$_opts{unit}/" . YMDHMS ($testStartTime));
\r
762 eval { mkpath LOGBASE . "/" . $_east->getSaveTo };
\r
764 error "Unable to create log directory\n$@", 1 if $@;
\r
766 chmod 0775, LOGBASE . "/" . $_east->getSaveTo;
\r
769 $_log = new Logger (
\r
771 path => LOGBASE . "/" . $_east->getSaveTo,
\r
775 $_log->log ("$FindBin::Script Version " . VERSION_NBR . "\nUsing view: $_opts{eastview}");
\r
778 verbose BOLD CYAN "Using view: " . RESET $_opts{eastview};
\r
780 announceTestrun $testName;
\r
784 my $testFailures = 0;
\r
788 # Set testTimer if specified
\r
789 if ($_opts{testtimeout}) {
\r
790 $SIG{ALRM} = \&testTimeout;
\r
791 alarm $_opts{testtimeout};
\r
794 ($_east->{runID}, $errMsg) = $_rantestdb->startTestrun (UnixDatetime2SQLDatetime localtime $testStartTime);
\r
796 return ($_east->{runID}, $errMsg) if $_east->{runID} == 0;
\r
798 $_validationNbr = 0;
\r
800 if (ref $_opts{exec} eq "ARRAY") {
\r
801 foreach (@{$_opts{exec}}) {
\r
804 $_opts{class} = shift @tokens;
\r
805 $_opts{test} = join " ", @tokens;
\r
809 $result = executeTestStep;
\r
811 if ($result == -1) {
\r
815 $testFailures += $result;
\r
819 if ($_opts{exec}) {
\r
820 @tokens = split /\s+/, $_opts{exec};
\r
822 $_opts{class} = shift @tokens;
\r
823 $_opts{test} = join " ", @tokens;
\r
827 $result = executeTestStep;
\r
829 if ($result == -1) {
\r
832 $testFailures += $result;
\r
837 my $execType = $_opts{rfr} ? "Run for Record"
\r
838 : $_opts{regression} ? "Regression" : "Normal";
\r
840 return 1 if $result == -1;
\r
842 # Disconnect from EAST
\r
843 $_east->disconnect;
\r
845 # Assign 'Failed' and 'Timedout' 0 if they are not initialized
\r
846 $_stats{Failed} ||= 0;
\r
847 $_stats{Timedout} ||= 0;
\r
849 my $testErrors = $_stats{Failed} + $_stats{Timedout};
\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
854 if ($testFailures == 0 and $_opts{val}) {
\r
855 my @validations = ref $_opts{val} eq "ARRAY"
\r
859 $testFailures += runValidations @validations;
\r
863 verbose BOLD YELLOW . "Test #$_testNbr\t" . RESET CYAN $testName
\r
864 . (($testFailures == 0) ? GREEN " Success" : RED " Failure") . RESET;
\r
866 $_log->log ("Test #$_testNbr\t$testName " . (($testFailures == 0) ? "Success" : "Failure"));
\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
884 error $dbErrMsg if $_runID == 0;
\r
886 return $testFailures;
\r
892 return if $ENV{PATH} =~ /$view/;
\r
896 if ($view =~ /(\S+)_SIM/) {
\r
899 error "Unable to find userdir", 1;
\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
908 $ENV{PATH} = join (":", @paths) . ":" . $ENV{PATH};
\r
911 sub runSuiteFile ($) {
\r
914 error "View must be specified when running in suite mode", 1 unless $_opts{eastview};
\r
916 setPath $_opts{eastview};
\r
920 if ($_opts{eastview} =~ /(\S+)_SIM/) {
\r
923 error "Unable to find userdir", 1;
\r
926 unless (open FILE, $file) {
\r
927 error "Unable to open file $file - $!";
\r
931 my @lines = <FILE>;
\r
938 my $suiteStartTime = time;
\r
939 my $suiteFailures = 0;
\r
940 my $suiteName = fileparse ($file, ".suite");
\r
942 $_log = new Logger (
\r
943 name => $suiteName,
\r
948 $_log->log ("$FindBin::Script Version " . VERSION_NBR);
\r
950 ($_east->{suiteID}) = $_rantestdb->startSuiterun ($suiteName);
\r
952 verbose BOLD MAGENTA "Suite\t" . RESET GREEN $suiteName . RESET;
\r
954 $_log->log ("Suite\t$suiteName");
\r
960 my @components = split;
\r
963 my $viewPath = "$ENV{MNT_DIR}/snapshot_views/$userdir/$_opts{eastview}/vobs/simdev/test/";
\r
964 my $testFile = "$viewPath/" . shift @components;
\r
966 unless (-e $testFile) {
\r
967 error "Unable to find test file $testFile (Line: $i)";
\r
971 unless (/\.test/) {
\r
972 error "Not a .test file: $testFile (Line: $i)";
\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
979 my @savedOptions = @ARGV;
\r
985 my $status = GetOptions (
\r
997 ) || usage "Invalid parameter";
\r
1000 @ARGV = @savedOptions;
\r
1002 # Restore the original command line options:
\r
1003 %_opts = %_cmdline_opts;
\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
1012 $suiteFailures += runTestFile $testFile;
\r
1014 # Need to disconnect $_east to shut down the previous run
\r
1015 my $savedSuiteID = $_east->{suiteID};
\r
1017 $_east->disconnect;
\r
1019 # Collect logfiles
\r
1020 $_east->collectLogFiles;
\r
1022 if ($suiteFailures == 0 and $_opts{val}) {
\r
1023 my @validations = ref $_opts{val} eq "ARRAY"
\r
1027 $suiteFailures += runValidations @validations;
\r
1030 $_east = new Nethawk::East;
\r
1032 $_east->{suiteID} = $savedSuiteID;
\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
1041 $_log->log ("Suite\t$suiteName" . ($suiteFailures == 0) ? "Success" : "Failure");
\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
1051 error $errMsg if $_east->{suiteID} != 0;
\r
1053 return $suiteFailures;
\r
1059 unless (-e $file) {
\r
1060 error "File $file does not exist";
\r
1064 $_term->AddHistory ("source $file")
\r
1065 unless $_debugging or !-t STDIN;
\r
1067 $SIG{INT} = \&interrupted;
\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
1075 error "File $file is not a .suite or .test file", 1;
\r
1080 $SIG{QUIT} = \&saveHistory;
\r
1082 # Set a more friendly umask
\r
1087 verbose => sub { set_verbose },
\r
1088 debug => sub { set_debug },
\r
1089 usage => sub { usage; exit 0 },
\r
1100 "checkin_on_error",
\r
1104 ) || usage "Invalid parameter";
\r
1106 # Special case elock command
\r
1107 if (scalar @ARGV > 0 and $ARGV[0] =~ /elock/i) {
\r
1112 usage "Extraneous parameters: " . join " ", @ARGV if scalar @ARGV > 0;
\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
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
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
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
1132 usage "<eastview> and <view> are mutually exclusive$suffix" if $_opts{view};
\r
1135 usage "-rfr and -regression are mutually exclusive" if $_opts{rfr} && $_opts{regression};
\r
1137 # Make "view" an alias for "eastview" but only if there is no eastview
\r
1139 $_opts{eastview} = delete $_opts{view} if $_opts{view} && !$_opts{eastview};
\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
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
1165 %_cmdline_opts = %_opts;
\r
1167 set_verbose if $_opts{rfr};
\r
1169 # Instantiate a new East object
\r
1170 $_east = new Nethawk::East;
\r
1172 # Set testcase ID into East object
\r
1173 $_east->setTestCaseID ($_opts{rfr});
\r
1175 $_debugging = get_debug;
\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
1181 unless ($_debugging or !-t STDIN) {
\r
1182 $_term = new Term::ReadLine $FindBin::Script;
\r
1184 $_term->{AUTORESET} = 1;
\r
1186 # Restore previous history, if any
\r
1187 $_term->ReadHistory (HISTORY_FILE);
\r
1190 # Announce ourselves
\r
1191 verbose DESC . RESET;
\r
1193 # Open Rantest Database
\r
1194 $_rantestdb = new RantestDB ("pswit", "!qaz2w3e");
\r
1196 if ($_opts{test}) {
\r
1197 $SIG{INT} = \&interrupted;
\r
1201 # Separate off options
\r
1202 my $testName = $_opts{test};
\r
1204 if ($_opts{test} =~ /(\S+)\s+\-.*$/) {
\r
1208 $testName = fileparse ($testName, "\.profile");
\r
1210 $_east->setSaveTo ("$testName/$_opts{type}$_opts{unit}/" . YMDHMS);
\r
1212 eval { mkpath LOGBASE . "/" . $_east->getSaveTo };
\r
1214 return (1, $@) if $@;
\r
1216 chmod 0775, LOGBASE . "/" . $_east->getSaveTo;
\r
1218 $_log = new Logger (
\r
1219 name => $testName,
\r
1220 path => LOGBASE . "/" . $_east->getSaveTo,
\r
1224 $_log->log ("$FindBin::Script Version " . VERSION_NBR . "\nUsing view: $_opts{eastview}");
\r
1228 $_term->AddHistory ("$_opts{class} $_opts{test}") unless $_debugging && -t STDIN;
\r
1230 # Disconnect from EAST
\r
1231 $_east->disconnect;
\r
1233 # Collect logfiles
\r
1234 $_east->collectLogFiles;
\r
1235 } elsif ($_opts{file}) {
\r
1236 runFile $_opts{file};
\r
1238 $_east->setSaveTo ("rantest/" . YMDHMS);
\r
1240 eval { mkpath LOGBASE . "/" . $_east->getSaveTo };
\r
1242 return (1, $@) if $@;
\r
1244 chmod 0777, LOGBASE . "/" . $_east->getSaveTo;
\r
1246 $_log = new Logger (
\r
1247 path => LOGBASE . "/" . $_east->getSaveTo,
\r
1251 display DESC if !get_verbose;
\r
1253 if ($_opts{eastview}) {
\r
1254 $_log->log ("$FindBin::Script Version " . VERSION_NBR . "\nUsing view: $_opts{eastview}");
\r
1256 $_log->log ("$FindBin::Script Version " . VERSION_NBR);
\r
1264 unless ($_debugging) {
\r
1265 $cmd = $_term->readline (PROMPT . RESET);
\r
1267 display_nolf PROMPT . RESET;
\r
1272 # Handle Control-d
\r
1273 unless (defined $cmd) {
\r
1281 next if $cmd eq "";
\r
1283 if ($cmd =~ /exit|quit/i) {
\r
1284 $_term->remove_history ($_term->where_history);
\r
1289 if ($cmd =~ /^elock/i) {
\r
1290 if ($cmd =~ /^elock\s+(\w+)/i) {
\r
1299 my @tokens = split /\s+/, $cmd;
\r
1301 $_opts{class} = shift @tokens;
\r
1302 $_opts{test} = join " ", @tokens;
\r
1304 $cmd = lc $_opts{class};
\r
1306 if ($cmd eq "help") {
\r
1308 $_term->remove_history ($_term->where_history) unless $_debugging;
\r
1310 } elsif ($cmd eq "usage") {
\r
1312 $_term->remove_history ($_term->where_history) unless $_debugging;
\r
1314 } elsif ($cmd eq "version") {
\r
1316 $_term->remove_history ($_term->where_history) unless $_debugging;
\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
1325 # Remove quotes, if any. Note no check for balancing.
\r
1326 $value =~ s/[\"\']//g;
\r
1329 $_opts{$optionName} = $value;
\r
1331 } elsif ($cmd eq "get") {
\r
1332 if ($_opts{$tokens[0]}) {
\r
1333 display "$tokens[0] = $_opts{$tokens[0]}";
\r
1335 display "$tokens[0] is not set";
\r
1339 $_opts{class} = lc $_opts{class};
\r
1341 if ( $_opts{class} eq "manual" ) {
\r
1342 $_opts{test} = " ";
\r
1349 # Disconnect from EAST
\r
1350 $_east->disconnect;
\r
1352 # Assign 'Failed' and 'Timedout' 0 if they are not initialized
\r
1353 $_stats{Failed} ||= 0;
\r
1354 $_stats{Timedout} ||= 0;
\r
1356 my $testErrors = $_stats{Failed} + $_stats{Timedout};
\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
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
1373 # Now exit with the correct status
\r
1374 exit ($_stats{Failed} + $_stats{Timedout});
\r