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