]> git.ipfire.org Git - thirdparty/openssl.git/blobdiff - test/quic_tserver_test.c
Enhance quic_tserver test to fully test thread assisted mode
[thirdparty/openssl.git] / test / quic_tserver_test.c
index a9c08e9e0c5172d9c755cd1425e489d6c37e0443..eeb23b4b908180d3fc2fce287cb864ec0f01a3c0 100644 (file)
 #include "internal/common.h"
 #include "internal/sockets.h"
 #include "internal/quic_tserver.h"
+#include "internal/quic_ssl.h"
 #include "internal/time.h"
 #include "testutil.h"
 
 static const char msg1[] = "The quick brown fox jumped over the lazy dogs.";
 static char msg2[1024], msg3[1024];
+static OSSL_TIME fake_time;
 
 static const char *certfile, *keyfile;
 
@@ -29,7 +31,17 @@ static int is_want(SSL *s, int ret)
 
 static unsigned char scratch_buf[2048];
 
-static int test_tserver_actual(int use_thread_assist, int use_inject)
+static OSSL_TIME fake_now(void *arg)
+{
+    return fake_time;
+}
+
+static OSSL_TIME real_now(void *arg)
+{
+    return ossl_time_now();
+}
+
+static int do_test(int use_thread_assist, int use_fake_time, int use_inject)
 {
     int testresult = 0, ret;
     int s_fd = -1, c_fd = -1;
@@ -45,11 +57,15 @@ static int test_tserver_actual(int use_thread_assist, int use_inject)
     SSL *c_ssl = NULL;
     short port = 8186;
     int c_connected = 0, c_write_done = 0, c_begin_read = 0, s_read_done = 0;
-    int c_wait_eos = 0;
+    int c_wait_eos = 0, c_done_eos = 0;
+    int c_start_idle_test = 0, c_done_idle_test = 0;
     size_t l = 0, s_total_read = 0, s_total_written = 0, c_total_read = 0;
+    size_t idle_units_done = 0;
     int s_begin_write = 0;
     OSSL_TIME start_time;
     unsigned char alpn[] = { 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' };
+    OSSL_TIME (*now_cb)(void *arg) = use_fake_time ? fake_now : real_now;
+    size_t limit_ms = 1000;
 
     ina.s_addr = htonl(0x7f000001UL);
 
@@ -84,8 +100,12 @@ static int test_tserver_actual(int use_thread_assist, int use_inject)
     if (!BIO_up_ref(s_net_bio))
         goto err;
 
+    fake_time = ossl_ms2time(1000);
+
     tserver_args.net_rbio = s_net_bio;
     tserver_args.net_wbio = s_net_bio;
+    if (use_fake_time)
+        tserver_args.now_cb = fake_now;
 
     if (!TEST_ptr(tserver = ossl_quic_tserver_new(&tserver_args, certfile,
                                                   keyfile))) {
@@ -129,6 +149,9 @@ static int test_tserver_actual(int use_thread_assist, int use_inject)
     if (!TEST_ptr(c_ssl = SSL_new(c_ctx)))
         goto err;
 
+    if (use_fake_time)
+        ossl_quic_conn_set_override_now_cb(c_ssl, fake_now, NULL);
+
     /* 0 is a success for SSL_set_alpn_protos() */
     if (!TEST_false(SSL_set_alpn_protos(c_ssl, alpn, sizeof(alpn))))
         goto err;
@@ -153,21 +176,23 @@ static int test_tserver_actual(int use_thread_assist, int use_inject)
     if (!TEST_true(SSL_set_blocking_mode(c_ssl, 0)))
         goto err;
 
-    start_time = ossl_time_now();
+    start_time = now_cb(NULL);
 
     for (;;) {
-        if (ossl_time_compare(ossl_time_subtract(ossl_time_now(), start_time),
-                              ossl_ms2time(1000)) >= 0) {
+        if (ossl_time_compare(ossl_time_subtract(now_cb(NULL), start_time),
+                              ossl_ms2time(limit_ms)) >= 0) {
             TEST_error("timeout while attempting QUIC server test");
             goto err;
         }
 
-        ret = SSL_connect(c_ssl);
-        if (!TEST_true(ret == 1 || is_want(c_ssl, ret)))
-            goto err;
+        if (!c_start_idle_test) {
+            ret = SSL_connect(c_ssl);
+            if (!TEST_true(ret == 1 || is_want(c_ssl, ret)))
+                goto err;
 
-        if (ret == 1)
-            c_connected = 1;
+            if (ret == 1)
+                c_connected = 1;
+        }
 
         if (c_connected && !c_write_done) {
             if (!TEST_int_eq(SSL_write(c_ssl, msg1, sizeof(msg1) - 1),
@@ -229,7 +254,7 @@ static int test_tserver_actual(int use_thread_assist, int use_inject)
             }
         }
 
-        if (c_wait_eos) {
+        if (c_wait_eos && !c_done_eos) {
             unsigned char c;
 
             ret = SSL_read_ex(c_ssl, &c, sizeof(c), &l);
@@ -245,16 +270,50 @@ static int test_tserver_actual(int use_thread_assist, int use_inject)
                                  SSL_ERROR_ZERO_RETURN))
                     goto err;
 
-                /* DONE */
-                break;
+                c_done_eos = 1;
+                if (use_thread_assist && use_fake_time) {
+                    if (!TEST_true(ossl_quic_tserver_is_connected(tserver)))
+                        goto err;
+                    c_start_idle_test = 1;
+                    limit_ms = 120000; /* extend time limit */
+                } else {
+                    /* DONE */
+                    break;
+                }
+            }
+        }
+
+        if (c_start_idle_test && !c_done_idle_test) {
+            /* This is more than our default idle timeout of 30s. */
+            if (idle_units_done < 600) {
+                fake_time = ossl_time_add(fake_time, ossl_ms2time(100));
+                ++idle_units_done;
+                ossl_quic_conn_force_assist_thread_wake(c_ssl);
+            } else {
+                c_done_idle_test = 1;
             }
         }
 
+        if (c_done_idle_test) {
+            /*
+             * If we have finished the fake idling duration, the connection
+             * should still be healthy in TA mode.
+             */
+            if (!TEST_true(ossl_quic_tserver_is_connected(tserver)))
+                goto err;
+
+            /* DONE */
+            break;
+        }
+
         /*
          * This is inefficient because we spin until things work without
          * blocking but this is just a test.
          */
-        SSL_tick(c_ssl);
+        if (!c_start_idle_test || c_done_idle_test)
+            /* Inhibit manual ticking during idle test to test TA mode. */
+            SSL_tick(c_ssl);
+
         ossl_quic_tserver_tick(tserver);
 
         if (use_inject) {
@@ -310,6 +369,21 @@ static int test_tserver(int idx)
     return test_tserver_actual(use_thread_assist, use_inject);
 }
 
+static int test_tserver_simple(void)
+{
+    return do_test(/*thread_assisted=*/0, /*fake_time=*/0, /*use_inject=*/0);
+}
+
+static int test_tserver_thread(void)
+{
+    return do_test(/*thread_assisted=*/1, /*fake_time=*/0, /*use_inject=*/0);
+}
+
+static int test_tserver_thread_fake_time(void)
+{
+    return do_test(/*thread_assisted=*/1, /*fake_time=*/1, /*use_inject=*/0);
+}
+
 OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n")
 
 int setup_tests(void)
@@ -323,6 +397,8 @@ int setup_tests(void)
             || !TEST_ptr(keyfile = test_get_argument(1)))
         return 0;
 
-    ADD_ALL_TESTS(test_tserver, 4);
+    ADD_TEST(test_tserver_simple);
+    ADD_TEST(test_tserver_thread);
+    ADD_TEST(test_tserver_thread_fake_time);
     return 1;
 }