1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
2de46bf2fSDmitri Tikhonov/* Test ACK merge */
3de46bf2fSDmitri Tikhonov
4de46bf2fSDmitri Tikhonov#include <assert.h>
5de46bf2fSDmitri Tikhonov#include <regex.h>
6de46bf2fSDmitri Tikhonov#include <stdlib.h>
7de46bf2fSDmitri Tikhonov#include <string.h>
8de46bf2fSDmitri Tikhonov
9de46bf2fSDmitri Tikhonov#include "lsquic.h"
10de46bf2fSDmitri Tikhonov#include "lsquic_types.h"
11de46bf2fSDmitri Tikhonov#include "lsquic_int_types.h"
12de46bf2fSDmitri Tikhonov#include "lsquic_sizes.h"
13de46bf2fSDmitri Tikhonov#include "lsquic_parse.h"
14de46bf2fSDmitri Tikhonov
15de46bf2fSDmitri Tikhonovstruct test
16de46bf2fSDmitri Tikhonov{
17de46bf2fSDmitri Tikhonov    int                 lineno;
18de46bf2fSDmitri Tikhonov    int                 expect_failure;
19de46bf2fSDmitri Tikhonov    char                a[MAX_ACKI_STR_SZ];
20de46bf2fSDmitri Tikhonov    char                b[MAX_ACKI_STR_SZ];
21de46bf2fSDmitri Tikhonov    char                result[MAX_ACKI_STR_SZ];
22de46bf2fSDmitri Tikhonov};
23de46bf2fSDmitri Tikhonov
24de46bf2fSDmitri Tikhonov
25de46bf2fSDmitri Tikhonovstatic const struct test tests[] =
26de46bf2fSDmitri Tikhonov{
27de46bf2fSDmitri Tikhonov
28de46bf2fSDmitri Tikhonov    {
29de46bf2fSDmitri Tikhonov        .lineno     = __LINE__,
30de46bf2fSDmitri Tikhonov        .expect_failure = 1,
31de46bf2fSDmitri Tikhonov        .a          = "",
32de46bf2fSDmitri Tikhonov        .b          = "[3-3]",
33de46bf2fSDmitri Tikhonov    },
34de46bf2fSDmitri Tikhonov
35de46bf2fSDmitri Tikhonov    {
36de46bf2fSDmitri Tikhonov        .lineno     = __LINE__,
37de46bf2fSDmitri Tikhonov        .expect_failure = 1,
38de46bf2fSDmitri Tikhonov        .a          = "",
39de46bf2fSDmitri Tikhonov        .b          = "",
40de46bf2fSDmitri Tikhonov    },
41de46bf2fSDmitri Tikhonov
42de46bf2fSDmitri Tikhonov    {
43de46bf2fSDmitri Tikhonov        .lineno     = __LINE__,
44de46bf2fSDmitri Tikhonov        .a          = "[3-3]",
45de46bf2fSDmitri Tikhonov        .b          = "[3-3]",
46de46bf2fSDmitri Tikhonov        .result     = "[3-3]",
47de46bf2fSDmitri Tikhonov    },
48de46bf2fSDmitri Tikhonov
49de46bf2fSDmitri Tikhonov    {
50de46bf2fSDmitri Tikhonov        .lineno     = __LINE__,
51de46bf2fSDmitri Tikhonov        .a          = "[3-2]",
52de46bf2fSDmitri Tikhonov        .b          = "[1-1]",
53de46bf2fSDmitri Tikhonov        .result     = "[3-1]",
54de46bf2fSDmitri Tikhonov    },
55de46bf2fSDmitri Tikhonov
56de46bf2fSDmitri Tikhonov    {
57de46bf2fSDmitri Tikhonov        .lineno     = __LINE__,
58de46bf2fSDmitri Tikhonov        .a          = "[15-15][3-2]",
59de46bf2fSDmitri Tikhonov        .b          = "[1-1]",
60de46bf2fSDmitri Tikhonov        .result     = "[15-15][3-1]",
61de46bf2fSDmitri Tikhonov    },
62de46bf2fSDmitri Tikhonov
63de46bf2fSDmitri Tikhonov    {
64de46bf2fSDmitri Tikhonov        .lineno     = __LINE__,
65de46bf2fSDmitri Tikhonov        .a          = "[15-10][5-2]",
66de46bf2fSDmitri Tikhonov        .b          = "[9-6][1-1]",
67de46bf2fSDmitri Tikhonov        .result     = "[15-1]",
68de46bf2fSDmitri Tikhonov    },
69de46bf2fSDmitri Tikhonov
70de46bf2fSDmitri Tikhonov    {
71de46bf2fSDmitri Tikhonov        .lineno     = __LINE__,
72de46bf2fSDmitri Tikhonov        .a          = "[15-10][5-2]",
73de46bf2fSDmitri Tikhonov        .b          = "[15-10][5-2]",
74de46bf2fSDmitri Tikhonov        .result     = "[15-10][5-2]",
75de46bf2fSDmitri Tikhonov    },
76de46bf2fSDmitri Tikhonov
77de46bf2fSDmitri Tikhonov    {
78de46bf2fSDmitri Tikhonov        .lineno     = __LINE__,
79de46bf2fSDmitri Tikhonov        .a          = "[33803-33803][33800-33800][33788-33788][33775-33775][33759-33759][33744-33744][33732-33732][33717-33717][33706-33706][33691-33691][33679-33679][33664-33664][33649-33649][33638-33638][33622-33622][33613-33613][33585-33585][33574-33574][33562-33562][33546-33546][33531-33531][33516-33516][33504-33504][33490-33490][33483-33483][33481-32910][32906-32906][32894-32894][32880-32880][32869-32869][32854-32854][32844-32844][32817-32817][32806-32806][32791-32791][32780-32780][32766-32766][32752-32752][32741-32741][32726-32726][32716-32716][32702-32702][32697-32697][32682-32682][32672-32672][32657-32657][32651-32651][32636-32636][32626-32626][32611-32611][32600-32600][32589-32589][32574-32574][32564-32564][32551-32551][32536-32536][32525-32525][32511-32511][32500-32500][32485-32485][32475-32475][32460-32460][32449-32449][32438-32438][32423-32423][32412-32412][32399-32399][32385-32385][32375-32375][32360-32360][32349-32349][32334-32334][32326-32326][32312-32312][32302-32302][32287-32287][32277-32277][32262-32262][32252-32252][32239-32239][32224-32224][32214-32214][32200-32200][32190-32190][32175-32175][32161-32161][32151-32151][32136-32136][32126-32126][32111-32111][32103-32103][32090-32090][32080-32080][32069-32033][32008-30698][30696-30467]",
80de46bf2fSDmitri Tikhonov        .b          = "[33480-32910][32906-32906][32894-32894][32880-32880][32869-32869][32854-32854][32844-32844][32817-32817][32806-32806][32791-32791][32780-32780][32766-32766][32752-32752][32741-32741][32726-32726][32716-32716][32702-32702][32697-32697][32682-32682][32672-32672][32657-32657][32651-32651][32636-32636][32626-32626][32611-32611][32600-32600][32589-32589][32574-32574][32564-32564][32551-32551][32536-32536][32525-32525][32511-32511][32500-32500][32485-32485][32475-32475][32460-32460][32449-32449][32438-32438][32423-32423][32412-32412][32399-32399][32385-32385][32375-32375][32360-32360][32349-32349][32334-32334][32326-32326][32312-32312][32302-32302][32287-32287][32277-32277][32262-32262][32252-32252][32239-32239][32224-32224][32214-32214][32200-32200][32190-32190][32175-32175][32161-32161][32151-32151][32136-32136][32126-32126][32111-32111][32103-32103][32090-32090][32080-32080][32069-32033][32008-30698][30696-30467]",
81de46bf2fSDmitri Tikhonov        .result     = "[33803-33803][33800-33800][33788-33788][33775-33775][33759-33759][33744-33744][33732-33732][33717-33717][33706-33706][33691-33691][33679-33679][33664-33664][33649-33649][33638-33638][33622-33622][33613-33613][33585-33585][33574-33574][33562-33562][33546-33546][33531-33531][33516-33516][33504-33504][33490-33490][33483-33483][33481-32910][32906-32906][32894-32894][32880-32880][32869-32869][32854-32854][32844-32844][32817-32817][32806-32806][32791-32791][32780-32780][32766-32766][32752-32752][32741-32741][32726-32726][32716-32716][32702-32702][32697-32697][32682-32682][32672-32672][32657-32657][32651-32651][32636-32636][32626-32626][32611-32611][32600-32600][32589-32589][32574-32574][32564-32564][32551-32551][32536-32536][32525-32525][32511-32511][32500-32500][32485-32485][32475-32475][32460-32460][32449-32449][32438-32438][32423-32423][32412-32412][32399-32399][32385-32385][32375-32375][32360-32360][32349-32349][32334-32334][32326-32326][32312-32312][32302-32302][32287-32287][32277-32277][32262-32262][32252-32252][32239-32239][32224-32224][32214-32214][32200-32200][32190-32190][32175-32175][32161-32161][32151-32151][32136-32136][32126-32126][32111-32111][32103-32103][32090-32090][32080-32080][32069-32033][32008-30698][30696-30467]",
82de46bf2fSDmitri Tikhonov    },
83de46bf2fSDmitri Tikhonov
84de46bf2fSDmitri Tikhonov};
85de46bf2fSDmitri Tikhonov
86de46bf2fSDmitri Tikhonov
87de46bf2fSDmitri Tikhonovstatic regex_t re;
88de46bf2fSDmitri Tikhonov
89de46bf2fSDmitri Tikhonov
90de46bf2fSDmitri Tikhonovstatic void
91de46bf2fSDmitri Tikhonovinit_ranges (struct ack_info *a, const char *s)
92de46bf2fSDmitri Tikhonov{
93de46bf2fSDmitri Tikhonov    regmatch_t m[3];
94de46bf2fSDmitri Tikhonov
95de46bf2fSDmitri Tikhonov    while (0 == regexec(&re, s, sizeof(m) / sizeof(m[0]), m, 0))
96de46bf2fSDmitri Tikhonov    {
97de46bf2fSDmitri Tikhonov        a->ranges[a->n_ranges].high = atoi(s + m[1].rm_so);
98de46bf2fSDmitri Tikhonov        a->ranges[a->n_ranges].low  = atoi(s + m[2].rm_so);
99de46bf2fSDmitri Tikhonov        /* Self-check: */
100de46bf2fSDmitri Tikhonov        assert(a->ranges[a->n_ranges].high >= a->ranges[a->n_ranges].low);
101de46bf2fSDmitri Tikhonov        ++a->n_ranges;
102de46bf2fSDmitri Tikhonov        s += m[0].rm_eo;
103de46bf2fSDmitri Tikhonov    }
104de46bf2fSDmitri Tikhonov}
105de46bf2fSDmitri Tikhonov
106de46bf2fSDmitri Tikhonov
107de46bf2fSDmitri Tikhonovstatic void
108de46bf2fSDmitri Tikhonovrun_test_ext (const struct test *test, const char *a_str, const char *b_str)
109de46bf2fSDmitri Tikhonov{
110de46bf2fSDmitri Tikhonov    struct ack_info a, b;
111de46bf2fSDmitri Tikhonov    int s;
112de46bf2fSDmitri Tikhonov    char ack_str[MAX_ACKI_STR_SZ];
113de46bf2fSDmitri Tikhonov
114de46bf2fSDmitri Tikhonov    memset(&a, 0, sizeof(a));
115de46bf2fSDmitri Tikhonov    memset(&b, 0, sizeof(b));
116de46bf2fSDmitri Tikhonov
117de46bf2fSDmitri Tikhonov    init_ranges(&a, a_str);
118de46bf2fSDmitri Tikhonov    init_ranges(&b, b_str);
119de46bf2fSDmitri Tikhonov
120de46bf2fSDmitri Tikhonov    s = lsquic_merge_acks(&a, &b);
121de46bf2fSDmitri Tikhonov    if (test->expect_failure)
122de46bf2fSDmitri Tikhonov    {
123de46bf2fSDmitri Tikhonov        assert(s != 0);
124de46bf2fSDmitri Tikhonov        return;
125de46bf2fSDmitri Tikhonov    }
126de46bf2fSDmitri Tikhonov
127de46bf2fSDmitri Tikhonov    assert(s == 0);
128de46bf2fSDmitri Tikhonov    lsquic_acki2str(&a, ack_str, sizeof(ack_str));
129de46bf2fSDmitri Tikhonov    assert(0 == strcmp(ack_str, test->result));
130de46bf2fSDmitri Tikhonov}
131de46bf2fSDmitri Tikhonov
132de46bf2fSDmitri Tikhonov
133de46bf2fSDmitri Tikhonovstatic void
134de46bf2fSDmitri Tikhonovrun_test (const struct test *test)
135de46bf2fSDmitri Tikhonov{
136de46bf2fSDmitri Tikhonov    run_test_ext(test, test->a, test->b);
137de46bf2fSDmitri Tikhonov    /* If flipped result should be the same: */
138de46bf2fSDmitri Tikhonov    run_test_ext(test, test->b, test->a);
139de46bf2fSDmitri Tikhonov}
140de46bf2fSDmitri Tikhonov
141de46bf2fSDmitri Tikhonov
142de46bf2fSDmitri Tikhonovstatic void
143de46bf2fSDmitri Tikhonovtest_out_of_ranges (int success)
144de46bf2fSDmitri Tikhonov{
145de46bf2fSDmitri Tikhonov    struct ack_info a, b;
146de46bf2fSDmitri Tikhonov    int i, s;
147de46bf2fSDmitri Tikhonov
148de46bf2fSDmitri Tikhonov    memset(&a, 0, sizeof(a));
149de46bf2fSDmitri Tikhonov    memset(&b, 0, sizeof(b));
150de46bf2fSDmitri Tikhonov
151de46bf2fSDmitri Tikhonov    for (i = 0; i < 129 - success; ++i)
152de46bf2fSDmitri Tikhonov    {
153de46bf2fSDmitri Tikhonov        a.ranges[i].high = a.ranges[i].low = 100000 - i * 10;
154de46bf2fSDmitri Tikhonov        b.ranges[i].high = b.ranges[i].low = 100000 - 5 - i * 10;
155de46bf2fSDmitri Tikhonov    }
156de46bf2fSDmitri Tikhonov    a.n_ranges = i;
157de46bf2fSDmitri Tikhonov    b.n_ranges = i;
158de46bf2fSDmitri Tikhonov
159de46bf2fSDmitri Tikhonov    s = lsquic_merge_acks(&a, &b);
160de46bf2fSDmitri Tikhonov    if (success)
161de46bf2fSDmitri Tikhonov        assert(s == 0);
162de46bf2fSDmitri Tikhonov    else
163de46bf2fSDmitri Tikhonov        assert(s != 0);
164de46bf2fSDmitri Tikhonov}
165de46bf2fSDmitri Tikhonov
166de46bf2fSDmitri Tikhonov
167de46bf2fSDmitri Tikhonovint
168de46bf2fSDmitri Tikhonovmain (void)
169de46bf2fSDmitri Tikhonov{
170de46bf2fSDmitri Tikhonov    const struct test *test;
171de46bf2fSDmitri Tikhonov    int s;
172de46bf2fSDmitri Tikhonov
173de46bf2fSDmitri Tikhonov    s = regcomp(&re, "\\[([0-9][0-9]*)-([0-9][0-9]*)\\]", REG_EXTENDED);
174de46bf2fSDmitri Tikhonov    assert(s == 0);
175de46bf2fSDmitri Tikhonov
176de46bf2fSDmitri Tikhonov    for (test = tests; test < tests + sizeof(tests) / sizeof(tests[0]); ++test)
177de46bf2fSDmitri Tikhonov        run_test(test);
178de46bf2fSDmitri Tikhonov
179de46bf2fSDmitri Tikhonov    test_out_of_ranges(0);
180de46bf2fSDmitri Tikhonov    test_out_of_ranges(1);
181de46bf2fSDmitri Tikhonov
182de46bf2fSDmitri Tikhonov    regfree(&re);
183de46bf2fSDmitri Tikhonov
184de46bf2fSDmitri Tikhonov    return 0;
185de46bf2fSDmitri Tikhonov}
186