test_ackparse_ietf.c revision fb73393f
1/* Copyright (c) 2017 - 2020 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_types.h"
11#include "lsquic_parse.h"
12#include "lsquic_rechist.h"
13#include "lsquic_util.h"
14#include "lsquic.h"
15#include "lsquic_hash.h"
16#include "lsquic_conn.h"
17
18static struct lsquic_conn lconn = LSCONN_INITIALIZER_CIDLEN(lconn, 0);
19
20static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_ID27);
21
22
23static void
24test_max_ack (void)
25{
26    lsquic_rechist_t rechist;
27    lsquic_time_t now;
28    unsigned i;
29    int has_missing, sz[2];
30    const struct lsquic_packno_range *range;
31    unsigned char buf[1500];
32    struct ack_info acki;
33
34    lsquic_rechist_init(&rechist, &lconn, 0);
35    now = lsquic_time_now();
36
37    for (i = 1; i <= 300; ++i)
38    {
39        lsquic_rechist_received(&rechist, i * 10, now);
40        now += i * 1000;
41    }
42
43    memset(buf, 0xAA, sizeof(buf));
44
45    lsquic_packno_t largest = 0;
46    sz[0] = pf->pf_gen_ack_frame(buf, sizeof(buf),
47        (gaf_rechist_first_f)        lsquic_rechist_first,
48        (gaf_rechist_next_f)         lsquic_rechist_next,
49        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
50        &rechist, now, &has_missing, &largest, NULL);
51    assert(sz[0] > 0);
52    assert(sz[0] <= (int) sizeof(buf));
53    assert(has_missing);
54
55    assert(0 == buf[ sz[0] - 1 ]);  /* Number of timestamps */
56    assert(0xAA == buf[ sz[0] ]);
57
58    sz[1] = pf->pf_parse_ack_frame(buf, sizeof(buf), &acki, 0);
59    assert(sz[1] == sz[0]);
60    assert(256 == acki.n_ranges);
61
62    for (range = lsquic_rechist_first(&rechist), i = 0;
63                        range && i < acki.n_ranges;
64                                    range = lsquic_rechist_next(&rechist), ++i)
65    {
66        assert(range->high == acki.ranges[i].high);
67        assert(range->low  == acki.ranges[i].low);
68    }
69    assert(i == 256);
70
71    lsquic_rechist_cleanup(&rechist);
72}
73
74
75static void
76test_ack_truncation (void)
77{
78    lsquic_rechist_t rechist;
79    lsquic_time_t now;
80    unsigned i;
81    int has_missing, sz[2];
82    const struct lsquic_packno_range *range;
83    unsigned char buf[1500];
84    struct ack_info acki;
85    size_t bufsz;
86
87    lsquic_rechist_init(&rechist, &lconn, 0);
88    now = lsquic_time_now();
89
90    for (i = 1; i <= 300; ++i)
91    {
92        lsquic_rechist_received(&rechist, i * 10, now);
93        now += i * 1000;
94    }
95
96    for (bufsz = 200; bufsz < 210; ++bufsz)
97    {
98        memset(buf, 0xAA, sizeof(buf));
99        lsquic_packno_t largest = 0;
100        sz[0] = pf->pf_gen_ack_frame(buf, bufsz,
101            (gaf_rechist_first_f)        lsquic_rechist_first,
102            (gaf_rechist_next_f)         lsquic_rechist_next,
103            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
104            &rechist, now, &has_missing, &largest, NULL);
105        assert(sz[0] > 0);
106        assert(sz[0] <= (int) bufsz);
107        assert(has_missing);
108
109        assert(0 == buf[ sz[0] - 1 ]);  /* Number of timestamps */
110        assert(0xAA == buf[ sz[0] ]);
111
112        sz[1] = pf->pf_parse_ack_frame(buf, sizeof(buf), &acki, 0);
113        assert(sz[1] == sz[0]);
114        assert(acki.n_ranges < 256);
115
116        for (range = lsquic_rechist_first(&rechist), i = 0;
117                            range && i < acki.n_ranges;
118                                        range = lsquic_rechist_next(&rechist), ++i)
119        {
120            assert(range->high == acki.ranges[i].high);
121            assert(range->low  == acki.ranges[i].low);
122        }
123    }
124
125    lsquic_rechist_cleanup(&rechist);
126}
127
128
129int
130main (void)
131{
132    lsquic_global_init(LSQUIC_GLOBAL_SERVER);
133    test_max_ack();
134    test_ack_truncation();
135    return 0;
136}
137