This allows us to test the daemon running as a host process, allowing us to meaningfully test it using valgrind. This commit only adds a single test that check that the daemon starts up, can be pinged, and exits. --- .gitignore | 1 + Makefile.am | 1 + configure.ac | 2 + tests/daemon/Makefile.am | 36 +++++++++++ tests/daemon/captive-daemon.pm.in | 125 ++++++++++++++++++++++++++++++++++++++ tests/daemon/test-daemon-start.pl | 35 +++++++++++ 6 files changed, 200 insertions(+) create mode 100644 tests/daemon/Makefile.am create mode 100644 tests/daemon/captive-daemon.pm.in create mode 100755 tests/daemon/test-daemon-start.pl diff --git a/.gitignore b/.gitignore index 6f14915..6089122 100644 --- a/.gitignore +++ b/.gitignore @@ -528,6 +528,7 @@ Makefile.in /tests/data/lib-i586.so.xz /tests/data/test-grep.txt.gz /tests/data/test.iso +/tests/daemon/captive-daemon.pm /tests/disks/test-qemu-drive-libvirt.xml /tests/events/test-libvirt-auth-callbacks /tests/guests/blank-*.img diff --git a/Makefile.am b/Makefile.am index ad6d9d3..c545ea1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -30,6 +30,7 @@ SUBDIRS += tests/data generator src examples po if ENABLE_DAEMON SUBDIRS += daemon +SUBDIRS += tests/daemon endif if ENABLE_APPLIANCE SUBDIRS += appliance diff --git a/configure.ac b/configure.ac index 8775c4b..66ac5df 100644 --- a/configure.ac +++ b/configure.ac @@ -1775,6 +1775,8 @@ AC_CONFIG_FILES([Makefile tests/charsets/Makefile tests/create/Makefile tests/data/Makefile + tests/daemon/Makefile + tests/daemon/captive-daemon.pm tests/discard/Makefile tests/disks/Makefile tests/disks/test-qemu-drive-libvirt.xml diff --git a/tests/daemon/Makefile.am b/tests/daemon/Makefile.am new file mode 100644 index 0000000..0d2f1cd --- /dev/null +++ b/tests/daemon/Makefile.am @@ -0,0 +1,36 @@ +# libguestfs +# Copyright (C) 2015 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# Tests in this subdirectory run the daemon as a captive host process +# and send commands directly to it. There is a small Perl library +# called 'captive-daemon.pm' in this directory to help with this. + +include $(top_srcdir)/subdir-rules.mk + +check_DATA = captive-daemon.pm + +TESTS = \ + test-daemon-start.pl + +TESTS_ENVIRONMENT = $(top_builddir)/run --test $(VG) + +EXTRA_DIST = \ + captive-daemon.pm \ + $(TESTS) + +check-valgrind: + $(MAKE) check TEST_WITH_VALGRIND=1 diff --git a/tests/daemon/captive-daemon.pm.in b/tests/daemon/captive-daemon.pm.in new file mode 100644 index 0000000..991a9a1 --- /dev/null +++ b/tests/daemon/captive-daemon.pm.in @@ -0,0 +1,125 @@ +# libguestfs +# Copyright (C) 2015 Red Hat Inc. +# @configure_input@ +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# Small library to help testing the daemon directly. + +package CaptiveDaemon; + +use strict; +use warnings; + +use Sys::Guestfs; + +$| = 1; + +# Filled in by autoconf. +my %var; +$var{top_builddir} = "@top_builddir@"; +$var{abs_top_srcdir} = "@abs_top_srcdir@"; +$var{abs_top_builddir} = "@abs_top_builddir@"; +$var{VALGRIND} = "@VALGRIND@"; + +# Now we have to substitute the above variables into this one: +my $VG = '@VG@'; +$VG =~ s/\$\(([A-Za-z_]+)\)/ $var{"$1"} /ge; + +# Refuse to run if the user is trying to run tests as root. There's +# too much risk that things will go badly wrong. +if ($> == 0) { + print "$0: don't run the libguestfs tests as root!\n"; + exit 77 +} + +sub run_tests { + my $g = Sys::Guestfs->new(); + my $tmpdir = $g->get_tmpdir; + my $verbose = $g->get_verbose; + $g->close; + + # Choose a random name for the socket. The daemon will create the + # socket so we don't need to do that. + my @chars = ("A".."Z", "a".."z", "0".."9"); + my $sockname = $tmpdir; + $sockname .= "/"; + $sockname .= $chars[rand @chars] for 1..8; + + # Assemble the command we will run in the subprocess. + my $cmd = + "$var{top_builddir}/daemon/guestfsd --channel $sockname -r -t -l"; + if ($verbose) { + $cmd = $cmd . " -v" + } + if ($ENV{TEST_WITH_VALGRIND}) { + $cmd = $VG . " " . $cmd + } + + if ($verbose) { + print "$0: running: $cmd\n"; + } + + # Fork to run the daemon in the background. + my $pid = fork (); + die "fork: $!" unless defined $pid; + if ($pid == 0) { + # Child process: the daemon. + exec $cmd or die "guestfsd: $!"; + } + + # Wait for the daemon to create the socket, but if it doesn't + # appear after a short timeout, assume there has been a failure. + for (my $i = 0; $i < 10; ++$i) { + last if -S $sockname; + sleep 1; + } + die "subprocess did not create the socket, check earlier messages\n" + unless -S $sockname; + + # Create the libguestfs handle and connect to the daemon using + # libguestfs live. + $g = Sys::Guestfs->new (); + $g->set_backend ("unix:" . $sockname); + $g->launch; + + # Run the user tests. + my $r = ::tests ($g); + + # Close the socket. The daemon should now exit. + $g->shutdown (); + $g->close (); + unlink $sockname; + + waitpid ($pid, 0) or die "waitpid: $!"; + if ($? != 0) { + my $signal = $? & 127; + die "ERROR: guestfsd died on signal $signal\n" if $signal; + my $crash = $? & 128; + die "ERROR: guestfsd core dumped\n" if $crash; + my $status = $? >> 8; + die "ERROR: guestfsd died with exit code 119 (valgrind failure)\n" + if $status == 119; + + # Note we allow guestfsd to die with exit code 1, because + # that indicates a read failure from the socket. + die "ERROR: guestfsd died with exit code $status\n" if $status > 1; + } + + # Exit with failure if the user test failed. + exit 1 unless $r +} + +1; diff --git a/tests/daemon/test-daemon-start.pl b/tests/daemon/test-daemon-start.pl new file mode 100755 index 0000000..91e008a --- /dev/null +++ b/tests/daemon/test-daemon-start.pl @@ -0,0 +1,35 @@ +#!/usr/bin/perl -w +# libguestfs +# Copyright (C) 2015 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# Test that the daemon starts and stops. + +use strict; +use warnings; + +require 'captive-daemon.pm'; + +sub tests { + my $g = shift; + + $g->ping_daemon; + + # Return true to indicate the test succeeded. + 1; +} + +CaptiveDaemon::run_tests () -- 2.3.1