Commit 4dfe954b authored by Leigh Stoller's avatar Leigh Stoller

Various changes:

1. Support for Tour steps. See associated change in geni-lib.

2. Add regression testing of the Tour. I had left that out, now we are
   doing that.

3. Add option to rspec2genilib to not add the stub Tour description,
   since that makes regression testing difficult.
parent 85ff7cfe
......@@ -102,6 +102,7 @@ sub new($$)
/^description$/i && do {
my $type = GeniXML::FindAttr("type", $child);
my $text = $child->textContent();
$text =~ s/^\s+//;
# Kill terminating newline for rtecheck
chomp($text);
$text =~ s/\"/\\"/g;
......@@ -114,6 +115,7 @@ sub new($$)
/^instructions$/i && do {
my $type = GeniXML::FindAttr("type", $child);
my $text = $child->textContent();
$text =~ s/^\s+//;
# Kill terminating newline for rtecheck
chomp($text);
# This happens a lot.
......@@ -126,12 +128,37 @@ sub new($$)
}
last SWITCH;
};
fatal("Unknown element in rspec_tour: $name\n");
/^steps$/i && do {
my @steps = ();
foreach my $stepchild ($child->nonBlankChildNodes()) {
my ($ns,$name) = split(":", $stepchild->nodeName);
$name = $ns if (!defined($name));
if ($name ne "step") {
fatal("Unknown element in steps: $name");
}
my $type = GetTextOrFail("point_type", $stepchild);
my $id = GetTextOrFail("point_id", $stepchild);
my $desc = FindFirst("n:description", $stepchild);
my $text = $desc->textContent();
# Kill terminating newline for rtecheck
chomp($text);
push(@steps, {
"type" => $type,
"id" => $id,
"description" => $text});
}
# We see a lot of empty steps
$tour->{'steps'} = \@steps
if (scalar(@steps));
last SWITCH;
};
fatal("Unknown element in rspec_tour: $name");
};
}
return
if (! (exists($tour->{"description"}) ||
exists($tour->{"instructions"})));
exists($tour->{"instructions"}) ||
exists($tour->{"steps"})));
$self->{'tour'} = $tour;
};
......@@ -280,6 +307,16 @@ sub instructions($)
return $self->tour()->{'instructions'};
}
sub steps($)
{
my ($self) = @_;
return undef
if (!defined($self->tour()) ||
!exists($self->tour()->{'steps'}));
return $self->tour()->{'steps'};
}
sub addNode($$)
{
my ($self, $node) = @_;
......@@ -366,7 +403,7 @@ sub CompareValues($$$)
if (!defined($val1));
$val2 = "undef"
if (!defined($val2));
print STDERR "$text: $val1 != $val2\n";
print STDERR "$text: '$val1' != '$val2'\n";
return 1;
}
......@@ -413,6 +450,10 @@ sub CompareHashes($$$)
return 1
if (CompareHashes("$text: $key", $v1, $v2));
}
elsif (ref($v1) eq "ARRAY") {
return 1
if (CompareLists("$text: $key", $v1, $v2));
}
# Hmm, we assume all blessed refs are our own and have compare methods.
elsif (blessed($v1)) {
return 1
......@@ -508,7 +549,7 @@ sub Compare($$)
/^tour$/i && do {
# Need to deal with whitespace changes.
return 1
if (0 && APT_Rspec::CompareHashes($key, $val1, $val2));
if (APT_Rspec::CompareHashes($key, $val1, $val2));
last SWITCH;
};
/^(bscounter|namespaces|nodelist|linklist)$/i && do {
......@@ -1031,7 +1072,7 @@ sub addNode($$$)
# Maybe we should do something comment lines.
last SWITCH;
};
/^(vnode|host)$/i && do {
/^(vnode|host|location)$/i && do {
# Manifest crap.
last SWITCH;
};
......
......@@ -36,19 +36,22 @@ sub usage()
{
print STDERR "Usage: checkprofile [-a | pid,name]\n";
print STDERR "Options:\n";
print STDERR" -a : Run rspec2genilib converter on all rspec profiles\n";
print STDERR" -r : Run converted geni-lib\n";
print STDERR" -c : Compare rspecs after running geni-lib\n";
print STDERR" -t : Run RTE check on converted geni-lib script\n";
print STDERR" -g : Print the geni-lib\n";
print STDERR" -x : Only include rspecs with matching token\n";
print STDERR " -a : Run rspec2genilib converter on all rspec profiles\n";
print STDERR " -r : Run converted geni-lib\n";
print STDERR " -c : Compare rspecs after running geni-lib\n";
print STDERR " -t : Run RTE check on converted geni-lib script\n";
print STDERR " -g : Print the geni-lib\n";
print STDERR " -s : Print rspec before and after\n";
print STDERR " -x : Only include rspecs with matching token\n";
print STDERR " -G : Also test script based profiles, no RTE of course\n";
exit(-1);
}
my $optlist = "dargscx:t";
my $optlist = "dargscx:tG";
my $debug = 0;
my $all = 0;
my $regress = 0;
my $compare = 0;
my $doscript = 0;
my $printgl = 0;
my $printrspec = 0;
my $rtecheck = 0;
......@@ -67,7 +70,8 @@ my $XMLLINT = "/usr/local/bin/xmllint";
# Protos
sub fatal($);
sub ConvertProfile($);
sub CheckProfile($);
sub CheckScriptProfile($);
#
# Turn off line buffering on output
......@@ -115,6 +119,9 @@ if (defined($options{"c"})) {
if (defined($options{"g"})) {
$printgl = 1;
}
if (defined($options{"G"})) {
$doscript = 1;
}
if (defined($options{"s"})) {
$printrspec = 1;
}
......@@ -122,7 +129,7 @@ if (defined($options{"t"})) {
$rtecheck = 1;
}
if (defined($options{"x"})) {
$clause = "and rspec like '%" . $options{"x"} . "%'";
$clause = "where rspec like '%" . $options{"x"} . "%'";
}
usage()
if (!$all && @ARGV != 1);
......@@ -134,7 +141,7 @@ if (!$all) {
}
}
if (defined($profile)) {
exit(ConvertProfile($profile));
exit(CheckProfile($profile));
}
else {
#
......@@ -144,24 +151,40 @@ else {
DBQueryFatal("select p.profileid from apt_profiles as p ".
"left join apt_profile_versions as v on ".
" v.profileid=p.profileid and v.version=p.version ".
"where v.script is null $clause ".
"$clause ".
"order by p.pid,p.name");
my $count = 0;
my $errors = 0;
while (my ($id) = $query_result->fetchrow_array()) {
my $profile = APT_Profile->Lookup($id);
next
if (!defined($profile));
next
if (defined($profile->script()) && !$doscript);
print "Converting $profile\n";
ConvertProfile($profile);
$count++;
$errors++
if (CheckProfile($profile));
}
print "##########\n";
print "$count profiles, $errors failed\n";
}
#
# Run the converter on a profile.
#
sub ConvertProfile($)
sub CheckProfile($)
{
my ($profile) = @_;
#
# We test script based profiles differently.
#
if (defined($profile->script())) {
return CheckScriptProfile($profile);
}
my ($in, $filename) = tempfile("/tmp/convertXXXXX", UNLINK => 1);
if (!defined($in)) {
fatal("Could not open temporary file for rspec");
......@@ -171,7 +194,7 @@ sub ConvertProfile($)
if ($printrspec) {
system("$XMLLINT --format $filename");
}
my $output = emutil::ExecQuiet("$CONVERTER $filename");
my $output = emutil::ExecQuiet("$CONVERTER -t $filename");
if ($?) {
#print STDERR $profile->rspec() . "\n";
print STDERR $output;
......@@ -235,6 +258,63 @@ sub ConvertProfile($)
return -1;
}
#
# Check a script based profile.
#
sub CheckScriptProfile($)
{
my ($profile) = @_;
my ($in, $filename) = tempfile("/tmp/convertXXXXX", UNLINK => 1);
if (!defined($in)) {
fatal("Could not open temporary file for script");
return -1;
}
print $in $profile->script();
my $output = emutil::ExecQuiet("$RUNGENILIB $filename");
if ($?) {
print STDERR $output;
print STDERR "*** $RUNGENILIB failed\n";
goto bad;
}
if ($printgl) {
print $profile->script() . "\n";
}
if ($printrspec) {
print $output . "\n";
}
if ($regress) {
if ($compare) {
#
# Compare current rspec against newly generated rspec.
#
my $rspec1 = eval { APT_Rspec->new($profile->rspec()) };
if ($@) {
print STDERR $@;
print STDERR "*** Could not parse profile rspec into object\n";
goto bad;
}
my $rspec2 = eval { APT_Rspec->new($output) };
if ($@) {
print STDERR $@;
print STDERR "*** Could not parse output rspec into object\n";
goto bad;
}
if ($rspec1->Compare($rspec2)) {
print STDERR "*** rspecs comparison failed\n";
goto bad;
}
}
}
unlink0($in, $filename);
return 0;
bad:
unlink0($in, $filename);
return -1;
}
exit(0);
sub fatal($) {
......
......@@ -43,13 +43,13 @@ sub usage()
print STDERR " -o file - Specify output file for geni-lib\n";
print STDERR " -s file - Specify output file for post geni-lib rspec\n";
print STDERR " -r - Regression test; run geni-lib, compare rspecs\n";
print STDERR " -t - Do not spit out the Tour (for regression)\n";
print STDERR " -t - Do not add stub docstring (for regression)\n";
exit(-1);
}
my $optlist = "do:rs:t";
my $debug = 0;
my $regress = 0;
my $notour = 0;
my $nodocstr = 0;
my $ofile;
my $rfile;
......@@ -104,13 +104,14 @@ if (defined($options{"d"})) {
$debug = 1;
}
if (defined($options{"t"})) {
$notour = 1;
$nodocstr = 1;
}
if (defined($options{"o"})) {
$ofile = $options{"o"};
}
if (defined($options{"r"})) {
$regress = 1;
$regress = 1;
$nodocstr = 1;
if (defined($options{"s"})) {
$rfile = $options{"s"};
}
......@@ -589,21 +590,53 @@ sub SpitTour($$)
my $description = $rspec->description();
my $instructions = $rspec->instructions();
return
if ($nodocstr &&
! ((defined($description) && $description->{"text"} ne "") ||
(defined($instructions) && $instructions->{"text"} ne "")));
my $docstring = '"""';
if (defined($description)) {
$docstring .= $description->{'text'};
}
else {
$docstring .= "Please give this script a description.";
if ($nodocstr) {
$docstring .= "\n";
}
else {
$docstring .= "Please give this script a description.";
}
}
if (defined($instructions)) {
$docstring .= "\n\n" . "Instructions:" . "\n" . $instructions->{'text'};
my $text = $instructions->{'text'};
$docstring .= "\n\n" . "Instructions:" . "\n" . $text;
}
$docstring .= '"""';
print $where $docstring . "\n\n";
}
sub SpitSteps($$)
{
my ($rspec, $where) = @_;
my $steps = $rspec->steps();
return
if (!defined($steps) || !scalar(@{$steps}));
print $where "# Create a Tour object and the steps to it\n";
print $where "tour = emulab.Tour()\n";
print $where "tour.useDocstring()\n";
foreach my $step (@{$steps}) {
my $type = $step->{"type"};
my $id = $step->{"id"};
my $desc = $step->{"description"};
$desc =~ s/\"/\\"/g;
print $where "tour.addStep('$id', '$type', \"$desc\")\n";
}
print $where "request.addTour(tour)\n\n\n";
}
sub SpitPreamble($)
{
my ($where) = @_;
......@@ -685,8 +718,9 @@ if (!defined($outfd)) {
fatal("Could not open temporary file for result rspec");
return -1;
}
SpitTour($rspec, $outfd) if (!$notour);
SpitTour($rspec, $outfd);
SpitPreamble($outfd);
SpitSteps($rspec, $outfd);
SpitNodeStatements($rspec, $outfd);
SpitLinkStatements($rspec, $outfd);
SpitTopLevelStatements($rspec, $outfd);
......
......@@ -135,7 +135,7 @@ if (!defined($fd)) {
}
print $fd $rspec;
my $genilib = emutil::ExecQuiet("$RSPECTOGENILIB $filename");
my $genilib = emutil::ExecQuiet("$RSPECTOGENILIB -t $filename");
if ($?) {
print STDERR $genilib;
print STDERR "Could not convert rspec back to geni-lib\n";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment