]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Test repeated StreamDNS read scheduling 12536/head
authorOndřej Surý <ondrej@sury.org>
Sat, 8 Aug 2026 08:30:51 +0000 (10:30 +0200)
committerOndřej Surý <ondrej@isc.org>
Sat, 8 Aug 2026 09:14:19 +0000 (11:14 +0200)
Exercise duplicate reads directly and stress resolver TCP responses.

Assisted-by: Codex:gpt-5
tests/isc/tcpdns_test.c

index fcd1de8329ece295bcdc3049040e1e6809b7c708..69a75111c0214bcb45c8a6791327831b56c704de 100644 (file)
@@ -30,6 +30,7 @@
 #include <cmocka.h>
 
 #include <isc/async.h>
+#include <isc/job.h>
 #include <isc/lib.h>
 #include <isc/loop.h>
 #include <isc/nonce.h>
@@ -67,6 +68,41 @@ tcpdns_connect(void) {
                                NULL, NULL, NULL, get_proxy_type(), NULL);
 }
 
+static isc_job_t trailing_job = ISC_JOB_INITIALIZER;
+
+static void
+trailing_cb(void *arg) {
+       UNUSED(arg);
+}
+
+static void
+double_read_cb(isc_nmhandle_t *handle, isc_result_t eresult,
+              isc_region_t *region, void *cbarg) {
+       uint64_t magic = 0;
+
+       UNUSED(cbarg);
+
+       assert_int_equal(eresult, ISC_R_SUCCESS);
+       assert_true(region->length >= sizeof(magic));
+       memmove(&magic, region->base, sizeof(magic));
+       assert_int_equal(magic, send_magic);
+       atomic_fetch_add(&creads, 1);
+
+       /*
+        * Both calls take the asynchronous path because this callback is still
+        * processing the previous message.  They must share one pending job.
+        */
+       isc_nm_read(handle, double_read_cb, NULL);
+       isc_nm_read(handle, double_read_cb, NULL);
+       isc_job_run(isc_loop(), &trailing_job, trailing_cb, NULL);
+       assert_ptr_not_equal(handle->sock->job.link.prev, &handle->sock->job);
+
+       isc_loopmgr_shutdown();
+       isc_nmhandle_close(handle);
+       isc_refcount_decrement(&active_creads);
+       isc_nmhandle_detach(&handle);
+}
+
 ISC_LOOP_TEST_IMPL(tcpdns_noop) {
        start_listening(ISC_NM_LISTEN_ONE, noop_accept_cb, noop_recv_cb);
 
@@ -110,6 +146,14 @@ ISC_LOOP_TEST_IMPL(tcpdns_recv_one) {
        isc_async_current(stream_recv_send_connect, tcpdns_connect);
 }
 
+ISC_LOOP_TEST_IMPL(tcpdns_double_read) {
+       start_listening(ISC_NM_LISTEN_ONE, listen_accept_cb, listen_read_cb);
+
+       atomic_store(&nsends, 1);
+       connect_readcb = double_read_cb;
+       isc_async_current(stream_recv_send_connect, tcpdns_connect);
+}
+
 ISC_LOOP_TEST_IMPL(tcpdns_recv_two) {
        start_listening(ISC_NM_LISTEN_ONE, listen_accept_cb, listen_read_cb);
 
@@ -154,6 +198,8 @@ ISC_TEST_ENTRY_CUSTOM(tcpdns_timeout_recovery, stream_timeout_recovery_setup,
                      stream_timeout_recovery_teardown)
 ISC_TEST_ENTRY_CUSTOM(tcpdns_recv_one, stream_recv_one_setup,
                      stream_recv_one_teardown)
+ISC_TEST_ENTRY_CUSTOM(tcpdns_double_read, stream_recv_one_setup,
+                     stream_recv_one_teardown)
 ISC_TEST_ENTRY_CUSTOM(tcpdns_recv_two, stream_recv_two_setup,
                      stream_recv_two_teardown)
 ISC_TEST_ENTRY_CUSTOM(tcpdns_recv_send, stream_recv_send_setup,