1/* Copyright (c) 2017 - 2022 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
8#include "lsquic.h"
9#include "lsquic_types.h"
10#include "lsquic_parse.h"
11
12
13struct test {
14    int                 lineno;
15    const struct parse_funcs *
16                        pf;
17    uint64_t            offset;
18    size_t              avail;      /* Space to write stream frame to */
19    size_t              min_sz;     /* Minimum size needed to generate CRYPTO
20                                     * frame.  Any sizes smaller than this
21                                     * should fail.
22                                     */
23    size_t              data_sz;
24    char                data[0x100];
25
26    /* Output.  This is how we expect the resulting frame to look.
27     */
28    int                 len;        /* Return value of pf_gen_crypto_frame() */
29    char                out[0x100];
30};
31
32struct test_ctx {
33    const struct test   *test;
34    unsigned             off;
35};
36
37
38static size_t
39crypto_read (void *ctx, void *buf, size_t len, int *fin)
40{
41    struct test_ctx *test_ctx = ctx;
42    if (test_ctx->test->data_sz - test_ctx->off < len)
43        len = test_ctx->test->data_sz - test_ctx->off;
44    memcpy(buf, test_ctx->test->data, len);
45    test_ctx->off += len;
46    return len;
47}
48
49
50static void
51init_ctx (struct test_ctx *test_ctx, const struct test *test)
52{
53    test_ctx->test = test;
54    test_ctx->off  = 0;
55}
56
57
58static void
59run_test (const struct test *const test)
60{
61
62    int len;
63    size_t min;
64    struct test_ctx test_ctx;
65    unsigned char out[0x100];
66
67    if (test->len > 0)
68    {
69        /* Test that all sizes under specified min fail to produce a frame */
70        for (min = 0; min < test->min_sz; ++min)
71        {
72            init_ctx(&test_ctx, test);
73            len = test->pf->pf_gen_crypto_frame(out, min, 0, test->offset, 0,
74                        test->data_sz, crypto_read, &test_ctx);
75            assert(-1 == len);
76        }
77
78        /* Test that it succeeds now: */
79        init_ctx(&test_ctx, test);
80        len = test->pf->pf_gen_crypto_frame(out, min, 0, test->offset, 0,
81                    test->data_sz, crypto_read, &test_ctx);
82        assert(len == (int) min);
83    }
84
85    init_ctx(&test_ctx, test);
86    len = test->pf->pf_gen_crypto_frame(out, test->avail, 0, test->offset, 0,
87                test->data_sz, crypto_read, &test_ctx);
88
89    if (test->len > 0) {
90        assert(test->len == len);
91        assert(0 == memcmp(test->out, out, test->len));
92    }
93    else
94    {
95        assert(len < 0);
96    }
97}
98
99
100int
101main (void)
102{
103    const struct test tests[] = {
104
105        {   .lineno     = __LINE__,
106            .pf         = select_pf_by_ver(LSQVER_ID27),
107            .offset     = 0,
108            .data_sz    = 10,
109            .data       = "0123456789",
110            .avail      = 0x100,
111            .out        =
112            { /* Type */    0x06,
113              /* Offset */  0x00,
114              /* Size */    0x0A,
115              /* Data */    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
116            },
117            .len        = 1 + 1 + 1 + 10,
118            .min_sz     = 1 + 1 + 1 + 1,
119        },
120
121        {   .lineno     = __LINE__,
122            .pf         = select_pf_by_ver(LSQVER_ID27),
123            .offset     = 500,
124            .data_sz    = 10,
125            .data       = "0123456789",
126            .avail      = 0x100,
127            .out        =
128            { /* Type */    0x06,
129              /* Offset */  0x41, 0xF4,
130              /* Size */    0x0A,
131              /* Data */    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
132            },
133            .len        = 1 + 2 + 1 + 10,
134            .min_sz     = 1 + 2 + 1 + 1,
135        },
136
137    };
138
139    unsigned i;
140    for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
141        run_test(&tests[i]);
142    return 0;
143}
144