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