1229fce07SDmitri Tikhonov/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc.  See LICENSE. */
250aadb33SDmitri Tikhonov/*
350aadb33SDmitri Tikhonov * Test how ACK frame is encoded.  Receive history module is tested by a
450aadb33SDmitri Tikhonov * separate unit test.
550aadb33SDmitri Tikhonov */
650aadb33SDmitri Tikhonov
750aadb33SDmitri Tikhonov#include <assert.h>
850aadb33SDmitri Tikhonov#include <stdio.h>
950aadb33SDmitri Tikhonov#include <stdlib.h>
1050aadb33SDmitri Tikhonov#include <string.h>
1150aadb33SDmitri Tikhonov
1250aadb33SDmitri Tikhonov#include "lsquic_types.h"
1350aadb33SDmitri Tikhonov#include "lsquic_int_types.h"
1450aadb33SDmitri Tikhonov#include "lsquic_rechist.h"
1550aadb33SDmitri Tikhonov#include "lsquic_parse.h"
1650aadb33SDmitri Tikhonov#include "lsquic_util.h"
1750aadb33SDmitri Tikhonov#include "lsquic_logger.h"
1850aadb33SDmitri Tikhonov#include "lsquic.h"
1950aadb33SDmitri Tikhonov
20052a1c28SDmitri Tikhonovstatic const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_035);
2150aadb33SDmitri Tikhonov
2250aadb33SDmitri Tikhonovstatic void
2350aadb33SDmitri Tikhonovtest1 (void) /* Inverse of quic_framer_test.cc -- NewAckFrameOneAckBlock */
2450aadb33SDmitri Tikhonov{
2550aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
2650aadb33SDmitri Tikhonov    lsquic_time_t now = lsquic_time_now();
2716a9b66aSDmitri Tikhonov    lsquic_packno_t largest = 0;
2850aadb33SDmitri Tikhonov
2950aadb33SDmitri Tikhonov    lsquic_rechist_init(&rechist, 0);
3050aadb33SDmitri Tikhonov
3150aadb33SDmitri Tikhonov    unsigned i;
3250aadb33SDmitri Tikhonov    for (i = 1; i <= 0x1234; ++i)
3350aadb33SDmitri Tikhonov        (void) lsquic_rechist_received(&rechist, i, now);
3450aadb33SDmitri Tikhonov
3550aadb33SDmitri Tikhonov    const unsigned char expected_ack_frame[] = {
3650aadb33SDmitri Tikhonov        0x45,
3750aadb33SDmitri Tikhonov        0x34, 0x12,             /* Largest acked */
3850aadb33SDmitri Tikhonov        0xFF, 0x87,             /* Delta time */
3950aadb33SDmitri Tikhonov        0x34, 0x12,             /* Block length */
4050aadb33SDmitri Tikhonov        0x00,                   /* Number of timestamps */
4150aadb33SDmitri Tikhonov    };
4250aadb33SDmitri Tikhonov    unsigned char outbuf[0x100];
4350aadb33SDmitri Tikhonov
4450aadb33SDmitri Tikhonov    int has_missing = -1;
4550aadb33SDmitri Tikhonov    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
4650aadb33SDmitri Tikhonov        (gaf_rechist_first_f)        lsquic_rechist_first,
4750aadb33SDmitri Tikhonov        (gaf_rechist_next_f)         lsquic_rechist_next,
4850aadb33SDmitri Tikhonov        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
4916a9b66aSDmitri Tikhonov        &rechist, now + 0x7FF8000, &has_missing, &largest);
5050aadb33SDmitri Tikhonov    assert(("ACK frame generation successful", w > 0));
5150aadb33SDmitri Tikhonov    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
5250aadb33SDmitri Tikhonov    assert(("ACK frame contents are as expected",
5350aadb33SDmitri Tikhonov        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
5450aadb33SDmitri Tikhonov    assert(("ACK frame has no missing packets", has_missing == 0));
5516a9b66aSDmitri Tikhonov    assert(largest == 0x1234);
5650aadb33SDmitri Tikhonov
5750aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
5850aadb33SDmitri Tikhonov}
5950aadb33SDmitri Tikhonov
6050aadb33SDmitri Tikhonovstatic void
6150aadb33SDmitri Tikhonovtest2 (void) /* Inverse of quic_framer_test.cc -- NewAckFrameOneAckBlock, minus
6250aadb33SDmitri Tikhonov              * delta times.
6350aadb33SDmitri Tikhonov              */
6450aadb33SDmitri Tikhonov{
6550aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
6650aadb33SDmitri Tikhonov    lsquic_time_t now = lsquic_time_now();
6750aadb33SDmitri Tikhonov
6850aadb33SDmitri Tikhonov    lsquic_rechist_init(&rechist, 0);
6950aadb33SDmitri Tikhonov
7050aadb33SDmitri Tikhonov    /* Encode the following ranges:
7150aadb33SDmitri Tikhonov     *    high      low
7250aadb33SDmitri Tikhonov     *    0x1234    0x1234
7350aadb33SDmitri Tikhonov     *    0x1232    0x384
7450aadb33SDmitri Tikhonov     *    0x1F3     0xA
7550aadb33SDmitri Tikhonov     *    0x4       0x1
7650aadb33SDmitri Tikhonov     */
7750aadb33SDmitri Tikhonov    unsigned i;
7850aadb33SDmitri Tikhonov    for (i = 4; i >= 1; --i)
7950aadb33SDmitri Tikhonov        (void) lsquic_rechist_received(&rechist, i, now);
8050aadb33SDmitri Tikhonov    (void) lsquic_rechist_received(&rechist, 0x1234, now);
8150aadb33SDmitri Tikhonov    for (i = 0xA; i <= 0x1F3; ++i)
8250aadb33SDmitri Tikhonov        (void) lsquic_rechist_received(&rechist, i, now);
8350aadb33SDmitri Tikhonov    for (i = 0x1232; i >= 0x384; --i)
8450aadb33SDmitri Tikhonov        (void) lsquic_rechist_received(&rechist, i, now);
8550aadb33SDmitri Tikhonov
8650aadb33SDmitri Tikhonov    const unsigned char expected_ack_frame[] = {
8750aadb33SDmitri Tikhonov        0x65,
8850aadb33SDmitri Tikhonov        0x34, 0x12,                 /* Largest acked */
8950aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Zero delta time. */
9050aadb33SDmitri Tikhonov        0x04,                       /* Num ack blocks ranges. */
9150aadb33SDmitri Tikhonov        0x01, 0x00,                 /* First ack block length. */
9250aadb33SDmitri Tikhonov        0x01,                       /* Gap to next block. */
9350aadb33SDmitri Tikhonov        0xaf, 0x0e,                 /* Ack block length. */
9450aadb33SDmitri Tikhonov        0xff,                       /* Gap to next block. */
9550aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Ack block length. */
9650aadb33SDmitri Tikhonov        0x91,                       /* Gap to next block. */
9750aadb33SDmitri Tikhonov        0xea, 0x01,                 /* Ack block length. */
9850aadb33SDmitri Tikhonov        0x05,                       /* Gap to next block. */
9950aadb33SDmitri Tikhonov        0x04, 0x00,                 /* Ack block length. */
10050aadb33SDmitri Tikhonov        0x00,                       /* Number of timestamps. */
10150aadb33SDmitri Tikhonov    };
10250aadb33SDmitri Tikhonov    unsigned char outbuf[0x100];
10350aadb33SDmitri Tikhonov
10450aadb33SDmitri Tikhonov    int has_missing = -1;
10516a9b66aSDmitri Tikhonov    lsquic_packno_t largest = 0;
10650aadb33SDmitri Tikhonov    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
10750aadb33SDmitri Tikhonov        (gaf_rechist_first_f)        lsquic_rechist_first,
10850aadb33SDmitri Tikhonov        (gaf_rechist_next_f)         lsquic_rechist_next,
10950aadb33SDmitri Tikhonov        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
11016a9b66aSDmitri Tikhonov        &rechist, now, &has_missing, &largest);
11150aadb33SDmitri Tikhonov    assert(("ACK frame generation successful", w > 0));
11250aadb33SDmitri Tikhonov    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
11350aadb33SDmitri Tikhonov    assert(("ACK frame contents are as expected",
11450aadb33SDmitri Tikhonov        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
11550aadb33SDmitri Tikhonov    assert(("ACK frame has missing packets", has_missing > 0));
11616a9b66aSDmitri Tikhonov    assert(largest == 0x1234);
11750aadb33SDmitri Tikhonov
11850aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
11950aadb33SDmitri Tikhonov}
12050aadb33SDmitri Tikhonov
12150aadb33SDmitri Tikhonovstatic void
12250aadb33SDmitri Tikhonovtest3 (void)
12350aadb33SDmitri Tikhonov{
12450aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
12550aadb33SDmitri Tikhonov    lsquic_time_t now = lsquic_time_now();
12650aadb33SDmitri Tikhonov
12750aadb33SDmitri Tikhonov    lsquic_rechist_init(&rechist, 0);
12850aadb33SDmitri Tikhonov
12950aadb33SDmitri Tikhonov    /* Encode the following ranges:
13050aadb33SDmitri Tikhonov     *    high      low
13150aadb33SDmitri Tikhonov     *    3         3
13250aadb33SDmitri Tikhonov     *    1         1
13350aadb33SDmitri Tikhonov     */
13450aadb33SDmitri Tikhonov    (void) lsquic_rechist_received(&rechist, 1, now);
13550aadb33SDmitri Tikhonov    (void) lsquic_rechist_received(&rechist, 3, now);
13650aadb33SDmitri Tikhonov
13750aadb33SDmitri Tikhonov    const unsigned char expected_ack_frame[] = {
13850aadb33SDmitri Tikhonov        0x60,
13950aadb33SDmitri Tikhonov        0x03,
14050aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Zero delta time. */
14150aadb33SDmitri Tikhonov        0x01,                       /* Num ack blocks ranges. */
14250aadb33SDmitri Tikhonov        0x01,                       /* First ack block length. */
14350aadb33SDmitri Tikhonov        0x01,                       /* Gap to next block. */
14450aadb33SDmitri Tikhonov        0x01,                       /* Ack block length. */
14550aadb33SDmitri Tikhonov        0x00,                       /* Number of timestamps. */
14650aadb33SDmitri Tikhonov    };
14750aadb33SDmitri Tikhonov    unsigned char outbuf[0x100];
14850aadb33SDmitri Tikhonov
14950aadb33SDmitri Tikhonov    int has_missing = -1;
15016a9b66aSDmitri Tikhonov    lsquic_packno_t largest = 0;
15150aadb33SDmitri Tikhonov    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
15250aadb33SDmitri Tikhonov        (gaf_rechist_first_f)        lsquic_rechist_first,
15350aadb33SDmitri Tikhonov        (gaf_rechist_next_f)         lsquic_rechist_next,
15450aadb33SDmitri Tikhonov        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
15516a9b66aSDmitri Tikhonov        &rechist, now, &has_missing, &largest);
15650aadb33SDmitri Tikhonov    assert(("ACK frame generation successful", w > 0));
15750aadb33SDmitri Tikhonov    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
15850aadb33SDmitri Tikhonov    assert(("ACK frame contents are as expected",
15950aadb33SDmitri Tikhonov        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
16050aadb33SDmitri Tikhonov    assert(("ACK frame has missing packets", has_missing > 0));
16116a9b66aSDmitri Tikhonov    assert(largest == 0x03);
16250aadb33SDmitri Tikhonov
16350aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
16450aadb33SDmitri Tikhonov}
16550aadb33SDmitri Tikhonov
16650aadb33SDmitri Tikhonov
16750aadb33SDmitri Tikhonovstatic void
16850aadb33SDmitri Tikhonovtest4 (void)
16950aadb33SDmitri Tikhonov{
17050aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
17150aadb33SDmitri Tikhonov    int i;
17250aadb33SDmitri Tikhonov
17350aadb33SDmitri Tikhonov    lsquic_rechist_init(&rechist, 0);
17450aadb33SDmitri Tikhonov
17550aadb33SDmitri Tikhonov    lsquic_time_t now = lsquic_time_now();
17650aadb33SDmitri Tikhonov    lsquic_rechist_received(&rechist, 1, now);
17750aadb33SDmitri Tikhonov
17850aadb33SDmitri Tikhonov    {
17950aadb33SDmitri Tikhonov        const unsigned char expected_ack_frame[] = {
18050aadb33SDmitri Tikhonov            0x40,
18150aadb33SDmitri Tikhonov            0x01,                   /* Largest acked */
18250aadb33SDmitri Tikhonov            0x00, 0x00,             /* Delta time */
18350aadb33SDmitri Tikhonov            0x01,                   /* Block length */
18450aadb33SDmitri Tikhonov            0x00,                   /* Number of timestamps */
18550aadb33SDmitri Tikhonov        };
18650aadb33SDmitri Tikhonov        unsigned char outbuf[0x100];
18750aadb33SDmitri Tikhonov        int has_missing = -1;
18816a9b66aSDmitri Tikhonov        lsquic_packno_t largest = 0;
18950aadb33SDmitri Tikhonov        int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
19050aadb33SDmitri Tikhonov            (gaf_rechist_first_f)        lsquic_rechist_first,
19150aadb33SDmitri Tikhonov            (gaf_rechist_next_f)         lsquic_rechist_next,
19250aadb33SDmitri Tikhonov            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
19316a9b66aSDmitri Tikhonov            &rechist, now, &has_missing, &largest);
19450aadb33SDmitri Tikhonov        assert(("ACK frame generation successful", w > 0));
19550aadb33SDmitri Tikhonov        assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
19650aadb33SDmitri Tikhonov        assert(("ACK frame contents are as expected",
19750aadb33SDmitri Tikhonov            0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
19850aadb33SDmitri Tikhonov        assert(("ACK frame has no missing packets", has_missing == 0));
19916a9b66aSDmitri Tikhonov        assert(largest == 1);
20050aadb33SDmitri Tikhonov    }
20150aadb33SDmitri Tikhonov
20250aadb33SDmitri Tikhonov    for (i = 3; i <= 5; ++i)
20350aadb33SDmitri Tikhonov        lsquic_rechist_received(&rechist, i, now);
20450aadb33SDmitri Tikhonov
20550aadb33SDmitri Tikhonov    {
20650aadb33SDmitri Tikhonov        const unsigned char expected_ack_frame[] = {
20750aadb33SDmitri Tikhonov            0x60,
20850aadb33SDmitri Tikhonov            0x05,                   /* Largest acked */
20950aadb33SDmitri Tikhonov            0x00, 0x00,             /* Delta time */
21050aadb33SDmitri Tikhonov            0x01,                   /* Num ack blocks */
21150aadb33SDmitri Tikhonov            0x03,                   /* First block length [3, 5] */
21250aadb33SDmitri Tikhonov            0x01,                   /* Gap to next block */
21350aadb33SDmitri Tikhonov            0x01,                   /* Second block length [1, 1] */
21450aadb33SDmitri Tikhonov            0x00,                   /* Number of timestamps */
21550aadb33SDmitri Tikhonov        };
21650aadb33SDmitri Tikhonov        unsigned char outbuf[0x100];
21750aadb33SDmitri Tikhonov        int has_missing = -1;
21816a9b66aSDmitri Tikhonov        lsquic_packno_t largest = 0;
21950aadb33SDmitri Tikhonov        int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
22050aadb33SDmitri Tikhonov            (gaf_rechist_first_f)        lsquic_rechist_first,
22150aadb33SDmitri Tikhonov            (gaf_rechist_next_f)         lsquic_rechist_next,
22250aadb33SDmitri Tikhonov            (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
22316a9b66aSDmitri Tikhonov            &rechist, now, &has_missing, &largest);
22450aadb33SDmitri Tikhonov        assert(("ACK frame generation successful", w > 0));
22550aadb33SDmitri Tikhonov        assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
22650aadb33SDmitri Tikhonov        assert(("ACK frame contents are as expected",
22750aadb33SDmitri Tikhonov            0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
22850aadb33SDmitri Tikhonov        assert(("ACK frame has missing packets", has_missing > 0));
22916a9b66aSDmitri Tikhonov        assert(largest == 5);
23050aadb33SDmitri Tikhonov    }
23150aadb33SDmitri Tikhonov
23250aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
23350aadb33SDmitri Tikhonov}
23450aadb33SDmitri Tikhonov
23550aadb33SDmitri Tikhonov
23650aadb33SDmitri Tikhonovstatic void
23750aadb33SDmitri Tikhonovtest_4byte_packnos (void)
23850aadb33SDmitri Tikhonov{
23950aadb33SDmitri Tikhonov    lsquic_packno_t packno;
24050aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
24150aadb33SDmitri Tikhonov    struct packet_interval *pint;
24250aadb33SDmitri Tikhonov    lsquic_time_t now = lsquic_time_now();
24350aadb33SDmitri Tikhonov
24450aadb33SDmitri Tikhonov    lsquic_rechist_init(&rechist, 0);
24550aadb33SDmitri Tikhonov
24650aadb33SDmitri Tikhonov    packno = 0x23456789;
24750aadb33SDmitri Tikhonov    (void) lsquic_rechist_received(&rechist, packno - 33, now);
24850aadb33SDmitri Tikhonov    pint = TAILQ_FIRST(&rechist.rh_pints.pk_intervals);
24950aadb33SDmitri Tikhonov    (void) lsquic_rechist_received(&rechist, packno, now);
25050aadb33SDmitri Tikhonov
25150aadb33SDmitri Tikhonov    /* Adjust: */
25250aadb33SDmitri Tikhonov    pint->range.low = 1;
25350aadb33SDmitri Tikhonov
25450aadb33SDmitri Tikhonov    const unsigned char expected_ack_frame[] = {
25550aadb33SDmitri Tikhonov        0x60
25650aadb33SDmitri Tikhonov            | (2 << 2)  /* Four-byte largest acked */
25750aadb33SDmitri Tikhonov            | (2 << 0)  /* Four-byte ACK block length */
25850aadb33SDmitri Tikhonov        ,
25950aadb33SDmitri Tikhonov        0x89, 0x67, 0x45, 0x23,
26050aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Zero delta time. */
26150aadb33SDmitri Tikhonov        0x01,                       /* Num ack blocks ranges. */
26250aadb33SDmitri Tikhonov        0x01, 0x00, 0x00, 0x00,     /* First ack block length. */
26350aadb33SDmitri Tikhonov        33 - 1,                     /* Gap to next block. */
26450aadb33SDmitri Tikhonov        0x68, 0x67, 0x45, 0x23,     /* Ack block length. */
26550aadb33SDmitri Tikhonov        0x00,                       /* Number of timestamps. */
26650aadb33SDmitri Tikhonov    };
26750aadb33SDmitri Tikhonov    unsigned char outbuf[0x100];
26850aadb33SDmitri Tikhonov
26950aadb33SDmitri Tikhonov    int has_missing = -1;
27016a9b66aSDmitri Tikhonov    lsquic_packno_t largest = 0;
27150aadb33SDmitri Tikhonov    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
27250aadb33SDmitri Tikhonov        (gaf_rechist_first_f)        lsquic_rechist_first,
27350aadb33SDmitri Tikhonov        (gaf_rechist_next_f)         lsquic_rechist_next,
27450aadb33SDmitri Tikhonov        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
27516a9b66aSDmitri Tikhonov        &rechist, now, &has_missing, &largest);
27650aadb33SDmitri Tikhonov    assert(("ACK frame generation successful", w > 0));
27750aadb33SDmitri Tikhonov    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
27850aadb33SDmitri Tikhonov    assert(("ACK frame contents are as expected",
27950aadb33SDmitri Tikhonov        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
28050aadb33SDmitri Tikhonov    assert(("ACK frame has missing packets", has_missing > 0));
28116a9b66aSDmitri Tikhonov    assert(largest == 0x23456789);
28250aadb33SDmitri Tikhonov
28350aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
28450aadb33SDmitri Tikhonov}
28550aadb33SDmitri Tikhonov
28650aadb33SDmitri Tikhonov
28750aadb33SDmitri Tikhonovstatic void
28850aadb33SDmitri Tikhonovtest_6byte_packnos (void)
28950aadb33SDmitri Tikhonov{
29050aadb33SDmitri Tikhonov    lsquic_packno_t packno;
29150aadb33SDmitri Tikhonov    lsquic_rechist_t rechist;
29250aadb33SDmitri Tikhonov    struct packet_interval *pint;
29350aadb33SDmitri Tikhonov    lsquic_time_t now = lsquic_time_now();
29450aadb33SDmitri Tikhonov
29550aadb33SDmitri Tikhonov    lsquic_rechist_init(&rechist, 0);
29650aadb33SDmitri Tikhonov
29750aadb33SDmitri Tikhonov    packno = 0xABCD23456789;
29850aadb33SDmitri Tikhonov    (void) lsquic_rechist_received(&rechist, packno - 33, now);
29950aadb33SDmitri Tikhonov    pint = TAILQ_FIRST(&rechist.rh_pints.pk_intervals);
30050aadb33SDmitri Tikhonov    (void) lsquic_rechist_received(&rechist, packno, now);
30150aadb33SDmitri Tikhonov
30250aadb33SDmitri Tikhonov    /* Adjust: */
30350aadb33SDmitri Tikhonov    pint->range.low = 1;
30450aadb33SDmitri Tikhonov
30550aadb33SDmitri Tikhonov    const unsigned char expected_ack_frame[] = {
30650aadb33SDmitri Tikhonov        0x60
30750aadb33SDmitri Tikhonov            | (3 << 2)  /* Six-byte largest acked */
30850aadb33SDmitri Tikhonov            | (3 << 0)  /* Six-byte ACK block length */
30950aadb33SDmitri Tikhonov        ,
31050aadb33SDmitri Tikhonov        0x89, 0x67, 0x45, 0x23, 0xCD, 0xAB,
31150aadb33SDmitri Tikhonov        0x00, 0x00,                 /* Zero delta time. */
31250aadb33SDmitri Tikhonov        0x01,                       /* Num ack blocks ranges. */
31350aadb33SDmitri Tikhonov        0x01, 0x00, 0x00, 0x00, 0x00, 0x00,    /* First ack block length. */
31450aadb33SDmitri Tikhonov        33 - 1,                     /* Gap to next block. */
31550aadb33SDmitri Tikhonov        0x68, 0x67, 0x45, 0x23, 0xCD, 0xAB,   /* Ack block length. */
31650aadb33SDmitri Tikhonov        0x00,                       /* Number of timestamps. */
31750aadb33SDmitri Tikhonov    };
31850aadb33SDmitri Tikhonov    unsigned char outbuf[0x100];
31950aadb33SDmitri Tikhonov
32050aadb33SDmitri Tikhonov    int has_missing = -1;
32116a9b66aSDmitri Tikhonov    lsquic_packno_t largest = 0;
32250aadb33SDmitri Tikhonov    int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
32350aadb33SDmitri Tikhonov        (gaf_rechist_first_f)        lsquic_rechist_first,
32450aadb33SDmitri Tikhonov        (gaf_rechist_next_f)         lsquic_rechist_next,
32550aadb33SDmitri Tikhonov        (gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
32616a9b66aSDmitri Tikhonov        &rechist, now, &has_missing, &largest);
32750aadb33SDmitri Tikhonov    assert(("ACK frame generation successful", w > 0));
32850aadb33SDmitri Tikhonov    assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
32950aadb33SDmitri Tikhonov    assert(("ACK frame contents are as expected",
33050aadb33SDmitri Tikhonov        0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
33150aadb33SDmitri Tikhonov    assert(("ACK frame has missing packets", has_missing > 0));
33216a9b66aSDmitri Tikhonov    assert(largest == 0xABCD23456789ULL);
33350aadb33SDmitri Tikhonov
33450aadb33SDmitri Tikhonov    lsquic_rechist_cleanup(&rechist);
33550aadb33SDmitri Tikhonov}
33650aadb33SDmitri Tikhonov
33750aadb33SDmitri Tikhonov
33850aadb33SDmitri Tikhonov
33950aadb33SDmitri Tikhonovint
34050aadb33SDmitri Tikhonovmain (void)
34150aadb33SDmitri Tikhonov{
342c51ce338SDmitri Tikhonov    lsquic_global_init(LSQUIC_GLOBAL_SERVER);
34350aadb33SDmitri Tikhonov    lsquic_log_to_fstream(stderr, 0);
34450aadb33SDmitri Tikhonov    lsq_log_levels[LSQLM_PARSE]   = LSQ_LOG_DEBUG;
34550aadb33SDmitri Tikhonov
34650aadb33SDmitri Tikhonov    test1();
34750aadb33SDmitri Tikhonov
34850aadb33SDmitri Tikhonov    test2();
34950aadb33SDmitri Tikhonov
35050aadb33SDmitri Tikhonov    test3();
35150aadb33SDmitri Tikhonov
35250aadb33SDmitri Tikhonov    test4();
35350aadb33SDmitri Tikhonov
35450aadb33SDmitri Tikhonov    test_4byte_packnos();
35550aadb33SDmitri Tikhonov
35650aadb33SDmitri Tikhonov    test_6byte_packnos();
35750aadb33SDmitri Tikhonov
35850aadb33SDmitri Tikhonov    return 0;
35950aadb33SDmitri Tikhonov}
360