From: Konrad Rzeszutek Wilk Date: Tue, 25 Jul 2017 16:53:28 +0000 (-0400) Subject: livepatch: Add livepatch_test.pl test-case X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=b8f2451110e9cced08d7e5f621b5b0e7fd9e20d3;p=xentesttools%2Fbootstrap.git livepatch: Add livepatch_test.pl test-case which mirrors what is in OSSTest but is standalone. Signed-off-by: Konrad Rzeszutek Wilk --- diff --git a/root_image/debugspace/livepatch_test.pl b/root_image/debugspace/livepatch_test.pl new file mode 100755 index 0000000..37fb668 --- /dev/null +++ b/root_image/debugspace/livepatch_test.pl @@ -0,0 +1,160 @@ +#!/usr/bin/perl -w +# Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved. +# + +use Data::Dumper; +use File::Temp qw(tempfile); + + +my @livepatch_files = qw(xen_hello_world.livepatch + xen_replace_world.livepatch + xen_bye_world.livepatch + xen_nop.livepatch); + +my $livepatch_dir="/usr/lib/debug/livepatch"; +my $xen_extra_info; +my $xen_minor_ver; + +sub populate_data { + my @lines = split('\n', $_); + foreach my $line (@lines) { + my ($key, $values) = split /:/, $line; + $values = join("", $values); + chomp($values); + if ($key =~ m/xen_extra/) { + $xen_extra_info = $values; + } + if ($key =~ m/xen_minor/) { + $xen_minor_ver = $values; + } + } + return 1 if $xen_extra_info && $xen_minor_ver; + return 0; +} + +sub check_for_hello_world { + return m/xen_extra/ && m/Hello World/; +} + +sub check_for_stock { + return m/xen_extra/ && m/$xen_extra_info/; +} + +# Make sure the xen_major or xen_minor are not the same as +# $xen_major_ver or $xen_minor_ver +sub check_versions { + my @lines = split('\n', $_); + foreach my $line (@lines) { + my ($key, $values) = split /:/, $line; + $values = join("", $values); + chomp($values); + if ($key =~ m/xen_minor/) { + if ($values ne $xen_minor_ver ) { + return 1; + } + } + } + return 0; +} + +my @livepatch_tests = ( + # Whether we can actually execute it. + { C => "xen-livepatch list" }, + # And we better have a clean slate.. + { C => "xen-livepatch list", OutputCheck => sub { return !m/xen_/; } }, + # Sets the default values + { C => "xl info", OutputCheck => \&populate_data }, + # Sanity check that populate_data did its job. + { C => "xl info", + OutputCheck => \&check_for_stock }, + # Let it rip! + { C => "xen-livepatch revert xen_hello_world", rc => 256 }, + { C => "xen-livepatch load xen_hello_world.livepatch" }, + { C => "xen-livepatch load xen_hello_world.livepatch", rc => 256 }, + { C => "xen-livepatch list", + OutputCheck => sub { m/xen_hello_world/ } }, + { C => "xl info", + OutputCheck => \&check_for_hello_world }, + { C => "xen-livepatch revert xen_hello_world" }, + { C => "xl info", + OutputCheck => \&check_for_stock }, + { C => "xen-livepatch unload xen_hello_world" }, + { C => "xen-livepatch unload xen_hello_world", rc => 256 }, + { C => "xl info", + OutputCheck => \&check_for_stock }, + { C => "xen-livepatch load xen_hello_world.livepatch" }, + { C => "xl info", + OutputCheck => \&check_for_hello_world }, + { C => "xen-livepatch load xen_bye_world.livepatch" }, + { C => "xl info", + OutputCheck => sub { m/xen_extra/ && m/Bye World/ } }, + { C => "xen-livepatch upload xen_replace xen_replace_world.livepatch" }, + { C => "xen-livepatch replace xen_replace" }, + { C => "xl info", + OutputCheck => sub { m/xen_extra/ && m/Hello Again Wo/ } }, + { C => "xen-livepatch apply xen_hello_world", rc => 256 }, + { C => "xen-livepatch apply xen_bye_world", rc => 256 }, + { C => "xen-livepatch apply xen_replace" }, + { C => "xen-livepatch revert xen_replace" }, + { C => "xen-livepatch unload xen_replace" }, + { C => "xen-livepatch unload xen_hello_world" }, + { C => "xen-livepatch unload xen_bye_world" }, + { C => "xen-livepatch list", + OutputCheck => sub { !m/xen_/ } }, + { C => "xl info", + OutputCheck => \&check_for_stock }, + { C => "xen-livepatch load xen_nop.livepatch" }, + { C => "xen-livepatch revert xen_nop" }, + { C => "xen-livepatch apply xen_nop" }, + { C => "xl info", + OutputCheck => \&check_versions }, + { C => "xen-livepatch unload xen_nop", rc => 256 }, + { C => "xen-livepatch revert xen_nop" }, + { C => "xen-livepatch unload xen_nop" }, + ); + +# Copied from https://stackoverflow.com/questions/11514947/capture-the-output-of-perl-system +sub mysystem { + my $cmd = shift; #"rsync -avz --progress -h $fullfile $copyfile"; + my ($fh, $filename) = tempfile(); + # http://stackoverflow.com/a/6872163/2923406 + # I want to have rsync progress output on the terminal AND capture it in case of error. + # Need to use pipefail because 'tee' would be the last cmd otherwise and hence $? would be wrong. + my @cmd = ("bash", "-c", "set -o pipefail && $cmd 2>&1 | tee $filename"); + my $ret = system(@cmd); + my $outerr = join('', <$fh>); + close $fh; + system("rm $filename"); + return ($ret,$outerr); +} + +sub livepatch_test () { + print "Have ".(scalar @livepatch_tests)." test-cases\n"; + my $rc; + my $output; + + foreach my $test (@livepatch_tests) { + # Default rc is zero. + my $expected_rc = defined($test->{rc}) ? $test->{rc} : 0; + my $cmd = "(set -e;cd $livepatch_dir;$test->{C})"; + print "Executing: '$cmd' .."; + my ($rc, $output)=mysystem($cmd); + + if ($rc != $expected_rc) { + print "FAILED (got $rc, expected: $expected_rc): \n"; + die $rc; + } + if (defined($test->{OutputCheck})) { + $_ = $output; + $rc=$test->{OutputCheck}->(); + if ($rc ne 1) { + die "FAILED! OutputCheck=$test->{OutputCheck}, input=$output\n"; + } + } + } + return 0; +} + +my $livepatch_result = livepatch_test(); +print("Livepatch test returned $livepatch_result"); +exit $livepatch_result; diff --git a/root_image/etc/init.d/rcS b/root_image/etc/init.d/rcS index c1490c4..3813e1e 100755 --- a/root_image/etc/init.d/rcS +++ b/root_image/etc/init.d/rcS @@ -181,6 +181,9 @@ if [ $? == 0 ]; then reboot fi ;; + livepatch) + /livepatch_test.pl + ;; esac fi echo "while (true); do if [ -e /tmp/go ]; then sleep 2;init -q; rm /tmp/go; break; fi; sleep 1; echo "."; done" >> /tmp/reinit