From 586a59e00d00f2b1347f015911545b722f2d1f8b Mon Sep 17 00:00:00 2001 From: Romain d'Alverny Date: Mon, 5 Dec 2011 22:55:33 +0000 Subject: First import, test suite attempt for built ISOs Code heavily taken from previous dams work, reorganized in a test suite to better separate test cases. Does basic things already (in t/). Needs more fixes (esp. in t_install_iso/). --- README.txt | 35 +++++++++++++ Tools.pm | 35 +++++++++++++ t/000_test_env.t | 24 +++++++++ t/001_check_file.t | 97 +++++++++++++++++++++++++++++++++++++ t/003_is_hybrid.t | 82 +++++++++++++++++++++++++++++++ t_install_iso/010_check_autorun.t | 94 +++++++++++++++++++++++++++++++++++ t_install_iso/011_check_idx.t | 78 +++++++++++++++++++++++++++++ t_install_iso/012_check_ids.t | 22 +++++++++ t_install_iso/013_check_rpms.t | 31 ++++++++++++ t_install_iso/014_check_bad_words.t | 27 +++++++++++ t_install_iso/016_check_pubkey.t | 95 ++++++++++++++++++++++++++++++++++++ test_iso.pl | 57 ++++++++++++++++++++++ 12 files changed, 677 insertions(+) create mode 100644 README.txt create mode 100644 Tools.pm create mode 100644 t/000_test_env.t create mode 100644 t/001_check_file.t create mode 100644 t/003_is_hybrid.t create mode 100644 t_install_iso/010_check_autorun.t create mode 100644 t_install_iso/011_check_idx.t create mode 100644 t_install_iso/012_check_ids.t create mode 100644 t_install_iso/013_check_rpms.t create mode 100644 t_install_iso/014_check_bad_words.t create mode 100644 t_install_iso/016_check_pubkey.t create mode 100644 test_iso.pl diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..7bd0373 --- /dev/null +++ b/README.txt @@ -0,0 +1,35 @@ +Mageia ISO check script +======================= + +Test suite for ISOs built for Mageia. +All ISOs should pass this test suite after being built, before being released. + +License: GPL-2+ +Code: svn://svn.mageia.org/svn/soft/isocheck + http://svnweb.mageia.org/soft/isocheck +Doc: https://wiki.mageia.org/Isocheck + +Requirements +------------ + +User running this script must be able to mount an ISO image. + +Depends on: + - cdrkit, cdrkit-isotools + - gpg + - mono + - Perl + - Test::Most + - TAP::Harness + + +TODO +---- + - clean up + - handle properly DVDs, CDs, LiveCDs + - fix t_install_iso tests (ids, idx, rpms, pubkey - especially cauldron/stable) + + +Style +----- + - 4 spaces indent, no tab \ No newline at end of file diff --git a/Tools.pm b/Tools.pm new file mode 100644 index 0000000..2e4ce72 --- /dev/null +++ b/Tools.pm @@ -0,0 +1,35 @@ +# +# + +package Tools; + +use strict; +use warnings; + +our $VERSION = '0.1'; + +use base 'Exporter'; + +#our @EXPORT = qw(parse_mageia_iso_name); + +sub parse_mageia_iso_name { + my ($name) = @_; + my %info = (); + + if ($name =~ m/^(Mageia)-(\d+)(-(alpha|beta|RC)(\d*))?(-(.*))?-(i586|x86_64|dual)?(-(CD|DVD|BD))?(-(build\_\w+))?\.(.*)$/) { + $info{"full"} = $name; + $info{"name"} = $1 if defined $1; + $info{"version"} = $2 if defined $2; + $info{"release"} = "$4$5" if defined $4; + $info{"variant"} = $7 if defined $7; + $info{"arch"} = $8 if defined $8; + $info{"medium"} = $10 if defined $10; + $info{"build"} = $12 if defined $12; + $info{"ext"} = $13 if defined $13; + + } + + return %info; +} + +1; diff --git a/t/000_test_env.t b/t/000_test_env.t new file mode 100644 index 0000000..9484e5b --- /dev/null +++ b/t/000_test_env.t @@ -0,0 +1,24 @@ +# +# These tests check that the testing environment is complete. +# + +use Test::Most; + +bail_on_fail; + +my ($image_path) = @ARGV; + +# FIXME why need to be root? for mounting the ISO only? +# FIXME USER or USERNAME? +is($ENV{USERNAME}, 'root', "Current user is root."); + +# TODO move this elsewhere maybe? +sub pkg_check { my ($pkg) = @_; return system("rpm -q $pkg >/dev/null"); } + +my @packages = qw(cdrkit cdrkit-isotools mono gnupg); + +foreach my $p (@packages) { + is(pkg_check($p), 0, sprintf("%s is installed.", $p)); +} + +done_testing(); diff --git a/t/001_check_file.t b/t/001_check_file.t new file mode 100644 index 0000000..f82b149 --- /dev/null +++ b/t/001_check_file.t @@ -0,0 +1,97 @@ +# +# +# + +use Test::Most; +use File::Basename; +use Tools; + +my ($image_path) = @ARGV; + +my $name = basename($image_path); +my %info = (); + +bail_on_fail; + +note $image_path; +note $name; + +%info = Tools::parse_mageia_iso_name($name); +if (scalar %info) { + pass 'ISO has valid filename.'; + while (my ($k, $v) = each %info) { + note uc($k), "=$v\n"; + } +} else { + fail 'ISO has valid filename.'; + diag 'See https://wiki.mageia.org/en/Product_naming'; +} + +# are files available? +ok -r $image_path, 'ISO file is readable.' + or diag("$image_path: $!"); + +# is file size correct? +my $du = `du --apparent-size --block-size=M $image_path`; +my @size_name = split(/\t/, $du); +my $size = $size_name[0]; + +# FIXME put correct sizes here +my %max_sizes = ( "CD" => "740M", "DVD" => "4200M" ); +ok ($size le $max_sizes{$info{"medium"}}, + sprintf("File has a working size (%s) for its medium type (%s, max %s).", + $size, $info{"medium"}, $max_sizes{$info{"medium"}})); + +# +ok -r $image_path . '.md5', 'MD5 checksum is available.'; +ok -r $image_path . '.sha1', 'SHA1 checkum is available.'; + +TODO: { + local $TODO = ".idx & .lst" if 1; + + ok -r $image_path, '.idx list file is available.'; + ok -r $image_path, '.lst list file is available.'; +} + + +# verify checksums +my $md5file = $image_path . '.md5'; +my $sha1file = $image_path . '.sha1'; + +my @ts = split(/ /, `md5sum $image_path`); +my $md5 = $ts[0]; +@ts = split(/ /, `cat $md5file`); +$md5file = $ts[0]; +is ($md5, $md5file, 'MD5/.md5 checksums match.'); + +@ts = split(/ /, `sha1sum $image_path`); +my $sha1 = $ts[0]; +@ts = split(/ /, `cat $sha1file`); +$sha1file = $ts[0]; +is ($sha1, $sha1file, 'SHA1/.sha1 checksums match.'); + + +# inspect iso definition +my $volume_id = `isoinfo -d -i $image_path | grep "Volume id"`; +my @info = (0, 0, 0, 0); +my @temp = split(/ /, $volume_id); + +note ('TODO, test to check here!'); + + +# bootable? +ok (`isoinfo -d -i $image_path | grep bootable`, 'ISO is bootable.'); + +# TODO check burnable? +my $burner = "/dev/sr0"; + +# FIXME is -eject really needed? +my $_burning = `cdrecord -dummy speed=42 dev=$burner -v -eject -data $image_path 2> is_burnable.log`; +my $result = `cat is_burnable.log | grep overburn | wc -l | tr -d '\n'`; + +-r "is_burnable.log" and system "rm is_burnable.log"; + +is ($result, 0, "ISO can be burnt."); + + +done_testing(); diff --git a/t/003_is_hybrid.t b/t/003_is_hybrid.t new file mode 100644 index 0000000..37ccbcd --- /dev/null +++ b/t/003_is_hybrid.t @@ -0,0 +1,82 @@ +# +# +# +use Test::Most; + +bail_on_fail; + +my ($image_path) = @ARGV; + +ok (is_hybrid($image_path, 0), "Is hybrid"); + +# Verification if the Iso is hybrid +sub is_hybrid { + my ($img, $full) = @_; + + open(my $iso, $img); + my $hybrid = hybrid1($iso); + $hybrid &= hybrid2($iso); + $hybrid &= hybrid3($iso); + if ($full) { + # system "dd if=$img of=/dev/my-pendrive bs=8"; + } + close($iso); + + return $hybrid; +} + + +# Check the first 512 bytes of the iso +sub hybrid1 { + my ($iso) = @_; + my $buffer; + my $hybrid; + + foreach (0 .. 512) { + read($iso, $buffer, 1); + if ($buffer ne '\x00') { + $hybrid = 1; + } + } + + return $hybrid; +} + +#Check the 0x1fe & 0x1ff bytes of the iso +sub hybrid2 { + my ($iso) = @_; + my $hybrid; + my $buffer; + my $byte = "\x55"; + + seek($iso, 0x1fe, 0); + read($iso, $buffer, 1); + if ($buffer eq $byte) { + read($iso, $buffer, 1); + $byte = "\xaa"; + if ($buffer eq $byte) { + $hybrid = 1; + } + } + + return $hybrid; +} + +# check from the 0x200 to the 0x8000 bytes +sub hybrid3 { + my ($iso) = @_; + my $hybrid = 1; + my $buffer; + + seek($iso, 0x200, 0); + foreach (0x200 .. 0x8000) { + read($iso, $buffer, 1); + if ($buffer eq '\x00') { + $hybrid = 0; + } + } + + return $hybrid; +} + +done_testing(); diff --git a/t_install_iso/010_check_autorun.t b/t_install_iso/010_check_autorun.t new file mode 100644 index 0000000..757951e --- /dev/null +++ b/t_install_iso/010_check_autorun.t @@ -0,0 +1,94 @@ +# +# Check autorun +# +use Test::Most tests => 13; +use File::Basename; +use Tools; + +my ($image_path) = @ARGV; + +my $name = basename($image_path); + +bail_on_fail; + +set_failure_handler( sub { + print "umount iso\n"; + system 'umount /media/iso_check; rm -r /media/iso_check'; +}); + +my %info = Tools::parse_mageia_iso_name($name); +skip 'Autorun is only on DVDs.', 13 unless $info{"medium"} eq 'DVD'; + +# +ok (-r "/media/iso_check/autorun.inf", 'autorun.inf is there'); + +BAIL_OUT('Autorun stuff is missing anyway.') if !(-r "/media/iso_check/autorun.inf"); + +# +my $lines = `cat -e /media/iso_check/autorun.inf | wc -l`; +my $num = `cat -e /media/iso_check/autorun.inf | grep "\\^M" | wc -l`; +chomp($num); +chomp($lines); +my $last = `cat -e /media/iso_check/autorun.inf | tail -n 1 | grep "\\^M" | wc -l`; + +# TODO rewrite this +if ( ($lines != $num && $lines - 1 != $num) + || ($lines == 0) + || ($lines -1 == $num && $last == 1)) { + fail('autorun.inf valid EOL chars'); +} else { + pass('autorun.inf valid EOL chars'); +} + +# +my $directory; +$directory = "/media/iso_check/autorun/" if -r "/media/iso_check/autorun"; +$directory = "/media/iso_check/dosutils/autorun/" if -r "/media/iso_check/dosutils/autorun"; +ok -r $directory, 'dosutils directory is there'; + +# +my $exe = $directory . "autorun.exe"; +ok -r $exe, 'autorun.exe is there'; + +BAIL_OUT('autorun.exe is not here.') if !(-r $exe); + +# +my $file = $directory . "autorun.ico"; +$file = $directory . "mageia.ico" if !(-r $file); +ok -r $file, 'autorun.ico is there'; + +# +foreach my $a ("de-DE/", "es-ES/", "fr-FR/", "it-IT/", "pt-BR/", "ru-RU/", "zh-CN/") { + $file = $directory . $a . "autorun.resources.dll"; + ok -r $file, "$file is there"; +} + +# FIXME what does this do? does it work? +# in the meantime, skipped +SKIP: { + skip 'Not clear what this does', 1 unless 0; + + my $_cp = `cp $exe .`; + eval { + local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required + alarm 5; + my $_nread = sysread my $_SOCKET, my $_buffer, my $_size; + my $_mono = `mono autorun.exe 2> autorun_exe.log`; + alarm 0; + if ($@) { + die unless $@ eq "alarm\n"; # propagate unexpected errors + # timed out + } else { + # didn't + } + }; + + open(my $exe_log, 'autorun_exe.log'); + my $line = <$exe_log>; + + isnt (substr($line, 0, 20), 'Cannot open assembly', 'autorun.exe is launchable'); + + my $_rm = `rm autorun.exe autorun_exe.log`; +} + +done_testing(); diff --git a/t_install_iso/011_check_idx.t b/t_install_iso/011_check_idx.t new file mode 100644 index 0000000..de9b8bb --- /dev/null +++ b/t_install_iso/011_check_idx.t @@ -0,0 +1,78 @@ +# TODO +# +# +use Test::Most; + +bail_on_fail; + +SKIP: { + skip "TODO", 1 unless 0; +} + +done_testing(); + +# get the product to verify in idxlist +sub check_idx { + my ($log, $distro, $image, $verbo) = @_; + my $idx; + my $valid = 1; + my $col; + $col = 0 if member($distro, qw(Free FREE)); + $col = 2 if member($distro, qw(PWP Powerpack)); + $col = 3 if member($distro, qw(One ONE one)); + $col = 1 if -r "/media/iso_check/i586/" && -r "/media/iso_check/x86_64/"; + if ($col == 3) { + substr($image, -3 , 3) = ''; + $idx = $image . "lst"; + $valid &= check_idx_list($idx, $log, $col, $verbo) if -r $idx && -r "idxlist"; + } + else { + substr($image, -3 , 3) = ''; + $idx = $image . "idx"; + $valid &= check_idx_list($idx, $log, $col, $verbo) if -r $idx && -r "idxlist"; + } + + return $valid; +} + + +# Verification of the presence of the packages on the iso +sub check_idx_list { + my ($idx, $log, $col, $verb) = @_; + my $pkg; + my $valid = 1; + my $file; + my @media; + + print "\n" if $verb; + print $log "\n"; + + open(my $list, 'idxlist') or fail('check_idx_list'); + while ($pkg = <$list>) { + if (substr($pkg, 0, 1) ne '#') { + chomp($pkg); + @media = split(/ /, $pkg); + if ($media[$col] == 1) { + $file = `cat $idx | cut -d ' ' -f 2 | grep $media[4]` if $col != 3; + $file = `cat $idx | grep $media[4]` if $col == 3; + if ($file eq '') { + print $log "$media[4] NOT FOUND in $idx\n"; + print "$media[4] NOT FOUND in $idx\n" if $verb; + $valid = 0; + } + else { + print $file if $verb; + #print $log $file; + } + } + } + } + print $log "\n"; + print $log "Comparison between idxlist and .idx OK\n" if $valid != 0; + print $log "Comparison between idxlist and .idx NOT OK\n" if $valid == 0; + print "\n" if $verb; + print "Comparison between idxlist and .idx: OK\n" if $valid != 0 && $verb; + print "Comparison between idxlist and .idx: NOT OK\n" if $valid == 0 && $verb; + + return $valid; +} diff --git a/t_install_iso/012_check_ids.t b/t_install_iso/012_check_ids.t new file mode 100644 index 0000000..1078cfc --- /dev/null +++ b/t_install_iso/012_check_ids.t @@ -0,0 +1,22 @@ +# +# Check if PCI ids are on the ISO +# + +use Test::Most tests => 1; +use File::Basename; + +my ($image_path) = @ARGV; + +bail_on_fail; + +my $valid; +my $valid2; + +$valid = -r "/media/iso_check/i586/isolinux/pci.ids" if -r "/media/iso_check/i586"; +$valid2 = -r "/media/iso_check/x86_64/isolinux/pci.ids" if -r "/media/iso_check/x86_64"; +$valid &= $valid2 if -r "/media/iso_check/x86_64" && -r "/media/iso_check/i586"; +$valid = $valid2 if -r "/media/iso_check/x86_64" && !$valid; + +ok ($valid, 'HDT can find pci.ids.'); + +done_testing(); diff --git a/t_install_iso/013_check_rpms.t b/t_install_iso/013_check_rpms.t new file mode 100644 index 0000000..bd83030 --- /dev/null +++ b/t_install_iso/013_check_rpms.t @@ -0,0 +1,31 @@ +# +# Verification of the signature of all the rpm packages present on the iso +# +use Test::Most; + +bail_on_fail; + +SKIP: { + skip "Not working yet", 1 unless 0; + +my $_find = `find /media/iso_check/* -name *.rpm > find_all_rpm.log`; +open(my $list, 'find_all_rpm.log'); + +my $pkg; +my $sign; +my $valid = 1; + +while ($pkg = <$list>) { + $sign = ''; + chomp($pkg); + $sign = `rpm -K $pkg | grep 'gpg OK'`; + ok ($sign, "$pkg is correctly signed."); + + $valid = 0 if !$sign; +} +close($list); +my $_res = `rm -rf find_all_rpm.log`; + +} + +done_testing(); diff --git a/t_install_iso/014_check_bad_words.t b/t_install_iso/014_check_bad_words.t new file mode 100644 index 0000000..88cf122 --- /dev/null +++ b/t_install_iso/014_check_bad_words.t @@ -0,0 +1,27 @@ +# +# This function search if there is any temporary files ( .file.swp and file~) +# or file with "bad" words. +# +use Test::Most tests => 2; + +bail_on_fail; + +# +my $res = `find /media/iso_check/ -name '*~' -or -iname '*.swp'`; +if ($res) { + fail('Has no swap temporary file (*~ or *.swp).'); + note $res; +} else { + pass('Has no swap temp file.'); +} + +# +$res = `find /media/iso_check/ -iname '*roxx*' -or -iname '*sucks*' -or -iname 'ubuntu*' -or -iname 'microsoft*' -or -iname 'mandrake*' -or -iname 'mandriva'`; +if ($res) { + fail('Has no blacklisted word.'); + note $res; +} else { + pass('Has no blacklisted word.'); +} + +done_testing(); diff --git a/t_install_iso/016_check_pubkey.t b/t_install_iso/016_check_pubkey.t new file mode 100644 index 0000000..fc5ffaa --- /dev/null +++ b/t_install_iso/016_check_pubkey.t @@ -0,0 +1,95 @@ +# +# TODO check pubkeys FIXME this looks like a mess. +# This function get the path of the pubkeys +# +use Test::Most; +use File::Basename; +use Tools; + +my ($image_path) = @ARGV; +my $name = basename($image_path); +my %info = Tools::parse_mageia_iso_name($name); + +bail_on_fail; + +my $url; +my $path; +my $pubkey = 1; +my $media; + +system "ls /media/iso_check/i586/media/ > temp_media_on_iso.log" if -r "/media/iso_check/i586/media/"; +system "ls /media/iso_check/x86_64/media/ >> temp_media_on_iso.log" if -r "/media/iso_check/x86_64/media/"; + +ok (-r "temp_media_on_iso.log", "Got a log for media contents"); + +open(my $file, "temp_media_on_iso.log") if -r "temp_media_on_iso.log"; + +while ($media = <$file>) { + chomp($media); + if ($info{"arch"} ne "dual" && $media ne 'media_info') { + $path = "/media/iso_check/" . $info{"arch"} . "/media/$media/media_info/pubkey"; + $url = "pubkey/" . $info{"arch"} . "-$media-pubkey"; + #$url .= "-cooker" if !$finale; + $pubkey &= check_key($path, $url, $media, $info{"arch"}) if -r $path && -r $url; + } + elsif ($media ne 'media_info') { + foreach my $arch ("i586", "x86_64") { + $path = "/media/iso_check/$arch/media/$media/media_info/pubkey"; + $url = "pubkey/$arch-$media-pubkey"; + #$url .= "-cooker" if !$finale; + -r $path and -r $url and $pubkey &= check_key($path, $url, $media, $arch); + } + } +} +-r "temp_media_on_iso.log" and system "rm temp_media_on_iso.log"; + + +#This function get the gpg -a key of the pubkey to compare it +sub get_gpg { + my ($pubkey) = @_; + my $key; + my $file; + system "gpg -a $pubkey > get_gpg_key.log"; + open($file, "get_gpg_key.log"); + while (my $a = <$file>) { + if (substr($a, 0, 11) eq "pub 1024D/") { + $key = substr($a, 11, 8); + } + } + system "rm get_gpg_key.log"; + + return $key; +} + + +#Verification of the pubkey with the original pubkey +sub check_key { # sed "s/pub\w1024D/\(.*\) /\1/" + my ($iso_file, $ref_file, $media, $arch) = @_; + my $unvalid; + my $valid = 1; + my $file = get_gpg($iso_file); + my $sign = `cat $ref_file`; + chomp($sign); + if ($file eq $sign) { + if (member($media, qw(core nonfree))) { + note "$arch-$media pubkey is valid.\t\tOK\n" if $arch eq 'i586'; + note "$arch-$media pubkey is valid.\t\tOK\n" if $arch eq 'x86_64' && member($media, qw(core nonfree)); + note "$arch-$media pubkey is valid.\tOK\n" if $arch eq 'x86_64' && $media eq 'non-free'; + } else { + note "$arch-$media pubkey is valid.\tOK\n"; + } + note "$arch-$media pubkey is valid.\n"; + return $valid; + } else { + if (member($media, qw(core))) { + note "$arch-$media pubkey isn't valid.\t\tNOK\n"; + } else { + note "$arch-$media pubkey isn't valid.\tNOK\n"; + } + note "$arch-$media pubkey isn't valid.\n"; + return $unvalid; + } + return $unvalid; +} + +done_testing(); diff --git a/test_iso.pl b/test_iso.pl new file mode 100644 index 0000000..0c67efb --- /dev/null +++ b/test_iso.pl @@ -0,0 +1,57 @@ +#!/usr/bin/perl -w +# + +use 5.010; +use MDK::Common; +use TAP::Harness; +use Tools; + +my ($image_path) = @ARGV; + +if (!defined $image_path) { + print "Usage: ./test_iso.pl path_to_iso/file.iso\n\n"; + exit; +} + +my $harness = TAP::Harness->new({ + formatter_class => 'TAP::Formatter::Console', + merge => 1, + verbosity => 1, + normalize => 1, + color => 1, + test_args => [ + $image_path, + "Testing" + ] +}); + +print "# Date: ", `date --rfc-3339='ns' -u`; +print "# Testing: $image_path\n"; +print "# Host: ", `uname -n`; + +$harness->runtests(<./t/*.t>); + +print "# Mounting ISO in /media/iso_check"; +-r "/media/iso_check" or system 'mkdir /media/iso_check'; +system "mount -r " . if_(!-b $image_path, "-o loop ") . "$image_path /media/iso_check/"; +print "... ok\n"; + +my $name = basename($image_path); +my %info = Tools::parse_mageia_iso_name($name); + +# FIXME the difference is actually regular versus LiveCD +if ($info{"medium"} eq "DVD") { + $harness->runtests(<./t_install_iso/*.t>); +} elsif ($info{"medium"} eq "CD") { + # LiveCD specific + # CD specific +} +# Umounting the iso +print "# Umounting ISO\n"; + +# FIXME this fails sometimes; no idea why. Force umount? +system 'umount -fr /media/iso_check'; +system 'rm -r /media/iso_check'; +print "... ok\n"; +print "# Date: ", `date --rfc-3339='ns' -u`; +print "# Test is over.\n"; -- cgit v1.2.1