mirror of
https://github.com/xcat2/xcat-core.git
synced 2025-05-24 20:52:08 +00:00
1311 lines
40 KiB
Perl
Executable File
1311 lines
40 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";
|
|
my $rootdir = "$::XCATROOT/share/xcat/tools/autotest";
|
|
my $needhelp = 0;
|
|
my $configinfo = undef;
|
|
my $configfile = undef;
|
|
my $casedir = "$rootdir/testcase";
|
|
my $bundledir = "$rootdir/bundle";
|
|
my $resultdir = "$rootdir/result";
|
|
my $bundlelist = undef;
|
|
my $caselist = undef;
|
|
my $cmdlist = undef;
|
|
my $showbundlesorcommands = undef;
|
|
my $needshow = 0;
|
|
my $restore = 0;
|
|
my $ret = 0;
|
|
my $string1 = undef;
|
|
my $showbundlefiles = 0;
|
|
my $showcommandslist = 0;
|
|
my $stop_to_keep_env = 0;
|
|
|
|
#-----------------------------------
|
|
=head1
|
|
System label usage:
|
|
In order to make install xCAT to be the first case for automation daily regression, "System" label is used in this xcattest command.
|
|
xcattest -f /opt/xcat/share/xcat/tools/autotest/default.conf:System -t install_xCAT_on_rhels_sles
|
|
xcattest -f /opt/xcat/share/xcat/tools/autotest/default.conf:System -t install_xCAT_on_ubuntu
|
|
System label means only the [System] aspect will be loaded and no other inital action will be done.
|
|
=cut
|
|
|
|
#-----------------------------------
|
|
my $initallabel = undef;
|
|
my $loadsysteminfo = "System";
|
|
|
|
#Create result directory
|
|
mkdir $resultdir unless -d $resultdir;
|
|
|
|
# create a log for xcattest
|
|
my $timestamp = `date +"%Y%m%d%H%M%S"`;
|
|
open(LOG, ">$resultdir/xcattest.log.$timestamp")
|
|
or die "Can't open logfile for writing: $!";
|
|
|
|
if (
|
|
!GetOptions("h|?" => \$needhelp,
|
|
"f=s" => \$configinfo,
|
|
"b=s" => \$bundlelist,
|
|
"t=s" => \$caselist,
|
|
"c=s" => \$cmdlist,
|
|
"s=s" => \$showbundlesorcommands,
|
|
"l" => \$needshow,
|
|
"restore" => \$restore)
|
|
)
|
|
{
|
|
&usage;
|
|
exit 1;
|
|
}
|
|
|
|
if ($needhelp)
|
|
{
|
|
&usage;
|
|
exit 0;
|
|
}
|
|
|
|
|
|
if (&checkoptions)
|
|
{
|
|
&usage;
|
|
exit 1;
|
|
}
|
|
|
|
#show bundle files under $bundledir with .bundle as file suffix
|
|
my %bundlefilesinfo = ();
|
|
if ($showbundlefiles)
|
|
{
|
|
&listbundlefiles;
|
|
exit 0;
|
|
}
|
|
|
|
#show commands, which is the folder name $casedir, with case* files and test cases
|
|
if ($showcommandslist)
|
|
{
|
|
&listcommands;
|
|
exit 0;
|
|
}
|
|
|
|
#load case to $cases
|
|
# key type
|
|
#$cases[x](x>0): hash
|
|
# name string
|
|
# os:AIX/Linux string
|
|
# arch:ppc64/x386 string
|
|
# hcp:hmc/mm/bmc/fsp string
|
|
# cmd: array
|
|
# check: array
|
|
|
|
my @cases = ();
|
|
if ($needshow) {
|
|
&loadcase;
|
|
exit 0;
|
|
}
|
|
|
|
|
|
# create a log for run test cases
|
|
&log_this("xCAT automated test started at " . scalar(localtime()));
|
|
open(LOG_ERR, ">$resultdir/failedcases.$timestamp")
|
|
or die "Can't open error logfile for writing: $!";
|
|
|
|
#read config file
|
|
log_this("******************************");
|
|
log_this("Reading Configure");
|
|
log_this("******************************");
|
|
#config{object}{type}{name}{attr}
|
|
#config{table}{name}{entry}{key}
|
|
#config{script_prev}->[]
|
|
#config{script_post}->[]
|
|
#config{var}{varname}
|
|
my %config = ();
|
|
$ret = &getConfig;
|
|
if ($ret != 0) {
|
|
goto EXIT;
|
|
}
|
|
|
|
#if not only load System aspects from config file, then init test enviroment
|
|
if (!defined($initallabel)){
|
|
log_this("******************************");
|
|
log_this("Initialize xCAT test evironment");
|
|
log_this("******************************");
|
|
$ret = &init;
|
|
if ($ret != 0) {
|
|
goto EXIT;
|
|
}
|
|
}
|
|
|
|
my @filespath = ();
|
|
#loading and check cases
|
|
log_this("******************************");
|
|
log_this("loading test cases");
|
|
log_this("******************************");
|
|
$ret = &loadcase;
|
|
if ($ret != 0) {
|
|
goto EXIT;
|
|
}
|
|
|
|
#run case
|
|
log_this("******************************");
|
|
log_this("Start to run test cases");
|
|
log_this("******************************");
|
|
&reordercases if (defined($bundlelist) || defined($caselist));
|
|
&runcase;
|
|
|
|
EXIT:
|
|
log_this("******************************");
|
|
log_this("un-initialize xCAT test evironment");
|
|
log_this("******************************");
|
|
if ($restore) {
|
|
&uninit;
|
|
}
|
|
|
|
&log_this("\nxCAT automated test finished at " . scalar(localtime()));
|
|
&log_this("Please check results in the $resultdir, \nand see $resultdir/failedcases.$timestamp file for failed cases.\nsee $resultdir/performance.report.$timestamp file for time consumption");
|
|
close(LOG);
|
|
close(LOG_ERR);
|
|
my $reportfile = "$resultdir/performance.report.$timestamp";
|
|
my $tmpreport = "$resultdir/xcattest.log.$timestamp";
|
|
&getreport($tmpreport, $reportfile);
|
|
|
|
if ($stop_to_keep_env) {
|
|
exit 1;
|
|
} else {
|
|
exit 0;
|
|
}
|
|
|
|
# end main
|
|
|
|
#
|
|
# logger
|
|
#
|
|
|
|
sub log_this
|
|
{
|
|
print LOG join("\n", @_), "\n";
|
|
my $msg = join("\n", @_);
|
|
if ($msg =~ /\[Pass\]/) {
|
|
print color("green"), "$msg\n", color("reset");
|
|
} elsif ($msg =~ /\[Failed\]/) {
|
|
print color("red"), "$msg\n", color("reset");
|
|
} else {
|
|
print "$msg\n";
|
|
}
|
|
}
|
|
|
|
sub log_error
|
|
{
|
|
print LOG_ERR join("\n", @_), "\n";
|
|
}
|
|
|
|
sub include_file
|
|
{
|
|
my $file = shift;
|
|
my $idir = shift;
|
|
my @text = ();
|
|
unless ($file =~ /^\//) {
|
|
$file = $idir . "/" . $file;
|
|
}
|
|
open(INCLUDE, $file) || return "#INCLUDEBAD:cannot open $file#";
|
|
while (<INCLUDE>) {
|
|
chomp($_);
|
|
s/\s+$//; #remove trailing spaces
|
|
next if /^\s*$/; #-- skip empty lines
|
|
push(@text, $_);
|
|
}
|
|
close(INCLUDE);
|
|
return join(",", @text);
|
|
}
|
|
|
|
sub sort_caserange
|
|
{
|
|
my @caserange = @_;
|
|
my $bundletext = join(',', @caserange);
|
|
#handle the #INLCUDE# tag recursively
|
|
my $idir = "$rootdir/bundle";
|
|
my $doneincludes = 0;
|
|
while (not $doneincludes) {
|
|
$doneincludes = 1;
|
|
if ($bundletext =~ /#INCLUDE:[^#^\n]+#/) {
|
|
$doneincludes = 0;
|
|
$bundletext =~ s/#INCLUDE:([^#^\n]+)#/include_file($1,$idir)/eg;
|
|
}
|
|
}
|
|
@caserange=split(",",$bundletext);
|
|
my @diff;
|
|
foreach my $case (@caserange) {
|
|
unless (grep { $_ eq $case } @diff) {
|
|
push @diff, $case;
|
|
}
|
|
}
|
|
my %index;
|
|
my @same = grep($index{$_}++, @caserange);
|
|
my @error =grep /INCLUDEBAD/, @caserange;
|
|
return (\@diff, \@same, \@error);
|
|
}
|
|
|
|
sub getConfig
|
|
{
|
|
my $type = undef; #Script_Prev,Script_Post,Table,Object,System,Custom
|
|
my $sub_type = undef; # The string after $type_
|
|
# Script-->
|
|
# Script_Prev
|
|
# Script_Post
|
|
# Table--->
|
|
# Table_xxxxx
|
|
# Object-->
|
|
# Object_xxxx
|
|
# System---->
|
|
# Custom---->
|
|
|
|
my $name = undef;
|
|
my $attr = undef;
|
|
my $value = undef;
|
|
my $c = 0;
|
|
my $cmd = undef;
|
|
my $mgt_name = undef;
|
|
|
|
if (!open(FILE, "$configfile")) {
|
|
log_this("Error: can't open xCAT config file: $configfile");
|
|
return 1;
|
|
}
|
|
|
|
#Only load System information
|
|
if (defined($initallabel) && ($initallabel eq $loadsysteminfo)) {
|
|
while (my $line = <FILE>) {
|
|
$line = &trim($line);
|
|
next if (length($line) == 0);
|
|
|
|
#Only read System variable
|
|
if ($line =~ /\[System\]/) {
|
|
$type = "Varible";
|
|
}
|
|
if (defined($type) && ($type eq "Varible")) {
|
|
if ($line =~ /(\w+)\s*=\s*([\w\.\-\+\/:]+)/) {
|
|
$config{var}{$1} = $2;
|
|
}
|
|
}
|
|
}
|
|
}else{
|
|
#Load all config files information
|
|
while (my $line = <FILE>) {
|
|
$line = &trim($line);
|
|
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{table}{$sub_type}{$name}{__KEY__} ne $attr)) {
|
|
$config{table}{$sub_type}{$name}{$attr} = $value;
|
|
} else {
|
|
$name = $value;
|
|
$config{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)) {
|
|
print "Please give name for Object\n";
|
|
close FILE;
|
|
return 1;
|
|
} else {
|
|
$config{object}{$sub_type}{$name}{$attr} = $value;
|
|
}
|
|
}
|
|
} elsif ($type eq "Script") {
|
|
##SCRIPT_BLOCK##
|
|
if ($sub_type eq "Prev") {
|
|
$config{script_prev}->[$c] = $line;
|
|
$c = $c + 1;
|
|
}
|
|
elsif ($sub_type eq "Post") {
|
|
$config{script_post}->[$c] = $line;
|
|
$c = $c + 1;
|
|
}
|
|
} elsif ($type eq "Varible") {
|
|
##NODE_BLOCK##
|
|
if ($line =~ /(\w+)\s*=\s*([\w\.\-\+\/:]+)/) {
|
|
$config{var}{$1} = $2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (exists $config{object}) {
|
|
foreach my $type (keys %{ $config{object} }) {
|
|
foreach my $name (keys %{ $config{object}{$type} }) {
|
|
log_this("OBJECT:$name,TYPE:$type");
|
|
foreach my $attr (keys %{ $config{object}{$type}{$name} }) {
|
|
log_this(" $attr = $config{object}{$type}{$name}{$attr};");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (exists $config{table}) {
|
|
foreach my $type (keys %{ $config{table} }) {
|
|
log_this("TABLE:$type");
|
|
foreach my $name (keys %{ $config{table}{$type} }) {
|
|
log_this(" $config{table}{$type}{$name}{__KEY__} = $name");
|
|
foreach my $attr (keys %{ $config{table}{$type}{$name} }) {
|
|
if ($attr ne '__KEY__') {
|
|
log_this(" $attr = $config{table}{$type}{$name}{$attr}");
|
|
}
|
|
}
|
|
log_this("\n");
|
|
}
|
|
}
|
|
}
|
|
if (exists $config{script_prev}) {
|
|
log_this("Script_Prev:");
|
|
foreach $cmd (@{ $config{script_prev} }) {
|
|
log_this(" $cmd");
|
|
}
|
|
}
|
|
|
|
if (exists $config{script_post}) {
|
|
log_this("Script_Post:");
|
|
foreach $cmd (@{ $config{script_post} }) {
|
|
log_this(" $cmd");
|
|
}
|
|
}
|
|
|
|
if (exists $config{var}) {
|
|
log_this("Varible:");
|
|
foreach my $varname (keys %{ $config{var} }) {
|
|
log_this(" $varname = $config{var}{$varname}");
|
|
}
|
|
}
|
|
|
|
close FILE;
|
|
return 0;
|
|
}
|
|
|
|
sub init
|
|
{
|
|
if ($restore) {
|
|
log_this("******************************");
|
|
log_this("Backup current xCAT database");
|
|
log_this("******************************");
|
|
&runcmd("mkdir -p /tmp/xCATdbbackup");
|
|
&runcmd("dumpxCATdb -p /tmp/xCATdbbackup");
|
|
if ($::RUNCMD_RC != 0) {
|
|
&log_this("Fail to backup xCAT database");
|
|
&runcmd("rm -rf /tmp/xCATdbbackup");
|
|
$restore = 0;
|
|
return 1;
|
|
}
|
|
}
|
|
my $cmd = undef;
|
|
foreach $cmd (@{ $config{script_prev} }) {
|
|
log_this("$cmd");
|
|
&runcmd($cmd);
|
|
if ($::RUNCMD_RC != 0) {
|
|
&log_this("Fail to run $cmd");
|
|
return 1;
|
|
}
|
|
}
|
|
if (exists $config{object}) {
|
|
foreach my $type (keys %{ $config{object} }) {
|
|
foreach my $name (keys %{ $config{object}{$type} }) {
|
|
$cmd = "chdef -t $type -o $name";
|
|
foreach my $attr (keys %{ $config{object}{$type}{$name} }) {
|
|
$cmd = $cmd . " $attr=$config{object}{$type}{$name}{$attr}";
|
|
}
|
|
log_this($cmd);
|
|
runcmd($cmd);
|
|
if ($::RUNCMD_RC != 0) {
|
|
log_this("Fail to run $cmd");
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (exists $config{table}) {
|
|
foreach my $type (keys %{ $config{table} }) {
|
|
foreach my $name (keys %{ $config{table}{$type} }) {
|
|
$cmd = "chtab $config{table}{$type}{$name}{__KEY__}=$name";
|
|
foreach my $attr (keys %{ $config{table}{$type}{$name} }) {
|
|
if ($attr ne '__KEY__') {
|
|
$cmd = $cmd . " $type.$attr=$config{table}{$type}{$name}{$attr}";
|
|
}
|
|
}
|
|
log_this($cmd);
|
|
&runcmd($cmd);
|
|
if ($::RUNCMD_RC != 0) {
|
|
&log_this("Fail to run $cmd");
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!exists $config{var}{OS}) {
|
|
my @output = runcmd("uname");
|
|
$config{var}{OS} = $output[0];
|
|
log_this("Detecting: OS = $config{var}{OS}");
|
|
} else {
|
|
$config{var}{OS} = lc($config{var}{OS});
|
|
}
|
|
|
|
if (!exists $config{var}{ARCH}) {
|
|
if (!exists $config{var}{CN}) {
|
|
$config{var}{ARCH} = "Unknown";
|
|
log_this("Error: No compute node defined, can't get ARCH of compute node");
|
|
} else {
|
|
$config{var}{ARCH} = getnodeattr($config{var}{CN}, "arch");
|
|
if ($config{var}{ARCH} =~ /ppc/) {
|
|
$config{var}{ARCH} = 'ppc';
|
|
} elsif ($config{var}{ARCH} =~ /86/) {
|
|
$config{var}{ARCH} = 'x86';
|
|
}
|
|
log_this("Detecting: ARCH = $config{var}{ARCH}");
|
|
}
|
|
}
|
|
if (!exists $config{var}{HCP}) {
|
|
if (!exists $config{var}{CN}) {
|
|
$config{var}{HCP} = "Unknown";
|
|
log_this("Error: No compute node defined, can't get HCP TYPE of compute node");
|
|
} else {
|
|
$config{var}{HCP} = getnodeattr($config{var}{CN}, "mgt");
|
|
log_this("Detecting: HCP = $config{var}{HCP}");
|
|
}
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
sub uninit
|
|
{
|
|
my $cmd = undef;
|
|
|
|
# if(exists $config{object}){
|
|
# foreach my $type (keys %{$config{object}}){
|
|
# foreach my $name (keys %{$config{object}{$type}}){
|
|
# $cmd = "rmdef -t $type -o $name";
|
|
# log_this($cmd);
|
|
# runcmd($cmd);
|
|
# if($::RUNCMD_RC != 0){
|
|
# log_this("Fail to run $cmd");
|
|
# return 1;
|
|
# }
|
|
# }
|
|
# }
|
|
# }
|
|
# if(exists $config{table}){
|
|
# foreach my $type (keys %{$config{table}}){
|
|
# foreach my $name (keys %{$config{table}{$type}}){
|
|
# $cmd = "chtab -d $config{table}{$type}{$name}{__KEY__}=$name $type";
|
|
# log_this($cmd);
|
|
# runcmd($cmd);
|
|
# if($::RUNCMD_RC != 0){
|
|
# log_this("Fail to run $cmd");
|
|
# return 1;
|
|
# }
|
|
# }
|
|
# }
|
|
# }
|
|
foreach $cmd (@{ $config{script_post} }) {
|
|
log_this($cmd);
|
|
runcmd($cmd);
|
|
if ($::RUNCMD_RC != 0) {
|
|
log_this("Error: Fail to run $cmd");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
&runcmd("restorexCATdb -p /tmp/xCATdbbackup");
|
|
&runcmd("rm -rf /tmp/xCATdbbackup");
|
|
return 0;
|
|
}
|
|
|
|
sub Get_Files_Recursive
|
|
{
|
|
my $dir = $_[0];
|
|
foreach $dir (@_)
|
|
{
|
|
opendir(my $d, $dir);
|
|
for (; ;)
|
|
{
|
|
my $direntry = readdir($d);
|
|
last unless defined $direntry;
|
|
next if $direntry =~ m/^\.\w*/;
|
|
next if $direntry eq '..';
|
|
if (-d $dir . "/" . $direntry)
|
|
{
|
|
Get_Files_Recursive($dir . "/" . $direntry);
|
|
}
|
|
else
|
|
{ my $dirpath = $dir . '/' . $direntry . "\n";
|
|
#print $dirpath;
|
|
|
|
#print $dir."\n";
|
|
push(@filespath, glob("$dirpath"));
|
|
|
|
}
|
|
}
|
|
closedir($d);
|
|
}
|
|
}
|
|
|
|
sub loadcase
|
|
{
|
|
my @files = ();
|
|
|
|
#if($cmdlist){
|
|
# my @cmds = split /,/,$cmdlist;
|
|
# for my $cmd (@cmds){
|
|
# push (@files, glob("$casedir/$cmd/*"));
|
|
# }
|
|
#} else {
|
|
# @files = glob("$casedir/*/*");
|
|
#}
|
|
Get_Files_Recursive("$casedir");
|
|
for (my $countfile = 0 ; $countfile < @filespath ; $countfile++)
|
|
{
|
|
#TODO:if commands are not right, no action or message now
|
|
if ($cmdlist) {
|
|
my @cmds = split /,/, $cmdlist;
|
|
for (my $countcmd = 0 ; $countcmd < @cmds ; $countcmd++) {
|
|
if ($filespath[$countfile] =~ m/\/$cmds[$countcmd]\/case/) {
|
|
push(@files, glob("$filespath[$countfile]"));
|
|
}
|
|
}
|
|
} else {
|
|
push(@files, glob("$filespath[$countfile]"));
|
|
}
|
|
}
|
|
|
|
|
|
my $file;
|
|
my $line;
|
|
my $i = 0;
|
|
my $j = -1;
|
|
my $z = 0;
|
|
my $skip = 0;
|
|
|
|
my @caserange = ();
|
|
my @rightcase = ();
|
|
my @notrightcase = ();
|
|
my @wrongnamecase= ();
|
|
my @samecase = ();
|
|
my @errorcase = ();
|
|
if ($bundlelist) {
|
|
my @bundles = split /,/, $bundlelist;
|
|
foreach my $bundle (@bundles) {
|
|
if (!open(FILE, "<$bundledir/$bundle")) {
|
|
log_this("can't open $bundledir/$bundle");
|
|
return 1;
|
|
}
|
|
while ($line = <FILE>) {
|
|
chomp($line);
|
|
next if (length($line) == 0);
|
|
push(@caserange, $line);
|
|
}
|
|
close(FILE);
|
|
my @refs=sort_caserange(@caserange);
|
|
@caserange=@{$refs[0]};
|
|
@samecase=@{$refs[1]};
|
|
@errorcase=@{$refs[2]};
|
|
}
|
|
}
|
|
|
|
#TODO:if cases are not existed, no action or message.
|
|
if ($caselist) {
|
|
@caserange = split /,/, $caselist;
|
|
}
|
|
|
|
foreach $file (@files) {
|
|
if (!open(FILE, "<$file")) {
|
|
log_this("can't open $file");
|
|
return 1;
|
|
}
|
|
while ($line = <FILE>) {
|
|
$line = &trim($line);
|
|
next if (length($line) == 0);
|
|
|
|
#skip comment lines
|
|
next if ($line =~ /^\s*#/);
|
|
|
|
#TODO: description line is treated as a comment line for now
|
|
next if ($line =~ /^description\s*:/);
|
|
|
|
if ($line =~ /^start\s*:\s*(.*)/) {
|
|
my $name =$1;
|
|
if ($name =~ /[^a-zA-Z0-9_-]/) {
|
|
$skip = 1;
|
|
push(@wrongnamecase, $name);
|
|
next;
|
|
}else {
|
|
$skip = 0;
|
|
if ($caserange[0] && !(grep { /^$name$/ } @caserange)) {
|
|
$skip = 1;
|
|
next;
|
|
}
|
|
$j = -1;
|
|
$cases[$i] = {};
|
|
$cases[$i]->{name} = $name;
|
|
$cases[$i]->{filename} = $file;
|
|
if (!$needshow) {
|
|
$cases[$i]->{cmd} = [];
|
|
$cases[$i]->{check} = [];
|
|
$cases[$i]->{cmdcheck} = [];
|
|
push(@rightcase, $name);
|
|
} else {
|
|
$skip = 1;
|
|
$i = $i + 1;
|
|
}
|
|
}
|
|
} elsif ($line =~ /^os\s*:\s*(\w[\w\,]+)/) {
|
|
next if $skip;
|
|
$string1 = $1;
|
|
if ($string1 =~ /^rhels\s*/ && -f "/etc/redhat-release") {
|
|
$cases[$i]->{os} = "rhels";
|
|
} elsif ($string1 =~ /^sles\s*/ && -f "/etc/SuSE-release") {
|
|
$cases[$i]->{os} = "sles";
|
|
} elsif ($string1 =~ /^ubuntu\s*/ && -f "/etc/lsb-release") {
|
|
$cases[$i]->{os} = "ubuntu";
|
|
}
|
|
else {
|
|
$cases[$i]->{os} = $string1;
|
|
|
|
}
|
|
|
|
chomp($cases[$i]->{os});
|
|
chomp($config{var}{OS});
|
|
if ($cases[$i]->{os} !~ /$config{var}{OS}/) {
|
|
if ((($config{var}{OS} =~ /^Linux\s*/i) && ($cases[$i]->{os} =~ /^aix\s*/i)) || (($config{var}{OS} =~ /^aix\s*/i) && ($cases[$i]->{os} !~ /^aix\s*/i)) || (($config{var}{OS} =~ /^rhels\s*/i) && ($cases[$i]->{os} !~ /^Linux\s*/i)) || (($config{var}{OS} =~ /^sles\s*/i) && ($cases[$i]->{os} !~ /^Linux\s*/i)) || (($config{var}{OS} =~ /^ubuntu\s*/i) && ($cases[$i]->{os} !~ /^Linux\s*/i))) {
|
|
push(@notrightcase, $cases[$i]->{name});
|
|
pop(@rightcase);
|
|
$skip = 1;
|
|
}
|
|
}
|
|
|
|
} elsif ($line =~ /^arch\s*:\s*(\w[\w\,]+)/) {
|
|
next if $skip;
|
|
$cases[$i]->{arch} = $1;
|
|
if ($cases[$i]->{arch} !~ /$config{var}{ARCH}/) {
|
|
push(@notrightcase, $cases[$i]->{name});
|
|
pop(@rightcase);
|
|
$skip = 1;
|
|
}
|
|
} elsif ($line =~ /^hcp\s*:\s*(\w[\w\,]+)/) {
|
|
next if $skip;
|
|
$cases[$i]->{hcp} = $1;
|
|
if ($cases[$i]->{hcp} !~ /$config{var}{HCP}/) {
|
|
push(@notrightcase, $cases[$i]->{name});
|
|
pop(@rightcase);
|
|
$skip = 1;
|
|
}
|
|
} elsif ($line =~ /^type\s*:\s*(\w[\w\,-]+)/) {
|
|
next if $skip;
|
|
$cases[$i]->{type} = $1;
|
|
if ($cases[$i]->{type} !~ /$config{var}{TYPE}/) {
|
|
push(@notrightcase, $cases[$i]->{name});
|
|
pop(@rightcase);
|
|
$skip = 1;
|
|
}
|
|
} elsif ($line =~ /^stop\s*:\s*(\w[\w\,]+)/) {
|
|
next if $skip;
|
|
$cases[$i]->{stop} = $1;
|
|
} elsif ($line =~ /^cmd\s*:\s*([\/\$\w].+)/) {
|
|
next if $skip;
|
|
$j = $j + 1;
|
|
$z = 0;
|
|
$cases[$i]->{cmd}->[$j] = &getvar($1);
|
|
if ($cases[$i]->{cmd}->[$j] eq '') {
|
|
close(FILE);
|
|
return 1;
|
|
}
|
|
} elsif ($line =~ /^check\s*:\s*(\w.+)/) {
|
|
next if $skip;
|
|
$cases[$i]->{check}->[$j][$z] = &getvar($1);
|
|
if ($cases[$i]->{check}->[$j][$z] eq '') {
|
|
close(FILE);
|
|
return 1;
|
|
}
|
|
$z = $z + 1;
|
|
} elsif ($line =~ /^cmdcheck\s*:\s*(\w.+)/) {
|
|
next if $skip;
|
|
$cases[$i]->{cmdcheck}->[$j][$z] = &getvar($1);
|
|
if ($cases[$i]->{cmdcheck}->[$j][$z] eq '') {
|
|
close(FILE);
|
|
return 1;
|
|
}
|
|
$z = $z + 1;
|
|
} elsif ($line =~ /^end/) {
|
|
next if $skip;
|
|
$i = $i + 1;
|
|
}
|
|
}
|
|
|
|
close(FILE);
|
|
}
|
|
|
|
if ($needshow) {
|
|
if (@cases) {
|
|
foreach my $case (@cases) {
|
|
log_this("$case->{name}");
|
|
}
|
|
}else {
|
|
log_this("Error: Please check the case name or command name");
|
|
}
|
|
log_this("Case name not supported:", @wrongnamecase) if (@wrongnamecase);
|
|
return 0;
|
|
}
|
|
|
|
if (@rightcase) {
|
|
log_this("To run:", @rightcase);
|
|
}else {
|
|
log_this("Error: No case to run, please check the case name or command name");
|
|
}
|
|
log_this("Not to run:", @notrightcase) if (@notrightcase);
|
|
log_this("Duplicated case:", @samecase) if (@samecase);
|
|
log_this("INCLUDEBAD case:", @errorcase) if (@errorcase);
|
|
log_this("Case name not supported:", @wrongnamecase) if (@wrongnamecase);
|
|
return 0;
|
|
}
|
|
sub getnodeattr
|
|
{
|
|
my ($node, $attr) = @_;
|
|
my @output = runcmd("lsdef -t node -o $node -i $attr");
|
|
my $t;
|
|
if ($::RUNCMD_RC) {
|
|
|
|
# return "Unknown";
|
|
foreach $t (1 .. 40) {
|
|
log_this("Error: could not get node attr $attr ");
|
|
@output = runcmd("lsdef -t node -o $node -i $attr");
|
|
last if ($::RUNCMD_RC == 0);
|
|
}
|
|
|
|
}
|
|
if ($::RUNCMD_RC == 0) {
|
|
foreach my $output1 (@output) {
|
|
if ($output1 =~ /$attr=(\w.+)/) {
|
|
log_this("$attr is $1");
|
|
return $1;
|
|
}
|
|
}
|
|
}
|
|
return "Unknown";
|
|
}
|
|
|
|
sub gettablevalue
|
|
{
|
|
my ($keyname, $key, $colname, $table) = @_;
|
|
my @output = runcmd("gettab $keyname=$key $table\.$colname");
|
|
return $output[0];
|
|
}
|
|
|
|
#to remove space and comment
|
|
sub trim
|
|
{
|
|
my $str = shift @_;
|
|
if ($str) {
|
|
|
|
# $str =~ s/\#/__wellnumber__/g;
|
|
$str =~ s/^\s+|#.+|\s+$//g;
|
|
|
|
# $str =~ s/__wellnumber__/#/g;
|
|
}
|
|
return $str;
|
|
}
|
|
|
|
sub getvar
|
|
{
|
|
my $str = shift @_;
|
|
while ($str =~ /\$\$(\w+)/) {
|
|
my $varname = $1;
|
|
if (exists($config{var}{$varname})) {
|
|
$str =~ s/\$\$$varname/$config{var}{$varname}/g;
|
|
} else {
|
|
log_this("Error: can't get varible $varname");
|
|
return '';
|
|
}
|
|
}
|
|
return $str;
|
|
}
|
|
|
|
sub getfunc
|
|
{
|
|
my $str = shift @_;
|
|
my $func = undef;
|
|
my @para = ();
|
|
my $parameter = undef;
|
|
my $value = undef;
|
|
while ($str =~ /__(\w+)\(([\s\,\w\$]*)\)__/) {
|
|
$func = $1;
|
|
$parameter = $2;
|
|
log_this("parameter is $parameter,fun is $func");
|
|
@para = split /\s*,\s*/, trim($parameter);
|
|
if ($func eq "GETNODEATTR") {
|
|
$value = getnodeattr(@para);
|
|
log_this("value is $value");
|
|
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;
|
|
}
|
|
|
|
sub runcase
|
|
{
|
|
my @output = ();
|
|
my $rc = 0;
|
|
my $j = 0;
|
|
my $z = 0;
|
|
my $lvalue = undef;
|
|
my $rvalue = undef;
|
|
my $op = undef;
|
|
my $failed = 0;
|
|
my $total = 0;
|
|
my $failnum = 0;
|
|
foreach my $case (@cases) {
|
|
my @record = ();
|
|
$failed = 0;
|
|
$j = 0;
|
|
$total = $total + 1;
|
|
my $now1 = timelocal(localtime());
|
|
my $time1 = scalar(localtime());
|
|
log_this("------START:$$case{name}::Time:$time1------");
|
|
push @record, "------START:$$case{name}::Time:$time1------";
|
|
push @record, "FILENAME:$$case{filename}";
|
|
|
|
foreach my $cmd (@{ $$case{cmd} }) {
|
|
$cmd = getfunc($cmd);
|
|
|
|
#by
|
|
my $runstart = timelocal(localtime());
|
|
log_this("\nRUN:$cmd");
|
|
push(@record, "\nRUN:$cmd");
|
|
@output = &runcmd($cmd);
|
|
$rc = $::RUNCMD_RC;
|
|
|
|
#by
|
|
my $runstop = timelocal(localtime());
|
|
my $diffduration = $runstop - $runstart;
|
|
log_this("\n[$cmd] Running Time:$diffduration sec");
|
|
push(@record, ("\n[$cmd] Running Time:$diffduration sec"));
|
|
|
|
log_this("RETURN: rc = $rc", "OUTPUT:", @output);
|
|
push(@record, ("RETURN rc = $rc", "OUTPUT:", @output));
|
|
|
|
|
|
foreach my $check (@{ $$case{check}->[$j] }) {
|
|
if ($failed) {
|
|
last;
|
|
}
|
|
if ($check =~ /rc\s*([=!]+)\s*(\d+)/) {
|
|
$lvalue = $rc;
|
|
$op = $1;
|
|
$rvalue = $2;
|
|
if ((($op eq '!=') && ($lvalue == $rvalue))
|
|
|| (($op eq '==') && ($lvalue != $rvalue))) {
|
|
$failed = 1;
|
|
}
|
|
if ($failed) {
|
|
log_this("CHECK:rc $op $rvalue\t[Failed]");
|
|
push(@record, "CHECK:rc $op $rvalue\t[Failed]");
|
|
last;
|
|
} else {
|
|
log_this("CHECK:rc $op $rvalue\t[Pass]");
|
|
push(@record, "CHECK:rc $op $rvalue\t[Pass]");
|
|
}
|
|
} elsif ($check =~ /output\s*([=!~]+)\s*(\S.*)/
|
|
&& $check !~ /output\s*([=!~])\1/) {
|
|
$lvalue = join("\n", @output);
|
|
$op = $1;
|
|
$rvalue = $2;
|
|
$rvalue = getfunc($rvalue);
|
|
if ((($op eq '=~') && ($lvalue !~ /$rvalue/))
|
|
|| (($op eq '!~') && ($lvalue =~ /$rvalue/))
|
|
|| (($op eq '==') && ($lvalue ne $rvalue))
|
|
|| (($op eq '!=') && ($lvalue eq $rvalue))) {
|
|
$failed = 1;
|
|
}
|
|
if ($failed) {
|
|
log_this("CHECK:output $op $rvalue\t[Failed]");
|
|
push(@record, "CHECK:output $op $rvalue\t[Failed]");
|
|
last;
|
|
} else {
|
|
log_this("CHECK:output $op $rvalue\t[Pass]");
|
|
push(@record, "CHECK:output $op $rvalue\t[Pass]");
|
|
}
|
|
} elsif ($check =~ /output\s*~~\s*(\S.*)/) {
|
|
$op = "~~";
|
|
$failed = 1;
|
|
$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) {
|
|
$failed = 0;
|
|
last;
|
|
}
|
|
} else {
|
|
next;
|
|
}
|
|
}
|
|
}
|
|
if ($failed) {
|
|
log_this("CHECK:output $op $rvalue $num\t[Failed]");
|
|
push(@record, "CHECK:output $op $rvalue\t[Failed]");
|
|
last;
|
|
} else {
|
|
log_this("CHECK:output $op $rvalue $num\t[Pass]");
|
|
push(@record, "CHECK:output $op $rvalue\t[Pass]");
|
|
}
|
|
}
|
|
}
|
|
foreach my $cmdcheck (@{ $$case{cmdcheck}->[$j] }) {
|
|
if ($cmdcheck) {
|
|
&runcmd($cmdcheck);
|
|
$rc = $::RUNCMD_RC;
|
|
if ($rc == 1) {
|
|
log_this("CMDCHECK:output $cmdcheck\t[Failed]");
|
|
push(@record, "CHECK:output $cmdcheck\t[Failed]");
|
|
} elsif ($rc == 0) {
|
|
log_this("CMDCHECK:output $cmdcheck\t[Pass]");
|
|
push(@record, "CHECK:output $cmdcheck\t[Pass]");
|
|
}
|
|
}
|
|
}
|
|
$j = $j + 1;
|
|
}
|
|
my $now2 = timelocal(localtime());
|
|
my $time2 = scalar(localtime());
|
|
my $diff = $now2 - $now1;
|
|
if ($failed) {
|
|
log_this("------END::$$case{name}::Failed::Time:$time2 ::Duration::$diff sec------");
|
|
push(@record, "------END::$$case{name}::Failed::Time:$time2 ::Duration::$diff sec------");
|
|
} else {
|
|
log_this("------END::$$case{name}::Passed::Time:$time2 ::Duration::$diff sec------");
|
|
push(@record, "------END::$$case{name}::Passed::Time:$time2 ::Duration::$diff sec------");
|
|
}
|
|
if ($failed) {
|
|
$failnum = $failnum + 1;
|
|
log_error(@record);
|
|
if (defined($$case{stop}) && ($$case{stop} =~ /^yes$/)) {
|
|
$stop_to_keep_env = 1;
|
|
last;
|
|
}
|
|
}
|
|
}
|
|
log_this("\n\n");
|
|
log_this("------Total: $total , Failed: $failnum------");
|
|
}
|
|
|
|
sub runcmd
|
|
{
|
|
my ($cmd) = @_;
|
|
my $rc = 0;
|
|
$::RUNCMD_RC = 0;
|
|
my $outref = [];
|
|
@$outref = `$cmd 2>&1`;
|
|
if ($?)
|
|
{
|
|
$rc = $?;
|
|
$rc = $rc >> 8;
|
|
$::RUNCMD_RC = $rc;
|
|
}
|
|
chomp(@$outref);
|
|
return @$outref;
|
|
|
|
}
|
|
|
|
sub usage
|
|
{
|
|
log_this("Usage:Run xcat test cases:");
|
|
log_this(" xcattest [-?|-h]");
|
|
log_this(" xcattest [-f configure file] [-b case bundle files]");
|
|
log_this(" xcattest [-f configure file] [-t cases list]");
|
|
log_this(" xcattest [-f configure file] [-c cmds list]");
|
|
log_this("Show xcat test cases, bundle files, commands lists:");
|
|
log_this(" xcattest [-b case bundle files] [-l]");
|
|
log_this(" xcattest [-t cases list] [-l]");
|
|
log_this(" xcattest [-c cmds list] [-l]");
|
|
log_this("Show all bundle files, all commands:");
|
|
log_this(" xcattest [-s command|bundle]");
|
|
log_this("");
|
|
return;
|
|
}
|
|
|
|
sub listbundlefiles
|
|
{
|
|
my @bundlefiles = ();
|
|
|
|
#get all .bundle files from /opt/xcat/share/xcat/tools/autotest/bundle/
|
|
opendir(DIR, $bundledir);
|
|
my @files = readdir(DIR);
|
|
foreach my $file (@files){
|
|
next if (-d $file);
|
|
if ($file =~ /\.bundle$/){
|
|
push(@bundlefiles, $file);
|
|
}
|
|
}
|
|
closedir(DIR);
|
|
|
|
#read all .bundle files, get descriptions for each file.
|
|
my $skip =0;
|
|
my $line;
|
|
foreach my $bundlefile (@bundlefiles) {
|
|
if (!open(FILE, "<$bundledir/$bundlefile")) {
|
|
log_this("Error: Can't open bundle file: $bundlefile");
|
|
log_this("Use 'xcattest -s bundle' to list out available bundles");
|
|
return 1;
|
|
}
|
|
$skip = 0;
|
|
while ($line = <FILE>) {
|
|
$line = &trim($line);
|
|
next if (length($line) == 0);
|
|
|
|
#description line is treated as a comment line for now
|
|
if ($line =~ /^description\s*:\s*(.*)/){
|
|
if (length($1) != 0) {
|
|
$bundlefilesinfo{$bundlefile} = $1;
|
|
$skip=1;
|
|
last;
|
|
}
|
|
}
|
|
}
|
|
close(FILE);
|
|
if (!$skip){
|
|
$bundlefilesinfo{$bundlefile} = "No description, add with \"description: details\" in bundle file";
|
|
}
|
|
}
|
|
&listformatbundleinfo(%bundlefilesinfo);
|
|
|
|
return 0;
|
|
}
|
|
|
|
sub listformatbundleinfo
|
|
{
|
|
my $maxlen = 0;
|
|
foreach my $filename (keys %bundlefilesinfo) {
|
|
$maxlen = length($filename) if (length($filename) > $maxlen);
|
|
}
|
|
$maxlen += 4;
|
|
|
|
my $desiredwidth = 120;
|
|
my $screenwidth = (`tput cols` + 0);
|
|
my $finallen = ($screenwidth > $desiredwidth ? $desiredwidth : $screenwidth);
|
|
|
|
print "bundle files and descriptions:\n";
|
|
|
|
foreach my $filename (sort { $a cmp $b } keys %bundlefilesinfo ) {
|
|
my @desc = split(" ", $bundlefilesinfo{$filename});
|
|
my $str = "";
|
|
my @formatdesc = ();
|
|
foreach my $word (@desc) {
|
|
if (length($str) + length($word) > $finallen - $maxlen) {
|
|
$str =~ s/([^\s]+)\s$/$1/g;
|
|
push @formatdesc, $str;
|
|
$str = "";
|
|
}
|
|
$str .= $word . " ";
|
|
}
|
|
$str =~ s/([^\s]+)\s$/$1/g;
|
|
push @formatdesc, $str;
|
|
|
|
print "$filename";
|
|
|
|
my $space = " " x ($maxlen - length($filename));
|
|
print "$space$formatdesc[0]\n";
|
|
delete $formatdesc[0];
|
|
$space = " " x $maxlen;
|
|
foreach my $line (@formatdesc) {
|
|
print "$space$line\n" if (length($line));
|
|
}
|
|
}
|
|
}
|
|
|
|
sub listcommands
|
|
{
|
|
my @files = ();
|
|
|
|
Get_Files_Recursive("$casedir");
|
|
for (my $countfile = 0 ; $countfile < @ filespath ; $countfile++)
|
|
{
|
|
if ($filespath[$countfile] =~ /testcase\/(.*)\/case/) {
|
|
log_this("$1");
|
|
}
|
|
}
|
|
}
|
|
|
|
sub getreport
|
|
{
|
|
open(INDOC, ">$_[1]") || die("open STDOUT failed");
|
|
print INDOC "Testcase Duration\n";
|
|
print INDOC "------------------------------------------------------------------------------\n";
|
|
close(INDOC);
|
|
open(STDOUT, ">>$_[1]") || die("open STDOUT failed");
|
|
open FD, "<$_[0]" or die "$?";
|
|
while (<FD>) {
|
|
if (/Time/) {
|
|
s/------//g;
|
|
$_ .= "\n" if /END/;
|
|
print STDOUT $_;
|
|
}
|
|
}
|
|
|
|
close(FD);
|
|
close(STDOUT);
|
|
}
|
|
|
|
|
|
sub reordercases
|
|
{
|
|
my @caserange = ();
|
|
my $line;
|
|
if ($bundlelist) {
|
|
my @bundles = split /,/, $bundlelist;
|
|
foreach my $bundle (@bundles) {
|
|
if (!open(FILE, "<$bundledir/$bundle")){
|
|
log_this("Error: Can't open bundle file: $bundle");
|
|
return 1;
|
|
}
|
|
while ($line = <FILE>) {
|
|
chomp($line);
|
|
next if ((length($line) == 0) || ($line =~ /^description\s*:\s*(.*)/));
|
|
push(@caserange, $line);
|
|
}
|
|
close(FILE);
|
|
my @refs=sort_caserange(@caserange);
|
|
@caserange=@{$refs[0]};
|
|
}
|
|
}
|
|
if ($caselist) {
|
|
@caserange = split /,/, $caselist;
|
|
}
|
|
|
|
my @tmpcases = ();
|
|
foreach my $case (@caserange) {
|
|
my $i = 0;
|
|
my $hit = 0;
|
|
foreach my $runcase (@cases) {
|
|
if ($runcase->{name} eq $case) {
|
|
$hit = 1;
|
|
last;
|
|
}
|
|
$i++;
|
|
next;
|
|
}
|
|
push(@tmpcases, $cases[$i]) if ($hit);
|
|
}
|
|
@cases = @tmpcases;
|
|
}
|
|
|
|
sub checkoptions
|
|
{
|
|
#-b,-c,-t,-s should be defined at least one
|
|
if (!defined($bundlelist) && !defined($caselist) && !defined($cmdlist) && !defined($showbundlesorcommands)) {
|
|
log_this("Error: please define options correctly, see below usage information:");
|
|
return 1;
|
|
}elsif ((defined($bundlelist) || defined($caselist) || defined($cmdlist)) && (! $needshow) && !defined($configinfo)) {
|
|
#config file must be defined if the using -c,-b,-t to run test cases
|
|
log_this("Error: To run test cases, please define the config file with -f option");
|
|
log_this(" To show test cases, please use the -l option");
|
|
return 1;
|
|
}elsif (defined($showbundlesorcommands) && (defined($bundlelist) || defined($caselist) || defined($cmdlist))) {
|
|
#-s can't be used together with -c,-b,-t
|
|
log_this("Error: -b,-c or -t can't be used together with -s");
|
|
return 1;
|
|
}elsif (defined($showbundlesorcommands) && $needshow) {
|
|
log_this("Error: -s, -l can't be used together");
|
|
return 1;
|
|
}
|
|
|
|
#check the -s option, the value should be bundle or command
|
|
if (defined($showbundlesorcommands)) {
|
|
if (($showbundlesorcommands ne "bundle") && ($showbundlesorcommands ne "command")) {
|
|
log_this("Error: please use \"bundle\" or \"command\" as the \-s value");
|
|
return 1;
|
|
}elsif ($showbundlesorcommands eq "bundle") {
|
|
$showbundlefiles = 1;
|
|
}else {
|
|
}
|
|
$showcommandslist= 1;
|
|
}
|
|
|
|
#get and check config file and System label
|
|
#this System label means only the [System] variable will be loaded
|
|
if (defined($configinfo)) {
|
|
if ($configinfo =~ /(.*):(.*)/) {
|
|
$configfile = $1;
|
|
$initallabel = $2;
|
|
if ($initallabel ne $loadsysteminfo) {
|
|
log_this("Error: $initallabel is not supported!");
|
|
return 1;
|
|
}
|
|
}else {
|
|
$configfile = $configinfo;
|
|
}
|
|
if (!(-e $configfile)) {
|
|
log_this("Error: Can't open config file: $configfile");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
#check bundle files
|
|
if (defined($bundlelist)) {
|
|
my @bundles = split /,/, $bundlelist;
|
|
foreach my $bundle (@bundles){
|
|
if ("$bundledir/$bundle" !~ /\.bundle$/) {
|
|
log_this("Error: please input the .bundle file");
|
|
log_this("Use 'xcattest -s bundle' to list all bundle files");
|
|
return 1;
|
|
}
|
|
if (!(-e "$bundledir/$bundle")) {
|
|
log_this("Error: Can't open bundle file: $bundle");
|
|
log_this("Use 'xcattest -s bundle' to list all bundle files");
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|