r5516 - trunk/varnish-cache/bin/varnishtest

phk at varnish-cache.org phk at varnish-cache.org
Fri Nov 5 01:03:53 CET 2010


Author: phk
Date: 2010-11-05 01:03:52 +0100 (Fri, 05 Nov 2010)
New Revision: 5516

Added:
   trunk/varnish-cache/bin/varnishtest/vtc_main.c
Modified:
   trunk/varnish-cache/bin/varnishtest/Makefile.am
   trunk/varnish-cache/bin/varnishtest/vtc.c
   trunk/varnish-cache/bin/varnishtest/vtc.h
   trunk/varnish-cache/bin/varnishtest/vtc_log.c
Log:
Major rewrite of the main-function of varnishtest:

Run tests in fork'ed subprocesses.
Support for running tests in parallel.
Command arguments straightened out.

Needs polishing, but I need to sleep.



Modified: trunk/varnish-cache/bin/varnishtest/Makefile.am
===================================================================
--- trunk/varnish-cache/bin/varnishtest/Makefile.am	2010-11-04 13:11:45 UTC (rev 5515)
+++ trunk/varnish-cache/bin/varnishtest/Makefile.am	2010-11-05 00:03:52 UTC (rev 5516)
@@ -16,6 +16,7 @@
 		vtc.h \
 		vtc_client.c \
 		vtc_http.c \
+		vtc_main.c \
 		vtc_log.c \
 		vtc_sema.c \
 		vtc_server.c \

Modified: trunk/varnish-cache/bin/varnishtest/vtc.c
===================================================================
--- trunk/varnish-cache/bin/varnishtest/vtc.c	2010-11-04 13:11:45 UTC (rev 5515)
+++ trunk/varnish-cache/bin/varnishtest/vtc.c	2010-11-05 00:03:52 UTC (rev 5516)
@@ -35,17 +35,17 @@
 #include <string.h>
 #include <ctype.h>
 #include <fcntl.h>
-#include <math.h>
 #include <limits.h>
 #include <signal.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <sys/wait.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <sys/wait.h>
 
 #include "libvarnish.h"
+#include "vev.h"
 #include "vsb.h"
 #include "vqueue.h"
 #include "miniobj.h"
@@ -56,7 +56,6 @@
 #include "compat/srandomdev.h"
 #endif
 
-#define		MAX_FILESIZE		(1024 * 1024)
 #define		MAX_TOKENS		200
 
 static char		*vtc_desc;
@@ -196,36 +195,6 @@
 }
 
 /**********************************************************************
- * Read a file into memory
- */
-
-static char *
-read_file(const char *fn)
-{
-	char *buf;
-	ssize_t sz = MAX_FILESIZE;
-	ssize_t s;
-	int fd;
-
-	fd = open(fn, O_RDONLY);
-	if (fd < 0)
-		return (NULL);
-	buf = malloc(sz);
-	assert(buf != NULL);
-	s = read(fd, buf, sz - 1);
-	if (s <= 0) {
-		free(buf);
-		return (NULL);
-	}
-	AZ(close (fd));
-	assert(s < sz);		/* XXX: increase MAX_FILESIZE */
-	buf[s] = '\0';
-	buf = realloc(buf, s + 1);
-	assert(buf != NULL);
-	return (buf);
-}
-
-/**********************************************************************
  * Execute a file
  */
 
@@ -503,214 +472,51 @@
 	{ NULL,		NULL }
 };
 
-struct priv_exec {
-	const char	*fn;
-	char		*buf;
-};
-
-static void *
-exec_file_thread(void *priv)
+int
+exec_file(const char *fn, const char *script, char *logbuf, unsigned loglen)
 {
 	unsigned old_err;
-	struct priv_exec *pe;
+	char *cwd, *p;
+	char topbuild[BUFSIZ];
 
-	pe = priv;
+	vtc_loginit(logbuf, loglen);
+	vltop = vtc_logopen("top");
+	AN(vltop);
 
-	vtc_thread = pthread_self();
-	parse_string(pe->buf, cmds, NULL, vltop);
-	old_err = vtc_error;
-	vtc_stop = 1;
-	vtc_log(vltop, 1, "RESETTING after %s", pe->fn);
-	reset_cmds(cmds);
-	vtc_error = old_err;
-	return (NULL);
-}
+	init_macro();
+	init_sema();
 
