Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package aws-c-http for openSUSE:Factory 
checked in at 2024-08-09 16:14:43
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/aws-c-http (Old)
 and      /work/SRC/openSUSE:Factory/.aws-c-http.new.7232 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "aws-c-http"

Fri Aug  9 16:14:43 2024 rev:6 rq:1192574 version:0.8.6

Changes:
--------
--- /work/SRC/openSUSE:Factory/aws-c-http/aws-c-http.changes    2024-08-01 
22:06:48.498354445 +0200
+++ /work/SRC/openSUSE:Factory/.aws-c-http.new.7232/aws-c-http.changes  
2024-08-09 16:15:12.292286136 +0200
@@ -1,0 +2,7 @@
+Wed Aug  7 13:24:54 UTC 2024 - John Paul Adrian Glaubitz 
<adrian.glaub...@suse.com>
+
+- Update to version 0.8.6
+  * Connection Manager Acquisition Timeout by @waahm7 in (#479)
+  * Support MaxPendingConnectionAcquisitions by @waahm7 in (#481)
+
+-------------------------------------------------------------------

Old:
----
  v0.8.5.tar.gz

New:
----
  v0.8.6.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ aws-c-http.spec ++++++
--- /var/tmp/diff_new_pack.j8sbL3/_old  2024-08-09 16:15:12.896311348 +0200
+++ /var/tmp/diff_new_pack.j8sbL3/_new  2024-08-09 16:15:12.896311348 +0200
@@ -19,7 +19,7 @@
 %define library_version 1.0.0
 %define library_soversion 1_0_0
 Name:           aws-c-http
-Version:        0.8.5
+Version:        0.8.6
 Release:        0
 Summary:        C99 implementation of the HTTP/1.1 and HTTP/2 specifications
 License:        Apache-2.0

++++++ v0.8.5.tar.gz -> v0.8.6.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/aws-c-http-0.8.5/include/aws/http/connection_manager.h 
new/aws-c-http-0.8.6/include/aws/http/connection_manager.h
--- old/aws-c-http-0.8.5/include/aws/http/connection_manager.h  2024-07-29 
22:12:51.000000000 +0200
+++ new/aws-c-http-0.8.6/include/aws/http/connection_manager.h  2024-08-06 
00:51:26.000000000 +0200
@@ -126,6 +126,20 @@
     uint64_t max_connection_idle_in_milliseconds;
 
     /**
+     * If set to a non-zero value, 
aws_http_connection_manager_acquire_connection() calls
+     * will give up after waiting this long for a connection from the pool,
+     * failing with error 
AWS_ERROR_HTTP_CONNECTION_MANAGER_ACQUISITION_TIMEOUT.
+     */
+    uint64_t connection_acquisition_timeout_ms;
+
+    /*
+     * If set to a non-zero value, 
aws_http_connection_manager_acquire_connection() calls will fail with
+     * AWS_ERROR_HTTP_CONNECTION_MANAGER_MAX_PENDING_ACQUISITIONS_EXCEEDED if 
there are already pending acquisitions
+     * equal to `max_pending_connection_acquisitions`.
+     */
+    uint64_t max_pending_connection_acquisitions;
+
+    /**
      * THIS IS AN EXPERIMENTAL AND UNSTABLE API
      * (Optional)
      * An array of network interface names. The manager will distribute the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-http-0.8.5/include/aws/http/http.h 
new/aws-c-http-0.8.6/include/aws/http/http.h
--- old/aws-c-http-0.8.5/include/aws/http/http.h        2024-07-29 
22:12:51.000000000 +0200
+++ new/aws-c-http-0.8.6/include/aws/http/http.h        2024-08-06 
00:51:26.000000000 +0200
@@ -60,6 +60,8 @@
     AWS_ERROR_HTTP_MANUAL_WRITE_NOT_ENABLED,
     AWS_ERROR_HTTP_MANUAL_WRITE_HAS_COMPLETED,
     AWS_ERROR_HTTP_RESPONSE_FIRST_BYTE_TIMEOUT,
+    AWS_ERROR_HTTP_CONNECTION_MANAGER_ACQUISITION_TIMEOUT,
+    AWS_ERROR_HTTP_CONNECTION_MANAGER_MAX_PENDING_ACQUISITIONS_EXCEEDED,
 
     AWS_ERROR_HTTP_END_RANGE = AWS_ERROR_ENUM_END_RANGE(AWS_C_HTTP_PACKAGE_ID)
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-http-0.8.5/source/connection_manager.c 
new/aws-c-http-0.8.6/source/connection_manager.c
--- old/aws-c-http-0.8.5/source/connection_manager.c    2024-07-29 
22:12:51.000000000 +0200
+++ new/aws-c-http-0.8.6/source/connection_manager.c    2024-08-06 
00:51:26.000000000 +0200
@@ -193,7 +193,10 @@
     struct aws_linked_list idle_connections;
 
     /*
-     * The set of all incomplete connection acquisition requests
+     * The set of all incomplete connection acquisition requests.
+     * This must be a FIFO list. When connections are requested by the user, 
they are added to the back. When we need to
+     * complete the acquisition, we pop from the front. In this way, the list 
is always sorted from the oldest (in terms
+     * of timeout timestamp) to the newest and we can cull it similar to 
idle_connections.
      */
     struct aws_linked_list pending_acquisitions;
 
@@ -286,6 +289,10 @@
      */
     uint64_t max_connection_idle_in_milliseconds;
 
+    uint64_t connection_acquisition_timeout_ms;
+
+    uint64_t max_pending_connection_acquisitions;
+
     /*
      * Task to cull idle connections.  This task is run periodically on the 
cull_event_loop if a non-zero
      * culling time interval is specified.
@@ -392,6 +399,7 @@
     struct aws_http_connection *connection;
     int error_code;
     struct aws_channel_task acquisition_task;
+    uint64_t timeout_timestamp;
 };
 
 static void s_connection_acquisition_task(
@@ -758,26 +766,17 @@
 }
 
 static void s_cull_task(struct aws_task *task, void *arg, enum aws_task_status 
status);
-static void s_schedule_connection_culling(struct aws_http_connection_manager 
*manager) {
-    if (manager->max_connection_idle_in_milliseconds == 0) {
-        return;
-    }
-
-    if (manager->cull_task == NULL) {
-        manager->cull_task = aws_mem_calloc(manager->allocator, 1, 
sizeof(struct aws_task));
-        aws_task_init(manager->cull_task, s_cull_task, manager, 
"cull_idle_connections");
-        /* For the task to properly run and cancel, we need to keep manager 
alive */
-        aws_ref_count_acquire(&manager->internal_ref_count);
-    }
 
-    if (manager->cull_event_loop == NULL) {
-        manager->cull_event_loop = 
aws_event_loop_group_get_next_loop(manager->bootstrap->event_loop_group);
+/*
+ * Calculates the next timestamp the idle connections should be culled. 
Manager lock must be held somewhere in the call
+ * stack. Returns UINT64_MAX if max_connection_idle_in_milliseconds is not set.
+ */
+static uint64_t s_calculate_idle_connection_cull_task_time_synced(struct 
aws_http_connection_manager *manager) {
+    if (manager->max_connection_idle_in_milliseconds == 0) {
+        return UINT64_MAX;
     }
-    AWS_FATAL_ASSERT(manager->cull_event_loop != NULL);
-
     uint64_t cull_task_time = 0;
 
-    aws_mutex_lock(&manager->lock);
     const struct aws_linked_list_node *end = 
aws_linked_list_end(&manager->idle_connections);
     struct aws_linked_list_node *oldest_node = 
aws_linked_list_begin(&manager->idle_connections);
     if (oldest_node != end) {
@@ -799,11 +798,68 @@
             now + aws_timestamp_convert(
                       manager->max_connection_idle_in_milliseconds, 
AWS_TIMESTAMP_MILLIS, AWS_TIMESTAMP_NANOS, NULL);
     }
-    aws_mutex_unlock(&manager->lock);
 
-    aws_event_loop_schedule_task_future(manager->cull_event_loop, 
manager->cull_task, cull_task_time);
+    return cull_task_time;
+}
+
+/*
+ * Calculates the next timestamp the pending acquisitions should be culled. 
Manager lock must be held somewhere in the
+ * call stack. Returns UINT64_MAX if connection_acquisition_timeout_ms is not 
set.
+ */
+static uint64_t s_calculate_pending_acquisition_cull_task_time_synced(struct 
aws_http_connection_manager *manager) {
+    if (manager->connection_acquisition_timeout_ms == 0) {
+        return UINT64_MAX;
+    }
+
+    uint64_t cull_task_time = 0;
+
+    const struct aws_linked_list_node *end = 
aws_linked_list_end(&manager->pending_acquisitions);
+    struct aws_linked_list_node *oldest_node = 
aws_linked_list_begin(&manager->pending_acquisitions);
+    if (oldest_node != end) {
+        /*
+         * front of the list has the closest cull time
+         */
+        struct aws_http_connection_acquisition *oldest_pending_acquire =
+            AWS_CONTAINER_OF(oldest_node, struct 
aws_http_connection_acquisition, node);
+        cull_task_time = oldest_pending_acquire->timeout_timestamp;
+    } else {
+        /*
+         * There are no acquisition in the list, so the absolute minimum 
anything could be culled is the full
+         * culling interval from now.
+         */
+        uint64_t now = 0;
+        manager->system_vtable->aws_high_res_clock_get_ticks(&now);
+        cull_task_time =
+            now + aws_timestamp_convert(
+                      manager->connection_acquisition_timeout_ms, 
AWS_TIMESTAMP_MILLIS, AWS_TIMESTAMP_NANOS, NULL);
+    }
+    return cull_task_time;
+}
+
+static void s_schedule_culling(struct aws_http_connection_manager *manager) {
+    if (manager->max_connection_idle_in_milliseconds == 0 && 
manager->connection_acquisition_timeout_ms == 0) {
+        return;
+    }
+
+    if (manager->cull_task == NULL) {
+        manager->cull_task = aws_mem_calloc(manager->allocator, 1, 
sizeof(struct aws_task));
+        aws_task_init(manager->cull_task, s_cull_task, manager, 
"cull_idle_connections");
+        /* For the task to properly run and cancel, we need to keep manager 
alive */
+        aws_ref_count_acquire(&manager->internal_ref_count);
+    }
+
+    if (manager->cull_event_loop == NULL) {
+        manager->cull_event_loop = 
aws_event_loop_group_get_next_loop(manager->bootstrap->event_loop_group);
+    }
+    AWS_FATAL_ASSERT(manager->cull_event_loop != NULL);
+
+    aws_mutex_lock(&manager->lock);
+    uint64_t idle_cull_time = 
s_calculate_idle_connection_cull_task_time_synced(manager);
+    uint64_t acquisition_cull_time = 
s_calculate_pending_acquisition_cull_task_time_synced(manager);
+    aws_mutex_unlock(&manager->lock);
 
-    return;
+    aws_event_loop_schedule_task_future(
+        manager->cull_event_loop, manager->cull_task, 
aws_min_u64(idle_cull_time, acquisition_cull_time));
 }
 
 struct aws_http_connection_manager *aws_http_connection_manager_new(
@@ -900,6 +956,9 @@
     manager->shutdown_complete_user_data = 
options->shutdown_complete_user_data;
     manager->enable_read_back_pressure = options->enable_read_back_pressure;
     manager->max_connection_idle_in_milliseconds = 
options->max_connection_idle_in_milliseconds;
+    manager->connection_acquisition_timeout_ms = 
options->connection_acquisition_timeout_ms;
+    manager->max_pending_connection_acquisitions = 
options->max_pending_connection_acquisitions;
+
     if (options->proxy_ev_settings) {
         manager->proxy_ev_settings = *options->proxy_ev_settings;
     }
@@ -938,7 +997,7 @@
     }
 
     /* NOTHING can fail after here */
-    s_schedule_connection_culling(manager);
+    s_schedule_culling(manager);
 
     AWS_LOGF_INFO(AWS_LS_HTTP_CONNECTION_MANAGER, "id=%p: Successfully 
created", (void *)manager);
 
@@ -1227,6 +1286,22 @@
     request->user_data = user_data;
     request->manager = manager;
 
+    if (manager->connection_acquisition_timeout_ms) {
+        uint64_t acquire_start_timestamp = 0;
+        if 
(manager->system_vtable->aws_high_res_clock_get_ticks(&acquire_start_timestamp) 
== AWS_OP_SUCCESS) {
+            request->timeout_timestamp =
+                acquire_start_timestamp +
+                aws_timestamp_convert(
+                    manager->connection_acquisition_timeout_ms, 
AWS_TIMESTAMP_MILLIS, AWS_TIMESTAMP_NANOS, NULL);
+        } else {
+            AWS_LOGF_WARN(
+                AWS_LS_HTTP_CONNECTION_MANAGER,
+                "id=%p: Failed to get current timestamp using 
aws_high_res_clock_get_ticks function. Ignoring the "
+                "connection_acquisition_timeout_ms value. ",
+                (void *)manager);
+        }
+    }
+
     struct aws_connection_management_transaction work;
     s_aws_connection_management_transaction_init(&work, manager);
 
@@ -1235,8 +1310,14 @@
     /* It's a use after free crime, we don't want to handle */
     AWS_FATAL_ASSERT(manager->state == AWS_HCMST_READY);
 
-    aws_linked_list_push_back(&manager->pending_acquisitions, &request->node);
-    ++manager->pending_acquisition_count;
+    if (manager->max_pending_connection_acquisitions == 0 ||
+        manager->pending_acquisition_count < 
manager->max_pending_connection_acquisitions) {
+        aws_linked_list_push_back(&manager->pending_acquisitions, 
&request->node);
+        ++manager->pending_acquisition_count;
+    } else {
+        request->error_code = 
AWS_ERROR_HTTP_CONNECTION_MANAGER_MAX_PENDING_ACQUISITIONS_EXCEEDED;
+        aws_linked_list_push_back(&work.completions, &request->node);
+    }
 
     s_aws_http_connection_manager_build_transaction(&work);
 
@@ -1545,10 +1626,11 @@
     s_aws_http_connection_manager_execute_transaction(&work);
 }
 
-static void s_cull_idle_connections(struct aws_http_connection_manager 
*manager) {
-    AWS_LOGF_INFO(AWS_LS_HTTP_CONNECTION_MANAGER, "id=%p: culling idle 
connections", (void *)manager);
+static void s_cull_task_impl(struct aws_http_connection_manager *manager) {
+    AWS_LOGF_INFO(
+        AWS_LS_HTTP_CONNECTION_MANAGER, "id=%p: culling idle connections and 
pending acquisitions", (void *)manager);
 
-    if (manager == NULL || manager->max_connection_idle_in_milliseconds == 0) {
+    if (manager == NULL) {
         return;
     }
 
@@ -1564,26 +1646,53 @@
 
     /* Only if we're not shutting down */
     if (manager->state == AWS_HCMST_READY) {
-        const struct aws_linked_list_node *end = 
aws_linked_list_end(&manager->idle_connections);
-        struct aws_linked_list_node *current_node = 
aws_linked_list_begin(&manager->idle_connections);
-        while (current_node != end) {
-            struct aws_linked_list_node *node = current_node;
-            struct aws_idle_connection *current_idle_connection =
-                AWS_CONTAINER_OF(node, struct aws_idle_connection, node);
-            if (current_idle_connection->cull_timestamp > now) {
-                break;
+        /* cull idle connections */
+        if (manager->max_connection_idle_in_milliseconds != 0) {
+            const struct aws_linked_list_node *idle_connections_end = 
aws_linked_list_end(&manager->idle_connections);
+            struct aws_linked_list_node *idle_connections_current = 
aws_linked_list_begin(&manager->idle_connections);
+            while (idle_connections_current != idle_connections_end) {
+                struct aws_linked_list_node *node = idle_connections_current;
+                struct aws_idle_connection *current_idle_connection =
+                    AWS_CONTAINER_OF(node, struct aws_idle_connection, node);
+                if (current_idle_connection->cull_timestamp > now) {
+                    break;
+                }
+
+                idle_connections_current = 
aws_linked_list_next(idle_connections_current);
+                aws_linked_list_remove(node);
+                aws_linked_list_push_back(&work.connections_to_release, node);
+                --manager->idle_connection_count;
+
+                AWS_LOGF_DEBUG(
+                    AWS_LS_HTTP_CONNECTION_MANAGER,
+                    "id=%p: culling idle connection (%p)",
+                    (void *)manager,
+                    (void *)current_idle_connection->connection);
             }
+        }
 
-            current_node = aws_linked_list_next(current_node);
-            aws_linked_list_remove(node);
-            aws_linked_list_push_back(&work.connections_to_release, node);
-            --manager->idle_connection_count;
-
-            AWS_LOGF_DEBUG(
-                AWS_LS_HTTP_CONNECTION_MANAGER,
-                "id=%p: culling idle connection (%p)",
-                (void *)manager,
-                (void *)current_idle_connection->connection);
+        /* cull pending acquisitions */
+        if (manager->connection_acquisition_timeout_ms != 0) {
+            const struct aws_linked_list_node *pending_acquisitions_end =
+                aws_linked_list_end(&manager->pending_acquisitions);
+            struct aws_linked_list_node *pending_acquisitions_current =
+                aws_linked_list_begin(&manager->pending_acquisitions);
+            while (pending_acquisitions_current != pending_acquisitions_end) {
+                struct aws_linked_list_node *node = 
pending_acquisitions_current;
+                struct aws_http_connection_acquisition 
*current_pending_acquire =
+                    AWS_CONTAINER_OF(node, struct 
aws_http_connection_acquisition, node);
+                if (current_pending_acquire->timeout_timestamp > now) {
+                    break;
+                }
+
+                pending_acquisitions_current = 
aws_linked_list_next(pending_acquisitions_current);
+                s_aws_http_connection_manager_move_front_acquisition(
+                    manager, NULL, 
AWS_ERROR_HTTP_CONNECTION_MANAGER_ACQUISITION_TIMEOUT, &work.completions);
+                AWS_LOGF_DEBUG(
+                    AWS_LS_HTTP_CONNECTION_MANAGER,
+                    "id=%p: Failing pending acquisition due to timeout",
+                    (void *)manager);
+            }
         }
     }
 
@@ -1601,10 +1710,9 @@
     }
 
     struct aws_http_connection_manager *manager = arg;
+    s_cull_task_impl(manager);
 
-    s_cull_idle_connections(manager);
-
-    s_schedule_connection_culling(manager);
+    s_schedule_culling(manager);
 }
 
 void aws_http_connection_manager_fetch_metrics(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-http-0.8.5/source/http.c 
new/aws-c-http-0.8.6/source/http.c
--- old/aws-c-http-0.8.5/source/http.c  2024-07-29 22:12:51.000000000 +0200
+++ new/aws-c-http-0.8.6/source/http.c  2024-08-06 00:51:26.000000000 +0200
@@ -151,6 +151,12 @@
     AWS_DEFINE_ERROR_INFO_HTTP(
         AWS_ERROR_HTTP_RESPONSE_FIRST_BYTE_TIMEOUT,
         "The server does not begin responding within the configuration after a 
request is fully sent."),
+    AWS_DEFINE_ERROR_INFO_HTTP(
+        AWS_ERROR_HTTP_CONNECTION_MANAGER_ACQUISITION_TIMEOUT,
+        "Connection Manager failed to acquire a connection within the defined 
timeout."),
+    AWS_DEFINE_ERROR_INFO_HTTP(
+        AWS_ERROR_HTTP_CONNECTION_MANAGER_MAX_PENDING_ACQUISITIONS_EXCEEDED,
+        "Max pending acquisitions reached"),
 };
 /* clang-format on */
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-http-0.8.5/tests/CMakeLists.txt 
new/aws-c-http-0.8.6/tests/CMakeLists.txt
--- old/aws-c-http-0.8.5/tests/CMakeLists.txt   2024-07-29 22:12:51.000000000 
+0200
+++ new/aws-c-http-0.8.6/tests/CMakeLists.txt   2024-08-06 00:51:26.000000000 
+0200
@@ -519,6 +519,7 @@
 # unit tests where connections are mocked
 add_net_test_case(test_connection_manager_setup_shutdown)
 add_net_test_case(test_connection_manager_acquire_release_mix_synchronous)
+add_net_test_case(test_connection_manager_acquisition_timeout)
 add_net_test_case(test_connection_manager_connect_callback_failure)
 add_net_test_case(test_connection_manager_connect_immediate_failure)
 add_net_test_case(test_connection_manager_proxy_setup_shutdown)
@@ -539,6 +540,7 @@
 add_net_test_case(test_connection_manager_acquire_release)
 add_net_test_case(test_connection_manager_close_and_release)
 add_net_test_case(test_connection_manager_acquire_release_mix)
+add_net_test_case(test_connection_manager_max_pending_acquisitions)
 
 # Integration test that requires proxy envrionment in us-east-1 region.
 # TODO: test the server name validation properly
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-http-0.8.5/tests/test_connection_manager.c 
new/aws-c-http-0.8.6/tests/test_connection_manager.c
--- old/aws-c-http-0.8.5/tests/test_connection_manager.c        2024-07-29 
22:12:51.000000000 +0200
+++ new/aws-c-http-0.8.6/tests/test_connection_manager.c        2024-08-06 
00:51:26.000000000 +0200
@@ -53,6 +53,9 @@
     struct aws_tls_connection_options *env_configured_tls;
     size_t max_connections;
     uint64_t max_connection_idle_in_ms;
+    uint64_t connection_acquisition_timeout_ms;
+    uint64_t max_pending_connection_acquisitions;
+
     uint64_t starting_mock_time;
     bool http2;
     struct aws_http2_setting *initial_settings_array;
@@ -82,6 +85,8 @@
     struct aws_condition_variable signal;
 
     struct aws_array_list connections;
+    /* aws_array_list<uint32> of error codes */
+    struct aws_array_list connection_errors_list;
     size_t connection_errors;
     size_t connection_releases;
 
@@ -154,6 +159,9 @@
     ASSERT_SUCCESS(
         aws_array_list_init_dynamic(&tester->connections, tester->allocator, 
10, sizeof(struct aws_http_connection *)));
 
+    ASSERT_SUCCESS(
+        aws_array_list_init_dynamic(&tester->connection_errors_list, 
tester->allocator, 10, sizeof(uint32_t)));
+
     aws_mutex_init(&tester->mock_time_lock);
     s_tester_set_mock_time(options->starting_mock_time);
 
@@ -220,6 +228,8 @@
         .shutdown_complete_user_data = tester,
         .shutdown_complete_callback = s_cm_tester_on_cm_shutdown_complete,
         .max_connection_idle_in_milliseconds = 
options->max_connection_idle_in_ms,
+        .connection_acquisition_timeout_ms = 
options->connection_acquisition_timeout_ms,
+        .max_pending_connection_acquisitions = 
options->max_pending_connection_acquisitions,
         .http2_prior_knowledge = !options->use_tls && options->http2,
         .initial_settings_array = options->initial_settings_array,
         .num_initial_settings = options->num_initial_settings,
@@ -343,6 +353,7 @@
     AWS_FATAL_ASSERT(aws_mutex_lock(&tester->lock) == AWS_OP_SUCCESS);
 
     if (connection == NULL) {
+        aws_array_list_push_back(&tester->connection_errors_list, &error_code);
         ++tester->connection_errors;
     } else {
         aws_array_list_push_back(&tester->connections, &connection);
@@ -408,6 +419,7 @@
     
ASSERT_SUCCESS(s_release_connections(aws_array_list_length(&tester->connections),
 false));
 
     aws_array_list_clean_up(&tester->connections);
+    aws_array_list_clean_up(&tester->connection_errors_list);
 
     for (size_t i = 0; i < aws_array_list_length(&tester->mock_connections); 
++i) {
         struct mock_connection *mock = NULL;
@@ -733,6 +745,36 @@
 }
 AWS_TEST_CASE(test_connection_manager_acquire_release_mix, 
s_test_connection_manager_acquire_release_mix);
 
+static int s_test_connection_manager_max_pending_acquisitions(struct 
aws_allocator *allocator, void *ctx) {
+    (void)ctx;
+
+    size_t num_connections = 2;
+    size_t num_pending_connections = 3;
+    struct cm_tester_options options = {
+        .allocator = allocator,
+        .max_connections = num_connections,
+        .max_pending_connection_acquisitions = num_connections,
+    };
+
+    ASSERT_SUCCESS(s_cm_tester_init(&options));
+
+    s_acquire_connections(num_connections + num_pending_connections);
+
+    ASSERT_SUCCESS(s_wait_on_connection_reply_count(num_connections + 
num_pending_connections));
+    ASSERT_UINT_EQUALS(num_pending_connections, s_tester.connection_errors);
+    for (size_t i = 0; i < num_pending_connections; i++) {
+        uint32_t error_code;
+        aws_array_list_get_at(&s_tester.connection_errors_list, &error_code, 
i);
+        
ASSERT_UINT_EQUALS(AWS_ERROR_HTTP_CONNECTION_MANAGER_MAX_PENDING_ACQUISITIONS_EXCEEDED,
 error_code);
+    }
+    ASSERT_SUCCESS(s_release_connections(num_connections, false));
+
+    ASSERT_SUCCESS(s_cm_tester_clean_up());
+
+    return AWS_OP_SUCCESS;
+}
+AWS_TEST_CASE(test_connection_manager_max_pending_acquisitions, 
s_test_connection_manager_max_pending_acquisitions);
+
 static int s_aws_http_connection_manager_create_connection_sync_mock(
     const struct aws_http_client_connection_options *options) {
     struct cm_tester *tester = &s_tester;
@@ -890,8 +932,6 @@
         ASSERT_SUCCESS(s_release_connections(1, false));
     }
 
-    ASSERT_SUCCESS(s_wait_on_connection_reply_count(15));
-
     for (size_t i = 15; i < 20; ++i) {
         ASSERT_SUCCESS(s_release_connections(1, false));
 
@@ -908,6 +948,46 @@
     test_connection_manager_acquire_release_mix_synchronous,
     s_test_connection_manager_acquire_release_mix_synchronous);
 
+static int s_test_connection_manager_acquisition_timeout(struct aws_allocator 
*allocator, void *ctx) {
+    (void)ctx;
+
+    size_t num_connections = 2;
+    size_t num_pending_connections = 3;
+    struct cm_tester_options options = {
+        .allocator = allocator,
+        .max_connections = num_connections,
+        .mock_table = &s_synchronous_mocks,
+        .connection_acquisition_timeout_ms = 1000,
+        .starting_mock_time = 0,
+    };
+
+    ASSERT_SUCCESS(s_cm_tester_init(&options));
+
+    s_add_mock_connections(num_connections, AWS_NCRT_SUCCESS, true);
+    s_acquire_connections(num_connections + num_pending_connections);
+
+    /* advance fake time enough to cause the acquire connections to timeout, 
also sleep for real to give the cull task
+     * a chance to run in the real event loop
+     */
+    uint64_t one_sec_in_nanos = aws_timestamp_convert(1, AWS_TIMESTAMP_SECS, 
AWS_TIMESTAMP_NANOS, NULL);
+    s_tester_set_mock_time(2 * one_sec_in_nanos);
+    aws_thread_current_sleep(2 * one_sec_in_nanos);
+
+    ASSERT_SUCCESS(s_wait_on_connection_reply_count(num_connections + 
num_pending_connections));
+    ASSERT_UINT_EQUALS(num_pending_connections, s_tester.connection_errors);
+    for (size_t i = 0; i < num_pending_connections; i++) {
+        uint32_t error_code;
+        aws_array_list_get_at(&s_tester.connection_errors_list, &error_code, 
i);
+        
ASSERT_UINT_EQUALS(AWS_ERROR_HTTP_CONNECTION_MANAGER_ACQUISITION_TIMEOUT, 
error_code);
+    }
+    ASSERT_SUCCESS(s_release_connections(num_connections, false));
+
+    ASSERT_SUCCESS(s_cm_tester_clean_up());
+
+    return AWS_OP_SUCCESS;
+}
+AWS_TEST_CASE(test_connection_manager_acquisition_timeout, 
s_test_connection_manager_acquisition_timeout);
+
 static int s_test_connection_manager_connect_callback_failure(struct 
aws_allocator *allocator, void *ctx) {
     (void)ctx;
 

Reply via email to