diff options
author | Amit Shah <amit.shah@redhat.com> | 2010-08-23 13:55:16 +0530 |
---|---|---|
committer | Amit Shah <amit.shah@redhat.com> | 2010-08-23 13:55:16 +0530 |
commit | e1f100f1fbe0285c7efdfc30f38bece766e59efe (patch) | |
tree | 6c740d4f2d9c57b74ad27baa3db9abdd5cd85981 /auto-virtserial.c | |
parent | 2c799e07ca9327ef662896c01856f2f6f5c0229d (diff) | |
download | test-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.c | 90 |
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; } |