-#ifndef HAVE_PTHREAD_TIMEDJOIN_NP
-static volatile sig_atomic_t alrm_flag = 0;
+	cwd = getcwd(NULL, PATH_MAX);
+	bprintf(topbuild, "%s/%s", cwd, TOP_BUILDDIR);
+	macro_def(vltop, NULL, "topbuild", topbuild);
 
-static void
-sigalrm(int x)
-{
+	macro_def(vltop, NULL, "bad_ip", "10.255.255.255");
 
-	(void)x;
-	alrm_flag = 1;
-	vtc_error = 1;
-}
-#endif
+	srandomdev();
+	bprintf(vtc_tmpdir, "/tmp/vtc.%d.%08x", getpid(), (unsigned)random());
+	AZ(mkdir(vtc_tmpdir, 0700));
+	macro_def(vltop, NULL, "tmpdir", vtc_tmpdir);
 
-static double
-exec_file(const char *fn, unsigned dur)
-{
-	double t0;
-	struct priv_exec pe;
-	pthread_t pt;
-#ifdef HAVE_PTHREAD_TIMEDJOIN_NP
-	double t;
-	struct timespec ts;
-#endif
-	void *v;
-	int i;
-
-	vtc_logreset();
-	t0 = TIM_mono();
 	vtc_stop = 0;
 	vtc_desc = NULL;
 	vtc_log(vltop, 1, "TEST %s starting", fn);
-	pe.buf = read_file(fn);
-	if (pe.buf == NULL)
-		vtc_log(vltop, 0, "Cannot read file '%s': %s",
-		    fn, strerror(errno));
-	pe.fn = fn;
 
-#ifdef HAVE_PTHREAD_TIMEDJOIN_NP
-	t = TIM_real() + dur;
-	ts.tv_sec = (long)floor(t);
-	ts.tv_nsec = (long)((t - ts.tv_sec) * 1e9);
+	p = strdup(script);
+	AN(p);
 
-	AZ(pthread_create(&pt, NULL, exec_file_thread, &pe));
-	i = pthread_timedjoin_np(pt, &v, &ts);
-	memset(&vtc_thread, 0, sizeof vtc_thread);
-#else
-	alrm_flag = 0;
-	(void)signal(SIGALRM, sigalrm);
-	alarm(dur);
-	AZ(pthread_create(&pt, NULL, exec_file_thread, &pe));
-	i = pthread_join(pt, &v);
-	alarm(0);
-	if (alrm_flag)
-		i = ETIMEDOUT;
-#endif
+	vtc_thread = pthread_self();
+	parse_string(p, cmds, NULL, vltop);
+	old_err = vtc_error;
+	vtc_stop = 1;
+	vtc_log(vltop, 1, "RESETTING after %s", fn);
+	reset_cmds(cmds);
+	vtc_error = old_err;
 
-	if (i != 0) {
-		if (i != ETIMEDOUT)
-			vtc_log(vltop, 1, "Weird condwait return: %d %s",
-			    i, strerror(i));
-		vtc_log(vltop, 1, "Test timed out");
-		vtc_error = 1;
-	}
-
 	if (vtc_error)
 		vtc_log(vltop, 1, "TEST %s FAILED", fn);
 	else 
 		vtc_log(vltop, 1, "TEST %s completed", fn);
 
-	t0 = TIM_mono() - t0;
-
-	if (vtc_error && vtc_verbosity == 0)
-		printf("%s", vtc_logfull());
-	else if (vtc_verbosity == 0)
-		printf("#    top  TEST %s passed (%.3fs)\n", fn, t0);
-
 	free(vtc_desc);
-	return (t0);
+	return (vtc_error);
 }
