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#ifndef WIN32
7#include <sys/time.h>
8#endif
9
10#include "lsquic.h"
11#include "lsquic_types.h"
12#include "lsquic_parse.h"
13
14//static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_043); // will not work on MSVC
15#define pf ((const struct parse_funcs *const)select_pf_by_ver(LSQVER_043))
16
17
18struct conn_close_parse_test {
19    int             lineno;
20    unsigned char   buf[0x100];
21    size_t          buf_len;
22    uint32_t        error_code;
23    uint16_t        reason_len;
24    uint8_t         reason_off;
25    int             retval;
26};
27
28static const struct conn_close_parse_test parse_tests[] = {
29
30    {
31        .lineno         = __LINE__,
32        .buf            = { 0x02, 0x00, 0x00, 0x00, 0x31, 0x00, 0x05, 'D', 'u', 'd', 'e', '!', },
33        .buf_len        = 0x100,
34        .error_code     = 0x31,
35        .reason_len     = 0x05,
36        .reason_off     = 7,
37        .retval         = 7 + 5,
38    },
39
40    {
41        .lineno         = __LINE__,
42        .buf            = { 0x02, 0x00, 0x00, 0x00, 0x31, 0x00, 0x05, 'D', 'u', 'd', 'e', '!', },
43        .buf_len        = 6,    /* Too short #1 */
44        .error_code     = 0x31,
45        .reason_len     = 0x05,
46        .reason_off     = 7,
47        .retval         = -1,
48    },
49
50    {
51        .lineno         = __LINE__,
52        .buf            = { 0x02, 0x00, 0x00, 0x00, 0x31, 0x00, 0x05, 'D', 'u', 'd', 'e', '!', },
53        .buf_len        = 9,    /* Too short #2 */
54        .error_code     = 0x31,
55        .reason_len     = 0x05,
56        .reason_off     = 7,
57        .retval         = -2,
58    },
59
60    {   .buf            = { 0 },    }
61};
62
63
64struct conn_close_gen_test {
65    int             lineno;
66    uint32_t        error_code;
67    const char     *reason;
68    int             retval;
69    unsigned char   buf[0x100];
70    size_t          buf_len;
71};
72
73
74static const struct conn_close_gen_test gen_tests[] = {
75
76    {
77        .lineno         = __LINE__,
78        .error_code     = 0x12345678,
79        .reason         = "Dude, where is my car?",
80        .retval         = 7 + sizeof("Dude, where is my car?") - 1,
81        .buf_len        = 0x100,
82        .buf            = {
83            0x02,
84            0x12, 0x34, 0x56, 0x78,
85            0x00, sizeof("Dude, where is my car?") - 1,
86            'D', 'u', 'd', 'e', ',', ' ', 'w', 'h', 'e', 'r', 'e', ' ', 'i', 's', ' ', 'm', 'y', ' ', 'c', 'a', 'r', '?',
87        },
88    },
89
90    {
91        .lineno         = __LINE__,
92        .error_code     = 0x12345678,
93        .reason         = NULL,
94        .retval         = 7,
95        .buf_len        = 0x100,
96        .buf            = {
97            0x02,
98            0x12, 0x34, 0x56, 0x78,
99            0x00, 0x00, /* Zero-sized string */
100        },
101    },
102
103    {
104        .lineno         = __LINE__,
105        .error_code     = 0x12345678,
106        .reason         = "Dude, where is my car?",
107        .retval         = -1,   /* Too short */
108        .buf_len        = 0x10,
109    },
110
111    {   .buf            = { 0 },    }
112
113};
114
115
116static void
117run_parse_tests (void)
118{
119    const struct conn_close_parse_test *test;
120    for (test = parse_tests; test->buf[0]; ++test)
121    {
122        uint64_t error_code = ~0;
123        uint16_t reason_len = ~0;
124        uint8_t reason_off = ~0;
125        int sz = pf->pf_parse_connect_close_frame(test->buf, test->buf_len,
126                                NULL, &error_code, &reason_len, &reason_off);
127        assert(sz == test->retval);
128        if (0 == sz)
129        {
130            assert(test->error_code == error_code);
131            assert(test->reason_len == reason_len);
132            assert(test->reason_off == reason_off);
133        }
134    }
135}
136
137
138static void
139run_gen_tests (void)
140{
141    const struct conn_close_gen_test *test;
142    for (test = gen_tests; test->buf[0]; ++test)
143    {
144        unsigned char buf[0x100];
145        int sz = pf->pf_gen_connect_close_frame(buf, sizeof(buf),
146                    0, test->error_code, test->reason,
147                    test->reason ? strlen(test->reason) : 0);
148        assert(sz == test->retval);
149        if (0 == sz)
150            assert(0 == memcmp(test->buf, buf, sz));
151    }
152}
153
154
155int
156main (void)
157{
158    run_parse_tests();
159    run_gen_tests();
160    return 0;
161}
162