test_streamgen.c revision 06b2a236
1/* Copyright (c) 2017 - 2021 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