test_streamgen.c revision fb73393f
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */ 2#include <assert.h> 3#include <stdio.h> 4#include <stdlib.h> 5#include <string.h> 6#include <sys/queue.h> 7#ifndef WIN32 8#include <sys/time.h> 9#endif 10 11#include "lsquic.h" 12#include "lsquic_types.h" 13#include "lsquic_parse.h" 14#include "lsquic_sfcw.h" 15#include "lsquic_varint.h" 16#include "lsquic_hq.h" 17#include "lsquic_hash.h" 18#include "lsquic_stream.h" 19 20struct test { 21 int lineno; 22 const struct parse_funcs * 23 pf; 24 /* Inputs. These are returned by lsquic_stream_tosend_fin(), 25 * lsquic_stream_tosend_read(), and lsquic_stream_tosend_offset(). 26 */ 27 int fin[2]; /* There may be two calls to lsquic_stream_tosend_fin() */ 28 uint64_t offset; 29 uint32_t stream_id; 30 size_t avail; /* Space to write stream frame to */ 31 size_t min_sz; /* Minimum size needed to generate stream frame. Any 32 * sizes smaller than this should fail. 33 */ 34 size_t data_sz; 35 char data[0x100]; 36 37 /* Output. This is how we expect the resulting frame to look. 38 */ 39 int len; /* Return value of gen_stream_frame() */ 40 char out[0x100]; 41}; 42 43 44static const struct test tests[] = { 45 /* 46 * Big-endian: 47 */ 48 { .lineno = __LINE__, 49 .pf = select_pf_by_ver(LSQVER_043), 50 .fin = { 0, 1, }, 51 .offset = 0x0807060504030201UL, 52 .stream_id = 0x210, 53 .data_sz = 10, 54 .data = "0123456789", 55 .avail = 0x100, 56 .out = 57 /* 1 f d ooo ss 1fdoooss */ 58 /* TYPE FIN DLEN OLEN SLEN */ 59 { 0x80 | 0x40 | 0x20 | 0x1C | 0x01, 60 0x02, 0x10, /* Stream ID */ 61 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, /* Offset */ 62 0x00, 0x0A, /* Data length */ 63 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 64 }, 65 .len = 1 + 2 + 8 + 2 + 10, 66 .min_sz = 1 + 2 + 8 + 0 + 1, 67 }, 68 69 { .lineno = __LINE__, 70 .pf = select_pf_by_ver(LSQVER_043), 71 .fin = { 0, 0, }, 72 .offset = 0x0807060504030201UL, 73 .stream_id = 0x210, 74 .data_sz = 10, 75 .data = "0123456789", 76 .avail = 0x100, 77 .out = 78 /* 1 f d ooo ss 1fdoooss */ 79 /* TYPE FIN DLEN OLEN SLEN */ 80 { 0x80 | 0x00 | 0x20 | 0x1C | 0x01, 81 0x02, 0x10, /* Stream ID */ 82 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, /* Offset */ 83 0x00, 0x0A, /* Data length */ 84 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 85 }, 86 .len = 1 + 2 + 8 + 2 + 10, 87 .min_sz = 1 + 2 + 8 + 0 + 1, 88 }, 89 90 { .lineno = __LINE__, 91 .pf = select_pf_by_ver(LSQVER_043), 92 .fin = { 1, 0, }, 93 .offset = 0x0807060504030201UL, 94 .stream_id = 0x210, 95 .data_sz = 10, 96 .data = "0123456789", 97 .avail = 0x100, 98 .out = 99 /* 1 f d ooo ss 1fdoooss */ 100 /* TYPE FIN DLEN OLEN SLEN */ 101 { 0x80 | 0x40 | 0x20 | 0x1C | 0x01, 102 0x02, 0x10, /* Stream ID */ 103 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, /* Offset */ 104 0x00, 0x00, /* Data length */ 105 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 106 }, 107 .len = 1 + 2 + 8 + 2, 108 .min_sz = 1 + 2 + 8 + 2, 109 }, 110 111 { .lineno = __LINE__, 112 .pf = select_pf_by_ver(LSQVER_043), 113 .fin = { 1, 0, }, 114 .offset = 0x0807060504030201UL, 115 .stream_id = 0x21, 116 .data_sz = 10, 117 .data = "0123456789", 118 .avail = 0x100, 119 .out = 120 /* 1 f d ooo ss 1fdoooss */ 121 /* TYPE FIN DLEN OLEN SLEN */ 122 { 0x80 | 0x40 | 0x20 | 0x1C | 0x00, 123 0x21, /* Stream ID */ 124 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, /* Offset */ 125 0x00, 0x00, /* Data length */ 126 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 127 }, 128 .len = 1 + 1 + 8 + 2, 129 .min_sz = 1 + 1 + 8 + 2, 130 }, 131 132 { .lineno = __LINE__, 133 .pf = select_pf_by_ver(LSQVER_043), 134 .fin = { 0, 0, }, 135 .offset = 0x77, 136 .stream_id = 0x210, 137 .data_sz = 10, 138 .data = "0123456789", 139 .avail = 0x100, 140 .out = 141 /* 1 f d ooo ss 1fdoooss */ 142 /* TYPE FIN DLEN OLEN SLEN */ 143 { 0x80 | 0x00 | 0x20 | 0x04 | 0x01, 144 0x02, 0x10, /* Stream ID */ 145 0x00, 0x77, /* Offset */ 146 0x00, 0x0A, /* Data length */ 147 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 148 }, 149 .len = 1 + 2 + 2 + 2 + 10, 150 .min_sz = 1 + 2 + 2 + 0 + 1, 151 }, 152 153 { .lineno = __LINE__, 154 .pf = select_pf_by_ver(LSQVER_043), 155 .fin = { 0, 0, }, 156 .offset = 0x0, 157 .stream_id = 0x210, 158 .data_sz = 10, 159 .data = "0123456789", 160 .avail = 0x100, 161 .out = 162 /* 1 f d ooo ss 1fdoooss */ 163 /* TYPE FIN DLEN OLEN SLEN */ 164 { 0x80 | 0x00 | 0x20 | 0x00 | 0x01, 165 0x02, 0x10, /* Stream ID */ 166 /* Offset */ 167 0x00, 0x0A, /* Data length */ 168 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 169 }, 170 .len = 1 + 2 + 0 + 2 + 10, 171 .min_sz = 1 + 2 + 0 + 0 + 1, 172 }, 173 174 { .lineno = __LINE__, 175 .pf = select_pf_by_ver(LSQVER_043), 176 .fin = { 0, 1, }, 177 .offset = 0x0, 178 .stream_id = 0x210, 179 .data_sz = 1, 180 .data = "0123456789", 181 .avail = 0x100, 182 .out = 183 /* 1 f d ooo ss 1fdoooss */ 184 /* TYPE FIN DLEN OLEN SLEN */ 185 { 0x80 | 0x40 | 0x20 | 0x00 | 0x01, 186 0x02, 0x10, /* Stream ID */ 187 /* Offset */ 188 0x00, 0x01, /* Data length */ 189 '0', 190 }, 191 .len = 1 + 2 + 0 + 2 + 1, 192 .min_sz = 1 + 2 + 0 + 0 + 1, 193 }, 194 195 { .lineno = __LINE__, 196 .pf = select_pf_by_ver(LSQVER_043), 197 .fin = { 0, 0, }, 198 .offset = 0xFFFFFF, 199 .stream_id = 0x210, 200 .data_sz = 10, 201 .data = "0123456789", 202 .avail = 0x100, 203 .out = 204 /* 1 f d ooo ss 1fdoooss */ 205 /* TYPE FIN DLEN OLEN SLEN */ 206 { 0x80 | 0x00 | 0x20 | 0x08 | 0x01, 207 0x02, 0x10, /* Stream ID */ 208 0xFF, 0xFF, 0xFF, /* Offset */ 209 0x00, 0x0A, /* Data length */ 210 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 211 }, 212 .len = 1 + 2 + 3 + 2 + 10, 213 .min_sz = 1 + 2 + 3 + 0 + 1, 214 }, 215 216 { .lineno = __LINE__, 217 .pf = select_pf_by_ver(LSQVER_043), 218 .fin = { 0, 0, }, 219 .offset = 0xFFFFFF + 1, 220 .stream_id = 0x210, 221 .data_sz = 10, 222 .data = "0123456789", 223 .avail = 0x100, 224 .out = 225 /* 1 f d ooo ss 1fdoooss */ 226 /* TYPE FIN DLEN OLEN SLEN */ 227 { 0x80 | 0x00 | 0x20 | 0x0C | 0x01, 228 0x02, 0x10, /* Stream ID */ 229 0x01, 0x00, 0x00, 0x00, /* Offset */ 230 0x00, 0x0A, /* Data length */ 231 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 232 }, 233 .len = 1 + 2 + 4 + 2 + 10, 234 .min_sz = 1 + 2 + 4 + 0 + 1, 235 }, 236 237 { .lineno = __LINE__, 238 .pf = select_pf_by_ver(LSQVER_043), 239 .fin = { 0, 0, }, 240 .offset = 0xFFFFFF + 1, 241 .stream_id = 0x210, 242 .data_sz = 10, 243 .data = "0123456789", 244 .avail = 10, 245 .out = 246 /* 1 f d ooo ss 1fdoooss */ 247 /* TYPE FIN DLEN OLEN SLEN */ 248 { 0x80 | 0x00 | 0x00 | 0x0C | 0x01, 249 0x02, 0x10, /* Stream ID */ 250 0x01, 0x00, 0x00, 0x00, /* Offset */ 251 '0', '1', '2', 252 }, 253 .len = 1 + 2 + 4 + 0 + 3, 254 .min_sz = 1 + 2 + 4 + 0 + 1, 255 }, 256 257 { .lineno = __LINE__, 258 .pf = select_pf_by_ver(LSQVER_043), 259 .fin = { 1, 0, }, 260 .offset = 0xB4, 261 .stream_id = 0x01, 262 .data_sz = 0, 263 .data = "0123456789", 264 .avail = 0x100, 265 .out = 266 /* 1 f d ooo ss 1fdoooss */ 267 /* TYPE FIN DLEN OLEN SLEN */ 268 { 0x80 | 0x40 | 0x20 | 0x04 | 0x00, 269 0x01, /* Stream ID */ 270 0x00, 0xB4, /* Offset */ 271 0x00, 0x00, /* Data length */ 272 }, 273 .len = 6, 274 .min_sz = 6, 275 }, 276 277 /* 278 * IETF QUIC Internet-Draft 17: 279 */ 280 281 { .lineno = __LINE__, 282 .pf = select_pf_by_ver(LSQVER_ID27), 283 .fin = { 0, 1, }, 284 .offset = 0x0807060504030201UL, 285 .stream_id = 0x210, 286 .data_sz = 10, 287 .data = "0123456789", 288 .avail = 0x100, 289 .out = 290 /* TYPE OFF DLEN FIN */ 291 { 0x08 | 1<<2 | 1<<1 | 1<<0, 292 0x42, 0x10, /* Stream ID */ 293 0xC8, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, /* Offset */ 294 0x0A, /* Data length */ 295 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 296 }, 297 .len = 1 + 2 + 8 + 1 + 10, 298 .min_sz = 1 + 2 + 8 + 0 + 1, 299 }, 300 301 { .lineno = __LINE__, 302 .pf = select_pf_by_ver(LSQVER_ID27), 303 .fin = { 0, 0, }, 304 .offset = 0, 305 .stream_id = 0x210, 306 .data_sz = 10, 307 .data = "0123456789", 308 .avail = 0x100, 309 .out = 310 /* TYPE OFF DLEN FIN */ 311 { 0x08 | 0<<2 | 1<<1 | 0<<0, 312 0x42, 0x10, /* Stream ID */ 313 0x0A, /* Data length */ 314 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 315 }, 316 .len = 1 + 2 + 0 + 1 + 10, 317 .min_sz = 1 + 2 + 0 + 0 + 1, 318 }, 319 320 { .lineno = __LINE__, 321 .pf = select_pf_by_ver(LSQVER_ID27), 322 .fin = { 0, 0, }, 323 .offset = 0, 324 .stream_id = 0x21, 325 .data_sz = 10, 326 .data = "0123456789", 327 .avail = 12, 328 .out = 329 /* TYPE OFF DLEN FIN */ 330 { 0x08 | 0<<2 | 0<<1 | 0<<0, 331 0x21, /* Stream ID */ 332 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 333 }, 334 .len = 1 + 1 + 0 + 0 + 10, 335 .min_sz = 1 + 1 + 0 + 0 + 1, 336 }, 337 338 { .lineno = __LINE__, 339 .pf = select_pf_by_ver(LSQVER_ID27), 340 .fin = { 0, 0, }, 341 .offset = 0x0807060504030201UL, 342 .stream_id = 0x210, 343 .data_sz = 10, 344 .data = "0123456789", 345 .avail = 0x100, 346 .out = 347 /* TYPE OFF DLEN FIN */ 348 { 0x08 | 1<<2 | 1<<1 | 0<<0, 349 0x42, 0x10, /* Stream ID */ 350 0xC8, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, /* Offset */ 351 0x0A, /* Data length */ 352 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 353 }, 354 .len = 1 + 2 + 8 + 1 + 10, 355 .min_sz = 1 + 2 + 8 + 0 + 1, 356 }, 357 358 { .lineno = __LINE__, 359 .pf = select_pf_by_ver(LSQVER_ID27), 360 .fin = { 1, 0, }, 361 .offset = 0x0807060504030201UL, 362 .stream_id = 0x210, 363 .data_sz = 0, 364 .data = "0123456789", 365 .avail = 11, 366 .out = 367 /* TYPE OFF DLEN FIN */ 368 { 0x08 | 1<<2 | 0<<1 | 1<<0, 369 0x42, 0x10, /* Stream ID */ 370 0xC8, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, /* Offset */ 371 }, 372 .len = 1 + 2 + 8, 373 .min_sz = 1 + 2 + 8, 374 }, 375 376 { .lineno = __LINE__, 377 .pf = select_pf_by_ver(LSQVER_ID27), 378 .fin = { 1, 0, }, 379 .offset = 0x0807060504030201UL, 380 .stream_id = 0x210, 381 .data_sz = 0, 382 .data = "0123456789", 383 .avail = 0x100, 384 .out = 385 /* TYPE OFF DLEN FIN */ 386 { 0x08 | 1<<2 | 1<<1 | 1<<0, 387 0x42, 0x10, /* Stream ID */ 388 0xC8, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, /* Offset */ 389 0x00, /* Data length */ 390 }, 391 .len = 1 + 2 + 8 + 1, 392 .min_sz = 1 + 2 + 8, 393 }, 394 395}; 396 397 398static struct test_ctx { 399 const struct test *test; 400 int next_fin; 401 lsquic_stream_t stream; 402} test_ctx; 403 404 405static int 406stream_tosend_fin (void *stream) 407{ 408 struct test_ctx *test_ctx2 = stream; 409 return test_ctx2->test->fin[ test_ctx2->next_fin++ ]; 410} 411 412 413static size_t 414stream_tosend_read (void *stream, void *buf, size_t len, int *reached_fin) 415{ 416 struct test_ctx *test_ctx2 = stream; 417 if (test_ctx2->test->data_sz < len) 418 len = test_ctx2->test->data_sz; 419 memcpy(buf, test_ctx2->test->data, len); 420 *reached_fin = stream_tosend_fin(stream); 421 return len; 422} 423 424 425static size_t 426stream_tosend_size (void *stream) 427{ 428 struct test_ctx *test_ctx2 = stream; 429 return test_ctx2->test->data_sz; 430} 431 432 433static void 434reset_ctx (const struct test *test) 435{ 436 test_ctx.test = test; 437 test_ctx.next_fin = 0; 438 test_ctx.stream.id = test->stream_id; 439} 440 441 442static void 443run_test (int i) 444{ 445 const struct test *const test = &tests[i]; 446 447 unsigned char out[0x100]; 448 int len; 449 size_t min; 450 451 if (test->len > 0) 452 { 453 /* Test that all sizes under specified min fail to produce a frame */ 454 for (min = 0; min < test->min_sz; ++min) 455 { 456 reset_ctx(test); 457 len = test->pf->pf_gen_stream_frame(out, min, test->stream_id, 458 test_ctx.test->offset, stream_tosend_fin(&test_ctx), 459 stream_tosend_size(&test_ctx), stream_tosend_read, &test_ctx); 460 assert(len < 0); 461 } 462 463 /* Test that it succeeds now: */ 464 reset_ctx(test); 465 len = test->pf->pf_gen_stream_frame(out, min, test->stream_id, 466 test_ctx.test->offset, stream_tosend_fin(&test_ctx), 467 stream_tosend_size(&test_ctx), stream_tosend_read, &test_ctx); 468 assert(len == (int) min); 469 } 470 471 reset_ctx(test); 472 len = test->pf->pf_gen_stream_frame(out, test->avail, test->stream_id, 473 test_ctx.test->offset, stream_tosend_fin(&test_ctx), 474 stream_tosend_size(&test_ctx), stream_tosend_read, &test_ctx); 475 476 if (test->len > 0) { 477 /* Check parser operation */ 478 assert(test->len == len); 479 assert(("Generated frame is correct", 0 == memcmp(test->out, out, test->len))); 480 } 481 else 482 { 483 assert(("This test should fail", len < 0)); 484 } 485} 486 487 488int 489main (void) 490{ 491 unsigned i; 492 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) 493 run_test(i); 494 return 0; 495} 496