diff options
author | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-08-07 09:13:39 +0000 |
---|---|---|
committer | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-08-07 09:13:39 +0000 |
commit | ea9fb36c36fe706603acf672ce768865763ff63a (patch) | |
tree | 56fa173aeebcc148f2d30e586e51a44b133226d4 /tools/console/testsuite | |
parent | 2ba532d76714318ee9bfb5d0c10cb053be7cba00 (diff) | |
download | xen-ea9fb36c36fe706603acf672ce768865763ff63a.tar.gz xen-ea9fb36c36fe706603acf672ce768865763ff63a.tar.bz2 xen-ea9fb36c36fe706603acf672ce768865763ff63a.zip |
Really include renamed console files. :-)
Signed-off-by: Keir Fraser <keir@xensource.com>
Diffstat (limited to 'tools/console/testsuite')
-rw-r--r-- | tools/console/testsuite/Makefile | 11 | ||||
-rw-r--r-- | tools/console/testsuite/README | 29 | ||||
-rw-r--r-- | tools/console/testsuite/console-dom0.c | 117 | ||||
-rw-r--r-- | tools/console/testsuite/console-domU.c | 76 | ||||
-rw-r--r-- | tools/console/testsuite/procpipe.c | 133 |
5 files changed, 366 insertions, 0 deletions
diff --git a/tools/console/testsuite/Makefile b/tools/console/testsuite/Makefile new file mode 100644 index 0000000000..33ae3c1618 --- /dev/null +++ b/tools/console/testsuite/Makefile @@ -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 --git a/tools/console/testsuite/README b/tools/console/testsuite/README new file mode 100644 index 0000000000..a799d6a82f --- /dev/null +++ b/tools/console/testsuite/README @@ -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. diff --git a/tools/console/testsuite/console-dom0.c b/tools/console/testsuite/console-dom0.c new file mode 100644 index 0000000000..9c88c181f8 --- /dev/null +++ b/tools/console/testsuite/console-dom0.c @@ -0,0 +1,117 @@ +/* Written by Anthony Liguori <aliguori@us.ibm.com> */ + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <string.h> +#include <unistd.h> +#include <termios.h> + +#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 --git a/tools/console/testsuite/console-domU.c b/tools/console/testsuite/console-domU.c new file mode 100644 index 0000000000..3a9c508a6a --- /dev/null +++ b/tools/console/testsuite/console-domU.c @@ -0,0 +1,76 @@ +/* Written by Anthony Liguori <aliguori@us.ibm.com> */ + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <termios.h> +#include <unistd.h> + +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 --git a/tools/console/testsuite/procpipe.c b/tools/console/testsuite/procpipe.c new file mode 100644 index 0000000000..fc9791d2b4 --- /dev/null +++ b/tools/console/testsuite/procpipe.c @@ -0,0 +1,133 @@ +/* Written by Anthony Liguori <aliguori@us.ibm.com> */ + +#include <stdio.h> +#include <getopt.h> +#include <errno.h> +#include <stdlib.h> +#include <err.h> + +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#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; +} |