Example #1
0
void
vtc_wait4(struct vtclog *vl, long pid,
    int expect_status, int expect_signal, int allow_core)
{
	int status, r;
	struct rusage ru;

	r = wait4(pid, &status, 0, &ru);
	if (r < 0)
		vtc_fatal(vl, "wait4 failed on pid %ld: %s",
		    pid, strerror(errno));
	assert(r == pid);
	vtc_log(vl, 2, "WAIT4 pid=%ld status=0x%04x (user %.6f sys %.6f)",
	    pid, status,
	    ru.ru_utime.tv_sec + 1e-6 * ru.ru_utime.tv_usec,
	    ru.ru_stime.tv_sec + 1e-6 * ru.ru_stime.tv_usec
	);

	if (WIFEXITED(status) && expect_signal <= 0 &&
	    WEXITSTATUS(status) == expect_status)
		return;

	if (expect_signal < 0)
		expect_signal = -expect_signal;

	if (WIFSIGNALED(status) && WCOREDUMP(status) <= allow_core &&
	    WTERMSIG(status) == expect_signal)
		return;
	vtc_log(vl, 1, "Expected exit: 0x%x signal: %d core: %d",
	    expect_status, expect_signal, allow_core);
	vtc_fatal(vl, "Bad exit status: 0x%04x exit 0x%x signal %d core %d",
	    status,
	    WEXITSTATUS(status),
	    WIFSIGNALED(status) ? WTERMSIG(status) : 0,
	    WCOREDUMP(status));
}
Example #2
0
static void
varnish_vcl(struct varnish *v, const char *vcl, enum VCLI_status_e expect)
{
	struct vsb *vsb;
	enum VCLI_status_e u;

	if (v->cli_fd < 0)
		varnish_launch(v);
	if (vtc_error)
		return;
	vsb = VSB_new_auto();
	AN(vsb);

	VSB_printf(vsb, "vcl.inline vcl%d << %s\n%s\n%s\n",
	    ++v->vcl_nbr, NONSENSE, vcl, NONSENSE);
	AZ(VSB_finish(vsb));

	u = varnish_ask_cli(v, VSB_data(vsb), NULL);
	if (u != expect) {
		VSB_delete(vsb);
		vtc_log(v->vl, 0,
		    "VCL compilation got %u expected %u",
		    u, expect);
		return;
	}
	if (u == CLIS_OK) {
		VSB_clear(vsb);
		VSB_printf(vsb, "vcl.use vcl%d", v->vcl_nbr);
		AZ(VSB_finish(vsb));
		u = varnish_ask_cli(v, VSB_data(vsb), NULL);
		assert(u == CLIS_OK);
	} else {
		vtc_log(v->vl, 2, "VCL compilation failed (as expected)");
	}
	VSB_delete(vsb);
}
Example #3
0
static void
cmd_http_fatal(CMD_ARGS)
{
	struct http *hp;
	CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);

	AZ(av[1]);
	if (!strcmp(av[0], "fatal"))
		hp->fatal = 0;
	else if (!strcmp(av[0], "non-fatal"))
		hp->fatal = -1;
	else {
		vtc_log(vl, 0, "XXX: fatal %s", cmd->name);
	}
}
Example #4
0
static void
cmd_http_loop(CMD_ARGS)
{
	struct http *hp;
	unsigned n, m;

	CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
	AN(av[1]);
	AN(av[2]);
	AZ(av[3]);
	n = strtoul(av[1], NULL, 0);
	for (m = 1 ; m <= n; m++) {
		vtc_log(vl, 4, "Loop #%u", m);
		parse_string(av[2], cmd, hp, vl);
	}
}
Example #5
0
static void
cmd_http_timeout(CMD_ARGS)
{
	struct http *hp;
	double d;

	(void)cmd;
	(void)vl;
	CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
	AN(av[1]);
	AZ(av[2]);
	d = VNUM(av[1]);
	if (isnan(d))
		vtc_log(vl, 0, "timeout is not a number (%s)", av[1]);
	hp->timeout = (int)(d * 1000.0);
}
Example #6
0
static void
cmd_varnishtest(CMD_ARGS)
{

	(void)priv;
	(void)cmd;
	(void)vl;

	if (av == NULL)
		return;
	assert(!strcmp(av[0], "varnishtest"));

	vtc_log(vl, 1, "TEST %s", av[1]);
	AZ(av[2]);
	vtc_desc = strdup(av[1]);
}
Example #7
0
static void
cmd_http_rxhdrs(CMD_ARGS)
{
	struct http *hp;

	(void)cmd;
	(void)vl;
	CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
	ONLY_SERVER(hp, av);
	assert(!strcmp(av[0], "rxhdrs"));
	av++;

	for(; *av != NULL; av++)
		vtc_log(hp->vl, 0, "Unknown http rxreq spec: %s\n", *av);
	http_rxhdr(hp);
	http_splitheader(hp, 1);
}
Example #8
0
static void
cmd_http_send(CMD_ARGS)
{
	struct http *hp;
	int i;

	(void)cmd;
	(void)vl;
	CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
	AN(av[1]);
	AZ(av[2]);
	vtc_dump(hp->vl, 4, "send", av[1], -1);
	i = write(hp->fd, av[1], strlen(av[1]));
	if (i != strlen(av[1]))
		vtc_log(hp->vl, hp->fatal, "Write error in http_send(): %s",
		    strerror(errno));
}
Example #9
0
static void
cmd_feature(CMD_ARGS)
{
	int i;

	(void)priv;
	(void)cmd;
	if (av == NULL)
		return;

	for (i = 1; av[i] != NULL; i++) {
#ifdef SO_RCVTIMEO_WORKS
		if (!strcmp(av[i], "SO_RCVTIMEO_WORKS"))
			continue;
#endif
		if (sizeof(void*) == 8 && !strcmp(av[i], "64bit"))
			continue;

		if (!strcmp(av[i], "!OSX")) {
#if !defined(__APPLE__) || !defined(__MACH__)
			continue;
#endif
		}
		if (!strcmp(av[i], "topbuild") && iflg)
			continue;

		if (!strcmp(av[i], "root") && !geteuid())
			continue;

		if (!strcmp(av[i], "user_varnish") &&
		    getpwnam("varnish") != NULL)
			continue;

		if (!strcmp(av[i], "user_vcache") &&
		    getpwnam("vcache") != NULL)
			continue;

		if (!strcmp(av[i], "group_varnish") &&
		    getgrnam("varnish") != NULL)
			continue;

		vtc_log(vl, 1, "SKIPPING test, missing feature: %s", av[i]);
		vtc_stop = 1;
		return;
	}
}
Example #10
0
vtc_log_VAS_Fail(const char *func, const char *file, int line,
    const char *cond, enum vas_e why)
{
	struct vtclog *vl;

	(void)why;
	vl = pthread_getspecific(log_key);
	if (vl == NULL || vl->act) {
		fprintf(stderr,
		    "Assert error in %s(), %s line %d:\n"
		    "  Condition(%s) not true.\n",
		    func, file, line, cond);
	} else {
		vtc_log(vl, 0, "Assert error in %s(), %s line %d:"
		    "  Condition(%s) not true.\n", func, file, line, cond);
	}
	abort();
}
Example #11
0
static void
cmd_http_txresp(CMD_ARGS)
{
	struct http *hp;
	const char *proto = "HTTP/1.1";
	const char *status = "200";
	const char *msg = "OK";
	char* body = NULL;

	(void)cmd;
	(void)vl;
	CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
	ONLY_SERVER(hp, av);
	AZ(strcmp(av[0], "txresp"));
	av++;

	VSB_clear(hp->vsb);

	for(; *av != NULL; av++) {
		if (!strcmp(*av, "-proto")) {
			proto = av[1];
			av++;
		} else if (!strcmp(*av, "-status")) {
			status = av[1];
			av++;
		} else if (!strcmp(*av, "-msg")) {
			msg = av[1];
			av++;
			continue;
		} else
			break;
	}

	VSB_printf(hp->vsb, "%s %s %s%s", proto, status, msg, nl);

	/* send a "Content-Length: 0" header unless something else happens */
	REPLACE(body, "");

	av = http_tx_parse_args(av, vl, hp, body);
	if (*av != NULL)
		vtc_log(hp->vl, 0, "Unknown http txresp spec: %s\n", *av);

	http_write(hp, 4, "txresp");
}
Example #12
0
static void
cmd_http_rxchunk(CMD_ARGS)
{
	struct http *hp;
	int ll, i;

	(void)cmd;
	(void)vl;
	CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
	ONLY_CLIENT(hp, av);

	i = http_rxchunk(hp);
	if (i == 0) {
		ll = hp->rxbuf + hp->prxbuf - hp->body;
		hp->bodyl = ll;
		sprintf(hp->bodylen, "%d", ll);
		vtc_log(hp->vl, 4, "bodylen = %s", hp->bodylen);
	}
}
static int
h_addlog(void *priv, enum VSL_tag_e tag, unsigned fd, unsigned len,
    unsigned spec, const char *ptr, uint64_t bitmap)
{
	struct varnish *v;
	int type;

	(void) bitmap;

	type = (spec & VSL_S_CLIENT) ? 'c' :
	    (spec & VSL_S_BACKEND) ? 'b' : '-';
	CAST_OBJ_NOTNULL(v, priv, VARNISH_MAGIC);

	v->vsl_tag_count[tag]++;

	vtc_log(v->vl, 4, "vsl| %5u %-12s %c %.*s", fd,
	    VSL_tags[tag], type, len, ptr);
	v->vsl_sleep = 100;
	return (0);
}
static struct varnish *
varnish_new(const char *name)
{
	struct varnish *v;
	struct vsb *vsb;
	char buf[1024];

	AN(name);
	ALLOC_OBJ(v, VARNISH_MAGIC);
	AN(v);
	REPLACE(v->name, name);

	v->vl = vtc_logopen(name);
	AN(v->vl);

	bprintf(buf, "${tmpdir}/%s", name);
	vsb = macro_expand(v->vl, buf);
	AN(vsb);
	v->workdir = strdup(VSB_data(vsb));
	AN(v->workdir);
	VSB_delete(vsb);

	bprintf(buf, "rm -rf %s ; mkdir -p %s ; echo ' %ld' > %s/_S",
	    v->workdir, v->workdir, random(), v->workdir);
	AZ(system(buf));

	if (*v->name != 'v')
		vtc_log(v->vl, 0, "Varnish name must start with 'v'");

	v->args = VSB_new_auto();

	v->storage = VSB_new_auto();
	VSB_printf(v->storage, "-sfile,%s,10M", v->workdir);
	AZ(VSB_finish(v->storage));

	v->cli_fd = -1;
	VTAILQ_INSERT_TAIL(&varnishes, v, list);


	return (v);
}
Example #15
0
struct vsb *
macro_expand(struct vtclog *vl, const char *text)
{
	struct vsb *vsb;
	const char *p, *q;
	char *m;

	vsb = VSB_new_auto();
	AN(vsb);
	while (*text != '\0') {
		p = strstr(text, "${");
		if (p == NULL) {
			VSB_cat(vsb, text);
			break;
		}
		VSB_bcat(vsb, text, p - text);
		q = strchr(p, '}');
		if (q == NULL) {
			VSB_cat(vsb, text);
			break;
		}
		assert(p[0] == '$');
		assert(p[1] == '{');
		assert(q[0] == '}');
		p += 2;
		m = macro_get(p, q);
		if (m == NULL) {
			VSB_delete(vsb);
			vtc_log(vl, 0, "Macro ${%.*s} not found", (int)(q - p),
			    p);
			return (NULL);
		}
		VSB_printf(vsb, "%s", m);
		free(m);
		text = q + 1;
	}
	AZ(VSB_finish(vsb));
	return (vsb);
}
Example #16
0
static void
gzip_body(const struct http *hp, const char *txt, char **body, int *bodylen)
{
	int l, i;
	z_stream vz;

	memset(&vz, 0, sizeof vz);

	l = strlen(txt);
	*body = calloc(l + OVERHEAD, 1);
	AN(*body);

	vz.next_in = TRUST_ME(txt);
	vz.avail_in = l;

	vz.next_out = TRUST_ME(*body);
	vz.avail_out = l + OVERHEAD;

	assert(Z_OK == deflateInit2(&vz,
	    hp->gziplevel, Z_DEFLATED, 31, 9, Z_DEFAULT_STRATEGY));
	assert(Z_STREAM_END == deflate(&vz, Z_FINISH));
	i = vz.stop_bit & 7;
	if (hp->gzipresidual >= 0 && hp->gzipresidual != i)
		vtc_log(hp->vl, hp->fatal,
		    "Wrong gzip residual got %d wanted %d",
		    i, hp->gzipresidual);
	*bodylen = vz.total_out;
	vtc_log(hp->vl, 4, "startbit = %ju %ju/%ju",
	    (uintmax_t)vz.start_bit,
	    (uintmax_t)vz.start_bit >> 3, (uintmax_t)vz.start_bit & 7);
	vtc_log(hp->vl, 4, "lastbit = %ju %ju/%ju",
	    (uintmax_t)vz.last_bit,
	    (uintmax_t)vz.last_bit >> 3, (uintmax_t)vz.last_bit & 7);
	vtc_log(hp->vl, 4, "stopbit = %ju %ju/%ju",
	    (uintmax_t)vz.stop_bit,
	    (uintmax_t)vz.stop_bit >> 3, (uintmax_t)vz.stop_bit & 7);
	assert(Z_OK == deflateEnd(&vz));
}
static void
varnish_vclbackend(struct varnish *v, const char *vcl)
{
	struct vsb *vsb, *vsb2;
	enum VCLI_status_e u;

	if (v->cli_fd < 0)
		varnish_launch(v);
	if (vtc_error)
		return;
	vsb = VSB_new_auto();
	AN(vsb);

	vsb2 = VSB_new_auto();
	AN(vsb2);

	cmd_server_genvcl(vsb2);
	AZ(VSB_finish(vsb2));

	VSB_printf(vsb, "vcl.inline vcl%d << %s\n%s\n%s\n%s\n",
	    ++v->vcl_nbr, NONSENSE, VSB_data(vsb2), vcl, NONSENSE);
	AZ(VSB_finish(vsb));

	u = varnish_ask_cli(v, VSB_data(vsb), NULL);
	if (u != CLIS_OK) {
		VSB_delete(vsb);
		VSB_delete(vsb2);
		vtc_log(v->vl, 0, "FAIL VCL does not compile");
		return;
	}
	VSB_clear(vsb);
	VSB_printf(vsb, "vcl.use vcl%d", v->vcl_nbr);
	AZ(VSB_finish(vsb));
	u = varnish_ask_cli(v, VSB_data(vsb), NULL);
	assert(u == CLIS_OK);
	VSB_delete(vsb);
	VSB_delete(vsb2);
}
Example #18
0
static void
cmd_http_recv(CMD_ARGS)
{
	struct http *hp;
	int i, n;
	char u[32];

	(void)cmd;
	(void)vl;
	CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
	AN(av[1]);
	AZ(av[2]);
	n = strtoul(av[1], NULL, 0);
	while (n > 0) {
		i = read(hp->fd, u, n > 32 ? 32 : n);
		if (i > 0)
			vtc_dump(hp->vl, 4, "recv", u, i);
		else
			vtc_log(hp->vl, hp->fatal, "recv() got %d (%s)", i,
			    strerror(errno));
		n -= i;
	}
}
Example #19
0
static void
cmd_http_send_n(CMD_ARGS)
{
	struct http *hp;
	int i, n, l;

	(void)cmd;
	(void)vl;
	CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
	AN(av[1]);
	AN(av[2]);
	AZ(av[3]);
	n = strtoul(av[1], NULL, 0);
		vtc_dump(hp->vl, 4, "send_n", av[2], -1);
	l = strlen(av[2]);
	while (n--) {
		i = write(hp->fd, av[2], l);
		if (i != l)
			vtc_log(hp->vl, hp->fatal,
			    "Write error in http_send(): %s",
			    strerror(errno));
	}
}
Example #20
0
void
macro_def(struct vtclog *vl, const char *instance, const char *name,
    const char *fmt, ...)
{
	char buf1[256];
	char buf2[256];
	struct macro *m;
	va_list ap;

	AN(fmt);

	if (instance != NULL) {
		bprintf(buf1, "%s_%s", instance, name);
		name = buf1;
	}

	AZ(pthread_mutex_lock(&macro_mtx));
	VTAILQ_FOREACH(m, &macro_list, list)
		if (!strcmp(name, m->name))
			break;
	if (m == NULL) {
		m = calloc(sizeof *m, 1);
		AN(m);
		REPLACE(m->name, name);
		VTAILQ_INSERT_TAIL(&macro_list, m, list);
	}
	AN(m);
	va_start(ap, fmt);
	free(m->val);
	m->val = NULL;
	vbprintf(buf2, fmt, ap);
	va_end(ap);
	m->val = strdup(buf2);
	AN(m->val);
	vtc_log(vl, 4, "macro def %s=%s", name, m->val);
	AZ(pthread_mutex_unlock(&macro_mtx));
}
Example #21
0
static void
cmd_http_txreq(CMD_ARGS)
{
	struct http *hp;
	const char *req = "GET";
	const char *url = "/";
	const char *proto = "HTTP/1.1";

	(void)cmd;
	(void)vl;
	CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
	ONLY_CLIENT(hp, av);
	AZ(strcmp(av[0], "txreq"));
	av++;

	VSB_clear(hp->vsb);

	for(; *av != NULL; av++) {
		if (!strcmp(*av, "-url")) {
			url = av[1];
			av++;
		} else if (!strcmp(*av, "-proto")) {
			proto = av[1];
			av++;
		} else if (!strcmp(*av, "-req")) {
			req = av[1];
			av++;
		} else
			break;
	}
	VSB_printf(hp->vsb, "%s %s %s%s", req, url, proto, nl);

	av = http_tx_parse_args(av, vl, hp, NULL);
	if (*av != NULL)
		vtc_log(hp->vl, 0, "Unknown http txreq spec: %s\n", *av);
	http_write(hp, 4, "txreq");
}
Example #22
0
void
macro_undef(struct vtclog *vl, const char *instance, const char *name)
{
	char buf1[256];
	struct macro *m;

	if (instance != NULL) {
		bprintf(buf1, "%s_%s", instance, name);
		name = buf1;
	}

	AZ(pthread_mutex_lock(&macro_mtx));
	VTAILQ_FOREACH(m, &macro_list, list)
		if (!strcmp(name, m->name))
			break;
	if (m != NULL) {
		vtc_log(vl, 4, "macro undef %s", name);
		VTAILQ_REMOVE(&macro_list, m, list);
		free(m->name);
		free(m->val);
		free(m);
	}
	AZ(pthread_mutex_unlock(&macro_mtx));
}
Example #23
0
static void
cmd_http_sendhex(CMD_ARGS)
{
	struct http *hp;
	char buf[3], *q;
	uint8_t *p;
	int i, j, l;

	(void)cmd;
	(void)vl;
	CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
	AN(av[1]);
	AZ(av[2]);
	l = strlen(av[1]) / 2;
	p = malloc(l);
	AN(p);
	q = av[1];
	for (i = 0; i < l; i++) {
		while (vct_issp(*q))
			q++;
		if (*q == '\0')
			break;
		memcpy(buf, q, 2);
		q += 2;
		buf[2] = '\0';
		if (!vct_ishex(buf[0]) || !vct_ishex(buf[1]))
			vtc_log(hp->vl, 0, "Illegal Hex char \"%c%c\"",
			    buf[0], buf[1]);
		p[i] = (uint8_t)strtoul(buf, NULL, 16);
	}
	vtc_hexdump(hp->vl, 4, "sendhex", (void*)p, i);
	j = write(hp->fd, p, i);
	assert(j == i);
	free(p);

}
Example #24
0
static void
cmd_err_shell(CMD_ARGS)
{
	(void)priv;
	(void)cmd;
	struct vsb *vsb;
	FILE *fp;
	int r, c;

	if (av == NULL)
		return;
	AN(av[1]);
	AN(av[2]);
	AZ(av[3]);
	vsb = VSB_new_auto();
	AN(vsb);
	vtc_dump(vl, 4, "cmd", av[2], -1);
	fp = popen(av[2], "r");
	if (fp == NULL)
		vtc_log(vl, 0, "popen fails: %s", strerror(errno));
	do {
		c = getc(fp);
		if (c != EOF)
			VSB_putc(vsb, c);
	} while (c != EOF);
	r = pclose(fp);
	vtc_log(vl, 4, "Status = %d", WEXITSTATUS(r));
	if (WIFSIGNALED(r))
		vtc_log(vl, 4, "Signal = %d", WTERMSIG(r));
	if (WEXITSTATUS(r) == 0) {
		vtc_log(vl, 0,
		    "expected error from shell");
	}
	AZ(VSB_finish(vsb));
	vtc_dump(vl, 4, "stdout", VSB_data(vsb), VSB_len(vsb));
	if (strstr(VSB_data(vsb), av[1]) == NULL)
		vtc_log(vl, 0,
		    "Did not find expected string: (\"%s\")", av[1]);
	else
		vtc_log(vl, 4,
		    "Found expected string: (\"%s\")", av[1]);
	VSB_delete(vsb);
}
Example #25
0
void
parse_string(const char *spec, const struct cmds *cmd, void *priv,
    struct vtclog *vl)
{
	char *token_s[MAX_TOKENS], *token_e[MAX_TOKENS];
	struct vsb *token_exp[MAX_TOKENS];
	char *p, *q, *f, *buf;
	int nest_brace;
	int tn;
	const struct cmds *cp;

