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