[Pkg-libvirt-commits] [libguestfs] 20/266: tests: Add test program to run qemu/appliance repeatedly.
Hilko Bengen
bengen at moszumanska.debian.org
Fri Oct 3 14:41:32 UTC 2014
This is an automated email from the git hooks/post-receive script.
bengen pushed a commit to annotated tag debian/1%1.27.35-1
in repository libguestfs.
commit de5924a2294a6aeb09e4b41b55f06d2f3ea5e0ec
Author: Richard W.M. Jones <rjones at redhat.com>
Date: Thu Jul 17 20:32:24 2014 +0000
tests: Add test program to run qemu/appliance repeatedly.
For example:
$ time ./run ./tests/qemu/qemu-boot -n 100
real 1m19.794s
user 0m10.001s
sys 0m5.928s
will run 100 appliance start/stops, from multiple threads.
---
.gitignore | 1 +
tests/qemu/Makefile.am | 27 ++++-
tests/qemu/qemu-boot.c | 270 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 297 insertions(+), 1 deletion(-)
diff --git a/.gitignore b/.gitignore
index e9170f4..5c614d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -529,6 +529,7 @@ Makefile.in
/tests/mountable/test-internal-parse-mountable
/tests/parallel/test-parallel
/tests/protocol/test-error-messages
+/tests/qemu/qemu-boot
/tests/regressions/rhbz501893
/tests/regressions/rhbz790721
/tests/regressions/rhbz914931
diff --git a/tests/qemu/Makefile.am b/tests/qemu/Makefile.am
index 40237ca..fa2fe92 100644
--- a/tests/qemu/Makefile.am
+++ b/tests/qemu/Makefile.am
@@ -29,4 +29,29 @@ TESTS = \
TESTS_ENVIRONMENT = $(top_builddir)/run --test
EXTRA_DIST = \
- $(TESTS)
+ $(TESTS) \
+ qemu-boot.c
+
+# qemu-boot is built but not run by default as it is mainly
+# a qemu & kernel diagnostic tool.
+
+check_PROGRAMS = qemu-boot
+
+qemu_boot_SOURCES = \
+ ../../df/estimate-max-threads.c \
+ ../../df/estimate-max-threads.h \
+ qemu-boot.c
+qemu_boot_CPPFLAGS = \
+ -DGUESTFS_PRIVATE=1 \
+ -I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \
+ -I$(top_srcdir)/src -I$(top_builddir)/src \
+ -I$(top_srcdir)/df
+qemu_boot_CFLAGS = \
+ -pthread \
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
+qemu_boot_LDADD = \
+ $(top_builddir)/src/libutils.la \
+ $(top_builddir)/src/libguestfs.la \
+ $(LIBXML2_LIBS) \
+ $(LIBVIRT_LIBS) \
+ $(top_builddir)/gnulib/lib/libgnu.la
diff --git a/tests/qemu/qemu-boot.c b/tests/qemu/qemu-boot.c
new file mode 100644
index 0000000..56eec57
--- /dev/null
+++ b/tests/qemu/qemu-boot.c
@@ -0,0 +1,270 @@
+/* libguestfs
+ * Copyright (C) 2014 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.
+ */
+
+/* Ancient libguestfs had a script called test-bootbootboot which just
+ * booted up the appliance in a loop. This was necessary back in the
+ * bad old days when qemu was not very reliable. This is the
+ * spiritual successor of that script, designed to find bugs in
+ * aarch64 KVM. You can control the number of boots that are done and
+ * the amount of parallelism.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <limits.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include "guestfs.h"
+#include "guestfs-internal-frontend.h"
+#include "estimate-max-threads.h"
+
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+/* Maximum number of threads we would ever run. Note this should not
+ * be > 20, unless libvirt is modified to increase the maximum number
+ * of clients. User can override this limit using -P.
+ */
+#define MAX_THREADS 12
+
+static size_t n; /* Number of qemu processes to run in total. */
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static int ignore_errors = 0;
+static int trace = 0;
+static int verbose = 0;
+
+struct thread_data {
+ int thread_num;
+ int r;
+};
+
+static void *start_thread (void *thread_data_vp);
+
+static void
+usage (int exitcode)
+{
+ fprintf (stderr,
+ "qemu-boot: A program for repeatedly running the libguestfs appliance.\n"
+ "qemu-boot [-i] [-P <nr-threads>] -n <nr-appliances>\n"
+ " -i Ignore errors\n"
+ " -P <n> Set number of parallel threads\n"
+ " (default is based on the amount of free memory)\n"
+ " -n <n> Set number of appliances to run before exiting\n"
+ " -v Verbose appliance\n"
+ " -x Enable libguestfs tracing\n");
+ exit (exitcode);
+}
+
+int
+main (int argc, char *argv[])
+{
+ enum { HELP_OPTION = CHAR_MAX + 1 };
+ static const char *options = "in:P:vx";
+ static const struct option long_options[] = {
+ { "help", 0, 0, HELP_OPTION },
+ { "ignore", 0, 0, 'i' },
+ { "number", 1, 0, 'n' },
+ { "processes", 1, 0, 'P' },
+ { "trace", 0, 0, 'x' },
+ { "verbose", 0, 0, 'v' },
+ { 0, 0, 0, 0 }
+ };
+ size_t P = 0, i, errors;
+ int c, option_index;
+ int err;
+ void *status;
+
+ for (;;) {
+ c = getopt_long (argc, argv, options, long_options, &option_index);
+ if (c == -1) break;
+
+ switch (c) {
+ case 0:
+ /* Options which are long only. */
+ fprintf (stderr, "%s: unknown long option: %s (%d)\n",
+ program_name, long_options[option_index].name, option_index);
+ exit (EXIT_FAILURE);
+
+ case 'i':
+ ignore_errors = 1;
+ break;
+
+ case 'n':
+ if (sscanf (optarg, "%zu", &n) != 1 || n == 0) {
+ fprintf (stderr, "%s: -n option not numeric and greater than 0\n",
+ program_name);
+ exit (EXIT_FAILURE);
+ }
+ break;
+
+ case 'P':
+ if (sscanf (optarg, "%zu", &P) != 1) {
+ fprintf (stderr, "%s: -P option not numeric\n", program_name);
+ exit (EXIT_FAILURE);
+ }
+ break;
+
+ case 'v':
+ verbose = 1;
+ break;
+
+ case 'x':
+ trace = 1;
+ break;
+
+ case HELP_OPTION:
+ usage (EXIT_SUCCESS);
+
+ default:
+ usage (EXIT_FAILURE);
+ }
+ }
+
+ if (n == 0) {
+ fprintf (stderr,
+ "%s: must specify number of processes to run (-n option)\n",
+ program_name);
+ exit (EXIT_FAILURE);
+ }
+
+ /* Calculate the number of threads to use. */
+ if (P > 0)
+ P = MIN (n, P);
+ else
+ P = MIN (n, MIN (MAX_THREADS, estimate_max_threads ()));
+
+ /* Start the worker threads. */
+ struct thread_data thread_data[P];
+ pthread_t threads[P];
+
+ for (i = 0; i < P; ++i) {
+ thread_data[i].thread_num = i;
+ err = pthread_create (&threads[i], NULL, start_thread, &thread_data[i]);
+ if (err != 0) {
+ fprintf (stderr, "%s: pthread_create[%zu]: %s\n",
+ program_name, i, strerror (err));
+ exit (EXIT_FAILURE);
+ }
+ }
+
+ /* Wait for the threads to exit. */
+ errors = 0;
+ for (i = 0; i < P; ++i) {
+ err = pthread_join (threads[i], &status);
+ if (err != 0) {
+ fprintf (stderr, "%s: pthread_join[%zu]: %s\n",
+ program_name, i, strerror (err));
+ errors++;
+ }
+ if (*(int *)status == -1)
+ errors++;
+ }
+
+ exit (errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+/* Worker thread. */
+static void *
+start_thread (void *thread_data_vp)
+{
+ struct thread_data *thread_data = thread_data_vp;
+ int quit = 0;
+ int err;
+ size_t i;
+ guestfs_h *g;
+ unsigned errors = 0;
+
+ for (;;) {
+ /* Take the next process. */
+ err = pthread_mutex_lock (&mutex);
+ if (err != 0) {
+ fprintf (stderr, "%s: pthread_mutex_lock: %s",
+ program_name, strerror (err));
+ goto error;
+ }
+
+ i = n;
+ if (i > 0) {
+ printf ("%zu to go ... \r", n);
+ fflush (stdout);
+
+ n--;
+ }
+ else
+ quit = 1;
+
+ err = pthread_mutex_unlock (&mutex);
+ if (err != 0) {
+ fprintf (stderr, "%s: pthread_mutex_unlock: %s",
+ program_name, strerror (err));
+ goto error;
+ }
+
+ if (quit) /* Work finished. */
+ break;
+
+ g = guestfs_create ();
+ if (g == NULL) {
+ perror ("guestfs_create");
+ errors++;
+ if (!ignore_errors)
+ goto error;
+ }
+
+ guestfs_set_trace (g, trace);
+ guestfs_set_verbose (g, verbose);
+
+ if (guestfs_add_drive_ro (g, "/dev/null") == -1) {
+ errors++;
+ if (!ignore_errors)
+ goto error;
+ }
+
+ if (guestfs_launch (g) == -1) {
+ errors++;
+ if (!ignore_errors)
+ goto error;
+ }
+
+ if (guestfs_shutdown (g) == -1) {
+ errors++;
+ if (!ignore_errors)
+ goto error;
+ }
+
+ guestfs_close (g);
+ }
+
+ if (errors > 0) {
+ fprintf (stderr, "%s: thread %d: %u errors were ignored\n",
+ program_name, thread_data->thread_num, errors);
+ goto error;
+ }
+
+ thread_data->r = 0;
+ return &thread_data->r;
+
+ error:
+ thread_data->r = -1;
+ return &thread_data->r;
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-libvirt/libguestfs.git
More information about the Pkg-libvirt-commits
mailing list