	AN(spec);
	buf = strdup(spec);
	AN(buf);
	for (p = buf; *p != '\0'; p++) {
		if (vtc_error || vtc_stop)
			break;
		/* Start of line */
		if (isspace(*p))
			continue;
		if (*p == '\n')
			continue;

		if (*p == '#') {
			for (; *p != '\0' && *p != '\n'; p++)
				;
			if (*p == '\0')
				break;
			continue;
		}

		q = strchr(p, '\n');
		if (q == NULL)
			q = strchr(p, '\0');
		if (q - p > 60)
			vtc_log(vl, 2, "=== %.60s...", p);
		else
			vtc_log(vl, 2, "=== %.*s", (int)(q - p), p);

		/* First content on line, collect tokens */
		tn = 0;
		f = p;
		while (*p != '\0') {
			assert(tn < MAX_TOKENS);
			if (*p == '\n') { /* End on NL */
				break;
			}
			if (isspace(*p)) { /* Inter-token whitespace */
				p++;
				continue;
			}
			if (*p == '\\' && p[1] == '\n') { /* line-cont */
				p += 2;
				continue;
			}
			if (*p == '"') { /* quotes */
				token_s[tn] = ++p;
				q = p;
				for (; *p != '\0'; p++) {
					if (*p == '"')
						break;
					if (*p == '\\') {
						p += VAV_BackSlash(p, q) - 1;
						q++;
					} else {
						if (*p == '\n')
							vtc_log(vl, 0,
				"Unterminated quoted string in line: %*.*s",
				(int)(p - f), (int)(p - f), f);
						assert(*p != '\n');
						*q++ = *p;
					}
				}
				token_e[tn++] = q;
				p++;
			} else if (*p == '{') { /* Braces */
				nest_brace = 0;
				token_s[tn] = p + 1;
				for (; *p != '\0'; p++) {
					if (*p == '{')
						nest_brace++;
					else if (*p == '}') {
						if (--nest_brace == 0)
							break;
					}
				}
				assert(*p == '}');
				token_e[tn++] = p++;
			} else { /* other tokens */
				token_s[tn] = p;
				for (; *p != '\0' && !isspace(*p); p++)
					;
				token_e[tn++] = p;
			}
		}
		assert(tn < MAX_TOKENS);
		token_s[tn] = NULL;
		for (tn = 0; token_s[tn] != NULL; tn++) {
			token_exp[tn] = NULL;
			AN(token_e[tn]);	/*lint !e771 */
			*token_e[tn] = '\0';	/*lint !e771 */
			if (NULL == strstr(token_s[tn], "${"))
				continue;
			token_exp[tn] = macro_expand(vl, token_s[tn]);
			if (vtc_error) {
				return;
			}
			token_s[tn] = VSB_data(token_exp[tn]);
			token_e[tn] = strchr(token_s[tn], '\0');
		}

		for (cp = cmd; cp->name != NULL; cp++)
			if (!strcmp(token_s[0], cp->name))
				break;
		if (cp->name == NULL) {
			vtc_log(vl, 0, "Unknown command: \"%s\"", token_s[0]);
			return;
		}

		assert(cp->cmd != NULL);
		cp->cmd(token_s, priv, cmd, vl);
	}
}
Example #26
0
static void
cmd_http_expect(CMD_ARGS)
{
	struct http *hp;
	const char *lhs, *clhs;
	char *cmp;
	const char *rhs, *crhs;
	vre_t *vre;
	const char *error;
	int erroroffset;
	int i, retval = -1;

	(void)cmd;
	(void)vl;
	CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
	AZ(strcmp(av[0], "expect"));
	av++;

	AN(av[0]);
	AN(av[1]);
	AN(av[2]);
	AZ(av[3]);
	lhs = cmd_var_resolve(hp, av[0]);
	cmp = av[1];
	rhs = cmd_var_resolve(hp, av[2]);

	clhs = lhs ? lhs : "<undef>";
	crhs = rhs ? rhs : "<undef>";

	if (!strcmp(cmp, "~") || !strcmp(cmp, "!~")) {
		vre = VRE_compile(crhs, 0, &error, &erroroffset);
		if (vre == NULL)
			vtc_log(hp->vl, 0, "REGEXP error: %s (@%d) (%s)",
			    error, erroroffset, crhs);
		i = VRE_exec(vre, clhs, strlen(clhs), 0, 0, NULL, 0, 0);
		retval = (i >= 0 && *cmp == '~') || (i < 0 && *cmp == '!');
		VRE_free(&vre);
	} else if (!strcmp(cmp, "==")) {
		retval = strcmp(clhs, crhs) == 0;
	} else if (!strcmp(cmp, "!=")) {
		retval = strcmp(clhs, crhs) != 0;
	} else if (lhs == NULL || rhs == NULL) {
		// fail inequality comparisons if either side is undef'ed
		retval = 0;
	} else if (!strcmp(cmp, "<")) {
		retval = isless(VNUM(lhs), VNUM(rhs));
	} else if (!strcmp(cmp, ">")) {
		retval = isgreater(VNUM(lhs), VNUM(rhs));
	} else if (!strcmp(cmp, "<=")) {
		retval = islessequal(VNUM(lhs), VNUM(rhs));
	} else if (!strcmp(cmp, ">=")) {
		retval = isgreaterequal(VNUM(lhs), VNUM(rhs));
	}

	if (retval == -1)
		vtc_log(hp->vl, 0,
		    "EXPECT %s (%s) %s %s (%s) test not implemented",
		    av[0], clhs, av[1], av[2], crhs);
	else
		vtc_log(hp->vl, retval ? 4 : 0, "EXPECT %s (%s) %s \"%s\" %s",
		    av[0], clhs, cmp, crhs, retval ? "match" : "failed");
}
static void
varnish_launch(struct varnish *v)
{
	struct vsb *vsb, *vsb1;
	int i, nfd, nap;
	struct vss_addr **ap;
	char abuf[128], pbuf[128];
	struct pollfd fd[2];
	enum VCLI_status_e u;
	char *r;

	v->vd = VSM_New();
	VSC_Setup(v->vd);

	/* Create listener socket */
	nap = VSS_resolve("127.0.0.1", "0", &ap);
	AN(nap);
	v->cli_fd = VSS_listen(ap[0], 1);
	VTCP_myname(v->cli_fd, abuf, sizeof abuf, pbuf, sizeof pbuf);

	AZ(VSB_finish(v->args));
	vtc_log(v->vl, 2, "Launch");
	vsb = VSB_new_auto();
	AN(vsb);
	VSB_printf(vsb, "cd ${pwd} &&");
	VSB_printf(vsb, " ${varnishd} -d -d -n %s", v->workdir);
	VSB_printf(vsb, " -l 10m,1m,-");
	VSB_printf(vsb, " -p auto_restart=off");
	VSB_printf(vsb, " -p syslog_cli_traffic=off");
	VSB_printf(vsb, " -a '%s'", "127.0.0.1:0");
	VSB_printf(vsb, " -S %s/_S", v->workdir);
	VSB_printf(vsb, " -M '%s %s'", abuf, pbuf);
	VSB_printf(vsb, " -P %s/varnishd.pid", v->workdir);
	VSB_printf(vsb, " %s", VSB_data(v->storage));
	VSB_printf(vsb, " %s", VSB_data(v->args));
	AZ(VSB_finish(vsb));
	vtc_log(v->vl, 3, "CMD: %s", VSB_data(vsb));
	vsb1 = macro_expand(v->vl, VSB_data(vsb));
	AN(vsb1);
	VSB_delete(vsb);
	vsb = vsb1;
	vtc_log(v->vl, 3, "CMD: %s", VSB_data(vsb));
	AZ(pipe(&v->fds[0]));
	AZ(pipe(&v->fds[2]));
	v->pid = fork();
	assert(v->pid >= 0);
	if (v->pid == 0) {
		assert(dup2(v->fds[0], 0) == 0);
		assert(dup2(v->fds[3], 1) == 1);
		assert(dup2(1, 2) == 2);
		AZ(close(v->fds[0]));
		AZ(close(v->fds[1]));
		AZ(close(v->fds[2]));
		AZ(close(v->fds[3]));
		for (i = 3; i <getdtablesize(); i++)
			(void)close(i);
		AZ(execl("/bin/sh", "/bin/sh", "-c", VSB_data(vsb), (char*)0));
		exit(1);
	} else {
		vtc_log(v->vl, 3, "PID: %ld", (long)v->pid);
	}
	AZ(close(v->fds[0]));
	AZ(close(v->fds[3]));
	v->fds[0] = v->fds[2];
	v->fds[2] = v->fds[3] = -1;
	VSB_delete(vsb);
	AZ(pthread_create(&v->tp, NULL, varnish_thread, v));
	AZ(pthread_create(&v->tp_vsl, NULL, varnishlog_thread, v));

	/* Wait for the varnish to call home */
	memset(fd, 0, sizeof fd);
	fd[0].fd = v->cli_fd;
	fd[0].events = POLLIN;
	fd[1].fd = v->fds[0];
	fd[1].events = 0; /* Only care about POLLHUP, which is output-only */
	i = poll(fd, 2, 10000);
	vtc_log(v->vl, 4, "CLIPOLL %d 0x%x 0x%x",
	    i, fd[0].revents, fd[1].revents);
	if (i == 0) {
		vtc_log(v->vl, 0, "FAIL timeout waiting for CLI connection");
		return;
	}
	if (fd[1].revents & POLLHUP) {
		vtc_log(v->vl, 0, "FAIL debug pipe closed");
		return;
	}
	if (!(fd[0].revents & POLLIN)) {
		vtc_log(v->vl, 0, "FAIL CLI connection wait failure");
		return;
	}
	nfd = accept(v->cli_fd, NULL, NULL);
	if (nfd < 0) {
		vtc_log(v->vl, 0, "FAIL no CLI connection accepted");
		return;
	}

	AZ(close(v->cli_fd));
	v->cli_fd = nfd;

	vtc_log(v->vl, 3, "CLI connection fd = %d", v->cli_fd);
	assert(v->cli_fd >= 0);


	/* Receive the banner or auth response */
	u = varnish_ask_cli(v, NULL, &r);
	if (vtc_error)
		return;
	if (u != CLIS_AUTH)
		vtc_log(v->vl, 0, "CLI auth demand expected: %u %s", u, r);

	bprintf(abuf, "%s/_S", v->workdir);
	nfd = open(abuf, O_RDONLY);
	assert(nfd >= 0);

	assert(sizeof abuf >= CLI_AUTH_RESPONSE_LEN + 7);
	strcpy(abuf, "auth ");
	VCLI_AuthResponse(nfd, r, abuf + 5);
	AZ(close(nfd));
	free(r);
	strcat(abuf, "\n");

	u = varnish_ask_cli(v, abuf, &r);
	if (vtc_error)
		return;
	if (u != CLIS_OK)
		vtc_log(v->vl, 0, "CLI auth command failed: %u %s", u, r);
	free(r);

	(void)VSL_Arg(v->vd, 'n', v->workdir);
	AZ(VSC_Open(v->vd, 1));
}
Example #28
0
static void
cmd_http_txresp(CMD_ARGS)
{
	struct http *hp;
	const char *proto = "HTTP/1.1";
	const char *status = "200";
	const char *msg = "Ok";
	int bodylen = 0;
	char *b, *c;
	char *body = NULL, *nullbody;
	int nolen = 0;


	(void)cmd;
	(void)vl;
	CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
	ONLY_SERVER(hp, av);
	assert(!strcmp(av[0], "txresp"));
	av++;

	VSB_clear(hp->vsb);

	/* send a "Content-Length: 0" header unless something else happens */
	REPLACE(body, "");
	nullbody = body;

	for(; *av != NULL; av++) {
		if (!strcmp(*av, "-proto")) {
			proto = av[1];
			av++;
		} else if (!strcmp(*av, "-status")) {
			status = av[1];
			av++;
		} else if (!strcmp(*av, "-msg")) {
			msg = av[1];
			av++;
			continue;
		} else
			break;
	}

	VSB_printf(hp->vsb, "%s %s %s%s", proto, status, msg, nl);

	for(; *av != NULL; av++) {
		if (!strcmp(*av, "-nolen")) {
			nolen = 1;
		} else if (!strcmp(*av, "-hdr")) {
			VSB_printf(hp->vsb, "%s%s", av[1], nl);
			av++;
		} else
			break;
	}
	for(; *av != NULL; av++) {
		if (!strcmp(*av, "-body")) {
			assert(body == nullbody);
			REPLACE(body, av[1]);

			AN(body);
			av++;
			bodylen = strlen(body);
			for (b = body; *b != '\0'; b++) {
				if(*b == '\\' && b[1] == '0') {
					*b = '\0';
					for(c = b+1; *c != '\0'; c++) {
						*c = c[1];
					}
					b++;
					bodylen--;
				}
			}
		} else if (!strcmp(*av, "-bodylen")) {
			assert(body == nullbody);
			body = synth_body(av[1], 0);
			bodylen = strlen(body);
			av++;
		} else if (!strcmp(*av, "-gzipresidual")) {
			hp->gzipresidual = strtoul(av[1], NULL, 0);
			av++;
		} else if (!strcmp(*av, "-gziplevel")) {
			hp->gziplevel = strtoul(av[1], NULL, 0);
			av++;
		} else if (!strcmp(*av, "-gziplen")) {
			assert(body == nullbody);
			b = synth_body(av[1], 1);
			gzip_body(hp, b, &body, &bodylen);
			VSB_printf(hp->vsb, "Content-Encoding: gzip%s", nl);
			// vtc_hexdump(hp->vl, 4, "gzip", (void*)body, bodylen);
			av++;
		} else if (!strcmp(*av, "-gzipbody")) {
			assert(body == nullbody);
			gzip_body(hp, av[1], &body, &bodylen);
			VSB_printf(hp->vsb, "Content-Encoding: gzip%s", nl);
			// vtc_hexdump(hp->vl, 4, "gzip", (void*)body, bodylen);
			av++;
		} else
			break;
	}
	if (*av != NULL)
		vtc_log(hp->vl, 0, "Unknown http txresp spec: %s\n", *av);
	if (body != NULL && !nolen)
		VSB_printf(hp->vsb, "Content-Length: %d%s", bodylen, nl);
	VSB_cat(hp->vsb, nl);
	if (body != NULL)
		VSB_bcat(hp->vsb, body, bodylen);
	http_write(hp, 4, "txresp");
}
Example #29
0
int
exec_file(const char *fn, const char *script, const char *tmpdir,
    char *logbuf, unsigned loglen)
{
	unsigned old_err;
	char *cwd, *p;
	FILE *f;
	struct extmacro *m;

	signal(SIGPIPE, SIG_IGN);

	vtc_loginit(logbuf, loglen);
	vltop = vtc_logopen("top");
	AN(vltop);

	init_macro();
	init_sema();

	/* Apply extmacro definitions */
	VTAILQ_FOREACH(m, &extmacro_list, list)
		macro_def(vltop, NULL, m->name, "%s", m->val);

	/* Other macro definitions */
	cwd = getcwd(NULL, PATH_MAX);
	macro_def(vltop, NULL, "pwd", "%s", cwd);
	macro_def(vltop, NULL, "topbuild", "%s/%s", cwd, TOP_BUILDDIR);

	/*
	 * We need an IP number which will not repond, ever, and that is a
	 * lot harder than it sounds.  This IP# is from RFC5737 and a
	 * C-class broadcast at that.
	 * If tests involving ${bad_ip} fails and you run linux, you should
	 * check your /proc/sys/net/ipv4/ip_nonlocal_bind setting.
	 */
	macro_def(vltop, NULL, "bad_ip", "192.0.2.255");

	/* Move into our tmpdir */
	AZ(chdir(tmpdir));
	macro_def(vltop, NULL, "tmpdir", "%s", tmpdir);

	/* Drop file to tell what was going on here */
	f = fopen("INFO", "w");
	AN(f);
	fprintf(f, "Test case: %s\n", fn);
	AZ(fclose(f));

	vtc_stop = 0;
	vtc_desc = NULL;
	vtc_log(vltop, 1, "TEST %s starting", fn);

	p = strdup(script);
	AN(p);

	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 (vtc_error)
		vtc_log(vltop, 1, "TEST %s FAILED", fn);
	else
		vtc_log(vltop, 1, "TEST %s completed", fn);

	free(vtc_desc);
	return (vtc_error);
}
Example #30
0
static void
cmd_http_txreq(CMD_ARGS)
{
	struct http *hp;
	const char *req = "GET";
	const char *url = "/";
	const char *proto = "HTTP/1.1";
	const char *body = NULL;

	(void)cmd;
	(void)vl;
	CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
	ONLY_CLIENT(hp, av);
	assert(!strcmp(av[0], "txreq"));
	av++;

	VSB_clear(hp->vsb);

	for(; *av != NULL; av++) {
		if (!strcmp(*av, "-url")) {
			url = av[1];
			av++;
		} else if (!strcmp(*av, "-proto")) {
			proto = av[1];
			av++;
		} else if (!strcmp(*av, "-req")) {
			req = av[1];
			av++;
		} else
			break;
	}
	VSB_printf(hp->vsb, "%s %s %s%s", req, url, proto, nl);
	for(; *av != NULL; av++) {
		if (!strcmp(*av, "-hdr")) {
			VSB_printf(hp->vsb, "%s%s", av[1], nl);
			av++;
		} else
			break;
	}
	for(; *av != NULL; av++) {
		if (!strcmp(*av, "-body")) {
			AZ(body);
			body = av[1];
			av++;
		} else if (!strcmp(*av, "-bodylen")) {
			AZ(body);
			body = synth_body(av[1], 0);
			av++;
		} else
			break;
	}
	if (*av != NULL)
		vtc_log(hp->vl, 0, "Unknown http txreq spec: %s\n", *av);
	if (body != NULL)
		VSB_printf(hp->vsb, "Content-Length: %ju%s",
		    (uintmax_t)strlen(body), nl);
	VSB_cat(hp->vsb, nl);
	if (body != NULL) {
		VSB_cat(hp->vsb, body);
		VSB_cat(hp->vsb, nl);
	}
	http_write(hp, 4, "txreq");
}