This test is being added to provoke MAXIMUM_WAIT_OBJECTS on Windows
platforms.
Currently the synchronous transfer in this test hangs on Windows
platforms. This is due to the following sequence of events:
* There are more than MAXIMUM_WAIT_OBJECTS event objects to wait for.
* WaitForMultipleObjects fails with an error.
* usbi_poll detects this error and returns it.
* sync_transfer_wait_for_completion() receives this error and cancels
the transfer.
* The transfer cancel never comes through as usbi_poll still has too many
event objects.
---
tests/libusbx_testlib.h | 17 +++++++++
tests/stress.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++
tests/testlib.c | 11 ++++++
3 files changed, 124 insertions(+)
diff --git a/tests/libusbx_testlib.h b/tests/libusbx_testlib.h
index 8b109a2..678ff86 100644
--- a/tests/libusbx_testlib.h
+++ b/tests/libusbx_testlib.h
@@ -158,4 +158,21 @@ libusb_context *
libusbx_testlib_init_ctx_or_fail(libusbx_testlib_ctx * tctx);
libusb_device_handle * libusbx_testlib_open_test_device(
libusbx_testlib_ctx * tctx, libusb_context * ctx);
+/**
+ * Fails the test with the given reason.
+ */
+void libusbx_testlib_fail(libusbx_testlib_ctx * tctx,
+ const char * file,
+ int line,
+ const char * reason);
+
+/**
+ * Helper macro to make calling libusbx_testlib_assert() easier.
+ */
+#define LIBUSBX_TEST_ASSERT(tctx, statement) \
+do { \
+ if (!(statement)) \
+ libusbx_testlib_fail((tctx), __FILE__, __LINE__, #statement); \
+} while (0)
+
#endif //LIBUSBX_TESTLIB_H
diff --git a/tests/stress.c b/tests/stress.c
index f64f4b7..c0868f6 100644
--- a/tests/stress.c
+++ b/tests/stress.c
@@ -144,12 +144,108 @@ static libusbx_testlib_result
test_default_context_change(libusbx_testlib_ctx *
return TEST_STATUS_SUCCESS;
}
+void LIBUSB_CALL transfer_cb(struct libusb_transfer * transfer)
+{
+ int * done = (int*) transfer->user_data;
+ *done = 1;
+}
+
+#define GET_MANY_CFG_COUNT 64
+/** Tests many concurrent getting device configuration control requests. */
+static libusbx_testlib_result test_many_get_configuration_requests(
+ libusbx_testlib_ctx * tctx)
+{
+ struct libusb_transfer* transfers[GET_MANY_CFG_COUNT];
+ unsigned char
transfer_data[GET_MANY_CFG_COUNT][LIBUSB_CONTROL_SETUP_SIZE];
+ int transfer_done[GET_MANY_CFG_COUNT];
+ unsigned char data[1];
+ int i, r, all_done;
+ libusb_context * ctx = NULL;
+ libusb_device_handle * dev = NULL;
+
+ libusbx_testlib_skip_if_no_device(tctx);
+ ctx = libusbx_testlib_init_ctx_or_fail(tctx);
+ dev = libusbx_testlib_open_test_device(tctx, ctx);
+
+ memset(transfers, 0, sizeof(transfers));
+ memset(transfer_data, 0, sizeof(transfer_data));
+ memset(transfer_done, 0, sizeof(transfer_done));
+
+ /* Issue all the control transfers */
+ for(i = 0; i < GET_MANY_CFG_COUNT; ++i) {
+ transfers[i] = libusb_alloc_transfer(0);
+ LIBUSBX_TEST_ASSERT(tctx, transfers[i] != NULL);
+
+ libusb_fill_control_setup(transfer_data[i],
+ LIBUSB_ENDPOINT_IN |
+ LIBUSB_REQUEST_TYPE_STANDARD |
+ LIBUSB_RECIPIENT_DEVICE,
+ LIBUSB_REQUEST_GET_CONFIGURATION,
+ 0, 0, 1);
+ libusb_fill_control_transfer(transfers[i],
+ dev, transfer_data[i],
+ &transfer_cb, &transfer_done[i],
+ 60000);
+
+ r = libusb_submit_transfer(transfers[i]);
+ LIBUSBX_TEST_ASSERT(tctx, r == LIBUSB_SUCCESS || r ==
LIBUSB_ERROR_NOT_SUPPORTED);
+ if (r == LIBUSB_ERROR_NOT_SUPPORTED) {
+ /* All platforms should support at least 16 concurrent
transfers */
+ LIBUSBX_TEST_ASSERT(tctx, i > 16);
+ /* Mark this request as already done */
+ transfer_done[i] = 1;
+ }
+ }
+
+ /* Issue a synchronous control transfer, this tests the error handling
+ * in the synchronous case. */
+ r = libusb_control_transfer(dev,
+ LIBUSB_ENDPOINT_IN |
+ LIBUSB_REQUEST_TYPE_STANDARD |
+ LIBUSB_RECIPIENT_DEVICE,
+ LIBUSB_REQUEST_GET_CONFIGURATION,
+ 0,
+ 0,
+ data, sizeof(data), 1000);
+ LIBUSBX_TEST_ASSERT(tctx, r == 1 ||
+ r == LIBUSB_SUCCESS || r == LIBUSB_ERROR_NOT_SUPPORTED);
+
+ /* Process events until all the transfers are finished.
+ * This isn't done in a very sensible way as it just polls
+ * every 250ms to see if all the transfers have completed. */
+ do {
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 250000;
+ r = libusb_handle_events_timeout(ctx, &tv);
+ LIBUSBX_TEST_ASSERT(tctx, r == LIBUSB_SUCCESS);
+ /* Check if all the transfers are done */
+ all_done = 1;
+ for (i = 0; i < GET_MANY_CFG_COUNT; ++i) {
+ if (!transfer_done[i])
+ all_done = 0;
+ }
+ } while (!all_done);
+
+ /* Destroy all the transfers */
+ for(i = 0; i < GET_MANY_CFG_COUNT; ++i) {
+ libusb_free_transfer(transfers[i]);
+ transfers[i] = NULL;
+ }
+
+ libusb_close(dev);
+ libusb_exit(ctx);
+ return TEST_STATUS_SUCCESS;
+
+}
+
/* Fill in the list of tests. */
static const libusbx_testlib_test tests[] = {
LIBUSBX_NAMED_TEST(init_and_exit),
LIBUSBX_NAMED_TEST(get_device_list),
LIBUSBX_NAMED_TEST(many_device_lists),
LIBUSBX_NAMED_TEST(default_context_change),
+ LIBUSBX_NAMED_TEST(many_get_configuration_requests),
LIBUSBX_NULL_TEST
};
diff --git a/tests/testlib.c b/tests/testlib.c
index 3437591..c804a3b 100644
--- a/tests/testlib.c
+++ b/tests/testlib.c
@@ -373,3 +373,14 @@ libusb_device_handle * libusbx_testlib_open_test_device(
}
return dev;
}
+
+void libusbx_testlib_fail(
+ libusbx_testlib_ctx * tctx,
+ const char * file,
+ int line,
+ const char * reason)
+{
+ libusbx_testlib_logf(tctx, "Assert failure, %s:%d %s",
+ file, line, reason);
+ libusbx_testlib_finish_current_test(tctx, TEST_STATUS_FAILURE);
+}
--
1.7.9.5
------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:
Build for Windows Store.
http://p.sf.net/sfu/windows-dev2dev
_______________________________________________
libusbx-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libusbx-devel