-
-/**********************************************************************
- * Print usage
- */
-
-static void
-usage(void)
-{
-	fprintf(stderr, "usage: varnishtest [-n iter] [-qv] file ...\n");
-	exit(1);
-}
-
-/**********************************************************************
- * Main
- */
-
-int
-main(int argc, char * const *argv)
-{
-	int ch, i, ntest = 1, ncheck = 0;
-	FILE *fok;
-	double tmax, t0, t00;
-	unsigned dur = 30;
-	const char *nmax;
-	char cmd[BUFSIZ];
-	char *cwd;
-	char topbuild[BUFSIZ];
-
-	setbuf(stdout, NULL);
-	setbuf(stderr, NULL);
-	vtc_loginit();
-	vltop = vtc_logopen("top");
-	AN(vltop);
-	while ((ch = getopt(argc, argv, "L:n:qt:v")) != -1) {
-		switch (ch) {
-		case 'n':
-			ntest = strtoul(optarg, NULL, 0);
-			break;
-		case 'q':
-			vtc_verbosity--;
-			break;
-		case 't':
-			dur = strtoul(optarg, NULL, 0);
-			break;
-		case 'v':
-			vtc_verbosity++;
-			break;
-		default:
-			usage();
-		}
-	}
-	argc -= optind;
-	argv += optind;
-
-	if (argc == 0)
-		usage();
-
-	init_macro();
-	init_sema();
-
-	srandomdev();
-	bprintf(vtc_tmpdir, "/tmp/vtc.%d.%08x", getpid(), (unsigned)random());
-	AZ(mkdir(vtc_tmpdir, 0700));
-	macro_def(vltop, NULL, "tmpdir", vtc_tmpdir);
-
-	cwd = getcwd(NULL, PATH_MAX);
-	bprintf(topbuild, "%s/%s", cwd, TOP_BUILDDIR);
-	macro_def(vltop, NULL, "topbuild", topbuild);
-
-	macro_def(vltop, NULL, "bad_ip", "10.255.255.255");
-	tmax = 0;
-	nmax = NULL;
-	t00 = TIM_mono();
-	for (i = 0; i < ntest; i++) {
-		for (ch = 0; ch < argc; ch++) {
-			t0 = exec_file(argv[ch], dur);
-			ncheck++;
-			if (t0 > tmax) {
-				tmax = t0;
-				nmax = argv[ch];
-			}
-			if (vtc_error)
-				break;
-		}
-		if (vtc_error)
-			break;
-	}
-
-	/* Remove tmpdir on success or non-verbosity */
-	if (vtc_error == 0 || vtc_verbosity == 0) {
-		bprintf(cmd, "rm -rf %s", vtc_tmpdir);
-		AZ(system(cmd));
-	}
-
-	if (vtc_error)
-		return (2);
-
-	t00 = TIM_mono() - t00;
-	if (ncheck > 1) {
-		printf("#    top  Slowest test: %s %.3fs\n", nmax, tmax);
-		printf("#    top  Total tests run:   %d\n", ncheck);
-		printf("#    top  Total duration: %.3fs\n", t00);
-	}
-
-	fok = fopen("_.ok", "w");
-	if (fok != NULL)
-		AZ(fclose(fok));
-	return (0);
-}

Modified: trunk/varnish-cache/bin/varnishtest/vtc.h
===================================================================
--- trunk/varnish-cache/bin/varnishtest/vtc.h	2010-11-04 13:11:45 UTC (rev 5515)
+++ trunk/varnish-cache/bin/varnishtest/vtc.h	2010-11-05 00:03:52 UTC (rev 5516)
@@ -58,7 +58,6 @@
 cmd_f cmd_varnish;
 cmd_f cmd_sema;
 
-extern int vtc_verbosity;
 extern volatile sig_atomic_t vtc_error; /* Error, bail out */
 extern int vtc_stop;		/* Abandon current test, no error */
 extern pthread_t	vtc_thread;
@@ -70,15 +69,15 @@
 
 void cmd_server_genvcl(struct vsb *vsb);
 
-void vtc_loginit(void);
-void vtc_logreset(void);
-const char *vtc_logfull(void);
+void vtc_loginit(char *buf, unsigned buflen);
 struct vtclog *vtc_logopen(const char *id);
 void vtc_logclose(struct vtclog *vl);
 void vtc_log(struct vtclog *vl, unsigned lvl, const char *fmt, ...);
 void vtc_dump(struct vtclog *vl, unsigned lvl, const char *pfx,
     const char *str);
 
