diff -urN xen-unstable-20050804/tools/consoled/testsuite/console-dom0.c xen-unstable.hg/tools/consoled/testsuite/console-dom0.c --- xen-unstable-20050804/tools/consoled/testsuite/console-dom0.c 1969-12-31 18:00:00.000000000 -0600 +++ xen-unstable.hg/tools/consoled/testsuite/console-dom0.c 2005-08-04 17:57:11.000000000 -0500 @@ -0,0 +1,117 @@ +/* Written by Anthony Liguori */ + +#include +#include +#include +#include +#include +#include + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +static void generate_random_buffer(char *buffer, size_t size) +{ + int i; + + for (i = 0; i < size; i++) { + buffer[i] = random() & 0xFF; + } +} + +static void canonicalize(char *buffer) +{ + char *reader, *writer; + + reader = writer = buffer; + + while (*reader) { + *writer = *reader; + if (*reader != '\r') writer++; + reader++; + } + *writer = *reader; +} + +int main(int argc, char **argv) +{ + char buffer[4096]; + char *line; + unsigned int seed; + size_t size; + int runs; + unsigned long long total_bytes = 0; + struct termios term; + + tcgetattr(STDIN_FILENO, &term); + cfmakeraw(&term); + tcsetattr(STDIN_FILENO, TCSAFLUSH, &term); + + tcgetattr(STDOUT_FILENO, &term); + cfmakeraw(&term); + tcsetattr(STDOUT_FILENO, TCSAFLUSH, &term); + + while ((line = fgets(buffer, sizeof(buffer), stdin))) { + canonicalize(line); + + if (strcmp(line, "!!!XEN Test Begin!!!\n") == 0) { + break; + } else { + fprintf(stderr, "%s", line); + } + } + + if (line == NULL) { + fprintf(stderr, "Client never sent start string.\n"); + return 1; + } + + seed = time(0); + + printf("%u\n", seed); fflush(stdout); + + fprintf(stderr, "Waiting for seed acknowledgement\n"); + line = fgets(buffer, sizeof(buffer), stdin); + if (line == NULL) { + fprintf(stderr, "Client never acknowledge seed.\n"); + return 1; + } + + canonicalize(line); + if (strcmp(line, "Seed Okay.\n") != 0) { + fprintf(stderr, "Incorrect seed acknowledgement.\n"); + fprintf(stderr, "[%s]", line); + return 1; + } else { + fprintf(stderr, "Processed seed.\n"); + } + + srandom(seed); + + for (runs = (random() % 100000) + 4096; runs > 0; runs--) { + + size = random() % 4096; + + fprintf(stderr, "Writing %d bytes.\n", size); + + generate_random_buffer(buffer, size); + fwrite(buffer, size, 1, stdout); + fflush(stdout); + + do { + line = fgets(buffer, sizeof(buffer), stdin); + if (line == NULL) { + fprintf(stderr, "Premature EOF from client.\n"); + return 1; + } + + canonicalize(line); + fprintf(stderr, "%s", line); + } while (strcmp(line, "Okay.\n") != 0); + + total_bytes += size; + } + + fprintf(stderr, "PASS: processed %llu byte(s).\n", total_bytes); + + return 0; +} diff -urN xen-unstable-20050804/tools/consoled/testsuite/console-domU.c xen-unstable.hg/tools/consoled/testsuite/console-domU.c --- xen-unstable-20050804/tools/consoled/testsuite/console-domU.c 1969-12-31 18:00:00.000000000 -0600 +++ xen-unstable.hg/tools/consoled/testsuite/console-domU.c 2005-08-04 17:57:14.000000000 -0500 @@ -0,0 +1,76 @@ +/* Written by Anthony Liguori */ + +#include +#include +#include +#include +#include + +static void canonicalize(char *buffer) +{ + char *reader, *writer; + + reader = writer = buffer; + + while (*reader) { + *writer = *reader; + if (*reader != '\r') writer++; + reader++; + } + *writer = *reader; +} + +int main(int argc, char **argv) +{ + char buffer[4096]; + char *line; + unsigned int seed; + size_t size; + int i; + int runs; + struct termios term; + + tcgetattr(STDIN_FILENO, &term); + cfmakeraw(&term); + tcsetattr(STDIN_FILENO, TCSAFLUSH, &term); + + tcgetattr(STDOUT_FILENO, &term); + cfmakeraw(&term); + tcsetattr(STDOUT_FILENO, TCSAFLUSH, &term); + + printf("!!!XEN Test Begin!!!\n"); fflush(stdout); + line = fgets(buffer, sizeof(buffer), stdin); + if (line == NULL) { + printf("Failure\n"); fflush(stdout); + return 1; + } + + canonicalize(line); + seed = strtoul(line, 0, 0); + + printf("Seed Okay.\n"); fflush(stdout); + + srandom(seed); + + for (runs = (random() % 100000) + 4096; runs > 0; runs--) { + size = random() % 4096; + + for (i = 0; i < size; i++) { + int ch; + int exp; + + ch = fgetc(stdin); + exp = random() & 0xFF; + if (ch != exp) { + printf("Expected %d got %d\n", + exp, ch); + fflush(stdout); + } + printf("Got %d/%d good bytes\n", i, size); + } + + printf("Okay.\n"); fflush(stdout); + } + + return 0; +} diff -urN xen-unstable-20050804/tools/consoled/testsuite/Makefile xen-unstable.hg/tools/consoled/testsuite/Makefile --- xen-unstable-20050804/tools/consoled/testsuite/Makefile 1969-12-31 18:00:00.000000000 -0600 +++ xen-unstable.hg/tools/consoled/testsuite/Makefile 2005-08-03 20:39:54.000000000 -0500 @@ -0,0 +1,11 @@ +CFLAGS=-g -Wall +CC=gcc +LDFLAGS=-static + +all: console-dom0 console-domU procpipe + +console-dom0: console-dom0.o +console-domU: console-domU.o +procpipe: procpipe.o + +clean:; $(RM) *.o console-domU console-dom0 procpipe diff -urN xen-unstable-20050804/tools/consoled/testsuite/procpipe.c xen-unstable.hg/tools/consoled/testsuite/procpipe.c --- xen-unstable-20050804/tools/consoled/testsuite/procpipe.c 1969-12-31 18:00:00.000000000 -0600 +++ xen-unstable.hg/tools/consoled/testsuite/procpipe.c 2005-08-04 17:57:17.000000000 -0500 @@ -0,0 +1,133 @@ +/* Written by Anthony Liguori */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define PACKAGE_NAME "procpipe" +#define PACKAGE_VERSION "0.0.1" + +#define GPL_SHORT \ +"This is free software; see the source for copying conditions. There is NO\n"\ +"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +#define PACKAGE_BUGS "aliguori@us.ibm.com" +#define PACKAGE_AUTHOR "Anthony Liguori" +#define PACKAGE_OWNER "IBM, Corp." +#define PACKAGE_LICENSE GPL_SHORT + +static void usage(const char *name) +{ + printf("Usage: %s [OPTIONS]\n" + "\n" + " -h, --help display this help and exit\n" + " -V, --version output version information and exit\n" + "\n" + "Report bugs to <%s>.\n" + , name, PACKAGE_BUGS); +} + +static void version(const char *name) +{ + printf("%s (%s) %s\n" + "Written by %s.\n" + "\n" + "Copyright (C) 2005 %s.\n" + "%s\n" + , name, PACKAGE_NAME, PACKAGE_VERSION, + PACKAGE_AUTHOR, PACKAGE_OWNER, PACKAGE_LICENSE); +} + +static pid_t exec(int stdout, int stdin, const char *cmd) +{ + pid_t pid; + + pid = fork(); + if (pid == 0) { + close(STDOUT_FILENO); + dup2(stdout, STDOUT_FILENO); + close(STDIN_FILENO); + dup2(stdin, STDIN_FILENO); + + execlp("/bin/sh", "sh", "-c", cmd, NULL); + } + + return pid; +} + +int main(int argc, char **argv) +{ + int ch, opt_ind = 0; + const char *sopt = "hV"; + struct option lopt[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'V' }, + { 0 } + }; + int host_stdout[2]; + int host_stdin[2]; + int res; + pid_t pid1, pid2; + int status; + + while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) { + switch (ch) { + case 'h': + usage(argv[0]); + exit(0); + case 'V': + version(argv[0]); + exit(0); + case '?': + errx(EINVAL, "Try `%s --help' for more information.", + argv[0]); + } + } + + if ((argc - optind) != 2) { + errx(EINVAL, "Two commands are required.\n" + "Try `%s --help' for more information.", argv[0]); + } + + res = pipe(host_stdout); + if (res == -1) { + err(errno, "pipe() failed"); + } + + res = pipe(host_stdin); + if (res == -1) { + err(errno, "pipe() failed"); + } + + pid1 = exec(host_stdout[1], host_stdin[0], argv[optind]); + if (pid1 == -1) { + err(errno, "exec(%s)", argv[optind]); + } + + pid2 = exec(host_stdin[1], host_stdout[0], argv[optind + 1]); + if (pid2 == -1) { + err(errno, "exec(%s)", argv[optind + 1]); + } + + waitpid(pid1, &status, 0); + if (WIFEXITED(status)) status = WEXITSTATUS(status); + + if (status != 0) { + printf("Child exited with status %d\n", status); + } + + waitpid(pid2, &status, 0); + if (WIFEXITED(status)) status = WEXITSTATUS(status); + + if (status != 0) { + printf("Child2 exited with status %d\n", status); + } + + return 0; +} diff -urN xen-unstable-20050804/tools/consoled/testsuite/README xen-unstable.hg/tools/consoled/testsuite/README --- xen-unstable-20050804/tools/consoled/testsuite/README 1969-12-31 18:00:00.000000000 -0600 +++ xen-unstable.hg/tools/consoled/testsuite/README 2005-08-04 17:56:45.000000000 -0500 @@ -0,0 +1,29 @@ +ABOUT + +This tool uses two programs, one that lives in dom0 and one that lives in domU +to verify that no data is lost. dom0 and domU share a handshake with each +other that they use to exchange a random seed. + +Both programs then generate a series of random numbers and then writes and +reads the numbers via the console. Because each side starts with the same seed +they know what data the other side is generating and therefore what should be +expected. + +RUNNNING + +console-domU should be installed within the guest image. It must be launched +from the client automatically. I use a custom initrd image and put it in the +/linuxrc. + +console-dom0 and console-domU will communicate with each other and stress the +console code. You can verify it at various levels by invoking it in different +ways. procpipe is used to connect the two. I use the following command for +testing: + +./procpipe ./console-dom0 'xm create -c /etc/xen/xmexample1' + +xmexample1 has no devices and no root set (this is what triggers /linuxrc). + +If it freezes, it probably means that console-domU is expecting more data from +console-dom0 (which means that some data got dropped). I'd like to add +timeouts in the future to handle this more gracefully.