test_ackgen_gquic_be.c revision fb3e20e0
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * Test how ACK frame is encoded.  Receive history module is tested by a
4 * separate unit test.
5 */
6
7#include <assert.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12#ifdef WIN32
13#include "vc_compat.h"
14#endif
15
16#include "lsquic_types.h"
17#include "lsquic_int_types.h"
18#include "lsquic_rechist.h"
19#include "lsquic_parse.h"
20#include "lsquic_util.h"
21#include "lsquic_logger.h"
22#include "lsquic.h"
23
24static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_043);
25
26static void
27test1 (void) /* Inverse of quic_framer_test.cc -- NewAckFrameOneAckBlock */
28{
29    lsquic_rechist_t rechist;
30    lsquic_time_t now = lsquic_time_now();
31    lsquic_packno_t largest = 0;
32
33    lsquic_rechist_init(&rechist, 0, 0);
34
35    unsigned i;
36    for (i = 1; i <= 0x1234; ++i)
37        (void) lsquic_rechist_received(&rechist, i, now);
38
39    const unsigned char expected_ack_frame[] = {
40        0x45,
41        0x12, 0x34,             /* Largest acked */
42        0x87, 0xFF,             /* Delta time */
43        0x12, 0x34,             /* Block length */
44        0x00,                   /* Number of timestamps */
45    };
46    unsigned char outbuf[0x100];
47
48    int has_missing = -1;
49    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
50        (gaf_rechist_first_f)        lsquic_rechist_first,
51        (gaf_rechist_next_f)         lsquic_rechist_next,
52        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
53        &rechist, now + 0x7FF8000, &has_missing, &largest, NULL);
54    assert(("ACK frame generation successful", w > 0));
55    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
56    assert(("ACK frame contents are as expected",
57        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
58    assert(("ACK frame has no missing packets", has_missing == 0));
59    assert(largest == 0x1234);
60
61    lsquic_rechist_cleanup(&rechist);
62}
63
64static void
65test2 (void) /* Inverse of quic_framer_test.cc -- NewAckFrameOneAckBlock, minus
66              * delta times.
67              */
68{
69    lsquic_rechist_t rechist;
70    lsquic_time_t now = lsquic_time_now();
71
72    lsquic_rechist_init(&rechist, 0, 0);
73
74    /* Encode the following ranges:
75     *    high      low
76     *    0x1234    0x1234
77     *    0x1232    0x384
78     *    0x1F3     0xA
79     *    0x4       0x1
80     */
81    unsigned i;
82    for (i = 4; i >= 1; --i)
83        (void) lsquic_rechist_received(&rechist, i, now);
84    (void) lsquic_rechist_received(&rechist, 0x1234, now);
85    for (i = 0xA; i <= 0x1F3; ++i)
86        (void) lsquic_rechist_received(&rechist, i, now);
87    for (i = 0x1232; i >= 0x384; --i)
88        (void) lsquic_rechist_received(&rechist, i, now);
89
90    const unsigned char expected_ack_frame[] = {
91        0x65,
92        0x12, 0x34,                 /* Largest acked */
93        0x00, 0x00,                 /* Zero delta time. */
94        0x04,                       /* Num ack blocks ranges. */
95        0x00, 0x01,                 /* First ack block length. */
96        0x01,                       /* Gap to next block. */
97        0x0e, 0xaf,                 /* Ack block length. */
98        0xff,                       /* Gap to next block. */
99        0x00, 0x00,                 /* Ack block length. */
100        0x91,                       /* Gap to next block. */
101        0x01, 0xea,                 /* Ack block length. */
102        0x05,                       /* Gap to next block. */
103        0x00, 0x04,                 /* Ack block length. */
104        0x00,                       /* Number of timestamps. */
105    };
106    unsigned char outbuf[0x100];
107
108    int has_missing = -1;
109    lsquic_packno_t largest = 0;
110    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
111        (gaf_rechist_first_f)        lsquic_rechist_first,
112        (gaf_rechist_next_f)         lsquic_rechist_next,
113        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
114        &rechist, now, &has_missing, &largest, NULL);
115    assert(("ACK frame generation successful", w > 0));
116    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
117    assert(("ACK frame contents are as expected",
118        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
119    assert(("ACK frame has missing packets", has_missing > 0));
120    assert(largest == 0x1234);
121
122    lsquic_rechist_cleanup(&rechist);
123}
124
125static void
126test3 (void)
127{
128    lsquic_rechist_t rechist;
129    lsquic_time_t now = lsquic_time_now();
130
131    lsquic_rechist_init(&rechist, 0, 0);
132
133    /* Encode the following ranges:
134     *    high      low
135     *    3         3
136     *    1         1
137     */
138    (void) lsquic_rechist_received(&rechist, 1, now);
139    (void) lsquic_rechist_received(&rechist, 3, now);
140
141    const unsigned char expected_ack_frame[] = {
142        0x60,
143        0x03,
144        0x00, 0x00,                 /* Zero delta time. */
145        0x01,                       /* Num ack blocks ranges. */
146        0x01,                       /* First ack block length. */
147        0x01,                       /* Gap to next block. */
148        0x01,                       /* Ack block length. */
149        0x00,                       /* Number of timestamps. */
150    };
151    unsigned char outbuf[0x100];
152
153    int has_missing = -1;
154    lsquic_packno_t largest = 0;
155    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
156        (gaf_rechist_first_f)        lsquic_rechist_first,
157        (gaf_rechist_next_f)         lsquic_rechist_next,
158        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
159        &rechist, now, &has_missing, &largest, NULL);
160    assert(("ACK frame generation successful", w > 0));
161    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
162    assert(("ACK frame contents are as expected",
163        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
164    assert(("ACK frame has missing packets", has_missing > 0));
165    assert(largest == 0x03);
166
167    lsquic_rechist_cleanup(&rechist);
168}
169
170
171static void
172test4 (void)
173{
174    lsquic_rechist_t rechist;
175    int i;
176
177    lsquic_rechist_init(&rechist, 0, 0);
178
179    lsquic_time_t now = lsquic_time_now();
180    lsquic_rechist_received(&rechist, 1, now);
181
182    {
183        const unsigned char expected_ack_frame[] = {
184            0x40,
185            0x01,                   /* Largest acked */
186            0x00, 0x00,             /* Delta time */
187            0x01,                   /* Block length */
188            0x00,                   /* Number of timestamps */
189        };
190        unsigned char outbuf[0x100];
191        int has_missing = -1;
192        lsquic_packno_t largest = 0;
193        int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
194            (gaf_rechist_first_f)        lsquic_rechist_first,
195            (gaf_rechist_next_f)         lsquic_rechist_next,
196            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
197            &rechist, now, &has_missing, &largest, NULL);
198        assert(("ACK frame generation successful", w > 0));
199        assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
200        assert(("ACK frame contents are as expected",
201            0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
202        assert(("ACK frame has no missing packets", has_missing == 0));
203        assert(largest == 1);
204    }
205
206    for (i = 3; i <= 5; ++i)
207        lsquic_rechist_received(&rechist, i, now);
208
209    {
210        const unsigned char expected_ack_frame[] = {
211            0x60,
212            0x05,                   /* Largest acked */
213            0x00, 0x00,             /* Delta time */
214            0x01,                   /* Num ack blocks */
215            0x03,                   /* First block length [3, 5] */
216            0x01,                   /* Gap to next block */
217            0x01,                   /* Second block length [1, 1] */
218            0x00,                   /* Number of timestamps */
219        };
220        unsigned char outbuf[0x100];
221        int has_missing = -1;
222        lsquic_packno_t largest = 0;
223        int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
224            (gaf_rechist_first_f)        lsquic_rechist_first,
225            (gaf_rechist_next_f)         lsquic_rechist_next,
226            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
227            &rechist, now, &has_missing, &largest, NULL);
228        assert(("ACK frame generation successful", w > 0));
229        assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
230        assert(("ACK frame contents are as expected",
231            0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
232        assert(("ACK frame has missing packets", has_missing > 0));
233        assert(largest == 5);
234    }
235
236    lsquic_rechist_cleanup(&rechist);
237}
238
239
240static void
241test_4byte_packnos (void)
242{
243    lsquic_packno_t packno;
244    lsquic_rechist_t rechist;
245    struct packet_interval *pint;
246    lsquic_time_t now = lsquic_time_now();
247
248    lsquic_rechist_init(&rechist, 0, 0);
249
250    packno = 0x23456789;
251    (void) lsquic_rechist_received(&rechist, packno - 33, now);
252    pint = TAILQ_FIRST(&rechist.rh_pints.pk_intervals);
253    (void) lsquic_rechist_received(&rechist, packno, now);
254
255    /* Adjust: */
256    pint->range.low = 1;
257
258    const unsigned char expected_ack_frame[] = {
259        0x60
260            | (2 << 2)  /* Four-byte largest acked */
261            | (2 << 0)  /* Four-byte ACK block length */
262        ,
263        0x23, 0x45, 0x67, 0x89,
264        0x00, 0x00,                 /* Zero delta time. */
265        0x01,                       /* Num ack blocks ranges. */
266        0x00, 0x00, 0x00, 0x01,     /* First ack block length. */
267        33 - 1,                     /* Gap to next block. */
268        0x23, 0x45, 0x67, 0x68,     /* Ack block length. */
269        0x00,                       /* Number of timestamps. */
270    };
271    unsigned char outbuf[0x100];
272
273    int has_missing = -1;
274    lsquic_packno_t largest = 0;
275    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
276        (gaf_rechist_first_f)        lsquic_rechist_first,
277        (gaf_rechist_next_f)         lsquic_rechist_next,
278        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
279        &rechist, now, &has_missing, &largest, NULL);
280    assert(("ACK frame generation successful", w > 0));
281    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
282    assert(("ACK frame contents are as expected",
283        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
284    assert(("ACK frame has missing packets", has_missing > 0));
285    assert(largest == 0x23456789);
286
287    lsquic_rechist_cleanup(&rechist);
288}
289
290
291static void
292test_6byte_packnos (void)
293{
294    lsquic_packno_t packno;
295    lsquic_rechist_t rechist;
296    struct packet_interval *pint;
297    lsquic_time_t now = lsquic_time_now();
298
299    lsquic_rechist_init(&rechist, 0, 0);
300
301    packno = 0xABCD23456789;
302    (void) lsquic_rechist_received(&rechist, packno - 33, now);
303    pint = TAILQ_FIRST(&rechist.rh_pints.pk_intervals);
304    (void) lsquic_rechist_received(&rechist, packno, now);
305
306    /* Adjust: */
307    pint->range.low = 1;
308
309    const unsigned char expected_ack_frame[] = {
310        0x60
311            | (3 << 2)  /* Six-byte largest acked */
312            | (3 << 0)  /* Six-byte ACK block length */
313        ,
314        0xAB, 0xCD, 0x23, 0x45, 0x67, 0x89,
315        0x00, 0x00,                 /* Zero delta time. */
316        0x01,                       /* Num ack blocks ranges. */
317        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* First ack block length. */
318        33 - 1,                     /* Gap to next block. */
319        0xAB, 0xCD, 0x23, 0x45, 0x67, 0x68, /* Ack block length. */
320        0x00,                       /* Number of timestamps. */
321    };
322    unsigned char outbuf[0x100];
323
324    int has_missing = -1;
325    lsquic_packno_t largest = 0;
326    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
327        (gaf_rechist_first_f)        lsquic_rechist_first,
328        (gaf_rechist_next_f)         lsquic_rechist_next,
329        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
330        &rechist, now, &has_missing, &largest, NULL);
331    assert(("ACK frame generation successful", w > 0));
332    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
333    assert(("ACK frame contents are as expected",
334        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
335    assert(("ACK frame has missing packets", has_missing > 0));
336    assert(largest == 0xABCD23456789ULL);
337
338    lsquic_rechist_cleanup(&rechist);
339}
340
341
342int
343main (void)
344{
345    lsquic_global_init(LSQUIC_GLOBAL_SERVER);
346    lsquic_log_to_fstream(stderr, 0);
347    lsq_log_levels[LSQLM_PARSE]   = LSQ_LOG_DEBUG;
348
349    test1();
350
351    test2();
352
353    test3();
354
355    test4();
356
357    test_4byte_packnos();
358
359    test_6byte_packnos();
360
361    return 0;
362}
363