mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-09-26 01:34:05 +00:00
b91795a8f4
Thirteen test files this branch adds call BAIL_OUT at fifty-one places: an extraction that stopped matching, a fixture that is not there, a harness that wrote no log. prove stops every remaining file on a bail-out, not only the file that called it, so one of them hides the results of every test that would have run after it. die is just as loud and costs only its own file. Fifteen comments the branch added also carried the incident rather than the constraint. Three pasted an error transcript, five traced a failure from a macro or a missing file out to a node that never boots, and the rest counted call sites, package sizes or dracut build numbers. Each now states the one fact the reader cannot re-derive from the code. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2218 lines
82 KiB
Perl
Executable File
2218 lines
82 KiB
Perl
Executable File
#!/usr/bin/env perl
|
|
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
|
|
use strict;
|
|
use warnings;
|
|
use Getopt::Long;
|
|
use Data::Dumper;
|
|
use Term::ANSIColor;
|
|
use Time::Local;
|
|
use File::Basename;
|
|
use File::Path;
|
|
|
|
BEGIN
|
|
{
|
|
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr';
|
|
}
|
|
use lib "$::XCATROOT/lib/perl";
|
|
|
|
#--------------global attributes----------------
|
|
my $program_path = dirname(File::Spec->rel2abs(__FILE__));
|
|
my $program_name = basename($0);
|
|
|
|
my $rootdir = "$program_path/../share/xcat/tools/autotest";
|
|
my $casedir = "$rootdir/testcase/";
|
|
$casedir = $ENV{'XCATTEST_CASEDIR'} if exists $ENV{'XCATTEST_CASEDIR'};
|
|
my $bundledir = "$rootdir/bundle/";
|
|
my $resultdir = "$rootdir/result/";
|
|
my $rst = 0;
|
|
my $setup_env_by_config_file = 1;
|
|
my $stop_to_keep_env = 0;
|
|
|
|
#Array to save all cases planed to handle
|
|
#these cases can be passed by option -b/-t/-c
|
|
#if without value passed by option -b/-t/-c, for "show information" function,
|
|
#the search scope is the all cases shipped by xcat_test package
|
|
my @cases_to_be_run = ();
|
|
|
|
#A hash to save the contect of config file
|
|
#The structure of %config
|
|
#config{object}{type}{name}{attr}
|
|
#config{table}{name}{entry}{key}
|
|
#config{script_prev}->[]
|
|
#config{script_post}->[]
|
|
#config{var}{varname}
|
|
my %config = ();
|
|
|
|
#Array of hash, to save the information of case
|
|
my @cases = ();
|
|
my %case_name_index_map;
|
|
|
|
#when loading cases, NORUN means just load case without attribute replacement.
|
|
#this is used for "show information" function
|
|
my $NORUN = 0;
|
|
my $RUN = 1;
|
|
|
|
#----------global logs attributes---------------
|
|
my $running_log_fd = undef;
|
|
my $running_log_name = undef;
|
|
my $failed_log_name = undef;
|
|
my $performance_log_name = undef;
|
|
my $xcatdebug = 0;
|
|
$xcatdebug = 1 if exists $ENV{'XCATTEST_DEBUG'};
|
|
|
|
#--------------command line attrbutes--------------
|
|
my $needhelp = 0;
|
|
my $configfile = undef;
|
|
my $bundlelist = undef;
|
|
my $caselist = undef;
|
|
my $cmdlist = undef;
|
|
my $list = undef;
|
|
my $restore = 0;
|
|
my $quiet = 0;
|
|
my $search_expression = undef;
|
|
|
|
my @total_label_set=();
|
|
my %case_label_map;
|
|
my @label_order = (["xcat_install"],
|
|
["mn_only"],
|
|
[ "sn_diskful", "sn_diskless" ],
|
|
[ "flat_cn_diskful", "flat_cn_diskless", "hierarchy_cn_diskful", "hierarchy_cn_diskless" ],
|
|
[ "cn_bmc_ready", "cn_os_ready" ],
|
|
["others"]);
|
|
|
|
#-------------usage--------------------
|
|
$::USAGE = "Usage:
|
|
To get help:
|
|
$program_name -h
|
|
|
|
To list the information about all cases shipped by xcat test package
|
|
$program_name -l {caselist|caseinfo|casenum}
|
|
To list the information about all bunldes shipped by xcat test package
|
|
$program_name -l bundleinfo
|
|
To list the information about label
|
|
$program_name -l labelinfo
|
|
To list the information about cases in specific bundles
|
|
$program_name -l {caselist|caseinfo|casenum} -b <bundle_list>
|
|
To list the information about cases related to specific commands
|
|
$program_name -l {caselist|caseinfo|casenum} -c <command_list>
|
|
To list the information about specific cases
|
|
$program_name -l {caselist|caseinfo|casenum} -t <case_list>
|
|
|
|
To list cases information that satisfy specific filter expression
|
|
$program_name -l {caselist|caseinfo|casenum} -s \"filter_expression\"
|
|
For short, show the cases list can use below command
|
|
$program_name -l -s \"filter_expression\"
|
|
To list information about cases in specific bundles and satisfy specific filter expression at same time
|
|
$program_name -l {caselist|caseinfo|casenum} -b <bundle_list> -s \"filter_expression\"
|
|
|
|
To run test cases in specific bundles
|
|
$program_name [-f {configure_file|configure_file:System}] -b <bundle_list> [-r] [-q]
|
|
To run specific test cases
|
|
$program_name [-f {configure_file|configure_file:System}] -t <case_list> [-r] [-q]
|
|
To run all cases related to specific commands
|
|
$program_name [-f {configure_file|configure_file:System}] -c <command_list> [-r] [-q]
|
|
To run test cases that satisfy specific filter expression
|
|
$program_name -s \"filter_expression\"
|
|
|
|
Options:
|
|
-h : Get $program_name usage information.
|
|
-l : list specific information. The valid options are caselist,caseinfo,casenum,bundleinfo. For list case information, caselist is default value.
|
|
-f : specify the configuration file. If 'System' tag is used, only [System] section in the configuration file will be used. If 'System' is not used all other sections of the configuration file will be used, like [Table], [Object], etc.
|
|
-c : Comma separated list of command names to test.
|
|
-t : Comma separated list of test case names to test.
|
|
-b : Comma separated list of bundle names to test. If a bundle name is specified without an absolute path, such like /<path/xxx.bundle, or ./xxx.bundle, bundles under $bundledir will be searched by default.
|
|
-r : Back up the original environment settings before running test, and restore them after running test.
|
|
-q : Just record all the output of $program_name into log file under $resultdir, not print to STDOUT. Print to STDOUT by default.
|
|
-s : Filter case by label. The acceptable value looks like 'label1+label2-label3\|label4\|label5', 'label1+label2-label3' works as sub expression.
|
|
'|' means union filter, it has lower priority, expression1|expression2 means the case either satisfies expression1 or satisfies expression2.
|
|
'+' means the case need have specific label. higher priority.
|
|
'-' means the case does not have specific label. higher priority.
|
|
";
|
|
|
|
#==============================================================================================
|
|
# main process
|
|
#==============================================================================================
|
|
$rst = pro_init();
|
|
if ($rst) {
|
|
print "Program $program_name initialization failed to exit.\n";
|
|
to_exit(1);
|
|
}
|
|
|
|
if (
|
|
!GetOptions("h" => \$needhelp,
|
|
"f=s" => \$configfile,
|
|
"b=s" => \$bundlelist,
|
|
"t=s" => \$caselist,
|
|
"c=s" => \$cmdlist,
|
|
"l:s" => \$list,
|
|
"q" => \$quiet,
|
|
"s=s" => \$search_expression,
|
|
"r" => \$restore)
|
|
)
|
|
{
|
|
log_this($running_log_fd, "$::USAGE");
|
|
to_exit(1);
|
|
}
|
|
|
|
#$list="caselist" unless($list);
|
|
|
|
if ($needhelp) {
|
|
log_this($running_log_fd, "$::USAGE");
|
|
to_exit(0);
|
|
}
|
|
|
|
my $error;
|
|
$rst = check_option_validity(\$error);
|
|
if ($rst) {
|
|
log_this($running_log_fd, "$error", "$::USAGE");
|
|
to_exit(1);
|
|
}
|
|
|
|
if($search_expression){
|
|
$rst = scan_existed_labels(\%case_label_map, \@total_label_set, \$error);
|
|
if($rst) {
|
|
log_this($running_log_fd, "$error");
|
|
to_exit(1);
|
|
}
|
|
if($xcatdebug){
|
|
print "------The total labels are:---------\n";
|
|
print Dumper \@total_label_set;
|
|
print "------The case and its labels:-------\n";
|
|
print Dumper \%case_label_map;
|
|
}
|
|
}
|
|
|
|
$rst = calculate_cases_to_be_run(\@cases_to_be_run, \$error);
|
|
if ($rst) {
|
|
log_this($running_log_fd, "$error");
|
|
to_exit(1);
|
|
}
|
|
|
|
if ($xcatdebug) {
|
|
print "----case to be run-----------------\n";
|
|
print Dumper \@cases_to_be_run;
|
|
}
|
|
|
|
if (defined $list) {
|
|
|
|
$list="caselist" if ($list eq "");
|
|
|
|
if ($list eq "caselist") {
|
|
if (@cases_to_be_run) {
|
|
|
|
#list the cases indicated by option -b,-c,-t, -s
|
|
foreach (@cases_to_be_run) {
|
|
log_this($running_log_fd, "$_");
|
|
}
|
|
} elsif (!@cases_to_be_run && $search_expression){
|
|
log_this($running_log_fd, "There are no cases match search expression $search_expression");
|
|
} else {
|
|
|
|
#list the cases shipped by xcat test package
|
|
$rst = load_case(\@cases_to_be_run, \@cases, \%case_name_index_map, \$error, $NORUN);
|
|
if ($rst) {
|
|
log_this($running_log_fd, "$error");
|
|
}
|
|
foreach my $case (@cases) {
|
|
log_this($running_log_fd, "$case->{name}");
|
|
}
|
|
}
|
|
} elsif ($list eq "caseinfo") {
|
|
if (!@cases_to_be_run && $search_expression){
|
|
log_this($running_log_fd, "There are no cases match search expression $search_expression");
|
|
} else {
|
|
$rst = show_case_info(\@cases_to_be_run, \$error);
|
|
if ($rst) {
|
|
log_this($running_log_fd, "$error");
|
|
to_exit(1);
|
|
}
|
|
}
|
|
} elsif ($list eq "casenum") {
|
|
if (@cases_to_be_run || (!@cases_to_be_run && $search_expression)) {
|
|
|
|
#list the case number indicated by option -b,-c,-t
|
|
my $casenum = @cases_to_be_run;
|
|
log_this($running_log_fd, "$casenum");
|
|
} else {
|
|
|
|
#list the case number shipped by xcat test package
|
|
$rst = load_case(\@cases_to_be_run, \@cases, \%case_name_index_map, \$error, $NORUN);
|
|
if ($rst) {
|
|
log_this($running_log_fd, "$error");
|
|
to_exit(1);
|
|
}
|
|
my $casenum = @cases;
|
|
log_this($running_log_fd, "$casenum");
|
|
}
|
|
} elsif ($list eq "bundleinfo") {
|
|
|
|
#list the bundle information shipped by xcat test package
|
|
$rst = show_bundle_info(\$error);
|
|
if ($rst) {
|
|
log_this($running_log_fd, "$error");
|
|
to_exit(1);
|
|
}
|
|
} elsif ($list eq "labelinfo"){
|
|
$rst = scan_existed_labels(\%case_label_map, \@total_label_set, \$error);
|
|
if($xcatdebug){
|
|
print "------The total labels are:---------\n";
|
|
print Dumper \@total_label_set;
|
|
print "------The case and its labels:-------\n";
|
|
print Dumper \%case_label_map;
|
|
}
|
|
my %label_conut;
|
|
my %case_label_str_map;
|
|
foreach my $case (keys %case_label_map){
|
|
$case_label_str_map{$case} = join (",", @{$case_label_map{$case}{labels}});
|
|
foreach my $label (@{$case_label_map{$case}{labels}}){
|
|
if(!exists $label_conut{$label}){
|
|
$label_conut{$label}=1;
|
|
}else{
|
|
$label_conut{$label}+=1;
|
|
}
|
|
}
|
|
}
|
|
|
|
log_this($running_log_fd, "-------------------------------");
|
|
log_this($running_log_fd, "The labels of cases:");
|
|
log_this($running_log_fd, "-------------------------------");
|
|
print_table(\%case_label_str_map);
|
|
my $label_total_num=@total_label_set;
|
|
log_this($running_log_fd, "\n-------------------------------");
|
|
log_this($running_log_fd, "There are $label_total_num different labels");
|
|
log_this($running_log_fd, "The number of cases of each label:");
|
|
log_this($running_log_fd, "-------------------------------");
|
|
print_table(\%label_conut);
|
|
log_this($running_log_fd, "-------------------------------");
|
|
my $total_case = keys %case_label_map;
|
|
my @cases_without_manual_labels=();
|
|
foreach my $case ( keys %case_label_map){
|
|
if(! exists ($case_label_map{$case}{manual_labels})){
|
|
push @cases_without_manual_labels, $case;
|
|
}
|
|
}
|
|
my $case_without_manual_label_num = @cases_without_manual_labels;
|
|
log_this($running_log_fd, "There are $total_case cases totaly, there are $case_without_manual_label_num cases without manual label.");
|
|
log_this($running_log_fd, "-------------------------------");
|
|
log_this($running_log_fd, "The cases without manual label are:");
|
|
log_this($running_log_fd, "-------------------------------");
|
|
foreach my $case (sort @cases_without_manual_labels){
|
|
print "$case\n";
|
|
}
|
|
}
|
|
|
|
to_exit(0);
|
|
}
|
|
|
|
unless (@cases_to_be_run) {
|
|
log_this($running_log_fd, "There is no case to run, Please indicate case by option -b,-c,-t,-s");
|
|
to_exit(1);
|
|
}
|
|
|
|
if (defined($configfile) && ($configfile =~ /(.*):(System)/)) {
|
|
$configfile = $1;
|
|
$setup_env_by_config_file = 0;
|
|
}
|
|
|
|
log_this($running_log_fd, "xCAT automated test started at " . scalar(localtime()));
|
|
if (defined($configfile)) {
|
|
log_this($running_log_fd, "******************************");
|
|
log_this($running_log_fd, "loading Configure file");
|
|
log_this($running_log_fd, "******************************");
|
|
$rst = load_config_file($configfile, \%config, \$error);
|
|
if ($rst) {
|
|
log_this($running_log_fd, "$error");
|
|
to_exit(1);
|
|
}
|
|
} else {
|
|
$setup_env_by_config_file = 0;
|
|
|
|
# Leverage environment variable to used in test case
|
|
foreach (keys %ENV) {
|
|
if (/^XCATTEST_/) {
|
|
my @envname = split("_", $_, 2);
|
|
$config{var}{ $envname[-1] } = $ENV{$_};
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($restore) {
|
|
log_this($running_log_fd, "******************************");
|
|
log_this($running_log_fd, "Backup current xCAT database");
|
|
log_this($running_log_fd, "******************************");
|
|
$rst = bakup_current_env(\$error);
|
|
if ($rst) {
|
|
log_this($running_log_fd, "$error");
|
|
to_exit(1);
|
|
}
|
|
}
|
|
|
|
if ($setup_env_by_config_file) {
|
|
log_this($running_log_fd, "******************************");
|
|
log_this($running_log_fd, "Initialize xCAT test environment by definition in configure file");
|
|
log_this($running_log_fd, "******************************");
|
|
$rst = setup_env_by_configure_file(\%config, \$error);
|
|
if ($rst) {
|
|
log_this($running_log_fd, "$error");
|
|
to_exit(1);
|
|
}
|
|
}
|
|
|
|
log_this($running_log_fd, "******************************");
|
|
log_this($running_log_fd, "To detect current test environment");
|
|
log_this($running_log_fd, "******************************");
|
|
$rst = detect_current_env(\%config, \$error);
|
|
if ($rst) {
|
|
log_this($running_log_fd, "$error");
|
|
to_exit(1);
|
|
}
|
|
|
|
log_this($running_log_fd, "******************************");
|
|
log_this($running_log_fd, "loading test cases");
|
|
log_this($running_log_fd, "******************************");
|
|
$rst = load_case(\@cases_to_be_run, \@cases, \%case_name_index_map, \$error, $RUN);
|
|
if ($rst && $rst < 2) {
|
|
log_this($running_log_fd, "$error");
|
|
to_exit(1);
|
|
}
|
|
|
|
if ($xcatdebug) {
|
|
print "=====Dumper loaded cases=======\n";
|
|
print Dumper \@cases;
|
|
print "=====Dumper case_name_index_map=======================\n";
|
|
print Dumper \%case_name_index_map;
|
|
print "=====Dumper cases to be run=====\n";
|
|
print Dumper \@cases_to_be_run;
|
|
}
|
|
|
|
unless (@cases_to_be_run) {
|
|
to_exit(1);
|
|
}
|
|
|
|
log_this($running_log_fd, "******************************");
|
|
log_this($running_log_fd, "Start to run test cases");
|
|
log_this($running_log_fd, "******************************");
|
|
$rst = run_case(\@cases_to_be_run, \@cases, \%case_name_index_map, \$error);
|
|
if ($rst) {
|
|
log_this($running_log_fd, "$error");
|
|
to_exit(1);
|
|
}
|
|
|
|
if ($restore) {
|
|
log_this($running_log_fd, "******************************");
|
|
log_this($running_log_fd, "restore xCAT test evironment");
|
|
log_this($running_log_fd, "******************************");
|
|
$rst = restore_current_env(\$error);
|
|
if ($rst) {
|
|
log_this($running_log_fd, "$error");
|
|
to_exit(1);
|
|
}
|
|
}
|
|
|
|
log_this($running_log_fd, "xCAT automated test finished at " . scalar(localtime()));
|
|
log_this($running_log_fd, "Please check results in the $resultdir, \nand see $failed_log_name file for failed cases.");
|
|
|
|
#To generate performance report
|
|
$rst = generate_performance_report($running_log_name, $performance_log_name, \$error);
|
|
if ($rst) {
|
|
log_this($running_log_fd, "$error");
|
|
to_exit(1);
|
|
}
|
|
log_this($running_log_fd, "see $performance_log_name file for time consumption");
|
|
|
|
if ($stop_to_keep_env) {
|
|
to_exit(1);
|
|
} else {
|
|
to_exit(0);
|
|
}
|
|
|
|
|
|
#==============================================================================================
|
|
# sub function implementation
|
|
#==============================================================================================
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: log_this
|
|
# Description: print message to log file and STDOUT.
|
|
# Set '-q' option in command line, just print message to log file
|
|
# Atrributes: $logdf: the file description of openning log file
|
|
# Return code: 0 Success 1 Failed
|
|
#--------------------------------------------------------
|
|
sub log_this {
|
|
my $logdf = shift;
|
|
my $msg = join("\n", @_);
|
|
|
|
#print message to STDOUT
|
|
if (!$quiet) {
|
|
if ($msg =~ /\[Pass\]/) {
|
|
print color("green"), "$msg\n", color("reset");
|
|
} elsif ($msg =~ /\[Failed\]/) {
|
|
print color("red"), "$msg\n", color("reset");
|
|
} else {
|
|
print "$msg\n";
|
|
}
|
|
}
|
|
|
|
#record message to log file
|
|
print $logdf "$msg\n";
|
|
|
|
return 0;
|
|
}
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: pro_init
|
|
# Description: Do program initialization
|
|
# Atrributes:
|
|
# Return code: 0 Success 1 Failed
|
|
#--------------------------------------------------------
|
|
sub pro_init {
|
|
mkpath("$resultdir") unless (-d "$resultdir");
|
|
|
|
my $timestamp = `date +"%Y%m%d%H%M%S"`;
|
|
chomp($timestamp);
|
|
$running_log_name = "$resultdir/xcattest.log.$timestamp";
|
|
if (!open($running_log_fd, ">$running_log_name")) {
|
|
print "Failed to generate running log file for $program_name: $!\n";
|
|
return 1;
|
|
}
|
|
|
|
$failed_log_name = "$resultdir/failedcases.$timestamp";
|
|
$performance_log_name = "$resultdir/performance.report.$timestamp";
|
|
return 0;
|
|
}
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: calculate_cases_to_be_run
|
|
# Description: calculate the case scope to be handle depending on option -b,-c,-t
|
|
# Atrributes:
|
|
# $cases_to_be_run_ref (output attribe)
|
|
# The reference of array to save the cases to be handled
|
|
# $error_ref (output attribe)
|
|
# The reference of scalar to save the error message generated during running current function
|
|
# Return code: 0 Success 1 Failed
|
|
#-------------------------------------------------------
|
|
sub calculate_cases_to_be_run {
|
|
my $cases_to_be_run_ref = shift;
|
|
my $error_ref = shift;
|
|
|
|
my $fd = undef;
|
|
my @cases = ();
|
|
|
|
$$error_ref = "";
|
|
if ($bundlelist) {
|
|
my @bundles = split(",", $bundlelist);
|
|
foreach my $bundle (@bundles) {
|
|
|
|
#if $bundle doesn't include path information, find $bundle under $bundledir by default
|
|
if ($bundle !~ /\//) {
|
|
$bundle = "$bundledir/$bundle";
|
|
}
|
|
if (!-e "$bundle") {
|
|
$$error_ref = "There isn't file $bundle\n";
|
|
last;
|
|
}
|
|
if (!open($fd, "$bundle")) {
|
|
$$error_ref = "Can't open file $bundle:$!\n";
|
|
last;
|
|
}
|
|
while (my $line = <$fd>) {
|
|
chomp($line);
|
|
$line =~ s/#.+//g if ($line =~ "#" && $line !~ "^#INCLUDE");
|
|
$line =~ s/^\s+|\s+$//g;
|
|
next if ((length($line) == 0) || ($line =~ /^description\s*:\s*(.*)/));
|
|
push(@cases, $line);
|
|
}
|
|
close($fd);
|
|
}
|
|
|
|
return 1 if (length($$error_ref) != 0);
|
|
|
|
#to handle "#INCLUDE:XXXXXXX#" line
|
|
my $casetxt = join(',', @cases);
|
|
for (; ;) {
|
|
if ($casetxt =~ /#INCLUDE:[^#^\n]+#/) {
|
|
$casetxt =~ s/#INCLUDE:([^#^\n]+)#/expend_include_file($1)/eg;
|
|
} else {
|
|
last;
|
|
}
|
|
}
|
|
@cases = split(",", $casetxt);
|
|
|
|
my @error = grep /INCLUDEBAD/, @cases;
|
|
if (@error) {
|
|
$$error_ref = join("\n", @error);
|
|
return 1;
|
|
}
|
|
@{$cases_to_be_run_ref} = @cases;
|
|
} elsif ($caselist) {
|
|
@cases_to_be_run = split(",", $caselist);
|
|
} elsif ($cmdlist) {
|
|
my @cmds = split /,/, $cmdlist;
|
|
my @files = ();
|
|
my @cmdfiles = ();
|
|
get_files_recursive("$casedir", \@files);
|
|
for (my $countfile = 0 ; $countfile < @files ; $countfile++) {
|
|
for (my $countcmd = 0 ; $countcmd < @cmds ; $countcmd++) {
|
|
if ($files[$countfile] =~ m/\/$cmds[$countcmd]\/case/) {
|
|
push(@cmdfiles, glob("$files[$countfile]"));
|
|
}
|
|
}
|
|
}
|
|
|
|
my $fd = undef;
|
|
foreach my $file (@cmdfiles) {
|
|
if (!open($fd, "<$file")) {
|
|
$$error_ref = "can't open $file:$!";
|
|
return 1;
|
|
}
|
|
while (my $line = <$fd>) {
|
|
$line =~ s/^\s+|#[^!].+|\s+$//g;
|
|
|
|
#skip blank and comment lines
|
|
next if (length($line) == 0 || ($line =~ /^\s*#/));
|
|
if ($line =~ /^start\s*:\s*(.*)/) {
|
|
push @{$cases_to_be_run_ref}, $1;
|
|
}
|
|
}
|
|
close($fd);
|
|
}
|
|
}
|
|
|
|
|
|
if($search_expression){
|
|
my @rest_cases_to_be_run=();
|
|
$rst = filter_case_by_label($cases_to_be_run_ref,\%case_label_map,\@rest_cases_to_be_run, $error_ref);
|
|
if ($rst) {
|
|
return 1;
|
|
}
|
|
|
|
@$cases_to_be_run_ref=@rest_cases_to_be_run;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: expend_include_file
|
|
# Description: To support '#INCLUDE" label in bundle file, to expend the include file
|
|
# Atrributes: $bundle (input attribute): the name of bundle
|
|
# Return code: 0 Success 1 Failed
|
|
#--------------------------------------------------------
|
|
sub expend_include_file {
|
|
my $bundle = shift;
|
|
|
|
my $fd = undef;
|
|
my $bundlepath = dirname($bundle);
|
|
my @cases = ();
|
|
|
|
if ($bundlepath eq ".") {
|
|
$bundle = "$bundledir/$bundle";
|
|
}
|
|
if (!-e "$bundle") {
|
|
return "#INCLUDEBAD:cannot find $bundle#";
|
|
}
|
|
if (!open($fd, "<$bundle")) {
|
|
return "#INCLUDEBAD:cannot open $bundle $!#";
|
|
}
|
|
while (my $line = <$fd>) {
|
|
chomp($line);
|
|
$line =~ s/#.+//g if ($line =~ "#" && $line !~ "^#INCLUDE");
|
|
$line =~ s/^\s+|\s+$//g;
|
|
next if ((length($line) == 0) || ($line =~ /^description\s*:\s*(.*)/));
|
|
push(@cases, $line);
|
|
}
|
|
close($fd);
|
|
return join(",", @cases);
|
|
}
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: to_exit
|
|
# Description: customize exit function, include clean up environment
|
|
# Atrributes:
|
|
# Return code:
|
|
#--------------------------------------------------------
|
|
sub to_exit {
|
|
my $exit_code = shift;
|
|
close($running_log_fd) if (defined $running_log_fd);
|
|
&runcmd("rm -rf /tmp/xCATdbbackup") if (-d "/tmp/xCATdbbackup");
|
|
exit $exit_code;
|
|
}
|
|
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: check_option_validity
|
|
# Description: check the validity of command line
|
|
# Atrributes:
|
|
# $error_ref (output attribe)
|
|
# The reference of scalar to save the error message generated during running current function
|
|
# Return code: 0 Success 1 Failed
|
|
#--------------------------------------------------------
|
|
sub check_option_validity {
|
|
my $error_ref = shift;
|
|
|
|
if ($list) {
|
|
my @vaild_list_method = ();
|
|
if ($bundlelist || $caselist || $cmdlist || $search_expression) {
|
|
@vaild_list_method = ("caselist", "caseinfo", "casenum");
|
|
} else {
|
|
@vaild_list_method = ("caselist", "caseinfo", "casenum", "bundleinfo", "labelinfo");
|
|
}
|
|
if (!(grep { /^$list$/ } @vaild_list_method)) {
|
|
$$error_ref = "Unsupport list method for option l";
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: show_case_info
|
|
# Description: to show case name and description
|
|
# Atrributes:
|
|
# $cases_to_be_run_ref (input attribe)
|
|
# The reference of array to save the cases to be handled
|
|
# $error_ref (output attribe)
|
|
# The reference of scalar to save the error message generated during running current function
|
|
# Return code: 0 Success 1 Failed
|
|
#--------------------------------------------------------
|
|
sub show_case_info {
|
|
my $cases_to_be_run_ref = shift;
|
|
my $error_ref = shift;
|
|
|
|
my @cases = ();
|
|
my %case_name_index_map;
|
|
my $rst = load_case($cases_to_be_run_ref, \@cases, \%case_name_index_map, $error_ref, $NORUN);
|
|
if ($rst) {
|
|
return 1;
|
|
}
|
|
|
|
#print Dumper \@cases;
|
|
my %caseinfo;
|
|
my $case_num = @{$cases_to_be_run_ref};
|
|
if ($case_num) {
|
|
foreach my $case (@{$cases_to_be_run_ref}) {
|
|
my $casedes = "without description";
|
|
$casedes = $cases[ $case_name_index_map{$case} ]->{description} if ($cases[ $case_name_index_map{$case} ]->{description});
|
|
$caseinfo{$case} = $casedes;
|
|
}
|
|
} else {
|
|
foreach my $case (@cases) {
|
|
my $casedes = "without description";
|
|
$casedes = $case->{description} if ($case->{description});
|
|
$caseinfo{ $case->{name} } = $casedes;
|
|
}
|
|
}
|
|
print_table(\%caseinfo);
|
|
return 0;
|
|
}
|
|
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: show_bundle_info
|
|
# Description: show bundle name and description
|
|
# Atrributes:
|
|
# $error_ref (output attribe)
|
|
# The reference of scalar to save the error message generated during running current function
|
|
# Return code: 0 Success 1 Failed
|
|
#--------------------------------------------------------
|
|
sub show_bundle_info {
|
|
my $error_ref = shift;
|
|
|
|
my %bundleinfo;
|
|
my $dd = undef;
|
|
my @bundlefiles = ();
|
|
if (!opendir(DIR, $bundledir)) {
|
|
$$error_ref = "Can't open directory $bundledir: $!";
|
|
return 1;
|
|
}
|
|
my @files = readdir(DIR);
|
|
foreach my $file (@files) {
|
|
next if (-d $file);
|
|
next if ($file =~ /^\./);
|
|
push(@bundlefiles, $file);
|
|
}
|
|
closedir(DIR);
|
|
|
|
foreach my $bundlefile (@bundlefiles) {
|
|
$bundleinfo{$bundlefile} = "without description";
|
|
}
|
|
my $fd = undef;
|
|
foreach my $bundlefile (@bundlefiles) {
|
|
if (!open($fd, "< $bundledir$bundlefile")) {
|
|
$$error_ref = "Can't open bundle file $bundledir$bundlefile $!";
|
|
return 1;
|
|
}
|
|
while (my $line = <$fd>) {
|
|
$line =~ s/^\s+|#.+|\s+$//g;
|
|
if ($line =~ /^description\s*:\s*(.*)/) {
|
|
$bundleinfo{$bundlefile} = $1;
|
|
last;
|
|
}
|
|
}
|
|
close($fd);
|
|
}
|
|
|
|
print_table(\%bundleinfo);
|
|
return 0;
|
|
}
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: load_config_file
|
|
# Description: load config file indicated by option -f
|
|
# Atrributes:
|
|
# $configfile (input attribute)
|
|
# The config file name
|
|
# $config_ref (output attribute)
|
|
# The reference of a hash to save the contect of config file
|
|
# The hash %config is a global attribute.
|
|
# The structure of %config:
|
|
# config{object}{type}{name}{attr}
|
|
# config{table}{name}{entry}{key}
|
|
# config{script_prev}->[]
|
|
# config{script_post}->[]
|
|
# config{var}{varname}
|
|
# $error_ref (output attribe)
|
|
# The reference of scalar to save the error message generated during running current function
|
|
# Return code: 0 Success 1 Failed
|
|
#--------------------------------------------------------
|
|
sub load_config_file {
|
|
my $configfile = shift;
|
|
my $config_ref = shift;
|
|
my $error_ref = shift;
|
|
|
|
my $type = undef;
|
|
my $sub_type = undef;
|
|
my $name = undef;
|
|
my $attr = undef;
|
|
my $value = undef;
|
|
my $c = 0;
|
|
my $cmd = undef;
|
|
my $mgt_name = undef;
|
|
my $fd = undef;
|
|
|
|
if (!open($fd, "$configfile")) {
|
|
$$error_ref = "Error: can't open xCAT config file $configfile: $!";
|
|
return 1;
|
|
}
|
|
|
|
while (my $line = <$fd>) {
|
|
$line =~ s/^\s+|#.+|\s+$//g;
|
|
next if (length($line) == 0);
|
|
|
|
#Table name can not contain "_"
|
|
if ($line =~ /\[\s*(\w+)\_(\w+)\s*\]/) {
|
|
$type = $1;
|
|
$sub_type = $2;
|
|
$name = undef;
|
|
$c = 0;
|
|
} elsif ($line =~ /\[\s*System|Custom\s*\]/) {
|
|
$type = "Varible";
|
|
} elsif ($type eq "Table") {
|
|
##TABLE BLOCK##
|
|
if ($line =~ /(\w+)\s*=\s*([\w\.\-]+)/) {
|
|
$attr = $1;
|
|
$value = $2;
|
|
if ($name && ($$config_ref{table}{$sub_type}{$name}{__KEY__} ne $attr)) {
|
|
$$config_ref{table}{$sub_type}{$name}{$attr} = $value;
|
|
} else {
|
|
$name = $value;
|
|
$$config_ref{table}{$sub_type}{$name}{__KEY__} = $attr;
|
|
}
|
|
}
|
|
} elsif ($type eq "Object") {
|
|
##OBJECT BLOCK##
|
|
if ($line =~ /(\w+)\s*=\s*([:,\w\.\-\/]+)/) {
|
|
$attr = $1;
|
|
$value = $2;
|
|
if ($attr eq "Name") {
|
|
$name = $value;
|
|
} elsif (!defined($name)) {
|
|
$$error = "Please give name for Object section";
|
|
close($fd);
|
|
return 1;
|
|
} else {
|
|
$$config_ref{object}{$sub_type}{$name}{$attr} = $value;
|
|
}
|
|
}
|
|
} elsif ($type eq "Script") {
|
|
##SCRIPT_BLOCK##
|
|
if ($sub_type eq "Prev") {
|
|
$$config_ref{script_prev}->[$c] = $line;
|
|
$c = $c + 1;
|
|
}
|
|
elsif ($sub_type eq "Post") {
|
|
$$config_ref{script_post}->[$c] = $line;
|
|
$c = $c + 1;
|
|
}
|
|
} elsif ($type eq "Varible") {
|
|
##NODE_BLOCK##
|
|
if ($line =~ /(\w+)\s*=\s*([\w\.\-\+\ \/:]+)/) {
|
|
$$config_ref{var}{$1} = $2;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (exists $$config_ref{object}) {
|
|
foreach my $type (keys %{ $$config_ref{object} }) {
|
|
foreach my $name (keys %{ $$config_ref{object}{$type} }) {
|
|
log_this($running_log_fd, "OBJECT:$name,TYPE:$type");
|
|
foreach my $attr (keys %{ $$config_ref{object}{$type}{$name} }) {
|
|
log_this($running_log_fd, " $attr = $$config_ref{object}{$type}{$name}{$attr};");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (exists $$config_ref{table}) {
|
|
foreach my $type (keys %{ $$config_ref{table} }) {
|
|
log_this($running_log_fd, "TABLE:$type");
|
|
foreach my $name (keys %{ $$config_ref{table}{$type} }) {
|
|
log_this($running_log_fd, " $$config_ref{table}{$type}{$name}{__KEY__} = $name");
|
|
foreach my $attr (keys %{ $$config_ref{table}{$type}{$name} }) {
|
|
if ($attr ne '__KEY__') {
|
|
log_this($running_log_fd, " $attr = $$config_ref{table}{$type}{$name}{$attr}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (exists $$config_ref{script_prev}) {
|
|
log_this($running_log_fd, "Script_Prev:");
|
|
foreach $cmd (@{ $$config_ref{script_prev} }) {
|
|
log_this($running_log_fd, " $cmd");
|
|
}
|
|
}
|
|
|
|
if (exists $$config_ref{script_post}) {
|
|
log_this($running_log_fd, "Script_Post:");
|
|
foreach $cmd (@{ $$config_ref{script_post} }) {
|
|
log_this($running_log_fd, " $cmd");
|
|
}
|
|
}
|
|
|
|
if (exists $$config_ref{var}) {
|
|
log_this($running_log_fd, "Varible:");
|
|
foreach my $varname (keys %{ $$config_ref{var} }) {
|
|
log_this($running_log_fd, " $varname = $$config_ref{var}{$varname}");
|
|
}
|
|
}
|
|
|
|
close($fd);
|
|
return 0;
|
|
}
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: load_case
|
|
# Description: load test case
|
|
# Atrributes:
|
|
# $cases_to_be_run_ref (input attribe)
|
|
# The reference of array to save the cases to be handled
|
|
# $case_ref (input attribe)
|
|
# The reference of a array of hash to save the contect of case
|
|
# The array @cases is a global attribute.
|
|
# The struture of @cases are:
|
|
# $cases[index]->{name}
|
|
# $cases[index]->{os}
|
|
# $cases[index]->{arch}
|
|
# $cases[index]->{hcp}
|
|
# $cases[index]->{type}
|
|
# $cases[index]->{stop}
|
|
# $cases[index]->{description}
|
|
# $cases[index]->{attribute}
|
|
# $cases[index]->{cmd}->[index][index]
|
|
# $cases[index]->{check}->[index][index]
|
|
# $cases[index]->{cmdcheck}->[index][index]
|
|
# $case_name_index_map_ref (input attribute)
|
|
# The reference of a hash to save the mapping of test name ane its index in @cases
|
|
# Due to there maybe is more than one implementation for one case
|
|
# $error_ref (output attribe)
|
|
# The reference of scalar to save the error message generated during running current function
|
|
# $run_case_flag (input attribute)
|
|
# The flag of whether run these case nex.
|
|
# 0 means no, just load case basic information, used by "searching informaiotn funtion of xcattest"
|
|
# 1 means yes, load case basic information and parse the attribure at the sametime. used by "run case funtion of xcattest"
|
|
# Return code: 0 Success 1 Failed
|
|
#--------------------------------------------------------
|
|
sub load_case {
|
|
my $cases_to_be_run_ref = shift;
|
|
my $case_ref = shift;
|
|
my $case_name_index_map_ref = shift;
|
|
my $error_ref = shift;
|
|
my $run_case_flag = shift;
|
|
|
|
#if @{$cases_to_be_run_ref} is empty, that means not indicate test case scope by command line option -b,-t,-c
|
|
#load all cases shipped by xcat test package
|
|
my $load_all_case_flag = 0;
|
|
my $case_num = @{$cases_to_be_run_ref};
|
|
$load_all_case_flag = 1 if ($case_num == 0);
|
|
|
|
@$case_ref = ();
|
|
%$case_name_index_map_ref=();
|
|
my @files = ();
|
|
get_files_recursive("$casedir", \@files);
|
|
|
|
my $line;
|
|
my $i = 0;
|
|
my $j = -1;
|
|
my $z = 0;
|
|
my $m = 0;
|
|
my $newcmdstart = 0;
|
|
my $skip = 0;
|
|
my $fd = undef;
|
|
|
|
my %invalidcases;
|
|
|
|
# invalidoptions saves invalid OS, or ARCH, or HCP
|
|
my %invalidoptions;
|
|
|
|
my %case_name_index_map_bak;
|
|
foreach my $file (@files) {
|
|
if (!open($fd, "<$file")) {
|
|
$$error_ref = "Can't open $file: $!";
|
|
return 1;
|
|
}
|
|
while ($line = <$fd>) {
|
|
if ($newcmdstart) {
|
|
$line =~ s/\s+$//g;
|
|
} else {
|
|
$line =~ s/^\s+|#[^!].+|\s+$//g;
|
|
}
|
|
|
|
#skip blank and comment lines
|
|
next if (length($line) == 0 || ($line =~ /^\s*#/));
|
|
|
|
if ($line =~ /^start\s*:\s*(.*)/) {
|
|
my $name = $1;
|
|
if ($load_all_case_flag) {
|
|
if (is_valid_case_name($name)) {
|
|
$skip = 0;
|
|
$j = -1;
|
|
$case_ref->[$i] = {};
|
|
$case_ref->[$i]->{name} = $name;
|
|
$case_ref->[$i]->{filename} = $file;
|
|
$case_ref->[$i]->{label} = 0;
|
|
$case_ref->[$i]->{label_str} = "";
|
|
if (exists($$case_name_index_map_ref{"$name"})) {
|
|
$case_name_index_map_bak{"$name"} = $$case_name_index_map_ref{"$name"};
|
|
}
|
|
$$case_name_index_map_ref{"$name"} = $i;
|
|
$newcmdstart = 0;
|
|
} else {
|
|
$skip = 1;
|
|
push @{ $invalidcases{"invalidcasename"} }, $name;
|
|
}
|
|
} else {
|
|
if (!(grep { /^$name$/ } @{$cases_to_be_run_ref})) {
|
|
$skip = 1;
|
|
next;
|
|
} else {
|
|
if (is_valid_case_name($name)) {
|
|
$skip = 0;
|
|
$j = -1;
|
|
$case_ref->[$i] = {};
|
|
$case_ref->[$i]->{name} = $name;
|
|
$case_ref->[$i]->{filename} = $file;
|
|
$case_ref->[$i]->{label} = 0;
|
|
$case_ref->[$i]->{label_str} = "";
|
|
if (exists($$case_name_index_map_ref{"$name"})) {
|
|
$case_name_index_map_bak{"$name"} = $$case_name_index_map_ref{"$name"};
|
|
}
|
|
$$case_name_index_map_ref{"$name"} = $i;
|
|
$newcmdstart = 0;
|
|
if (grep (/$case_ref->[$i]->{name}/, @{ $invalidcases{"noruncases"} })) {
|
|
delete_item_from_array($case_ref->[$i]->{name}, $invalidcases{"noruncases"});
|
|
}
|
|
} else {
|
|
$skip = 1;
|
|
push @{ $invalidcases{"invalidcasename"} }, $name;
|
|
}
|
|
}
|
|
}
|
|
} elsif ($line =~ /^os\s*:\s*(\w[\w\, ]+)/) {
|
|
next if $skip;
|
|
$case_ref->[$i]->{os} = $1;
|
|
|
|
if ($run_case_flag) {
|
|
|
|
#To judge whether need to skip the current case
|
|
my @validoslist = split(",", $case_ref->[$i]->{os});
|
|
my @newvalidoslist = ();
|
|
foreach my $validos (@validoslist) {
|
|
if ($validos =~ /linux/i) {
|
|
push(@newvalidoslist, ("rhels", "sles", "ubuntu"));
|
|
} else {
|
|
push(@newvalidoslist, $validos);
|
|
}
|
|
}
|
|
|
|
my $currentos = get_current_os();
|
|
my $valid = 0;
|
|
foreach my $os (@newvalidoslist) {
|
|
if ($currentos =~ /$os/i) {
|
|
$valid = 1;
|
|
if (grep (/$case_ref->[$i]->{name}/, @{ $invalidcases{"noruncases"} })) {
|
|
delete_item_from_array($case_ref->[$i]->{name}, $invalidcases{"noruncases"});
|
|
}
|
|
last;
|
|
}
|
|
}
|
|
unless ($valid) {
|
|
|
|
#$skip = 1;
|
|
if (exists($case_name_index_map_bak{ $case_ref->[$i]->{name} })) {
|
|
$$case_name_index_map_ref{ $case_ref->[$i]->{name} } = $case_name_index_map_bak{ $case_ref->[$i]->{name} };
|
|
} else {
|
|
delete $$case_name_index_map_ref{ $case_ref->[$i]->{name} };
|
|
if (!grep (/$case_ref->[$i]->{name}/, @{ $invalidcases{"noruncases"} })) {
|
|
push @{ $invalidcases{"noruncases"} }, $case_ref->[$i]->{name};
|
|
push @{ $invalidoptions{"invalid-os"} }, "$case_ref->[$i]->{os}";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
$newcmdstart = 0;
|
|
} elsif ($line =~ /^arch\s*:\s*(\w[\w\, ]+)/) {
|
|
next if $skip;
|
|
$case_ref->[$i]->{arch} = $1;
|
|
|
|
if ($run_case_flag) {
|
|
|
|
#To judge whether need to skip the current case
|
|
|
|
my @vaild_archs_tmp = split(",", $case_ref->[$i]->{arch});
|
|
my @vaild_archs=();
|
|
foreach my $arch (@vaild_archs_tmp){
|
|
my $tmp_str="";
|
|
if ($arch =~ /ppc/i && $arch !~ /le|el/i) {
|
|
$tmp_str = "ppc";
|
|
} elsif ($arch =~ /ppc/i && $arch =~ /le|el/i) {
|
|
$tmp_str = "ppc64le";
|
|
} elsif ($arch =~ /x86/i) {
|
|
$tmp_str = "x86";
|
|
}
|
|
push @vaild_archs, $tmp_str;
|
|
}
|
|
|
|
my $env_arch = "";
|
|
if (exists($config{var}{ARCH})) {
|
|
$env_arch = $config{var}{ARCH};
|
|
} else {
|
|
$env_arch = `uname -m`;
|
|
chomp($env_arch);
|
|
}
|
|
if ($env_arch =~ /ppc/i && $env_arch !~ /le|el/i) {
|
|
$env_arch = "ppc";
|
|
} elsif ($env_arch =~ /ppc/i && $env_arch =~ /le|el/i) {
|
|
$env_arch = "ppc64le";
|
|
} elsif ($env_arch =~ /x86/i) {
|
|
$env_arch = "x86";
|
|
}
|
|
|
|
my $valid = 0;
|
|
foreach my $arch (@vaild_archs){
|
|
if ($arch eq $env_arch) {
|
|
$valid = 1;
|
|
if (grep (/$case_ref->[$i]->{name}/, @{ $invalidcases{"noruncases"} })) {
|
|
delete_item_from_array($case_ref->[$i]->{name}, $invalidcases{"noruncases"});
|
|
}
|
|
last;
|
|
}
|
|
}
|
|
unless ($valid) {
|
|
if (exists($case_name_index_map_bak{ $case_ref->[$i]->{name} })) {
|
|
$$case_name_index_map_ref{ $case_ref->[$i]->{name} } = $case_name_index_map_bak{ $case_ref->[$i]->{name} };
|
|
} else {
|
|
delete $$case_name_index_map_ref{ $case_ref->[$i]->{name} };
|
|
if (!grep (/$case_ref->[$i]->{name}/, @{ $invalidcases{"noruncases"} })) {
|
|
push @{ $invalidcases{"noruncases"} }, $case_ref->[$i]->{name};
|
|
push @{ $invalidoptions{"invalid-arch"} }, "$case_ref->[$i]->{arch}";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
$newcmdstart = 0;
|
|
} elsif ($line =~ /^hcp\s*:\s*(\w[\w\, ]+)/) {
|
|
next if $skip;
|
|
$case_ref->[$i]->{hcp} = $1;
|
|
if ($run_case_flag) {
|
|
|
|
#To judge whether need to skip the current case
|
|
my $valid = 0;
|
|
my @valid_hcps = split(",", $case_ref->[$i]->{hcp});
|
|
|
|
foreach my $hcp (@valid_hcps){
|
|
$hcp =~ s/^\s+|\s+$//g;
|
|
if (exists($config{var}{HCP}) && ($hcp =~ /^$config{var}{HCP}$/i)) {
|
|
$valid = 1;
|
|
if (grep (/$case_ref->[$i]->{name}/, @{ $invalidcases{"noruncases"} })) {
|
|
delete_item_from_array($case_ref->[$i]->{name}, $invalidcases{"noruncases"});
|
|
}
|
|
last;
|
|
}
|
|
}
|
|
unless ($valid) {
|
|
if (exists($case_name_index_map_bak{ $case_ref->[$i]->{name} })) {
|
|
$$case_name_index_map_ref{ $case_ref->[$i]->{name} } = $case_name_index_map_bak{ $case_ref->[$i]->{name} };
|
|
} else {
|
|
delete $$case_name_index_map_ref{ $case_ref->[$i]->{name} };
|
|
if (!grep (/$case_ref->[$i]->{name}/, @{ $invalidcases{"noruncases"} })) {
|
|
push @{ $invalidcases{"noruncases"} }, $case_ref->[$i]->{name};
|
|
push @{ $invalidoptions{"invalid-hcp"} }, "$case_ref->[$i]->{hcp}";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
$newcmdstart = 0;
|
|
} elsif ($line =~ /^type\s*:\s*(\w[\w\,-]+)/) {
|
|
next if $skip;
|
|
$case_ref->[$i]->{type} = $1;
|
|
$newcmdstart = 0;
|
|
} elsif ($line =~ /^stop\s*:\s*(\w[\w\,]+)/) {
|
|
next if $skip;
|
|
$case_ref->[$i]->{stop} = $1;
|
|
$newcmdstart = 0;
|
|
} elsif ($line =~ /^description\s*:\s*(.+)/) {
|
|
next if $skip;
|
|
$case_ref->[$i]->{description} = $1;
|
|
$newcmdstart = 0;
|
|
} elsif ($line =~ /^attribute\s*:\s*(\w[\w\,]+)/) {
|
|
next if $skip;
|
|
$case_ref->[$i]->{attribute} = $1;
|
|
$newcmdstart = 0;
|
|
} elsif ($line =~ /^cmd\s*:\s*([\#\/\$\w].+)/) {
|
|
next if $skip;
|
|
$newcmdstart = 0;
|
|
$j = $j + 1;
|
|
$z = 0;
|
|
$m = 0;
|
|
if ($run_case_flag) {
|
|
$case_ref->[$i]->{cmd}->[$j][$m] = getvar($1, \%config);
|
|
if ($case_ref->[$i]->{cmd}->[$j][$m] =~ /miss attribute (.+)/) {
|
|
update_miss_attr($case_ref->[$i]->{cmd}->[$j][$m], $case_ref->[$i]->{name}, \@{ $invalidcases{"missattr"} });
|
|
}
|
|
} else {
|
|
$case_ref->[$i]->{cmd}->[$j][$m] = $1;
|
|
}
|
|
$newcmdstart = 1;
|
|
} elsif ($line =~ /^check\s*:\s*(\w.+)/) {
|
|
next if $skip;
|
|
if ($run_case_flag) {
|
|
$case_ref->[$i]->{check}->[$j][$z] = getvar($1, \%config);
|
|
if ($case_ref->[$i]->{check}->[$j][$z] =~ /miss attribute/) {
|
|
update_miss_attr($case_ref->[$i]->{check}->[$j][$z], $case_ref->[$i]->{name}, \@{ $invalidcases{"missattr"} });
|
|
}
|
|
} else {
|
|
$case_ref->[$i]->{check}->[$j][$z] = $1;
|
|
}
|
|
$z = $z + 1;
|
|
$newcmdstart = 0;
|
|
} elsif ($line =~ /^cmdcheck\s*:\s*(\w.+)/) {
|
|
next if $skip;
|
|
if ($run_case_flag) {
|
|
$case_ref->[$i]->{cmdcheck}->[$j][$z] = getvar($1, \%config);
|
|
if ($case_ref->[$i]->{cmdcheck}->[$j][$z] =~ /miss attribute/) {
|
|
update_miss_attr($case_ref->[$i]->{cmdcheck}->[$j][$z], $case_ref->[$i]->{name}, \@{ $invalidcases{"missattr"} });
|
|
}
|
|
} else {
|
|
$case_ref->[$i]->{cmdcheck}->[$j][$z] = $1;
|
|
}
|
|
$z = $z + 1;
|
|
$newcmdstart = 0;
|
|
} elsif ($line =~ /^end/) {
|
|
next if $skip;
|
|
$i = $i + 1;
|
|
$newcmdstart = 0;
|
|
} elsif ($newcmdstart) {
|
|
++$m;
|
|
$case_ref->[$i]->{cmd}->[$j][$m] = $line;
|
|
}
|
|
}
|
|
close($fd);
|
|
$newcmdstart = 0;
|
|
}
|
|
|
|
my @wrong_cases = ();
|
|
my $caseerror = 0;
|
|
if ($invalidcases{"invalidcasename"}) {
|
|
|
|
#log_this($running_log_fd, "Case name invalid:", @{ $invalidcases{"invalidcasename"} });
|
|
$$error_ref = "Case name invalid: " . join(",", @{ $invalidcases{"invalidcasename"} });
|
|
push @wrong_cases, @{ $invalidcases{"invalidcasename"} };
|
|
$caseerror = 2;
|
|
}
|
|
|
|
if ($run_case_flag) {
|
|
if ($invalidcases{"missattr"}) {
|
|
log_this($running_log_fd, "Miss attribute:", @{ $invalidcases{"missattr"} });
|
|
|
|
#$$error_ref = "Miss attribute: " . join(",", @{ $invalidcases{"missattr"} });
|
|
foreach my $line (@{ $invalidcases{"missattr"} }) {
|
|
my @name = split(" ", $line);
|
|
if (!(grep /$name[0]/, @wrong_cases)) {
|
|
push @wrong_cases, $name[0];
|
|
}
|
|
}
|
|
$caseerror = 2;
|
|
}
|
|
|
|
if ($invalidcases{"noruncases"} && @{ $invalidcases{"noruncases"} }) {
|
|
my $temp_invalid_op;
|
|
my $test_case = $invalidcases{"noruncases"}[0];
|
|
if (exists $invalidoptions{"invalid-os"}) {
|
|
$temp_invalid_op = $invalidoptions{"invalid-os"}[0];
|
|
print "Test case $test_case has an invalid OS option - $temp_invalid_op\n";
|
|
} elsif (exists $invalidoptions{"invalid-arch"}) {
|
|
$temp_invalid_op = $invalidoptions{"invalid-arch"}[0];
|
|
print "Test case $test_case has an invalid ARCH option - $temp_invalid_op\n";
|
|
} elsif (exists $invalidoptions{"invalid-hcp"}) {
|
|
$temp_invalid_op = $invalidoptions{"invalid-hcp"}[0];
|
|
print "Test case $test_case has an invalid HCP option - $temp_invalid_op\n";
|
|
}
|
|
push @wrong_cases, @{ $invalidcases{"noruncases"} };
|
|
$caseerror = 2;
|
|
}
|
|
|
|
# To filter unexisted cases
|
|
my @unexisted_cases;
|
|
foreach my $case (@{$cases_to_be_run_ref}) {
|
|
if (!(grep { /^$case$/ } @wrong_cases) && !defined($$case_name_index_map_ref{$case})) {
|
|
push @unexisted_cases, $case;
|
|
}
|
|
}
|
|
if (@unexisted_cases) {
|
|
log_this($running_log_fd, "Does not exist:", @unexisted_cases);
|
|
push @wrong_cases, @unexisted_cases;
|
|
$caseerror = 2;
|
|
}
|
|
|
|
if ($caseerror) {
|
|
my @new_cases_to_be_run = ();
|
|
foreach my $c (@{$cases_to_be_run_ref}) {
|
|
if (!(grep { /^$c$/ } @wrong_cases)) {
|
|
push @new_cases_to_be_run, $c;
|
|
}
|
|
}
|
|
@{$cases_to_be_run_ref} = @new_cases_to_be_run;
|
|
}
|
|
|
|
if (@{$cases_to_be_run_ref}) {
|
|
log_this($running_log_fd, "To run:", @{$cases_to_be_run_ref});
|
|
} else {
|
|
log_this($running_log_fd, "To run:", "There is no valid case to run");
|
|
}
|
|
}
|
|
return $caseerror;
|
|
}
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: bakup_current_env
|
|
# Description: back up the xcat db
|
|
# Atrributes:
|
|
# $error_ref (output attribe)
|
|
# The reference of scalar to save the error message generated during running current function
|
|
# Return code: 0 Success 1 Failed
|
|
#--------------------------------------------------------
|
|
sub bakup_current_env {
|
|
my $error_ref = shift;
|
|
&runcmd("mkdir -p /tmp/xCATdbbackup");
|
|
&runcmd("dumpxCATdb -p /tmp/xCATdbbackup");
|
|
if ($::RUNCMD_RC != 0) {
|
|
$$error_ref = "Fail to backup xCAT database";
|
|
&runcmd("rm -rf /tmp/xCATdbbackup");
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: restore_current_env
|
|
# Description: restore the xcat db
|
|
# Atrributes:
|
|
# $error_ref (output attribe)
|
|
# The reference of scalar to save the error message generated during running current function
|
|
# Return code: 0 Success 1 Failed
|
|
#--------------------------------------------------------
|
|
sub restore_current_env {
|
|
my $error_ref = shift;
|
|
&runcmd("restorexCATdb -p /tmp/xCATdbbackup");
|
|
&runcmd("rm -rf /tmp/xCATdbbackup");
|
|
return 0;
|
|
}
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: run_case
|
|
# Description:
|
|
# Atrributes:
|
|
# $cases_to_be_run_ref (input attribe)
|
|
# The reference of array to save the cases to be handled
|
|
# $case_ref (input attribe)
|
|
# The reference of a array of hash to save the contect of case
|
|
# The array @cases is a global attribute.
|
|
# Please refer load_case function's comment to get the struture of @cases
|
|
# $case_name_index_map_ref (input attribute)
|
|
# The reference of a hash to save the mapping of test name ane its index in @cases
|
|
# Due to there maybe is more than one implementation for one case
|
|
# $error_ref (output attribe)
|
|
# The reference of scalar to save the error message generated during running current function
|
|
# Return code: 0 Success 1 Failed
|
|
#--------------------------------------------------------
|
|
sub run_case {
|
|
my $cases_to_be_run_ref = shift;
|
|
my $cases_ref = shift;
|
|
my $case_name_index_map_ref = shift;
|
|
my $error_ref = shift;
|
|
|
|
my $total = 0;
|
|
my $failnum = 0;
|
|
|
|
my $failed_log_fd = undef;
|
|
if (!open($failed_log_fd, ">$failed_log_name")) {
|
|
$error_ref = "Failed to generate failed log file for $program_name: $!";
|
|
return 1;
|
|
}
|
|
|
|
foreach my $case (@{$cases_to_be_run_ref}) {
|
|
my @caselog = ();
|
|
|
|
my $failflag = 0;
|
|
my $j = 0;
|
|
++$total;
|
|
|
|
my $case_start_time = timelocal(localtime());
|
|
my $case_start_time_str = scalar(localtime());
|
|
|
|
log_this($running_log_fd, "------START::$cases_ref->[$case_name_index_map_ref->{$case}]->{name}::Time:$case_start_time_str------\n");
|
|
push @caselog, "------START::$cases_ref->[$case_name_index_map_ref->{$case}]->{name}::Time:$case_start_time_str------\n";
|
|
push @caselog, "FILENAME:$cases_ref->[$case_name_index_map_ref->{$case}]->{filename}\n";
|
|
|
|
foreach my $cmd (@{ $cases_ref->[ $case_name_index_map_ref->{$case} ]->{cmd} }) {
|
|
|
|
my $runstart = timelocal(localtime());
|
|
my $runstartstr = scalar(localtime());
|
|
my $cmdlen = @{$cmd};
|
|
my @output = ();
|
|
my $rc = 0;
|
|
if ($cmdlen == 1) {
|
|
|
|
#to run single line command
|
|
|
|
log_this($running_log_fd, "RUN:$cmd->[0] [$runstartstr]");
|
|
$cmd->[0] = getfunc($cmd->[0]);
|
|
@output = &runcmd($cmd->[0]);
|
|
$rc = $::RUNCMD_RC;
|
|
push(@caselog, "RUN:$cmd->[0] [$runstartstr]");
|
|
} else {
|
|
|
|
#to run multiple lines command
|
|
|
|
log_this($running_log_fd, "RUN: [$runstartstr]", @{$cmd});
|
|
@output = runscript($cmd);
|
|
$rc = $::RUNCMD_RC;
|
|
push(@caselog, ("RUN: [$runstartstr]", @{$cmd}));
|
|
}
|
|
|
|
my $runstop = timelocal(localtime());
|
|
my $diffduration = $runstop - $runstart;
|
|
log_this($running_log_fd, ("ElapsedTime:$diffduration sec", "RETURN rc = $rc", "OUTPUT:", @output));
|
|
push(@caselog, ("ElapsedTime:$diffduration sec", "RETURN rc = $rc", "OUTPUT:", @output));
|
|
|
|
# $checkfail is the result of this check, $failflag the result of the case. One
|
|
# variable for both makes a failed check read as failing every later check.
|
|
my $checkfail = 0;
|
|
foreach my $check (@{ $cases_ref->[ $case_name_index_map_ref->{$case} ]->{check}->[$j] }) {
|
|
$checkfail = 0;
|
|
|
|
if ($check =~ /rc\s*([=!]+)\s*(\d+)/) {
|
|
my $lvalue = $rc;
|
|
my $op = $1;
|
|
my $rvalue = $2;
|
|
if ((($op eq '!=') && ($lvalue == $rvalue))
|
|
|| (($op eq '==') && ($lvalue != $rvalue))) {
|
|
$checkfail = 1;
|
|
}
|
|
if ($checkfail) {
|
|
log_this($running_log_fd, "CHECK:rc $op $rvalue\t[Failed]");
|
|
push(@caselog, "CHECK:rc $op $rvalue\t[Failed]");
|
|
} else {
|
|
log_this($running_log_fd, "CHECK:rc $op $rvalue\t[Pass]");
|
|
push(@caselog, "CHECK:rc $op $rvalue\t[Pass]");
|
|
}
|
|
} elsif ($check =~ /output\s*(==|!=|=~|!~)\s*(\S.*)/) {
|
|
my $lvalue = join("\n", @output);
|
|
my $op = $1;
|
|
my $rvalue = $2;
|
|
|
|
$rvalue = getfunc($rvalue);
|
|
if ((($op eq '=~') && ($lvalue !~ /$rvalue/))
|
|
|| (($op eq '!~') && ($lvalue =~ /$rvalue/))
|
|
|| (($op eq '==') && ($lvalue ne $rvalue))
|
|
|| (($op eq '!=') && ($lvalue eq $rvalue))) {
|
|
$checkfail = 1;
|
|
} elsif (($op ne '=~') && ($op ne '!~') && ($op ne '==') && ($op ne '!=')) {
|
|
$checkfail = 1;
|
|
log_this($running_log_fd, "CHECK:output unrecognized operator: $op\t[Failed]");
|
|
push(@caselog, "CHECK:output unrecognized operator: $op\t[Failed]");
|
|
next;
|
|
}
|
|
if ($checkfail) {
|
|
log_this($running_log_fd, "CHECK:output $op $rvalue\t[Failed]");
|
|
push(@caselog, "CHECK:output $op $rvalue\t[Failed]");
|
|
} else {
|
|
log_this($running_log_fd, "CHECK:output $op $rvalue\t[Pass]");
|
|
push(@caselog, "CHECK:output $op $rvalue\t[Pass]");
|
|
}
|
|
} elsif ($check =~ /output\s*~~\s*(\S.*)/) {
|
|
my $op = "~~";
|
|
|
|
# This operator only sets $checkfail to 0, so the check always reports Pass.
|
|
my $rvalue = $1;
|
|
|
|
$rvalue = getfunc($rvalue);
|
|
my $num;
|
|
if ($rvalue =~ /(\d+)/) {
|
|
$num = $1;
|
|
}
|
|
$rvalue =~ s/(\d+)//;
|
|
foreach my $line (@output) {
|
|
chomp($line);
|
|
if ($line =~ /$rvalue/) {
|
|
if ($num =~ /^\d+$/) {
|
|
my $max = $num * 1.1;
|
|
my $min = $num * 0.9;
|
|
$line =~ /.*:.*: (\d+) /;
|
|
if ($1 < $max && $1 > $min) {
|
|
$checkfail = 0;
|
|
last;
|
|
}
|
|
} else {
|
|
next;
|
|
}
|
|
}
|
|
}
|
|
if ($checkfail) {
|
|
log_this($running_log_fd, "CHECK:output $op $rvalue\t[Failed]");
|
|
push(@caselog, "CHECK:output $op $rvalue\t[Failed]");
|
|
} else {
|
|
log_this($running_log_fd, "CHECK:output $op $rvalue\t[Pass]");
|
|
push(@caselog, "CHECK:output $op $rvalue\t[Pass]");
|
|
}
|
|
} else {
|
|
$checkfail = 1;
|
|
log_this($running_log_fd, "Unrecognized testcase syntax: CHECK:$check\t[Failed]");
|
|
push(@caselog, "Unrecognized testcase syntax: CHECK:$check\t[Failed]");
|
|
}
|
|
} continue {
|
|
$failflag = 1 if ($checkfail);
|
|
}
|
|
foreach my $cmdcheck (@{ $cases_ref->[ $case_name_index_map_ref->{$case} ]->{cmdcheck}->[$j] }) {
|
|
if ($cmdcheck) {
|
|
&runcmd($cmdcheck);
|
|
$rc = $::RUNCMD_RC;
|
|
if ($rc != 0) {
|
|
$failflag = 1;
|
|
log_this($running_log_fd, "CHECK:output $cmdcheck\t[Failed]");
|
|
push(@caselog, "CHECK:output $cmdcheck\t[Failed]");
|
|
} elsif ($rc == 0) {
|
|
log_this($running_log_fd, "CHECK:output $cmdcheck\t[Pass]");
|
|
push(@caselog, "CHECK:output $cmdcheck\t[Pass]");
|
|
}
|
|
}
|
|
}
|
|
$j = $j + 1;
|
|
log_this($running_log_fd, " ");
|
|
push(@caselog, " ");
|
|
}
|
|
my $case_end_time = timelocal(localtime());
|
|
my $case_end_time_str = scalar(localtime());
|
|
my $diff = $case_end_time - $case_start_time;
|
|
|
|
if ($failflag) {
|
|
log_this($running_log_fd, "------END::$cases_ref->[$case_name_index_map_ref->{$case}]->{name}::Failed::Time:$case_end_time_str ::Duration::$diff sec------");
|
|
push(@caselog, "------END::$cases_ref->[$case_name_index_map_ref->{$case}]->{name}::Failed::Time:$case_end_time_str ::Duration::$diff sec------");
|
|
} else {
|
|
log_this($running_log_fd, "------END::$cases_ref->[$case_name_index_map_ref->{$case}]->{name}::Passed::Time:$case_end_time_str ::Duration::$diff sec------");
|
|
push(@caselog, "------END::$cases_ref->[$case_name_index_map_ref->{$case}]->{name}::Passed::Time:$case_end_time_str ::Duration::$diff sec------");
|
|
}
|
|
|
|
if ($failflag) {
|
|
++$failnum;
|
|
print $failed_log_fd (join("\n", @caselog), "\n");
|
|
if (defined($cases_ref->[ $case_name_index_map_ref->{$case} ]->{stop}) && ($cases_ref->[ $case_name_index_map_ref->{$case} ]->{stop} =~ /^yes$/)) {
|
|
$stop_to_keep_env = 1;
|
|
last;
|
|
}
|
|
}
|
|
}
|
|
|
|
log_this($running_log_fd, "------Total: $total , Failed: $failnum------\n");
|
|
close($failed_log_fd);
|
|
return 0;
|
|
}
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: setup_env_by_configure_file
|
|
# Description: set up environment by the settings in config file
|
|
# Atrributes:
|
|
# $config_ref (input attribute)
|
|
# The reference of global hash %config.
|
|
# The structure of %config please refer to the comment of function load_config_file
|
|
# $error_ref (output attribe)
|
|
# The reference of scalar to save the error message generated during running current function
|
|
# Return code: 0 Success 1 Failed
|
|
#--------------------------------------------------------
|
|
sub setup_env_by_configure_file {
|
|
my $config_ref = shift;
|
|
my $error_ref = shift;
|
|
|
|
my $cmd = undef;
|
|
foreach $cmd (@{ $$config_ref{script_prev} }) {
|
|
log_this($running_log_fd, "$cmd");
|
|
&runcmd($cmd);
|
|
if ($::RUNCMD_RC != 0) {
|
|
$$error_ref = "Failed to run $cmd";
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if (exists $$config_ref{object}) {
|
|
foreach my $type (keys %{ $$config_ref{object} }) {
|
|
foreach my $name (keys %{ $$config_ref{object}{$type} }) {
|
|
$cmd = "chdef -t $type -o $name";
|
|
foreach my $attr (keys %{ $$config_ref{object}{$type}{$name} }) {
|
|
$cmd = $cmd . " $attr=$$config_ref{object}{$type}{$name}{$attr}";
|
|
}
|
|
log_this($running_log_fd, "$cmd");
|
|
runcmd($cmd);
|
|
if ($::RUNCMD_RC != 0) {
|
|
$$error_ref = "Failed to run $cmd";
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (exists $$config_ref{table}) {
|
|
foreach my $type (keys %{ $$config_ref{table} }) {
|
|
foreach my $name (keys %{ $$config_ref{table}{$type} }) {
|
|
$cmd = "chtab $$config_ref{table}{$type}{$name}{__KEY__}=$name";
|
|
foreach my $attr (keys %{ $$config_ref{table}{$type}{$name} }) {
|
|
if ($attr ne '__KEY__') {
|
|
$cmd = $cmd . " $type.$attr=$$config_ref{table}{$type}{$name}{$attr}";
|
|
}
|
|
}
|
|
log_this($running_log_fd, "$cmd");
|
|
&runcmd($cmd);
|
|
if ($::RUNCMD_RC != 0) {
|
|
$$error_ref = "Failed to run $cmd";
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: detect_current_env
|
|
# Description: detect some important attribute in current environment, such as os, arch, hcp...
|
|
# Atrributes:
|
|
# $config_ref (input attribute)
|
|
# The reference of global hash %config.
|
|
# The structure of %config please refer to the comment of function load_config_file
|
|
# $error_ref (output attribe)
|
|
# The reference of scalar to save the error message generated during running current function
|
|
# Return code: 0 Success 1 Failed
|
|
#--------------------------------------------------------
|
|
sub detect_current_env {
|
|
my $config_ref = shift;
|
|
my $error_ref = shift;
|
|
|
|
if (!exists $$config_ref{var}{OS}) {
|
|
my @output = runcmd("uname");
|
|
$$config_ref{var}{OS} = lc($output[0]);
|
|
log_this($running_log_fd, "Detecting: OS = $$config_ref{var}{OS}");
|
|
} else {
|
|
$$config_ref{var}{OS} = lc($$config_ref{var}{OS});
|
|
}
|
|
|
|
if (!exists $$config_ref{var}{ARCH}) {
|
|
if (!exists $$config_ref{var}{CN}) {
|
|
$$config_ref{var}{ARCH} = "Unknown";
|
|
log_this($running_log_fd, "Warning: No compute node defined, can't get ARCH of compute node");
|
|
} else {
|
|
$$config_ref{var}{ARCH} = getnodeattr($$config_ref{var}{CN}, "arch");
|
|
if ($$config_ref{var}{ARCH} =~ /le|el/i) {
|
|
$$config_ref{var}{ARCH} = 'ppc64le';
|
|
} elsif ($$config_ref{var}{ARCH} =~ /ppc/i) {
|
|
$$config_ref{var}{ARCH} = 'ppc';
|
|
} elsif ($$config_ref{var}{ARCH} =~ /86/i) {
|
|
$$config_ref{var}{ARCH} = 'x86';
|
|
}
|
|
log_this($running_log_fd, "Detecting: ARCH = $$config_ref{var}{ARCH}");
|
|
}
|
|
}
|
|
|
|
if (!exists $$config_ref{var}{HCP}) {
|
|
if (!exists $$config_ref{var}{CN}) {
|
|
$$config_ref{var}{HCP} = "Unknown";
|
|
log_this($running_log_fd, "Warning: No compute node defined, can't get HCP TYPE of compute node");
|
|
} else {
|
|
$$config_ref{var}{HCP} = getnodeattr($$config_ref{var}{CN}, "mgt");
|
|
log_this($running_log_fd, "Detecting: HCP = $$config_ref{var}{HCP}");
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: runcmd
|
|
# Description: run a command after 'cmd' label in one case
|
|
# Atrributes:
|
|
# Return code:
|
|
# $::RUNCMD_RC : the return code of command
|
|
# @$outref : the output of command
|
|
#--------------------------------------------------------
|
|
sub runcmd
|
|
{
|
|
my ($cmd) = @_;
|
|
my $rc = 0;
|
|
$::RUNCMD_RC = 0;
|
|
my $outref = [];
|
|
# xCAT-test cases use bashisms ([ x == y ], [[ ]]); on Ubuntu /bin/sh is dash, so run
|
|
# the command under bash. open('-|', LIST) execs bash directly -- no intervening
|
|
# /bin/sh, so the cases' embedded quotes/backticks are not re-parsed or re-expanded.
|
|
if (open(my $cfh, '-|', '/bin/bash', '-c', "$cmd 2>&1")) {
|
|
@$outref = <$cfh>;
|
|
close($cfh); # sets $? just like the backtick did
|
|
}
|
|
if ($?)
|
|
{
|
|
$rc = $?;
|
|
$rc = $rc >> 8;
|
|
$::RUNCMD_RC = $rc;
|
|
}
|
|
chomp(@$outref);
|
|
return @$outref;
|
|
|
|
}
|
|
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: runscript
|
|
# Description: run a script after 'cmd' label in one case
|
|
# Atrributes:
|
|
# $script_ref (input attribute)
|
|
# the reference of array where save every line of script
|
|
# Return code:
|
|
# $::RUNCMD_RC : the return code of command
|
|
# @$outref : the output of command
|
|
#--------------------------------------------------------
|
|
sub runscript {
|
|
my $script_ref = shift;
|
|
my $time = time();
|
|
my $tmpdir = "/tmp/xCATautotest$time/";
|
|
my $tmpfile = "$tmpdir/script";
|
|
my $rf;
|
|
mkpath("$tmpdir");
|
|
open($rf, ">$tmpfile");
|
|
foreach my $line (@$script_ref) {
|
|
$line = getfunc($line);
|
|
print $rf "$line\n";
|
|
}
|
|
close($rf);
|
|
chmod 0755, "$tmpfile";
|
|
my @output = runcmd("$tmpfile");
|
|
|
|
unlink("$tmpfile");
|
|
rmdir("$tmpdir");
|
|
return @output;
|
|
}
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: getnodeattr
|
|
# Description: get the value of node attribute from current environment
|
|
# Atrributes:
|
|
# Return code:
|
|
#--------------------------------------------------------
|
|
sub getnodeattr {
|
|
my $node = shift;
|
|
my $attr = shift;
|
|
my $maxtry = 40;
|
|
return getobjectattr('node', $node, $attr, $maxtry);
|
|
}
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: getobjectattr
|
|
# Description: get the value of object attribute from current DB
|
|
# Atrributes:
|
|
# Return code:
|
|
#--------------------------------------------------------
|
|
sub getobjectattr {
|
|
my $objtype = shift;
|
|
my $objname = shift;
|
|
my $attr = shift;
|
|
my $maxtry = shift;
|
|
$maxtry = 1 unless defined($maxtry) and $maxtry > 0;
|
|
foreach my $try (0 .. $maxtry) {
|
|
my @output = runcmd("lsdef -t $objtype -o $objname -i $attr");
|
|
if ($::RUNCMD_RC == 0) {
|
|
foreach my $line (@output) {
|
|
if ($line =~ /$attr=(\S.+)/) {
|
|
return $1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return "Unknown";
|
|
}
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: get_files_recursive
|
|
# Description: Search all file in one directory recursively
|
|
# Atrributes:
|
|
# $dir (input attribute)
|
|
# The target scan directory
|
|
# $files_path_ref (output attribute)
|
|
# the reference of array where save all vaild files under $dir
|
|
# Return code:
|
|
#--------------------------------------------------------
|
|
sub get_files_recursive
|
|
{
|
|
my $dir = shift;
|
|
my $files_path_ref = shift;
|
|
|
|
my $fd = undef;
|
|
opendir($fd, $dir);
|
|
for (; ;)
|
|
{
|
|
my $direntry = readdir($fd);
|
|
last unless (defined($direntry));
|
|
next if ($direntry =~ m/^\.\w*/);
|
|
next if ($direntry eq '..');
|
|
my $target = "$dir/$direntry";
|
|
if (-d $target) {
|
|
unless ($target =~ /xcat_inventory\/templates/){
|
|
get_files_recursive($target, $files_path_ref);
|
|
}
|
|
} else {
|
|
push(@{$files_path_ref}, glob("$target\n"));
|
|
}
|
|
}
|
|
closedir($fd);
|
|
}
|
|
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: is_valid_case_name
|
|
# Description: to check if a case name is valid
|
|
# Atrributes: $casename (input atrribute): the target case name
|
|
# Return code: 0 Success 1 Failed
|
|
#--------------------------------------------------------
|
|
sub is_valid_case_name {
|
|
my $casename = shift;
|
|
if ($casename =~ /[^a-zA-Z0-9_-]/) {
|
|
return 0;
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
#-------------------------------------------------------
|
|
# Fuction name: get_current_os
|
|
# Description: Return name of current OS. For rhels, also return major number
|
|
# Atrributes:
|
|
# Return code:
|
|
#--------------------------------------------------------
|
|
sub get_current_os {
|
|
if (-f "/etc/redhat-release") {
|
|
# Try to return "rhels" + major version, if can not get it, just return "rhels"
|
|
my $major_version = "";
|
|
my @output = &runcmd("cat /etc/redhat-release");
|
|
my $out_line = $output[0];
|
|
if ($out_line =~ (/(\d+)\.(\d*)/)) {
|
|
$major_version = $1;
|
|
}
|
|
return "rhels".$major_version;
|
|
} elsif (-f "/etc/lsb-release") {
|
|
return "ubuntu";
|
|
} elsif (-f "/etc/os-release") {
|
|
my $file="/etc/os-release";
|
|
&runcmd("grep -q sles $file");
|
|
if ($::RUNCMD_RC == 0) {
|
|
return "sles";
|
|
}
|
|
} elsif (-f "/etc/SuSE-release") {
|
|
return "sles";
|
|
} else {
|
|
return "aix";
|
|
}
|
|
}
|
|
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: generate_performance_report
|
|
# Description:
|
|
# Atrributes:
|
|
# Return code:
|
|
#--------------------------------------------------------
|
|
sub generate_performance_report {
|
|
my $runninglog = shift;
|
|
my $performancelog = shift;
|
|
my $error_ref = shift;
|
|
|
|
my $performance_log_fd = undef;
|
|
|
|
if (!open($performance_log_fd, ">$performancelog")) {
|
|
$$error_ref = "Failed to create performance log $performancelog: $!";
|
|
return 1;
|
|
}
|
|
|
|
print $performance_log_fd "Testcase Duration\n";
|
|
print $performance_log_fd "------------------------------------------------------------------------------\n";
|
|
|
|
my @output = runcmd("cat $runninglog");
|
|
my $cmdlineflag = 0;
|
|
my $line;
|
|
foreach my $line (@output) {
|
|
if ($line =~ /^------START:/) {
|
|
$line =~ s/------//g;
|
|
print $performance_log_fd "$line\n";
|
|
} elsif ($line =~ /^RUN:/) {
|
|
$cmdlineflag = 1;
|
|
print $performance_log_fd "$line;\n";
|
|
} elsif ($line =~ /^ElapsedTime:/) {
|
|
$cmdlineflag = 0;
|
|
print $performance_log_fd "$line\n";
|
|
} elsif ($cmdlineflag) {
|
|
print $performance_log_fd "$line\n";
|
|
} elsif ($line =~ /^------END:/) {
|
|
$line =~ s/------//g;
|
|
print $performance_log_fd "$line\n\n";
|
|
}
|
|
}
|
|
close($performance_log_fd);
|
|
return 0;
|
|
}
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: getvar
|
|
# Description: replace specific attribute in case definition by the value set in config file
|
|
# Atrributes:
|
|
# Return code:
|
|
#--------------------------------------------------------
|
|
sub getvar
|
|
{
|
|
my $str = shift;
|
|
my $config_ref = shift;
|
|
my @vars = ($str =~ /\$\$(\w+)/g);
|
|
my @reverse_sorted_vars = reverse sort @vars;
|
|
|
|
# let $$AA and $$A have the same chance to be replaced.
|
|
for my $varname (@reverse_sorted_vars) {
|
|
if (exists($$config_ref{var}{$varname})) {
|
|
$str =~ s/\$\$$varname/$$config_ref{var}{$varname}/g;
|
|
} else {
|
|
return "miss attribute $varname";
|
|
}
|
|
}
|
|
return $str;
|
|
}
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: getfunc
|
|
# Description: replace specific funciton in case definition
|
|
# Atrributes:
|
|
# Return code:
|
|
#--------------------------------------------------------
|
|
sub getfunc
|
|
{
|
|
my $str = shift;
|
|
|
|
while ($str =~ /__(\w+)\(([\s\,\w\$\-\.]*)\)__/) {
|
|
my $func = $1;
|
|
my $parameter = $2;
|
|
my $value = undef;
|
|
my @para = ();
|
|
|
|
#log_this("parameter is $parameter,fun is $func");
|
|
chomp($parameter);
|
|
@para = split /\s*,\s*/, $parameter;
|
|
if ($func eq "GETNODEATTR") {
|
|
$value = getnodeattr($para[0], $para[1]);
|
|
if ($value eq "Unknown") {
|
|
$value = '';
|
|
}
|
|
} elsif ($func eq "GETOBJECTATTR") {
|
|
$value = getobjectattr(@para);
|
|
if ($value eq "Unknown") {
|
|
$value = '';
|
|
}
|
|
} elsif ($func eq "INC") {
|
|
$value = $para[0] + 1;
|
|
} elsif ($func eq "GETTABLEVALUE") {
|
|
$value = gettablevalue(@para);
|
|
}
|
|
$str =~ s/__$func\($parameter\)__/$value/g;
|
|
}
|
|
return $str;
|
|
}
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: gettablevalue
|
|
# Description: get specific table value from current environment
|
|
# Atrributes:
|
|
# Return code:
|
|
#--------------------------------------------------------
|
|
sub gettablevalue
|
|
{
|
|
my ($keyname, $key, $colname, $table) = @_;
|
|
my @output = runcmd("gettab $keyname=$key $table\.$colname");
|
|
return $output[0];
|
|
}
|
|
|
|
#--------------------------------------------------------
|
|
# Fuction name: print_table
|
|
# Description: print a hash table in good format
|
|
# Atrributes:
|
|
# Return code:
|
|
#--------------------------------------------------------
|
|
sub print_table {
|
|
my $msg_ref = shift;
|
|
|
|
my $desiredwidth = 160;
|
|
my $screenwidth = (`tput cols` + 0);
|
|
my $finallen = ($screenwidth > $desiredwidth ? $desiredwidth : $screenwidth);
|
|
|
|
my $maxkeylen = 0;
|
|
foreach my $key (keys %{$msg_ref}) {
|
|
my $keylen = length($key);
|
|
$maxkeylen = $keylen if ($keylen > $maxkeylen);
|
|
}
|
|
$maxkeylen += 4;
|
|
|
|
foreach my $key (sort { $a cmp $b } keys %{$msg_ref}) {
|
|
my @desc = split(" ", $msg_ref->{$key});
|
|
my $str = "";
|
|
my @formatdesc = ();
|
|
foreach my $word (@desc) {
|
|
if (length($str) + length($word) > $finallen - $maxkeylen) {
|
|
$str =~ s/([^\s]+)\s$/$1/g;
|
|
push @formatdesc, $str;
|
|
$str = "";
|
|
}
|
|
$str .= $word . " ";
|
|
}
|
|
$str =~ s/([^\s]+)\s$/$1/g;
|
|
push @formatdesc, $str;
|
|
|
|
print color("green"), "$key", color("reset");
|
|
|
|
my $space = " " x ($maxkeylen - length($key));
|
|
print "$space$formatdesc[0]\n";
|
|
delete $formatdesc[0];
|
|
$space = " " x $maxkeylen;
|
|
foreach my $line (@formatdesc) {
|
|
print "$space$line\n" if (length($line));
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
sub update_miss_attr {
|
|
my $org_str = shift;
|
|
my $case_name = shift;
|
|
my $miss_attr_arr_ref = shift;
|
|
|
|
my $insert_flag = 0;
|
|
my $index = 0;
|
|
foreach my $str (@{$miss_attr_arr_ref}) {
|
|
my @words = split(" ", $str);
|
|
my @org_words = split(" ", $org_str);
|
|
if ($case_name eq "$words[0]") {
|
|
if (!(grep { /^$org_words[2]$/ } @words)) {
|
|
$miss_attr_arr_ref->[$index] .= " $org_words[2]";
|
|
}
|
|
$insert_flag = 1;
|
|
last;
|
|
}
|
|
++$index;
|
|
}
|
|
|
|
unless ($insert_flag) {
|
|
push @{$miss_attr_arr_ref}, "$case_name $org_str";
|
|
}
|
|
}
|
|
|
|
sub delete_item_from_array {
|
|
my $item = shift;
|
|
my $array_ref = shift;
|
|
|
|
my @tmp_arr = ();
|
|
foreach (@$array_ref) {
|
|
push @tmp_arr, $_ unless ($_ eq $item);
|
|
}
|
|
@$array_ref = @tmp_arr;
|
|
}
|
|
|
|
sub filter_case_by_label {
|
|
my $cases_to_be_run_ref = shift;
|
|
my $case_label_map_ref = shift;
|
|
my $rest_cases_to_be_run_ref = shift;
|
|
my $error_ref = shift;
|
|
|
|
my @targetcases = ();
|
|
foreach my $case (keys %{$case_label_map_ref}) {
|
|
if(@$cases_to_be_run_ref){
|
|
next unless(inarray($cases_to_be_run_ref, $case));
|
|
}
|
|
my $match_filter=0;
|
|
my @exps = split('\|', $search_expression);
|
|
foreach my $e (@exps) {
|
|
$e =~ s/\+/ /g;
|
|
$e =~ s/\-/ -/g;
|
|
my $match_sub_filter = 1;
|
|
my @tags = split(' ', $e);
|
|
foreach my $t (@tags) {
|
|
if ($t =~ /^-(.+)/) {
|
|
$match_sub_filter = 0 if (inarray ($case_label_map_ref->{$case}->{labels}, $1));
|
|
}else{
|
|
$match_sub_filter = 0 unless (inarray ($case_label_map_ref->{$case}->{labels}, $t));
|
|
}
|
|
last unless ($match_sub_filter);
|
|
}
|
|
|
|
if ($match_sub_filter){
|
|
$match_filter =1;
|
|
last;
|
|
}
|
|
}
|
|
push @targetcases, $case if ($match_filter);
|
|
}
|
|
#print Dumper \@targetcases;
|
|
|
|
#order cases which matches filters by Vertical Dimension Labels
|
|
for (my $i = 0 ; $i <= $#label_order ; $i++) {
|
|
foreach my $l (@{ $label_order[$i] }) {
|
|
foreach my $c (@targetcases) {
|
|
push @{$rest_cases_to_be_run_ref}, $c if (inarray($case_label_map_ref->{$c}->{labels}, $l));
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
sub scan_existed_labels {
|
|
my $case_label_map_ref = shift;
|
|
my $total_label_set_ref = shift;
|
|
my $error_ref = shift;
|
|
|
|
my $label_value = 1;
|
|
my @files = ();
|
|
my @cmdfiles = ();
|
|
get_files_recursive("$casedir", \@files);
|
|
|
|
foreach my $file (@files) {
|
|
my @output = runcmd("grep -E \"^start:|^hcp:|^os:|^arch:|^label:\" $file");
|
|
my $current_case_name = "";
|
|
my $cmd_cases_belong_to = calculate_case_belong_to_which_cmd($file);
|
|
#print "cmd_cases_belong_to = $cmd_cases_belong_to\n";
|
|
foreach my $line (@output) {
|
|
$line =~ s/^\s+|#[^!].+|\s+$//g;
|
|
|
|
#skip blank and comment lines
|
|
next if (length($line) == 0 || ($line =~ /^\s*#/));
|
|
|
|
my @labels = ();
|
|
if ($line =~ /^start\s*:\s*(.*)/) {
|
|
$current_case_name = $1;
|
|
if ($cmd_cases_belong_to){
|
|
$case_label_map_ref->{$current_case_name}->{labels} = [$cmd_cases_belong_to];
|
|
push @$total_label_set_ref, $cmd_cases_belong_to unless(inarray($total_label_set_ref, $cmd_cases_belong_to));
|
|
}else{
|
|
$case_label_map_ref->{$current_case_name}->{labels} = [];
|
|
}
|
|
} elsif ($line =~ /^os\s*:\s*(\w[\w\, ]+)/) {
|
|
my @oss = split(",", $1);
|
|
foreach my $os (@oss) {
|
|
$os =~ s/^\s+|\s+$//g;
|
|
my $label_str = lc("os=$os");
|
|
push @{$case_label_map_ref->{$current_case_name}->{labels}}, $label_str unless(inarray($case_label_map_ref->{$current_case_name}->{labels}, $label_str));
|
|
push @$total_label_set_ref, $label_str unless(inarray($total_label_set_ref, $label_str));
|
|
}
|
|
|
|
} elsif ($line =~ /^arch\s*:\s*(\w[\w\, ]+)/) {
|
|
my @archs = split(",", $1);
|
|
foreach my $arch (@archs) {
|
|
$arch =~ s/^\s+|\s+$//g;
|
|
my $label_str = lc("arch=$arch");
|
|
push @{$case_label_map_ref->{$current_case_name}->{labels}}, $label_str unless(inarray($case_label_map_ref->{$current_case_name}->{labels}, $label_str));
|
|
push @$total_label_set_ref, $label_str unless(inarray($total_label_set_ref, $label_str));
|
|
}
|
|
} elsif ($line =~ /^hcp\s*:\s*(\w[\w\, ]+)/) {
|
|
my @hcps = split(",", $1);
|
|
foreach my $hcp (@hcps) {
|
|
$hcp =~ s/^\s+|\s+$//g;
|
|
my $label_str = lc("hcp=$hcp");
|
|
push @{$case_label_map_ref->{$current_case_name}->{labels}}, $label_str unless(inarray($case_label_map_ref->{$current_case_name}->{labels}, $label_str));
|
|
push @$total_label_set_ref, $label_str unless(inarray($total_label_set_ref, $label_str));
|
|
|
|
}
|
|
} elsif ($line =~ /^label\s*:\s*(.+)/) {
|
|
my @tmp = split(",", $1);
|
|
foreach my $label_str (@tmp){
|
|
$label_str =~ s/^\s+|\s+$//g;
|
|
push @{$case_label_map_ref->{$current_case_name}->{labels}}, $label_str unless(inarray($case_label_map_ref->{$current_case_name}->{labels}, $label_str));
|
|
push @{$case_label_map_ref->{$current_case_name}->{manual_labels}},$label_str unless(inarray($case_label_map_ref->{$current_case_name}->{manual_labels}, $label_str));
|
|
push @$total_label_set_ref, $label_str unless(inarray($total_label_set_ref, $label_str));
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
sub calculate_case_belong_to_which_cmd {
|
|
my $file_path = shift;
|
|
my $command = undef;
|
|
|
|
$file_path =~ s|[\/]{2,}|\/|g;
|
|
if ($file_path =~ /\/autotest\/testcase/) {
|
|
my @path_str = split("/", $file_path);
|
|
#print Dumper \@path_str;
|
|
my $index = 0;
|
|
foreach my $str (@path_str) {
|
|
if ($str =~ "autotest") {
|
|
$index += 1;
|
|
last;
|
|
}
|
|
$index += 1;
|
|
}
|
|
#print "index=$index\n";
|
|
$command = lc($path_str[ $index + 1 ]);
|
|
}
|
|
return $command;
|
|
}
|
|
|
|
sub inarray{
|
|
my $array = shift;
|
|
my $element = shift;
|
|
my $hit = 0;
|
|
|
|
foreach my $e (@$array){
|
|
if (lc("$e") eq lc("$element")){
|
|
$hit = 1;
|
|
last;
|
|
}
|
|
}
|
|
return $hit;
|
|
}
|