aboutsummaryrefslogtreecommitdiffstats
path: root/tools/console/testsuite
diff options
context:
space:
mode:
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-08-07 09:13:39 +0000
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-08-07 09:13:39 +0000
commitea9fb36c36fe706603acf672ce768865763ff63a (patch)
tree56fa173aeebcc148f2d30e586e51a44b133226d4 /tools/console/testsuite
parent2ba532d76714318ee9bfb5d0c10cb053be7cba00 (diff)
downloadxen-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/Makefile11
-rw-r--r--tools/console/testsuite/README29
-rw-r--r--tools/console/testsuite/console-dom0.c117
-rw-r--r--tools/console/testsuite/console-domU.c76
-rw-r--r--tools/console/testsuite/procpipe.c133
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;
+}