summaryrefslogtreecommitdiffstats
path: root/auto-virtserial.c
diff options
context:
space:
mode:
authorAmit Shah <amit.shah@redhat.com>2010-08-23 13:55:16 +0530
committerAmit Shah <amit.shah@redhat.com>2010-08-23 13:55:16 +0530
commite1f100f1fbe0285c7efdfc30f38bece766e59efe (patch)
tree6c740d4f2d9c57b74ad27baa3db9abdd5cd85981 /auto-virtserial.c
parent2c799e07ca9327ef662896c01856f2f6f5c0229d (diff)
downloadtest-virtserial-e1f100f1fbe0285c7efdfc30f38bece766e59efe.tar.gz
test-virtserial-e1f100f1fbe0285c7efdfc30f38bece766e59efe.tar.xz
test-virtserial-e1f100f1fbe0285c7efdfc30f38bece766e59efe.zip
auto-test: Introduce a threaded read/write test
Introduce a test that creates a new thread and blocks on a port for read. The parent thread then writes to the port, and later the host writes something to the port, unblocking the read. Signed-off-by: Amit Shah <amit.shah@redhat.com>
Diffstat (limited to 'auto-virtserial.c')
-rw-r--r--auto-virtserial.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/auto-virtserial.c b/auto-virtserial.c
index 9503f74..f04a834 100644
--- a/auto-virtserial.c
+++ b/auto-virtserial.c
@@ -248,6 +248,24 @@ static int guest_open_guest_bigfile(int value)
return guest_cmd(&gpkt);
}
+static int guest_create_read_thread(int nr)
+{
+ struct guest_packet gpkt;
+
+ gpkt.key = KEY_CREATE_READ_THREAD;
+ gpkt.value = nr;
+ return guest_cmd(&gpkt);
+}
+
+static int guest_join_read_thread(int nr)
+{
+ struct guest_packet gpkt;
+
+ gpkt.key = KEY_JOIN_READ_THREAD;
+ gpkt.value = nr;
+ return guest_cmd(&gpkt);
+}
+
static void show_stats(void)
{
fprintf(stderr, "-----\n");
@@ -1095,6 +1113,71 @@ out_close:
return err;
}
+/*
+ * Tests guest's ability to be blocked on read in one thread while
+ * writing to the same chardev in another thread
+ *
+ * - Open guest port
+ * - Call threaded test
+ * - Wait for POLLOUT from guest for a specific timeout
+ * - Collect result.
+ *
+ * If POLLOUT doesn't get set, that means the test failed and the
+ * guest is stuck in a blocking read anyway. So this should be the
+ * last test to run.
+ */
+static int test_threaded_read_write(int nr)
+{
+ struct pollfd pollfd[1];
+ struct guest_packet gpkt;
+ int err, ret;
+
+ ret = guest_open_port(nr);
+ err = result(__func__, true, "open", ret, -1, -1, OP_GT, false);
+ if (err)
+ return err;
+
+ host_connect_chardev(nr);
+
+ guest_set_length(nr, sizeof(gpkt));
+
+ ret = guest_create_read_thread(nr);
+ err = result(__func__, true, "create thread",
+ ret, -1, -1, OP_GT, false);
+ if (err)
+ goto out;
+
+ ret = guest_write(nr, BUF_LENGTH);
+ err = result(__func__, chardevs[nr].caching, "guest_write",
+ ret, BUF_LENGTH, BUF_LENGTH, OP_EQ, false);
+ if (err)
+ goto out;
+
+ pollfd[0].fd = chardevs[nr].sock;
+ pollfd[0].events = POLLOUT;
+ /* Wait for 5s to see if guest writes out something */
+ ret = poll(pollfd, 1, 5000);
+ if (ret == -1)
+ error(errno, errno, "%s: poll\n", __func__);
+ if (!(pollfd[0].revents & POLLOUT))
+ error(EIO, EIO, "%s: no response from guest\n", __func__);
+
+ /*
+ * Write out something - doesn't matter what. This should make
+ * the guest read thread unblock and return.
+ */
+ write(chardevs[nr].sock, &gpkt, sizeof(gpkt));
+
+ ret = guest_join_read_thread(nr);
+ err = result(__func__, true, "read", ret,
+ sizeof(gpkt), sizeof(gpkt), OP_EQ, true);
+
+ host_close_chardev(nr);
+out:
+ guest_close_port(nr);
+ return err;
+}
+
enum {
TEST_OPEN = 0,
TEST_CLOSE,
@@ -1113,6 +1196,7 @@ enum {
TEST_H_FILE_SEND,
TEST_G_FILE_SEND,
TEST_CONSOLE,
+ TEST_THREADED_READ_WRITE,
TEST_END
};
@@ -1189,6 +1273,10 @@ static struct test_parameters {
.test_function = test_console,
.needs_guestok = false,
},
+ {
+ .test_function = test_threaded_read_write,
+ .needs_guestok = true,
+ },
};
static void post_test_cleanup(int nr)
@@ -1329,6 +1417,8 @@ static int start_tests(void)
/* The console test should work in any case. */
run_test(TEST_CONSOLE, 0);
+ run_test(TEST_THREADED_READ_WRITE, 2);
+
return 0;
}