[Libguestfs] [PATCH nbdkit] tests: Add a root only test of the file plugin with block devices.

Richard W.M. Jones rjones at redhat.com
Mon Aug 20 12:49:30 UTC 2018


You can also run only the root tests using:

  sudo make check-root
---
 .gitignore              |   1 +
 Makefile.am             |   3 +
 README                  |   7 ++
 tests/Makefile.am       |  10 +-
 tests/test-file-block.c | 217 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 237 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index d6686ea..a3d504e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,6 +69,7 @@ Makefile.in
 /tests/test-exit-with-parent
 /tests/test-ext2
 /tests/test-file
+/tests/test-file-block
 /tests/test-gzip
 /tests/test-layers
 /tests/test-lua
diff --git a/Makefile.am b/Makefile.am
index 0a79e56..c411ed6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -64,6 +64,9 @@ SUBDIRS += tests
 check-valgrind:
 	$(MAKE) -C tests check-valgrind
 
+check-root:
+	$(MAKE) -C tests check-root
+
 # Maintainer only: check no files are missing from EXTRA_DIST rules,
 # and that all generated files have been included in the tarball.
 # (Note you must have done 'make dist')
diff --git a/README b/README
index 473eea8..145cc49 100644
--- a/README
+++ b/README
@@ -125,6 +125,8 @@ To test for memory leaks (‘make check-valgrind’):
 
 For non-essential enhancements to the test suite:
 
+ - losetup (from util-linux package)
+
  - qemu-io (usually shipped with qemu)
 
  - socat