+int exec_file(const char *fn, const char *script, char *logbuf, unsigned loglen);
+
 void macro_def(struct vtclog *vl, const char *instance, const char *name,
     const char *fmt, ...);
 struct vsb *macro_expand(struct vtclog *vl, const char *text);

Modified: trunk/varnish-cache/bin/varnishtest/vtc_log.c
===================================================================
--- trunk/varnish-cache/bin/varnishtest/vtc_log.c	2010-11-04 13:11:45 UTC (rev 5515)
+++ trunk/varnish-cache/bin/varnishtest/vtc_log.c	2010-11-05 00:03:52 UTC (rev 5516)
@@ -44,10 +44,9 @@
 
 #include "vtc.h"
 
-int vtc_verbosity = 0;
-
-static struct vsb	*vtclog_full;
 static pthread_mutex_t	vtclog_mtx;
+static char		*vtclog_buf;
+static unsigned		vtclog_left;
 
 struct vtclog {
 	unsigned	magic;
@@ -60,31 +59,14 @@
 /**********************************************************************/
 
 void
-vtc_loginit()
+vtc_loginit(char *buf, unsigned buflen)
 {
 
-	AZ(vtclog_full);
-	vtclog_full = vsb_newauto();
-	AN(vtclog_full);
+	vtclog_buf = buf;
+	vtclog_left = buflen;
 	AZ(pthread_mutex_init(&vtclog_mtx, NULL));
 }
 
-void
-vtc_logreset()
-{
-
-	AN(vtclog_full);
-	vsb_clear(vtclog_full);
-}
-
-const char *
-vtc_logfull(void)
-{
-	vsb_finish(vtclog_full);
-	AZ(vsb_overflowed(vtclog_full));
-	return (vsb_data(vtclog_full));
-}
-
 /**********************************************************************/
 
 
@@ -124,14 +106,18 @@
 static void
 vtc_log_emit(const struct vtclog *vl, unsigned lvl)
 {
+	int l;
+
 	if (vtc_stop && lvl == 0)
 		return;
+	l = vsb_len(vl->vsb);
 	AZ(pthread_mutex_lock(&vtclog_mtx));
-	vsb_cat(vtclog_full, vsb_data(vl->vsb));
+	assert(vtclog_left > l);
+	memcpy(vtclog_buf,vsb_data(vl->vsb), l);
+	vtclog_buf += l;
+	*vtclog_buf = '\0';
+	vtclog_left -= l;
 	AZ(pthread_mutex_unlock(&vtclog_mtx));
-
-	if (lvl <= vtc_verbosity)
-		(void)fputs(vsb_data(vl->vsb), stdout);
 }
 
 //lint -e{818}

Added: trunk/varnish-cache/bin/varnishtest/vtc_main.c
===================================================================
--- trunk/varnish-cache/bin/varnishtest/vtc_main.c	                        (rev 0)
+++ trunk/varnish-cache/bin/varnishtest/vtc_main.c	2010-11-05 00:03:52 UTC (rev 5516)
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2008-2010 Redpill Linpro AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "svnid.h"
+SVNID("$Id: vtc.c 5507 2010-11-04 11:28:06Z phk $")
+
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "libvarnish.h"
+#include "vev.h"
+#include "vsb.h"
+#include "vqueue.h"
+#include "miniobj.h"
+
+#include "vtc.h"
+
+#define		MAX_FILESIZE		(1024 * 1024)
+
+
+struct vtc_tst {
+	unsigned		magic;
+#define TST_MAGIC		0x618d8b88
+	VTAILQ_ENTRY(vtc_tst)	list;
+	const char		*filename;
+	char			*script;
+	unsigned		ntodo;
+};
+
+struct vtc_job {
+	unsigned		magic;
+#define JOB_MAGIC		0x1b5fc419
+	struct vtc_tst		*tst;
+	pid_t			child;
+	struct vev		*ev;
+	struct vev		*evt;
+	char			*buf;
+	unsigned		bufsiz;
+	double			t0;
+};
+
+static VTAILQ_HEAD(, vtc_tst) tst_head = VTAILQ_HEAD_INITIALIZER(tst_head);
+static struct vev_base *vb;
+static int njob = 0;
+static int npar = 1;			/* Number of parallel tests */
+static unsigned vtc_maxdur = 30;	/* Max duration of any test */
+static int vtc_continue;		/* Continue on error */
+static int vtc_verbosity = 1;		/* Verbosity Level */
+static int vtc_good;
+static int vtc_fail;
+
+/**********************************************************************
+ * Read a file into memory
+ */
+
+static char *
+read_file(const char *fn)
+{
+	char *buf;
+	ssize_t sz = MAX_FILESIZE;
+	ssize_t s;
+	int fd;
+
+	fd = open(fn, O_RDONLY);
+	if (fd < 0)
+		return (NULL);
+	buf = malloc(sz);
+	assert(buf != NULL);
+	s = read(fd, buf, sz - 1);
+	if (s <= 0) {
+		free(buf);
+		return (NULL);
+	}
+	AZ(close (fd));
+	assert(s < sz);		/* XXX: increase MAX_FILESIZE */
+	buf[s] = '\0';
+	buf = realloc(buf, s + 1);
+	assert(buf != NULL);
+	return (buf);
+}
+
+/**********************************************************************
+ * Print usage
+ */
+
+static void
+usage(void)
+{
+	fprintf(stderr, "usage: varnishtest [-n iter] [-qv] file ...\n");
+	exit(1);
+}
+
+/**********************************************************************
+ * CallBack
+ */
+
+static int
+tst_cb(const struct vev *ve, int what)
+{
+	struct vtc_job *jp;
+	char buf[BUFSIZ];
+	int i, stx;
+	pid_t px;
+	double t;
+
+	CAST_OBJ_NOTNULL(jp, ve->priv, JOB_MAGIC);
+
+	// printf("%p %s %d\n", ve, jp->tst->filename, what);
+	if (what == 0) {
+		/* XXX: Timeout */
+		AZ(kill(jp->child, SIGKILL));
+		jp->evt = NULL;
+		return (1);
+	}
+	assert(what & EV_RD);
+
+	*buf = '\0';
+	i = read(ve->fd, buf, sizeof buf - 1);
+	if (i > 0) {
+		buf[i] = '\0';
+		printf("######## %s ########\n%s", jp->tst->filename, buf);
+	}
+	if (i == 0) {
+		njob--;
+		px = wait4(jp->child, &stx, 0, NULL);
+		t = TIM_mono() - jp->t0;
+		AZ(close(ve->fd));
+
+		if (stx && vtc_verbosity)
+			printf("%s\n", jp->buf);
+		else if (vtc_verbosity > 1)
+			printf("%s\n", jp->buf);
+
+		if (stx)
+			vtc_fail++;
+		else
+			vtc_good++;
+
+		if (stx) {
+			printf("#     top  TEST %s FAILED (%.3f)\n",
+			    jp->tst->filename, t);
+			if (!vtc_continue) {
+				/* XXX kill -9 other jobs ? */
+				exit (2);
+			}
+		} else if (vtc_verbosity) {
+			printf("#     top  TEST %s passed (%.3f)\n",
+			    jp->tst->filename, t);
+		}
+		AZ(munmap(jp->buf, jp->bufsiz));
+		if (jp->evt != NULL)
+			vev_del(vb, jp->evt);
+		FREE_OBJ(jp);
+		return (1);
+	}
+	return (0);
+}
+
+/**********************************************************************
+ * Start Test
+ */
+
+static void
+start_test(void)
+{
+	struct vtc_tst *tp;
+	int p[2], sfd, retval;
+	struct vtc_job *jp;
+
+	ALLOC_OBJ(jp, JOB_MAGIC);
+	AN(jp);
+
+	jp->bufsiz = 64*1024;		/* XXX */
+
+	jp->buf = mmap(NULL, jp->bufsiz, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);
+	assert(jp->buf != MAP_FAILED);
+	memset(jp->buf, 0, jp->bufsiz);
+
+	AZ(minherit(jp->buf, jp->bufsiz, INHERIT_SHARE));
+
+	tp = VTAILQ_FIRST(&tst_head);
+	CHECK_OBJ_NOTNULL(tp, TST_MAGIC);
+	AN(tp->ntodo);
+	tp->ntodo--;
+	VTAILQ_REMOVE(&tst_head, tp, list);
+	if (tp->ntodo >0)
+		VTAILQ_INSERT_TAIL(&tst_head, tp, list);
+
+	jp->tst = tp;
+
+	AZ(pipe(p));
+	assert(p[0] > STDERR_FILENO);
+	assert(p[1] > STDERR_FILENO);
+	jp->t0 = TIM_mono();
+	jp->child = fork();
+	assert(jp->child >= 0);
+	if (jp->child == 0) {
+		AZ(close(STDIN_FILENO));
+		assert(open("/dev/null", O_RDONLY) == STDIN_FILENO);
+		assert(dup2(p[1], STDOUT_FILENO) == STDOUT_FILENO);
+		assert(dup2(p[1], STDERR_FILENO) == STDERR_FILENO);
+		for (sfd = STDERR_FILENO + 1; sfd < 100; sfd++)
+			(void)close(sfd);
+		retval = exec_file(jp->tst->filename, jp->tst->script, jp->buf, jp->bufsiz);
+		_exit(retval);
+	}
+	AZ(close(p[1]));
+	AZ(minherit(jp->buf, jp->bufsiz, INHERIT_NONE));
+
+	jp->ev = vev_new();
+	AN(jp->ev);
+	jp->ev->fd_flags = EV_RD | EV_HUP | EV_ERR;
+	jp->ev->fd = p[0];
+	jp->ev->priv = jp;
+	jp->ev->callback = tst_cb;
+	AZ(vev_add(vb, jp->ev));
+
+	jp->evt = vev_new();
+	AN(jp->evt);
+	jp->evt->fd = -1;
+	jp->evt->timeout = vtc_maxdur;
+	jp->evt->priv = jp;
+	jp->evt->callback = tst_cb;
+	AZ(vev_add(vb, jp->evt));
+}
+
+/**********************************************************************
+ * Main
+ */
+
+int
+main(int argc, char * const *argv)
+{
+	int ch, i;
+	int ntest = 1;			/* Run tests this many times */
+	struct vtc_tst *tp;
+	char *p;
+
+	setbuf(stdout, NULL);
+	setbuf(stderr, NULL);
+	while ((ch = getopt(argc, argv, "j:kL:n:qt:v")) != -1) {
+		switch (ch) {
+		case 'j':
+			npar = strtoul(optarg, NULL, 0);
+			break;
+		case 'k':
+			vtc_continue = !vtc_continue;
+			break;
+		case 'n':
+			ntest = strtoul(optarg, NULL, 0);
+			break;
+		case 'q':
+			if (vtc_verbosity > 0)
+				vtc_verbosity--;
+			break;
+		case 't':
+			vtc_maxdur = strtoul(optarg, NULL, 0);
+			break;
+		case 'v':
+			if (vtc_verbosity < 2)
+				vtc_verbosity++;
+			break;
+		default:
+			usage();
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	for (;argc > 0; argc--, argv++) {
+		p = read_file(*argv);
+		if (p == NULL) {
+			fprintf(stderr, "Cannot stat file \"%s\": %s\n",
+			    *argv, strerror(errno));
+			if (vtc_continue)
+				continue;
+			exit (2);
+		}
+		ALLOC_OBJ(tp, TST_MAGIC);
+		AN(tp);
+		tp->filename = *argv;
+		tp->script = p;
+		tp->ntodo = ntest;
+		VTAILQ_INSERT_TAIL(&tst_head, tp, list);
+	}
+
+	vb = vev_new_base();
+
+	i = 0;
+	while(!VTAILQ_EMPTY(&tst_head) || i) {
+		if (!VTAILQ_EMPTY(&tst_head) && njob < npar) {
+			start_test();
+			njob++;
+			i = 1;
+			continue;
+		}
+		i = vev_schedule_one(vb);
+	}
+	if (vtc_continue)
+		fprintf(stderr, "%d tests failed, %d tests passed\n",
+		    vtc_fail, vtc_good);
+	if (vtc_fail)
+		return (1);
+	return (0);
+}




More information about the varnish-commit mailing list