litespeed-quic/test/unittests/test_ackgen_gquic_be.c

354 lines
12 KiB
C
Raw Normal View History

2017-09-22 21:00:03 +00:00
/* Copyright (c) 2017 LiteSpeed Technologies Inc. See LICENSE. */
/*
* Test how ACK frame is encoded. Receive history module is tested by a
* separate unit test.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lsquic_types.h"
#include "lsquic_int_types.h"
#include "lsquic_rechist.h"
#include "lsquic_parse.h"
#include "lsquic_util.h"
#include "lsquic_logger.h"
#include "lsquic.h"
static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_039);
static void
test1 (void) /* Inverse of quic_framer_test.cc -- NewAckFrameOneAckBlock */
{
lsquic_rechist_t rechist;
lsquic_time_t now = lsquic_time_now();
lsquic_rechist_init(&rechist, 0);
unsigned i;
for (i = 1; i <= 0x1234; ++i)
(void) lsquic_rechist_received(&rechist, i, now);
const unsigned char expected_ack_frame[] = {
0x45,
0x12, 0x34, /* Largest acked */
0x87, 0xFF, /* Delta time */
0x12, 0x34, /* Block length */
0x00, /* Number of timestamps */
};
unsigned char outbuf[0x100];
int has_missing = -1;
int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
(gaf_rechist_first_f) lsquic_rechist_first,
(gaf_rechist_next_f) lsquic_rechist_next,
(gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
&rechist, now + 0x7FF8000, &has_missing);
assert(("ACK frame generation successful", w > 0));
assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
assert(("ACK frame contents are as expected",
0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
assert(("ACK frame has no missing packets", has_missing == 0));
lsquic_packno_t ack_high = pf->pf_parse_ack_high(outbuf, sizeof(outbuf));
assert(0x1234 == ack_high);
lsquic_rechist_cleanup(&rechist);
}
static void
test2 (void) /* Inverse of quic_framer_test.cc -- NewAckFrameOneAckBlock, minus
* delta times.
*/
{
lsquic_rechist_t rechist;
lsquic_time_t now = lsquic_time_now();
lsquic_rechist_init(&rechist, 0);
/* Encode the following ranges:
* high low
* 0x1234 0x1234
* 0x1232 0x384
* 0x1F3 0xA
* 0x4 0x1
*/
unsigned i;
for (i = 4; i >= 1; --i)
(void) lsquic_rechist_received(&rechist, i, now);
(void) lsquic_rechist_received(&rechist, 0x1234, now);
for (i = 0xA; i <= 0x1F3; ++i)
(void) lsquic_rechist_received(&rechist, i, now);
for (i = 0x1232; i >= 0x384; --i)
(void) lsquic_rechist_received(&rechist, i, now);
const unsigned char expected_ack_frame[] = {
0x65,
0x12, 0x34, /* Largest acked */
0x00, 0x00, /* Zero delta time. */
0x04, /* Num ack blocks ranges. */
0x00, 0x01, /* First ack block length. */
0x01, /* Gap to next block. */
0x0e, 0xaf, /* Ack block length. */
0xff, /* Gap to next block. */
0x00, 0x00, /* Ack block length. */
0x91, /* Gap to next block. */
0x01, 0xea, /* Ack block length. */
0x05, /* Gap to next block. */
0x00, 0x04, /* Ack block length. */
0x00, /* Number of timestamps. */
};
unsigned char outbuf[0x100];
int has_missing = -1;
int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
(gaf_rechist_first_f) lsquic_rechist_first,
(gaf_rechist_next_f) lsquic_rechist_next,
(gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
&rechist, now, &has_missing);
assert(("ACK frame generation successful", w > 0));
assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
assert(("ACK frame contents are as expected",
0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
assert(("ACK frame has missing packets", has_missing > 0));
lsquic_packno_t ack_high = pf->pf_parse_ack_high(outbuf, sizeof(outbuf));
assert(0x1234 == ack_high);
lsquic_rechist_cleanup(&rechist);
}
static void
test3 (void)
{
lsquic_rechist_t rechist;
lsquic_time_t now = lsquic_time_now();
lsquic_rechist_init(&rechist, 0);
/* Encode the following ranges:
* high low
* 3 3
* 1 1
*/
(void) lsquic_rechist_received(&rechist, 1, now);
(void) lsquic_rechist_received(&rechist, 3, now);
const unsigned char expected_ack_frame[] = {
0x60,
0x03,
0x00, 0x00, /* Zero delta time. */
0x01, /* Num ack blocks ranges. */
0x01, /* First ack block length. */
0x01, /* Gap to next block. */
0x01, /* Ack block length. */
0x00, /* Number of timestamps. */
};
unsigned char outbuf[0x100];
int has_missing = -1;
int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
(gaf_rechist_first_f) lsquic_rechist_first,
(gaf_rechist_next_f) lsquic_rechist_next,
(gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
&rechist, now, &has_missing);
assert(("ACK frame generation successful", w > 0));
assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
assert(("ACK frame contents are as expected",
0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
assert(("ACK frame has missing packets", has_missing > 0));
lsquic_packno_t ack_high = pf->pf_parse_ack_high(outbuf, sizeof(outbuf));
assert(3 == ack_high);
lsquic_rechist_cleanup(&rechist);
}
static void
test4 (void)
{
lsquic_rechist_t rechist;
int i;
lsquic_rechist_init(&rechist, 0);
lsquic_time_t now = lsquic_time_now();
lsquic_rechist_received(&rechist, 1, now);
{
const unsigned char expected_ack_frame[] = {
0x40,
0x01, /* Largest acked */
0x00, 0x00, /* Delta time */
0x01, /* Block length */
0x00, /* Number of timestamps */
};
unsigned char outbuf[0x100];
int has_missing = -1;
int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
(gaf_rechist_first_f) lsquic_rechist_first,
(gaf_rechist_next_f) lsquic_rechist_next,
(gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
&rechist, now, &has_missing);
assert(("ACK frame generation successful", w > 0));
assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
assert(("ACK frame contents are as expected",
0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
assert(("ACK frame has no missing packets", has_missing == 0));
lsquic_packno_t ack_high = pf->pf_parse_ack_high(outbuf, sizeof(outbuf));
assert(1 == ack_high);
}
for (i = 3; i <= 5; ++i)
lsquic_rechist_received(&rechist, i, now);
{
const unsigned char expected_ack_frame[] = {
0x60,
0x05, /* Largest acked */
0x00, 0x00, /* Delta time */
0x01, /* Num ack blocks */
0x03, /* First block length [3, 5] */
0x01, /* Gap to next block */
0x01, /* Second block length [1, 1] */
0x00, /* Number of timestamps */
};
unsigned char outbuf[0x100];
int has_missing = -1;
int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
(gaf_rechist_first_f) lsquic_rechist_first,
(gaf_rechist_next_f) lsquic_rechist_next,
(gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
&rechist, now, &has_missing);
assert(("ACK frame generation successful", w > 0));
assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
assert(("ACK frame contents are as expected",
0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
assert(("ACK frame has missing packets", has_missing > 0));
lsquic_packno_t ack_high = pf->pf_parse_ack_high(outbuf, sizeof(outbuf));
assert(5 == ack_high);
}
lsquic_rechist_cleanup(&rechist);
}
static void
test_4byte_packnos (void)
{
lsquic_packno_t packno;
lsquic_rechist_t rechist;
struct packet_interval *pint;
lsquic_time_t now = lsquic_time_now();
lsquic_rechist_init(&rechist, 0);
packno = 0x23456789;
(void) lsquic_rechist_received(&rechist, packno - 33, now);
pint = TAILQ_FIRST(&rechist.rh_pints.pk_intervals);
(void) lsquic_rechist_received(&rechist, packno, now);
/* Adjust: */
pint->range.low = 1;
const unsigned char expected_ack_frame[] = {
0x60
| (2 << 2) /* Four-byte largest acked */
| (2 << 0) /* Four-byte ACK block length */
,
0x23, 0x45, 0x67, 0x89,
0x00, 0x00, /* Zero delta time. */
0x01, /* Num ack blocks ranges. */
0x00, 0x00, 0x00, 0x01, /* First ack block length. */
33 - 1, /* Gap to next block. */
0x23, 0x45, 0x67, 0x68, /* Ack block length. */
0x00, /* Number of timestamps. */
};
unsigned char outbuf[0x100];
int has_missing = -1;
int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
(gaf_rechist_first_f) lsquic_rechist_first,
(gaf_rechist_next_f) lsquic_rechist_next,
(gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
&rechist, now, &has_missing);
assert(("ACK frame generation successful", w > 0));
assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
assert(("ACK frame contents are as expected",
0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
assert(("ACK frame has missing packets", has_missing > 0));
lsquic_rechist_cleanup(&rechist);
}
static void
test_6byte_packnos (void)
{
lsquic_packno_t packno;
lsquic_rechist_t rechist;
struct packet_interval *pint;
lsquic_time_t now = lsquic_time_now();
lsquic_rechist_init(&rechist, 0);
packno = 0xABCD23456789;
(void) lsquic_rechist_received(&rechist, packno - 33, now);
pint = TAILQ_FIRST(&rechist.rh_pints.pk_intervals);
(void) lsquic_rechist_received(&rechist, packno, now);
/* Adjust: */
pint->range.low = 1;
const unsigned char expected_ack_frame[] = {
0x60
| (3 << 2) /* Six-byte largest acked */
| (3 << 0) /* Six-byte ACK block length */
,
0xAB, 0xCD, 0x23, 0x45, 0x67, 0x89,
0x00, 0x00, /* Zero delta time. */
0x01, /* Num ack blocks ranges. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* First ack block length. */
33 - 1, /* Gap to next block. */
0xAB, 0xCD, 0x23, 0x45, 0x67, 0x68, /* Ack block length. */
0x00, /* Number of timestamps. */
};
unsigned char outbuf[0x100];
int has_missing = -1;
int w = pf->pf_gen_ack_frame(outbuf, sizeof(outbuf),
(gaf_rechist_first_f) lsquic_rechist_first,
(gaf_rechist_next_f) lsquic_rechist_next,
(gaf_rechist_largest_recv_f) lsquic_rechist_largest_recv,
&rechist, now, &has_missing);
assert(("ACK frame generation successful", w > 0));
assert(("ACK frame length is correct", w == sizeof(expected_ack_frame)));
assert(("ACK frame contents are as expected",
0 == memcmp(outbuf, expected_ack_frame, sizeof(expected_ack_frame))));
assert(("ACK frame has missing packets", has_missing > 0));
lsquic_rechist_cleanup(&rechist);
}
int
main (void)
{
lsquic_log_to_fstream(stderr, 0);
lsq_log_levels[LSQLM_PARSE] = LSQ_LOG_DEBUG;
test1();
test2();
test3();
test4();
test_4byte_packnos();
test_6byte_packnos();
return 0;
}