@@ -175,6 +177,11 @@ nbdkit + plugins as a captive process, and tests them using
 libguestfs.  If there is a failure, look at the corresponding
 ‘tests/*.log’ file for debug information.
 
+A few tests require root privileges, and are skipped by default.  To
+run them you must do:
+
+    sudo make check-root
+
 DOWNLOAD TARBALLS
 =================
 
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ce383c2..e0ae6b3 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -95,6 +95,10 @@ EXTRA_DIST = \
 check-valgrind:
 	NBDKIT_VALGRIND=1 $(MAKE) check
 
+# To run only tests which require root, use:
+check-root:
+	$(MAKE) check TESTS="test-file-block"
+
 #----------------------------------------------------------------------
 # Basic server command line and start-up tests.
 
@@ -307,12 +311,16 @@ endif HAVE_GUESTFISH
 endif HAVE_EXT2
 
 # file plugin test.
-LIBGUESTFS_TESTS += test-file
+LIBGUESTFS_TESTS += test-file test-file-block
 
 test_file_SOURCES = test-file.c test.h
 test_file_CFLAGS = $(WARNINGS_CFLAGS) $(LIBGUESTFS_CFLAGS)
 test_file_LDADD = libtest.la $(LIBGUESTFS_LIBS)
 
+test_file_block_SOURCES = test-file-block.c test.h
+test_file_block_CFLAGS = $(WARNINGS_CFLAGS) $(LIBGUESTFS_CFLAGS)
+test_file_block_LDADD = libtest.la $(LIBGUESTFS_LIBS)
+
 # gzip plugin test.
 if HAVE_ZLIB
 if HAVE_GUESTFISH
diff --git a/tests/test-file-block.c b/tests/test-file-block.c
new file mode 100644
index 0000000..75c2c61
--- /dev/null
+++ b/tests/test-file-block.c
@@ -0,0 +1,217 @@
+/* nbdkit
+ * Copyright (C) 2013-2018 Red Hat Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Red Hat nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <guestfs.h>
+
+#include "test.h"
+
+static char *loopdev;                   /* Name of the loop device. */
+static void detach_loopdev (void);
+
+int
+main (int argc, char *argv[])
+{
+  guestfs_h *g;
+  int r;
+  int fd;
+  char cmd[64], buf[64];
+  char disk[] = "/tmp/diskXXXXXX"; /* Backing disk. */
+  FILE *pp;
+  char *data;
+  size_t len;
+  char *s;
+
+  /* This test can only be run as root, and will be skipped otherwise. */
+  if (geteuid () != 0) {
+    fprintf (stderr, "%s: this test has to be run as root.\n",
+             program_name);
+    exit (77);
+  }
+
+  /* losetup must be available. */
+  r = system ("losetup --version");
+  if (r != 0) {
+    fprintf (stderr, "%s: losetup program must be installed.\n",
+             program_name);
+    exit (77);
+  }
+
+  /* Create the temporary backing disk. */
+  fd = mkstemp (disk);
+  if (fd == -1) {
+    perror ("mkstemp");
+    exit (EXIT_FAILURE);
+  }
+  if (ftruncate (fd, 100 * 1024 * 1024) == -1) {
+    perror ("ftruncate");
+    unlink (disk);
+    exit (EXIT_FAILURE);
+  }
+
+  /* Create the loopback device. */
+  snprintf (cmd, sizeof cmd, "losetup -f --show %s", disk);
+  pp = popen (cmd, "r");
+  if (pp == NULL) {
+    perror ("popen: losetup");
+    unlink (disk);
+    exit (EXIT_FAILURE);
+  }
+  if (fgets (buf, sizeof buf, pp) == NULL) {
+    fprintf (stderr, "%s: could not read loop device name from losetup\n",
+             program_name);
+    unlink (disk);
+    exit (EXIT_FAILURE);
+  }
+  len = strlen (buf);
+  if (len > 0 && buf[len-1] == '\n') {
+    buf[len-1] = '\0';
+    len--;
+  }
+  pclose (pp);
+
+  /* We can delete the backing disk.  The loop device will hold it open. */
+  unlink (disk);
+
+  /* If we get to this point, set up an atexit handler to detach the
+   * loop device.
+   */
+  loopdev = malloc (len+1);
+  if (loopdev == NULL) {
+    perror ("malloc");
+    exit (EXIT_FAILURE);
+  }
+  strcpy (loopdev, buf);
+  atexit (detach_loopdev);
+
+  /* Start nbdkit. */
+  snprintf (buf, sizeof buf, "file=%s", loopdev);
+  if (test_start_nbdkit ("file", buf, NULL) == -1)
+    exit (EXIT_FAILURE);
+
+  g = guestfs_create ();
+  if (g == NULL) {
+    perror ("guestfs_create");
+    exit (EXIT_FAILURE);
+  }
+
+  r = guestfs_add_drive_opts (g, "",
+                              GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
+                              GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "nbd",
+                              GUESTFS_ADD_DRIVE_OPTS_SERVER, server,
+                              -1);
+  if (r == -1)
+    exit (EXIT_FAILURE);
+
+  if (guestfs_launch (g) == -1)
+    exit (EXIT_FAILURE);
+
+  /* Partition the disk. */
+  if (guestfs_part_disk (g, "/dev/sda", "mbr") == -1)
+    exit (EXIT_FAILURE);
+  if (guestfs_mkfs (g, "ext4", "/dev/sda1") == -1)
+    exit (EXIT_FAILURE);
+
+  if (guestfs_mount (g, "/dev/sda1", "/") == -1)
+    exit (EXIT_FAILURE);
+
+#define filename "/hello.txt"
+#define content "hello, people of the world"
+
+  if (guestfs_write (g, filename, content, strlen (content)) == -1)
+    exit (EXIT_FAILURE);
+
+  data = guestfs_cat (g, filename);
+  if (!data)
+    exit (EXIT_FAILURE);
+
+  if (strcmp (data, content) != 0) {
+    fprintf (stderr, "%s FAILED: unexpected content of %s file (actual: %s, expected: %s)\n",
+             program_name, filename, data, content);
+    exit (EXIT_FAILURE);
+  }
+
+  /* Run sync to test flush path. */
+  if (guestfs_sync (g) == -1)
+    exit (EXIT_FAILURE);
+
+  /* Run fstrim to test trim path.  However only recent versions of
+   * libguestfs have this, and it probably only works in recent
+   * versions of qemu.
+   */
+#ifdef GUESTFS_HAVE_FSTRIM
+  if (guestfs_fstrim (g, "/", -1) == -1)
+    exit (EXIT_FAILURE);
+#endif
+
+  /* Run fallocate(1) on the device to test zero path. */
+  if (guestfs_umount (g, "/") == -1)
+    exit (EXIT_FAILURE);
+  const char *sh[] = { "fallocate", "-nzl", "64k", "/dev/sda", NULL };
+  s = guestfs_debug (g, "sh", (char **) sh);
+  free (s);
+
+  if (guestfs_shutdown (g) == -1)
+    exit (EXIT_FAILURE);
+
+  guestfs_close (g);
+
+  /* The atexit handler should detach the loop device and clean up
+   * the backing disk.
+   */
+  exit (EXIT_SUCCESS);
+}
+
+/* atexit handler. */
+static void
+detach_loopdev (void)
+{
+  char cmd[64];
+
+  if (loopdev == NULL)
+    return;
+
+  snprintf (cmd, sizeof cmd, "losetup -d %s", loopdev);
+  system (cmd);
+  free (loopdev);
+  loopdev = NULL;
+}
-- 
2.18.0




More information about the Libguestfs mailing list