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
libusbx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libusbx-devel

Reply via email to