ia64/xen-unstable

changeset 6037:78a2f9cbd5b3

Attached is a randomized tester for consoled. It's a patch against
xen-unstable.hg but it doesn't add itself to any of the Makefiles but
just as a subdirectory of consoled. There's a README in the directory
that should be read otherwise you won't be able to do anything useful
with it :-)

Right now, we can get pretty far before seeing data corruption.
Previously, we'd see it almost immediately (after ~600 bytes, which is
the max the control channel can hold before filling up).

It's actual general enough that it could be also used to test network
traffic corruption but there are certainly better tools for that.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Aug 05 09:02:09 2005 +0000 (2005-08-05)
parents 5a86ab4c9b79
children 8727c784c07d
files tools/consoled/testsuite/Makefile tools/consoled/testsuite/README tools/consoled/testsuite/console-dom0.c tools/consoled/testsuite/console-domU.c tools/consoled/testsuite/procpipe.c
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/tools/consoled/testsuite/Makefile	Fri Aug 05 09:02:09 2005 +0000
     1.3 @@ -0,0 +1,11 @@
     1.4 +CFLAGS=-g -Wall
     1.5 +CC=gcc
     1.6 +LDFLAGS=-static
     1.7 +
     1.8 +all: console-dom0 console-domU procpipe
     1.9 +
    1.10 +console-dom0: console-dom0.o
    1.11 +console-domU: console-domU.o
    1.12 +procpipe: procpipe.o
    1.13 +
    1.14 +clean:; $(RM) *.o console-domU console-dom0 procpipe
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/consoled/testsuite/README	Fri Aug 05 09:02:09 2005 +0000
     2.3 @@ -0,0 +1,29 @@
     2.4 +ABOUT
     2.5 +
     2.6 +This tool uses two programs, one that lives in dom0 and one that lives in domU
     2.7 +to verify that no data is lost.  dom0 and domU share a handshake with each
     2.8 +other that they use to exchange a random seed.
     2.9 +
    2.10 +Both programs then generate a series of random numbers and then writes and
    2.11 +reads the numbers via the console.  Because each side starts with the same seed
    2.12 +they know what data the other side is generating and therefore what should be
    2.13 +expected.
    2.14 +
    2.15 +RUNNNING
    2.16 +
    2.17 +console-domU should be installed within the guest image.  It must be launched
    2.18 +from the client automatically.  I use a custom initrd image and put it in the
    2.19 +/linuxrc.
    2.20 +
    2.21 +console-dom0 and console-domU will communicate with each other and stress the
    2.22 +console code.  You can verify it at various levels by invoking it in different
    2.23 +ways.  procpipe is used to connect the two.  I use the following command for
    2.24 +testing:
    2.25 +
    2.26 +./procpipe ./console-dom0 'xm create -c /etc/xen/xmexample1'
    2.27 +
    2.28 +xmexample1 has no devices and no root set (this is what triggers /linuxrc).
    2.29 +
    2.30 +If it freezes, it probably means that console-domU is expecting more data from
    2.31 +console-dom0 (which means that some data got dropped).  I'd like to add
    2.32 +timeouts in the future to handle this more gracefully.
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/consoled/testsuite/console-dom0.c	Fri Aug 05 09:02:09 2005 +0000
     3.3 @@ -0,0 +1,117 @@
     3.4 +/* Written by Anthony Liguori <aliguori@us.ibm.com> */
     3.5 +
     3.6 +#include <stdio.h>
     3.7 +#include <stdlib.h>
     3.8 +#include <time.h>
     3.9 +#include <string.h>
    3.10 +#include <unistd.h>
    3.11 +#include <termios.h>
    3.12 +
    3.13 +#define MIN(a, b) (((a) < (b)) ? (a) : (b))
    3.14 +
    3.15 +static void generate_random_buffer(char *buffer, size_t size)
    3.16 +{
    3.17 +	int i;
    3.18 +
    3.19 +	for (i = 0; i < size; i++) {
    3.20 +		buffer[i] = random() & 0xFF;
    3.21 +	}
    3.22 +}
    3.23 +
    3.24 +static void canonicalize(char *buffer)
    3.25 +{
    3.26 +	char *reader, *writer;
    3.27 +
    3.28 +	reader = writer = buffer;
    3.29 +
    3.30 +	while (*reader) {
    3.31 +		*writer = *reader;
    3.32 +		if (*reader != '\r') writer++;
    3.33 +		reader++;
    3.34 +	}
    3.35 +	*writer = *reader;
    3.36 +}
    3.37 +
    3.38 +int main(int argc, char **argv)
    3.39 +{
    3.40 +	char buffer[4096];
    3.41 +	char *line;
    3.42 +	unsigned int seed;
    3.43 +	size_t size;
    3.44 +	int runs;
    3.45 +	unsigned long long total_bytes = 0;
    3.46 +	struct termios term;
    3.47 +
    3.48 +	tcgetattr(STDIN_FILENO, &term);
    3.49 +	cfmakeraw(&term);
    3.50 +	tcsetattr(STDIN_FILENO, TCSAFLUSH, &term);
    3.51 +
    3.52 +	tcgetattr(STDOUT_FILENO, &term);
    3.53 +	cfmakeraw(&term);
    3.54 +	tcsetattr(STDOUT_FILENO, TCSAFLUSH, &term);
    3.55 +
    3.56 +	while ((line = fgets(buffer, sizeof(buffer), stdin))) {
    3.57 +		canonicalize(line);
    3.58 +
    3.59 +		if (strcmp(line, "!!!XEN Test Begin!!!\n") == 0) {
    3.60 +			break;
    3.61 +		} else {
    3.62 +			fprintf(stderr, "%s", line);
    3.63 +		}
    3.64 +	}
    3.65 +
    3.66 +	if (line == NULL) {
    3.67 +		fprintf(stderr, "Client never sent start string.\n");
    3.68 +		return 1;
    3.69 +	}
    3.70 +
    3.71 +	seed = time(0);
    3.72 +
    3.73 +	printf("%u\n", seed); fflush(stdout);
    3.74 +
    3.75 +	fprintf(stderr, "Waiting for seed acknowledgement\n");
    3.76 +	line = fgets(buffer, sizeof(buffer), stdin);
    3.77 +	if (line == NULL) {
    3.78 +		fprintf(stderr, "Client never acknowledge seed.\n");
    3.79 +		return 1;
    3.80 +	}
    3.81 +
    3.82 +	canonicalize(line);
    3.83 +	if (strcmp(line, "Seed Okay.\n") != 0) {
    3.84 +		fprintf(stderr, "Incorrect seed acknowledgement.\n");
    3.85 +		fprintf(stderr, "[%s]", line);
    3.86 +		return 1;
    3.87 +	} else {
    3.88 +		fprintf(stderr, "Processed seed.\n");
    3.89 +	}
    3.90 +
    3.91 +	srandom(seed);
    3.92 +
    3.93 +	for (runs = (random() % 100000) + 4096; runs > 0; runs--) {
    3.94 +
    3.95 +		size = random() % 4096;
    3.96 +
    3.97 +		fprintf(stderr, "Writing %d bytes.\n", size);
    3.98 +
    3.99 +		generate_random_buffer(buffer, size);
   3.100 +		fwrite(buffer, size, 1, stdout);
   3.101 +		fflush(stdout);
   3.102 +
   3.103 +		do {
   3.104 +			line = fgets(buffer, sizeof(buffer), stdin);
   3.105 +			if (line == NULL) {
   3.106 +				fprintf(stderr, "Premature EOF from client.\n");
   3.107 +				return 1;
   3.108 +			}
   3.109 +
   3.110 +			canonicalize(line);
   3.111 +			fprintf(stderr, "%s", line);
   3.112 +		} while (strcmp(line, "Okay.\n") != 0);
   3.113 +
   3.114 +		total_bytes += size;
   3.115 +	}
   3.116 +
   3.117 +	fprintf(stderr, "PASS: processed %llu byte(s).\n", total_bytes);
   3.118 +
   3.119 +	return 0;
   3.120 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/consoled/testsuite/console-domU.c	Fri Aug 05 09:02:09 2005 +0000
     4.3 @@ -0,0 +1,76 @@
     4.4 +/* Written by Anthony Liguori <aliguori@us.ibm.com> */
     4.5 +
     4.6 +#include <stdio.h>
     4.7 +#include <stdlib.h>
     4.8 +#include <time.h>
     4.9 +#include <termios.h>
    4.10 +#include <unistd.h>
    4.11 +
    4.12 +static void canonicalize(char *buffer)
    4.13 +{
    4.14 +	char *reader, *writer;
    4.15 +
    4.16 +	reader = writer = buffer;
    4.17 +
    4.18 +	while (*reader) {
    4.19 +		*writer = *reader;
    4.20 +		if (*reader != '\r') writer++;
    4.21 +		reader++;
    4.22 +	}
    4.23 +	*writer = *reader;
    4.24 +}
    4.25 +
    4.26 +int main(int argc, char **argv)
    4.27 +{
    4.28 +	char buffer[4096];
    4.29 +	char *line;
    4.30 +	unsigned int seed;
    4.31 +	size_t size;
    4.32 +	int i;
    4.33 +	int runs;
    4.34 +	struct termios term;
    4.35 +
    4.36 +	tcgetattr(STDIN_FILENO, &term);
    4.37 +	cfmakeraw(&term);
    4.38 +	tcsetattr(STDIN_FILENO, TCSAFLUSH, &term);
    4.39 +
    4.40 +	tcgetattr(STDOUT_FILENO, &term);
    4.41 +	cfmakeraw(&term);
    4.42 +	tcsetattr(STDOUT_FILENO, TCSAFLUSH, &term);
    4.43 +
    4.44 +	printf("!!!XEN Test Begin!!!\n"); fflush(stdout);
    4.45 +	line = fgets(buffer, sizeof(buffer), stdin);
    4.46 +	if (line == NULL) {
    4.47 +		printf("Failure\n"); fflush(stdout);
    4.48 +		return 1;
    4.49 +	}
    4.50 +
    4.51 +	canonicalize(line);
    4.52 +	seed = strtoul(line, 0, 0);
    4.53 +
    4.54 +	printf("Seed Okay.\n"); fflush(stdout);
    4.55 +
    4.56 +	srandom(seed);
    4.57 +
    4.58 +	for (runs = (random() % 100000) + 4096; runs > 0; runs--) {
    4.59 +		size = random() % 4096;
    4.60 +
    4.61 +		for (i = 0; i < size; i++) {
    4.62 +			int ch;
    4.63 +			int exp;
    4.64 +
    4.65 +			ch = fgetc(stdin);
    4.66 +			exp = random() & 0xFF;
    4.67 +			if (ch != exp) {
    4.68 +				printf("Expected %d got %d\n",
    4.69 +				       exp, ch);
    4.70 +				fflush(stdout);
    4.71 +			}
    4.72 +			printf("Got %d/%d good bytes\n", i, size);
    4.73 +		}
    4.74 +		
    4.75 +		printf("Okay.\n"); fflush(stdout);
    4.76 +	}
    4.77 +
    4.78 +	return 0;
    4.79 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/consoled/testsuite/procpipe.c	Fri Aug 05 09:02:09 2005 +0000
     5.3 @@ -0,0 +1,133 @@
     5.4 +/* Written by Anthony Liguori <aliguori@us.ibm.com> */
     5.5 +
     5.6 +#include <stdio.h>
     5.7 +#include <getopt.h>
     5.8 +#include <errno.h>
     5.9 +#include <stdlib.h>
    5.10 +#include <err.h>
    5.11 +
    5.12 +#include <sys/types.h>
    5.13 +#include <sys/wait.h>
    5.14 +#include <unistd.h>
    5.15 +
    5.16 +#define PACKAGE_NAME "procpipe"
    5.17 +#define PACKAGE_VERSION "0.0.1"
    5.18 +
    5.19 +#define GPL_SHORT \
    5.20 +"This is free software; see the source for copying conditions.  There is NO\n"\
    5.21 +"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
    5.22 +
    5.23 +#define PACKAGE_BUGS "aliguori@us.ibm.com"
    5.24 +#define PACKAGE_AUTHOR "Anthony Liguori"
    5.25 +#define PACKAGE_OWNER "IBM, Corp."
    5.26 +#define PACKAGE_LICENSE GPL_SHORT
    5.27 +
    5.28 +static void usage(const char *name)
    5.29 +{
    5.30 +	printf("Usage: %s [OPTIONS]\n"
    5.31 +	       "\n"
    5.32 +	       "  -h, --help      display this help and exit\n"
    5.33 +	       "  -V, --version   output version information and exit\n"
    5.34 +	       "\n"
    5.35 +	       "Report bugs to <%s>.\n"
    5.36 +	       , name, PACKAGE_BUGS);
    5.37 +}
    5.38 +
    5.39 +static void version(const char *name)
    5.40 +{
    5.41 +	printf("%s (%s) %s\n"
    5.42 +	       "Written by %s.\n"
    5.43 +	       "\n"
    5.44 +	       "Copyright (C) 2005 %s.\n"
    5.45 +	       "%s\n"
    5.46 +	       , name, PACKAGE_NAME, PACKAGE_VERSION,
    5.47 +	       PACKAGE_AUTHOR, PACKAGE_OWNER, PACKAGE_LICENSE);
    5.48 +}
    5.49 +
    5.50 +static pid_t exec(int stdout, int stdin, const char *cmd)
    5.51 +{
    5.52 +	pid_t pid;
    5.53 +
    5.54 +	pid = fork();
    5.55 +	if (pid == 0) {
    5.56 +		close(STDOUT_FILENO);
    5.57 +		dup2(stdout, STDOUT_FILENO);
    5.58 +		close(STDIN_FILENO);
    5.59 +		dup2(stdin, STDIN_FILENO);
    5.60 +
    5.61 +		execlp("/bin/sh", "sh", "-c", cmd, NULL);
    5.62 +	}
    5.63 +
    5.64 +	return pid;
    5.65 +}
    5.66 +
    5.67 +int main(int argc, char **argv)
    5.68 +{
    5.69 +	int ch, opt_ind = 0;
    5.70 +	const char *sopt = "hV";
    5.71 +	struct option lopt[] = {
    5.72 +		{ "help", 0, 0, 'h' },
    5.73 +		{ "version", 0, 0, 'V' },
    5.74 +		{ 0 }
    5.75 +	};
    5.76 +	int host_stdout[2];
    5.77 +	int host_stdin[2];
    5.78 +	int res;
    5.79 +	pid_t pid1, pid2;
    5.80 +	int status;
    5.81 +
    5.82 +	while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
    5.83 +		switch (ch) {
    5.84 +		case 'h':
    5.85 +			usage(argv[0]);
    5.86 +			exit(0);
    5.87 +		case 'V':
    5.88 +			version(argv[0]);
    5.89 +			exit(0);
    5.90 +		case '?':
    5.91 +			errx(EINVAL, "Try `%s --help' for more information.",
    5.92 +			     argv[0]);
    5.93 +		}
    5.94 +	}
    5.95 +
    5.96 +	if ((argc - optind) != 2) {
    5.97 +		errx(EINVAL, "Two commands are required.\n"
    5.98 +		     "Try `%s --help' for more information.", argv[0]);
    5.99 +	}
   5.100 +
   5.101 +	res = pipe(host_stdout);
   5.102 +	if (res == -1) {
   5.103 +		err(errno, "pipe() failed");
   5.104 +	}
   5.105 +
   5.106 +	res = pipe(host_stdin);
   5.107 +	if (res == -1) {
   5.108 +		err(errno, "pipe() failed");
   5.109 +	}
   5.110 +
   5.111 +	pid1 = exec(host_stdout[1], host_stdin[0], argv[optind]);
   5.112 +	if (pid1 == -1) {
   5.113 +		err(errno, "exec(%s)", argv[optind]);
   5.114 +	}
   5.115 +
   5.116 +	pid2 = exec(host_stdin[1], host_stdout[0], argv[optind + 1]);
   5.117 +	if (pid2 == -1) {
   5.118 +		err(errno, "exec(%s)", argv[optind + 1]);
   5.119 +	}
   5.120 +
   5.121 +	waitpid(pid1, &status, 0);
   5.122 +	if (WIFEXITED(status)) status = WEXITSTATUS(status);
   5.123 +
   5.124 +	if (status != 0) {
   5.125 +		printf("Child exited with status %d\n", status);
   5.126 +	}
   5.127 +
   5.128 +	waitpid(pid2, &status, 0);
   5.129 +	if (WIFEXITED(status)) status = WEXITSTATUS(status);
   5.130 +
   5.131 +	if (status != 0) {
   5.132 +		printf("Child2 exited with status %d\n", status);
   5.133 +	}
   5.134 +
   5.135 +	return 0;
   5.136 +}