Home | History | Annotate | Line # | Download | only in test
      1 /*
      2  * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 #include "internal/quic_fc.h"
     11 #include "internal/quic_error.h"
     12 #include "testutil.h"
     13 
     14 static int test_txfc(int is_stream)
     15 {
     16     int testresult = 0;
     17     QUIC_TXFC conn_txfc, stream_txfc, *txfc, *parent_txfc;
     18 
     19     if (!TEST_true(ossl_quic_txfc_init(&conn_txfc, 0)))
     20         goto err;
     21 
     22     if (is_stream && !TEST_true(ossl_quic_txfc_init(&stream_txfc, &conn_txfc)))
     23         goto err;
     24 
     25     txfc = is_stream ? &stream_txfc : &conn_txfc;
     26     parent_txfc = is_stream ? &conn_txfc : NULL;
     27 
     28     if (!TEST_true(ossl_quic_txfc_bump_cwm(txfc, 2000)))
     29         goto err;
     30 
     31     if (is_stream && !TEST_true(ossl_quic_txfc_bump_cwm(parent_txfc, 2000)))
     32         goto err;
     33 
     34     if (!TEST_uint64_t_eq(ossl_quic_txfc_get_swm(txfc), 0))
     35         goto err;
     36 
     37     if (!TEST_uint64_t_eq(ossl_quic_txfc_get_cwm(txfc), 2000))
     38         goto err;
     39 
     40     if (!TEST_uint64_t_eq(ossl_quic_txfc_get_credit_local(txfc, 0), 2000))
     41         goto err;
     42 
     43     if (!TEST_uint64_t_eq(ossl_quic_txfc_get_credit_local(txfc, 100), 1900))
     44         goto err;
     45 
     46     if (is_stream) {
     47         if (!TEST_uint64_t_eq(ossl_quic_txfc_get_credit(txfc, 0), 2000))
     48             goto err;
     49 
     50         if (!TEST_uint64_t_eq(ossl_quic_txfc_get_credit(txfc, 100), 1900))
     51             goto err;
     52     }
     53 
     54     if (!TEST_false(ossl_quic_txfc_has_become_blocked(txfc, 0)))
     55         goto err;
     56 
     57     if (!TEST_true(ossl_quic_txfc_consume_credit(txfc, 500)))
     58         goto err;
     59 
     60     if (!TEST_uint64_t_eq(ossl_quic_txfc_get_credit_local(txfc, 0), 1500))
     61         goto err;
     62 
     63     if (is_stream && !TEST_uint64_t_eq(ossl_quic_txfc_get_credit(txfc, 0), 1500))
     64         goto err;
     65 
     66     if (!TEST_false(ossl_quic_txfc_has_become_blocked(txfc, 0)))
     67         goto err;
     68 
     69     if (!TEST_uint64_t_eq(ossl_quic_txfc_get_swm(txfc), 500))
     70         goto err;
     71 
     72     if (!TEST_true(ossl_quic_txfc_consume_credit(txfc, 100)))
     73         goto err;
     74 
     75     if (!TEST_uint64_t_eq(ossl_quic_txfc_get_swm(txfc), 600))
     76         goto err;
     77 
     78     if (!TEST_uint64_t_eq(ossl_quic_txfc_get_credit_local(txfc, 0), 1400))
     79         goto err;
     80 
     81     if (is_stream && !TEST_uint64_t_eq(ossl_quic_txfc_get_credit(txfc, 0), 1400))
     82         goto err;
     83 
     84     if (!TEST_false(ossl_quic_txfc_has_become_blocked(txfc, 0)))
     85         goto err;
     86 
     87     if (!TEST_true(ossl_quic_txfc_consume_credit(txfc, 1400)))
     88         goto err;
     89 
     90     if (!TEST_uint64_t_eq(ossl_quic_txfc_get_credit_local(txfc, 0), 0))
     91         goto err;
     92 
     93     if (is_stream && !TEST_uint64_t_eq(ossl_quic_txfc_get_credit(txfc, 0), 0))
     94         goto err;
     95 
     96     if (!TEST_uint64_t_eq(ossl_quic_txfc_get_swm(txfc), 2000))
     97         goto err;
     98 
     99     if (!TEST_true(ossl_quic_txfc_has_become_blocked(txfc, 0)))
    100         goto err;
    101 
    102     if (!TEST_true(ossl_quic_txfc_has_become_blocked(txfc, 0)))
    103         goto err;
    104 
    105     if (!TEST_true(ossl_quic_txfc_has_become_blocked(txfc, 1)))
    106         goto err;
    107 
    108     if (!TEST_false(ossl_quic_txfc_has_become_blocked(txfc, 0)))
    109         goto err;
    110 
    111     if (!TEST_false(ossl_quic_txfc_has_become_blocked(txfc, 0)))
    112         goto err;
    113 
    114     if (!TEST_false(ossl_quic_txfc_consume_credit(txfc, 1)))
    115         goto err;
    116 
    117     if (!TEST_uint64_t_eq(ossl_quic_txfc_get_cwm(txfc), 2000))
    118         goto err;
    119 
    120     if (!TEST_uint64_t_eq(ossl_quic_txfc_get_swm(txfc), 2000))
    121         goto err;
    122 
    123     if (!TEST_false(ossl_quic_txfc_bump_cwm(txfc, 2000)))
    124         goto err;
    125 
    126     if (!TEST_true(ossl_quic_txfc_bump_cwm(txfc, 2500)))
    127         goto err;
    128 
    129     if (is_stream && !TEST_true(ossl_quic_txfc_bump_cwm(parent_txfc, 2400)))
    130         goto err;
    131 
    132     if (!TEST_uint64_t_eq(ossl_quic_txfc_get_cwm(txfc), 2500))
    133         goto err;
    134 
    135     if (!TEST_uint64_t_eq(ossl_quic_txfc_get_swm(txfc), 2000))
    136         goto err;
    137 
    138     if (!TEST_uint64_t_eq(ossl_quic_txfc_get_credit_local(txfc, 0), 500))
    139         goto err;
    140 
    141     if (is_stream)
    142         ossl_quic_txfc_has_become_blocked(parent_txfc, 1);
    143 
    144     if (is_stream) {
    145         if (!TEST_uint64_t_eq(ossl_quic_txfc_get_credit(txfc, 400), 0))
    146             goto err;
    147 
    148         if (!TEST_true(ossl_quic_txfc_consume_credit(txfc, 399)))
    149             goto err;
    150 
    151         if (!TEST_false(ossl_quic_txfc_has_become_blocked(txfc, 0)))
    152             goto err;
    153 
    154         if (!TEST_uint64_t_eq(ossl_quic_txfc_get_credit(txfc, 0), 1))
    155             goto err;
    156 
    157         if (!TEST_true(ossl_quic_txfc_consume_credit(txfc, 1)))
    158             goto err;
    159 
    160         if (!TEST_true(ossl_quic_txfc_has_become_blocked(parent_txfc, 0)))
    161             goto err;
    162 
    163         if (!TEST_true(ossl_quic_txfc_has_become_blocked(parent_txfc, 1)))
    164             goto err;
    165 
    166         if (!TEST_false(ossl_quic_txfc_has_become_blocked(parent_txfc, 0)))
    167             goto err;
    168     } else {
    169         if (!TEST_true(ossl_quic_txfc_consume_credit(txfc, 499)))
    170             goto err;
    171 
    172         if (!TEST_false(ossl_quic_txfc_has_become_blocked(txfc, 0)))
    173             goto err;
    174 
    175         if (is_stream && !TEST_false(ossl_quic_txfc_has_become_blocked(parent_txfc, 0)))
    176             goto err;
    177 
    178         if (!TEST_true(ossl_quic_txfc_consume_credit(txfc, 1)))
    179             goto err;
    180 
    181         if (!TEST_true(ossl_quic_txfc_has_become_blocked(txfc, 0)))
    182             goto err;
    183 
    184         if (!TEST_true(ossl_quic_txfc_has_become_blocked(txfc, 1)))
    185             goto err;
    186 
    187         if (!TEST_false(ossl_quic_txfc_has_become_blocked(txfc, 0)))
    188             goto err;
    189     }
    190 
    191     testresult = 1;
    192 err:
    193     return testresult;
    194 }
    195 
    196 static OSSL_TIME cur_time;
    197 
    198 static OSSL_TIME fake_now(void *arg)
    199 {
    200     return cur_time;
    201 }
    202 
    203 #define RX_OPC_END 0
    204 #define RX_OPC_INIT_CONN 1 /* arg0=initial window, arg1=max window */
    205 #define RX_OPC_INIT_STREAM 2 /* arg0=initial window, arg1=max window */
    206 #define RX_OPC_RX 3 /* arg0=end, arg1=is_fin */
    207 #define RX_OPC_RETIRE 4 /* arg0=num_bytes, arg1=rtt in OSSL_TIME ticks, expect_fail */
    208 #define RX_OPC_CHECK_CWM_CONN 5 /* arg0=expected */
    209 #define RX_OPC_CHECK_CWM_STREAM 6 /* arg0=expected */
    210 #define RX_OPC_CHECK_SWM_CONN 7 /* arg0=expected */
    211 #define RX_OPC_CHECK_SWM_STREAM 8 /* arg0=expected */
    212 #define RX_OPC_CHECK_RWM_CONN 9 /* arg0=expected */
    213 #define RX_OPC_CHECK_RWM_STREAM 10 /* arg0=expected */
    214 #define RX_OPC_CHECK_CHANGED_CONN 11 /* arg0=expected, arg1=clear */
    215 #define RX_OPC_CHECK_CHANGED_STREAM 12 /* arg0=expected, arg1=clear */
    216 #define RX_OPC_CHECK_ERROR_CONN 13 /* arg0=expected, arg1=clear */
    217 #define RX_OPC_CHECK_ERROR_STREAM 14 /* arg0=expected, arg1=clear */
    218 #define RX_OPC_STEP_TIME 15 /* arg0=OSSL_TIME ticks to advance */
    219 #define RX_OPC_MSG 16
    220 
    221 struct rx_test_op {
    222     unsigned char op;
    223     size_t stream_idx;
    224     uint64_t arg0, arg1;
    225     unsigned char expect_fail;
    226     const char *msg;
    227 };
    228 
    229 #define RX_OP_END \
    230     { RX_OPC_END }
    231 #define RX_OP_INIT_CONN(init_window_size, max_window_size) \
    232     { RX_OPC_INIT_CONN, 0, (init_window_size), (max_window_size) },
    233 #define RX_OP_INIT_STREAM(stream_idx, init_window_size, max_window_size) \
    234     { RX_OPC_INIT_STREAM, (stream_idx), (init_window_size), (max_window_size) },
    235 #define RX_OP_RX(stream_idx, end, is_fin) \
    236     { RX_OPC_RX, (stream_idx), (end), (is_fin) },
    237 #define RX_OP_RETIRE(stream_idx, num_bytes, rtt, expect_fail) \
    238     { RX_OPC_RETIRE, (stream_idx), (num_bytes), (rtt), (expect_fail) },
    239 #define RX_OP_CHECK_CWM_CONN(expected) \
    240     { RX_OPC_CHECK_CWM_CONN, 0, (expected) },
    241 #define RX_OP_CHECK_CWM_STREAM(stream_id, expected) \
    242     { RX_OPC_CHECK_CWM_STREAM, (stream_id), (expected) },
    243 #define RX_OP_CHECK_SWM_CONN(expected) \
    244     { RX_OPC_CHECK_SWM_CONN, 0, (expected) },
    245 #define RX_OP_CHECK_SWM_STREAM(stream_id, expected) \
    246     { RX_OPC_CHECK_SWM_STREAM, (stream_id), (expected) },
    247 #define RX_OP_CHECK_RWM_CONN(expected) \
    248     { RX_OPC_CHECK_RWM_CONN, 0, (expected) },
    249 #define RX_OP_CHECK_RWM_STREAM(stream_id, expected) \
    250     { RX_OPC_CHECK_RWM_STREAM, (stream_id), (expected) },
    251 #define RX_OP_CHECK_CHANGED_CONN(expected, clear) \
    252     { RX_OPC_CHECK_CHANGED_CONN, 0, (expected), (clear) },
    253 #define RX_OP_CHECK_CHANGED_STREAM(stream_id, expected, clear) \
    254     { RX_OPC_CHECK_CHANGED_STREAM, (stream_id), (expected), (clear) },
    255 #define RX_OP_CHECK_ERROR_CONN(expected, clear) \
    256     { RX_OPC_CHECK_ERROR_CONN, 0, (expected), (clear) },
    257 #define RX_OP_CHECK_ERROR_STREAM(stream_id, expected, clear) \
    258     { RX_OPC_CHECK_ERROR_STREAM, (stream_id), (expected), (clear) },
    259 #define RX_OP_STEP_TIME(t) \
    260     { RX_OPC_STEP_TIME, 0, (t) },
    261 #define RX_OP_MSG(msg) \
    262     { RX_OPC_MSG, 0, 0, 0, 0, (msg) },
    263 
    264 #define RX_OP_INIT(init_window_size, max_window_size)  \
    265     RX_OP_INIT_CONN(init_window_size, max_window_size) \
    266     RX_OP_INIT_STREAM(0, init_window_size, max_window_size)
    267 #define RX_OP_CHECK_CWM(expected)  \
    268     RX_OP_CHECK_CWM_CONN(expected) \
    269     RX_OP_CHECK_CWM_STREAM(0, expected)
    270 #define RX_OP_CHECK_SWM(expected)  \
    271     RX_OP_CHECK_SWM_CONN(expected) \
    272     RX_OP_CHECK_SWM_STREAM(0, expected)
    273 #define RX_OP_CHECK_RWM(expected)  \
    274     RX_OP_CHECK_RWM_CONN(expected) \
    275     RX_OP_CHECK_RWM_STREAM(0, expected)
    276 #define RX_OP_CHECK_CHANGED(expected, clear)  \
    277     RX_OP_CHECK_CHANGED_CONN(expected, clear) \
    278     RX_OP_CHECK_CHANGED_STREAM(0, expected, clear)
    279 #define RX_OP_CHECK_ERROR(expected, clear)  \
    280     RX_OP_CHECK_ERROR_CONN(expected, clear) \
    281     RX_OP_CHECK_ERROR_STREAM(0, expected, clear)
    282 
    283 #define INIT_WINDOW_SIZE (1 * 1024 * 1024)
    284 #define INIT_S_WINDOW_SIZE (384 * 1024)
    285 
    286 /* 1. Basic RXFC Tests (stream window == connection window) */
    287 static const struct rx_test_op rx_script_1[] = {
    288     RX_OP_STEP_TIME(1000 * OSSL_TIME_MS)
    289         RX_OP_INIT(INIT_WINDOW_SIZE, 10 * INIT_WINDOW_SIZE)
    290     /* Check initial state. */
    291     RX_OP_CHECK_CWM(INIT_WINDOW_SIZE)
    292         RX_OP_CHECK_ERROR(0, 0)
    293             RX_OP_CHECK_CHANGED(0, 0)
    294     /* We cannot retire what we have not received. */
    295     RX_OP_RETIRE(0, 1, 0, 1)
    296     /* Zero bytes is a no-op and always valid. */
    297     RX_OP_RETIRE(0, 0, 0, 0)
    298     /* Consume some window. */
    299     RX_OP_RX(0, 50, 0)
    300     /* CWM has not changed. */
    301     RX_OP_CHECK_CWM(INIT_WINDOW_SIZE)
    302         RX_OP_CHECK_SWM(50)
    303 
    304     /* RX, Partial retire */
    305     RX_OP_RX(0, 60, 0)
    306         RX_OP_CHECK_SWM(60)
    307             RX_OP_RETIRE(0, 20, 50 * OSSL_TIME_MS, 0)
    308                 RX_OP_CHECK_RWM(20)
    309                     RX_OP_CHECK_SWM(60)
    310                         RX_OP_CHECK_CWM(INIT_WINDOW_SIZE)
    311                             RX_OP_CHECK_CHANGED(0, 0)
    312                                 RX_OP_CHECK_ERROR(0, 0)
    313 
    314     /* Fully retired */
    315     RX_OP_RETIRE(0, 41, 0, 1)
    316         RX_OP_RETIRE(0, 40, 0, 0)
    317             RX_OP_CHECK_SWM(60)
    318                 RX_OP_CHECK_RWM(60)
    319                     RX_OP_CHECK_CWM(INIT_WINDOW_SIZE)
    320                         RX_OP_CHECK_CHANGED(0, 0)
    321                             RX_OP_CHECK_ERROR(0, 0)
    322 
    323     /* Exhaustion of window - we do not enlarge the window this epoch */
    324     RX_OP_STEP_TIME(201 * OSSL_TIME_MS)
    325         RX_OP_RX(0, INIT_WINDOW_SIZE, 0)
    326             RX_OP_RETIRE(0, INIT_WINDOW_SIZE - 60, 50 * OSSL_TIME_MS, 0)
    327                 RX_OP_CHECK_SWM(INIT_WINDOW_SIZE)
    328                     RX_OP_CHECK_CHANGED(1, 0)
    329                         RX_OP_CHECK_CHANGED(1, 1)
    330                             RX_OP_CHECK_CHANGED(0, 0)
    331                                 RX_OP_CHECK_ERROR(0, 0)
    332                                     RX_OP_CHECK_CWM(INIT_WINDOW_SIZE * 2)
    333 
    334     /* Second epoch - we still do not enlarge the window this epoch */
    335     RX_OP_RX(0, INIT_WINDOW_SIZE + 1, 0)
    336         RX_OP_STEP_TIME(201 * OSSL_TIME_MS)
    337             RX_OP_RX(0, INIT_WINDOW_SIZE * 2, 0)
    338                 RX_OP_RETIRE(0, INIT_WINDOW_SIZE, 50 * OSSL_TIME_MS, 0)
    339                     RX_OP_CHECK_SWM(INIT_WINDOW_SIZE * 2)
    340                         RX_OP_CHECK_CHANGED(1, 0)
    341                             RX_OP_CHECK_CHANGED(1, 1)
    342                                 RX_OP_CHECK_CHANGED(0, 0)
    343                                     RX_OP_CHECK_ERROR(0, 0)
    344                                         RX_OP_CHECK_CWM(INIT_WINDOW_SIZE * 3)
    345 
    346     /* Third epoch - we enlarge the window */
    347     RX_OP_RX(0, INIT_WINDOW_SIZE * 2 + 1, 0)
    348         RX_OP_STEP_TIME(199 * OSSL_TIME_MS)
    349             RX_OP_RX(0, INIT_WINDOW_SIZE * 3, 0)
    350                 RX_OP_RETIRE(0, INIT_WINDOW_SIZE, 50 * OSSL_TIME_MS, 0)
    351                     RX_OP_CHECK_SWM(INIT_WINDOW_SIZE * 3)
    352                         RX_OP_CHECK_CHANGED(1, 0)
    353                             RX_OP_CHECK_CHANGED(1, 1)
    354                                 RX_OP_CHECK_CHANGED(0, 0)
    355                                     RX_OP_CHECK_ERROR(0, 0)
    356                                         RX_OP_CHECK_CWM(INIT_WINDOW_SIZE * 5)
    357 
    358     /* Fourth epoch - peer violates flow control */
    359     RX_OP_RX(0, INIT_WINDOW_SIZE * 5 - 5, 0)
    360         RX_OP_STEP_TIME(250 * OSSL_TIME_MS)
    361             RX_OP_RX(0, INIT_WINDOW_SIZE * 5 + 1, 0)
    362                 RX_OP_CHECK_SWM(INIT_WINDOW_SIZE * 5)
    363                     RX_OP_CHECK_ERROR(OSSL_QUIC_ERR_FLOW_CONTROL_ERROR, 0)
    364                         RX_OP_CHECK_ERROR(OSSL_QUIC_ERR_FLOW_CONTROL_ERROR, 1)
    365                             RX_OP_CHECK_ERROR(0, 0)
    366                                 RX_OP_CHECK_CWM(INIT_WINDOW_SIZE * 5)
    367     /*
    368      * No window expansion due to flow control violation; window expansion is
    369      * triggered by retirement only.
    370      */
    371     RX_OP_CHECK_CHANGED(0, 0)
    372 
    373         RX_OP_END
    374 };
    375 
    376 /* 2. Interaction between connection and stream-level flow control */
    377 static const struct rx_test_op rx_script_2[] = {
    378     RX_OP_STEP_TIME(1000 * OSSL_TIME_MS)
    379         RX_OP_INIT_CONN(INIT_WINDOW_SIZE, 10 * INIT_WINDOW_SIZE)
    380             RX_OP_INIT_STREAM(0, INIT_S_WINDOW_SIZE, 30 * INIT_S_WINDOW_SIZE)
    381                 RX_OP_INIT_STREAM(1, INIT_S_WINDOW_SIZE, 30 * INIT_S_WINDOW_SIZE)
    382 
    383                     RX_OP_RX(0, 10, 0)
    384                         RX_OP_CHECK_CWM_CONN(INIT_WINDOW_SIZE)
    385                             RX_OP_CHECK_CWM_STREAM(0, INIT_S_WINDOW_SIZE)
    386                                 RX_OP_CHECK_CWM_STREAM(1, INIT_S_WINDOW_SIZE)
    387                                     RX_OP_CHECK_SWM_CONN(10)
    388                                         RX_OP_CHECK_SWM_STREAM(0, 10)
    389                                             RX_OP_CHECK_SWM_STREAM(1, 0)
    390                                                 RX_OP_CHECK_RWM_CONN(0)
    391                                                     RX_OP_CHECK_RWM_STREAM(0, 0)
    392                                                         RX_OP_CHECK_RWM_STREAM(1, 0)
    393 
    394                                                             RX_OP_RX(1, 42, 0)
    395                                                                 RX_OP_RX(1, 42, 0) /* monotonic; equal or lower values ignored */
    396     RX_OP_RX(1, 35, 0)
    397         RX_OP_CHECK_CWM_CONN(INIT_WINDOW_SIZE)
    398             RX_OP_CHECK_CWM_STREAM(0, INIT_S_WINDOW_SIZE)
    399                 RX_OP_CHECK_CWM_STREAM(1, INIT_S_WINDOW_SIZE)
    400                     RX_OP_CHECK_SWM_CONN(52)
    401                         RX_OP_CHECK_SWM_STREAM(0, 10)
    402                             RX_OP_CHECK_SWM_STREAM(1, 42)
    403                                 RX_OP_CHECK_RWM_CONN(0)
    404                                     RX_OP_CHECK_RWM_STREAM(0, 0)
    405                                         RX_OP_CHECK_RWM_STREAM(1, 0)
    406 
    407                                             RX_OP_RETIRE(0, 10, 50 * OSSL_TIME_MS, 0)
    408                                                 RX_OP_CHECK_RWM_CONN(10)
    409                                                     RX_OP_CHECK_RWM_STREAM(0, 10)
    410                                                         RX_OP_CHECK_CWM_CONN(INIT_WINDOW_SIZE)
    411                                                             RX_OP_CHECK_CWM_STREAM(0, INIT_S_WINDOW_SIZE)
    412                                                                 RX_OP_CHECK_CWM_STREAM(1, INIT_S_WINDOW_SIZE)
    413 
    414                                                                     RX_OP_RETIRE(1, 42, 50 * OSSL_TIME_MS, 0)
    415                                                                         RX_OP_CHECK_RWM_CONN(52)
    416                                                                             RX_OP_CHECK_RWM_STREAM(1, 42)
    417                                                                                 RX_OP_CHECK_CWM_CONN(INIT_WINDOW_SIZE)
    418                                                                                     RX_OP_CHECK_CWM_STREAM(0, INIT_S_WINDOW_SIZE)
    419                                                                                         RX_OP_CHECK_CWM_STREAM(1, INIT_S_WINDOW_SIZE)
    420 
    421                                                                                             RX_OP_CHECK_CHANGED_CONN(0, 0)
    422 
    423     /* FC limited by stream but not connection */
    424     RX_OP_STEP_TIME(1000 * OSSL_TIME_MS)
    425         RX_OP_RX(0, INIT_S_WINDOW_SIZE, 0)
    426             RX_OP_CHECK_SWM_CONN(INIT_S_WINDOW_SIZE + 42)
    427                 RX_OP_CHECK_SWM_STREAM(0, INIT_S_WINDOW_SIZE)
    428                     RX_OP_CHECK_SWM_STREAM(1, 42)
    429                         RX_OP_CHECK_CWM_CONN(INIT_WINDOW_SIZE)
    430                             RX_OP_CHECK_CWM_STREAM(0, INIT_S_WINDOW_SIZE)
    431 
    432     /* We bump CWM when more than 1/4 of the window has been retired */
    433     RX_OP_RETIRE(0, INIT_S_WINDOW_SIZE - 10, 50 * OSSL_TIME_MS, 0)
    434         RX_OP_CHECK_CWM_STREAM(0, INIT_S_WINDOW_SIZE * 2)
    435             RX_OP_CHECK_CHANGED_STREAM(0, 1, 0)
    436                 RX_OP_CHECK_CHANGED_STREAM(0, 1, 1)
    437                     RX_OP_CHECK_CHANGED_STREAM(0, 0, 0)
    438 
    439     /*
    440      * This is more than 1/4 of the connection window, so CWM will
    441      * be bumped here too.
    442      */
    443     RX_OP_CHECK_CWM_CONN(INIT_S_WINDOW_SIZE + INIT_WINDOW_SIZE + 42)
    444         RX_OP_CHECK_RWM_CONN(INIT_S_WINDOW_SIZE + 42)
    445             RX_OP_CHECK_RWM_STREAM(0, INIT_S_WINDOW_SIZE)
    446                 RX_OP_CHECK_RWM_STREAM(1, 42)
    447                     RX_OP_CHECK_CHANGED_CONN(1, 0)
    448                         RX_OP_CHECK_CHANGED_CONN(1, 1)
    449                             RX_OP_CHECK_CHANGED_CONN(0, 0)
    450                                 RX_OP_CHECK_ERROR_CONN(0, 0)
    451                                     RX_OP_CHECK_ERROR_STREAM(0, 0, 0)
    452                                         RX_OP_CHECK_ERROR_STREAM(1, 0, 0)
    453 
    454     /* Test exceeding limit at stream level. */
    455     RX_OP_RX(0, INIT_S_WINDOW_SIZE * 2 + 1, 0)
    456         RX_OP_CHECK_ERROR_STREAM(0, OSSL_QUIC_ERR_FLOW_CONTROL_ERROR, 0)
    457             RX_OP_CHECK_ERROR_STREAM(0, OSSL_QUIC_ERR_FLOW_CONTROL_ERROR, 1)
    458                 RX_OP_CHECK_ERROR_STREAM(0, 0, 0)
    459                     RX_OP_CHECK_ERROR_CONN(0, 0) /* doesn't affect conn */
    460 
    461     /* Test exceeding limit at connection level. */
    462     RX_OP_RX(0, INIT_WINDOW_SIZE * 2, 0)
    463         RX_OP_CHECK_ERROR_CONN(OSSL_QUIC_ERR_FLOW_CONTROL_ERROR, 0)
    464             RX_OP_CHECK_ERROR_CONN(OSSL_QUIC_ERR_FLOW_CONTROL_ERROR, 1)
    465                 RX_OP_CHECK_ERROR_CONN(0, 0)
    466 
    467                     RX_OP_END
    468 };
    469 
    470 static const struct rx_test_op *rx_scripts[] = {
    471     rx_script_1,
    472     rx_script_2
    473 };
    474 
    475 static int run_rxfc_script(const struct rx_test_op *script)
    476 {
    477 #define MAX_STREAMS 3
    478     int testresult = 0;
    479     const struct rx_test_op *op = script;
    480     QUIC_RXFC conn_rxfc = { 0 }, stream_rxfc[MAX_STREAMS] = { 0 }; /* coverity */
    481     char stream_init_done[MAX_STREAMS] = { 0 };
    482     int conn_init_done = 0;
    483 
    484     cur_time = ossl_time_zero();
    485 
    486     for (; op->op != RX_OPC_END; ++op) {
    487         switch (op->op) {
    488         case RX_OPC_INIT_CONN:
    489             if (!TEST_true(ossl_quic_rxfc_init(&conn_rxfc, 0,
    490                     op->arg0, op->arg1,
    491                     fake_now, NULL)))
    492                 goto err;
    493 
    494             conn_init_done = 1;
    495             break;
    496 
    497         case RX_OPC_INIT_STREAM:
    498             if (!TEST_size_t_lt(op->stream_idx, OSSL_NELEM(stream_rxfc))
    499                 || !TEST_true(conn_init_done))
    500                 goto err;
    501 
    502             if (!TEST_true(ossl_quic_rxfc_init(&stream_rxfc[op->stream_idx],
    503                     &conn_rxfc,
    504                     op->arg0, op->arg1,
    505                     fake_now, NULL)))
    506                 goto err;
    507 
    508             stream_init_done[op->stream_idx] = 1;
    509             break;
    510 
    511         case RX_OPC_RX:
    512             if (!TEST_true(conn_init_done && op->stream_idx < OSSL_NELEM(stream_rxfc)
    513                     && stream_init_done[op->stream_idx]))
    514                 goto err;
    515 
    516             if (!TEST_true(ossl_quic_rxfc_on_rx_stream_frame(&stream_rxfc[op->stream_idx],
    517                     op->arg0,
    518                     (int)op->arg1)))
    519                 goto err;
    520 
    521             break;
    522 
    523         case RX_OPC_RETIRE:
    524             if (!TEST_true(conn_init_done && op->stream_idx < OSSL_NELEM(stream_rxfc)
    525                     && stream_init_done[op->stream_idx]))
    526                 goto err;
    527 
    528             if (!TEST_int_eq(ossl_quic_rxfc_on_retire(&stream_rxfc[op->stream_idx],
    529                                  op->arg0,
    530                                  ossl_ticks2time(op->arg1)),
    531                     !op->expect_fail))
    532                 goto err;
    533 
    534             break;
    535         case RX_OPC_CHECK_CWM_CONN:
    536             if (!TEST_true(conn_init_done))
    537                 goto err;
    538             if (!TEST_uint64_t_eq(ossl_quic_rxfc_get_cwm(&conn_rxfc),
    539                     op->arg0))
    540                 goto err;
    541             break;
    542         case RX_OPC_CHECK_CWM_STREAM:
    543             if (!TEST_true(op->stream_idx < OSSL_NELEM(stream_rxfc)
    544                     && stream_init_done[op->stream_idx]))
    545                 goto err;
    546             if (!TEST_uint64_t_eq(ossl_quic_rxfc_get_cwm(&stream_rxfc[op->stream_idx]),
    547                     op->arg0))
    548                 goto err;
    549             break;
    550         case RX_OPC_CHECK_SWM_CONN:
    551             if (!TEST_true(conn_init_done))
    552                 goto err;
    553             if (!TEST_uint64_t_eq(ossl_quic_rxfc_get_swm(&conn_rxfc),
    554                     op->arg0))
    555                 goto err;
    556             break;
    557         case RX_OPC_CHECK_SWM_STREAM:
    558             if (!TEST_true(op->stream_idx < OSSL_NELEM(stream_rxfc)
    559                     && stream_init_done[op->stream_idx]))
    560                 goto err;
    561             if (!TEST_uint64_t_eq(ossl_quic_rxfc_get_swm(&stream_rxfc[op->stream_idx]),
    562                     op->arg0))
    563                 goto err;
    564             break;
    565         case RX_OPC_CHECK_RWM_CONN:
    566             if (!TEST_true(conn_init_done))
    567                 goto err;
    568             if (!TEST_uint64_t_eq(ossl_quic_rxfc_get_rwm(&conn_rxfc),
    569                     op->arg0))
    570                 goto err;
    571             break;
    572         case RX_OPC_CHECK_RWM_STREAM:
    573             if (!TEST_true(op->stream_idx < OSSL_NELEM(stream_rxfc)
    574                     && stream_init_done[op->stream_idx]))
    575                 goto err;
    576             if (!TEST_uint64_t_eq(ossl_quic_rxfc_get_rwm(&stream_rxfc[op->stream_idx]),
    577                     op->arg0))
    578                 goto err;
    579             break;
    580         case RX_OPC_CHECK_CHANGED_CONN:
    581             if (!TEST_true(conn_init_done))
    582                 goto err;
    583             if (!TEST_int_eq(ossl_quic_rxfc_has_cwm_changed(&conn_rxfc,
    584                                  (int)op->arg1),
    585                     (int)op->arg0))
    586                 goto err;
    587             break;
    588         case RX_OPC_CHECK_CHANGED_STREAM:
    589             if (!TEST_true(op->stream_idx < OSSL_NELEM(stream_rxfc)
    590                     && stream_init_done[op->stream_idx]))
    591                 goto err;
    592             if (!TEST_int_eq(ossl_quic_rxfc_has_cwm_changed(&stream_rxfc[op->stream_idx],
    593                                  (int)op->arg1),
    594                     (int)op->arg0))
    595                 goto err;
    596             break;
    597         case RX_OPC_CHECK_ERROR_CONN:
    598             if (!TEST_true(conn_init_done))
    599                 goto err;
    600             if (!TEST_int_eq(ossl_quic_rxfc_get_error(&conn_rxfc,
    601                                  (int)op->arg1),
    602                     (int)op->arg0))
    603                 goto err;
    604             break;
    605         case RX_OPC_CHECK_ERROR_STREAM:
    606             if (!TEST_true(op->stream_idx < OSSL_NELEM(stream_rxfc)
    607                     && stream_init_done[op->stream_idx]))
    608                 goto err;
    609             if (!TEST_int_eq(ossl_quic_rxfc_get_error(&stream_rxfc[op->stream_idx],
    610                                  (int)op->arg1),
    611                     (int)op->arg0))
    612                 goto err;
    613             break;
    614         case RX_OPC_STEP_TIME:
    615             cur_time = ossl_time_add(cur_time, ossl_ticks2time(op->arg0));
    616             break;
    617         case RX_OPC_MSG:
    618             fprintf(stderr, "# %s\n", op->msg);
    619             break;
    620         default:
    621             goto err;
    622         }
    623     }
    624 
    625     testresult = 1;
    626 err:
    627     return testresult;
    628 }
    629 
    630 static int test_rxfc(int idx)
    631 {
    632     return run_rxfc_script(rx_scripts[idx]);
    633 }
    634 
    635 int setup_tests(void)
    636 {
    637     ADD_ALL_TESTS(test_txfc, 2);
    638     ADD_ALL_TESTS(test_rxfc, OSSL_NELEM(rx_scripts));
    639     return 1;
    640 }
    641