test_rechist.c revision f38b395a
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc.  See LICENSE. */
2#include <assert.h>
3#include <inttypes.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7
8#ifdef WIN32
9#include "vc_compat.h"
10#endif
11
12#include "lsquic_int_types.h"
13#include "lsquic_rechist.h"
14#include "lsquic_util.h"
15
16
17static void
18test4 (void)
19{
20    lsquic_rechist_t rechist;
21    const struct lsquic_packno_range *range;
22    lsquic_packno_t packno;
23
24    lsquic_rechist_init(&rechist, 0, 0);
25
26    for (packno = 11917; packno <= 11941; ++packno)
27        lsquic_rechist_received(&rechist, packno, 0);
28    for (packno = 11946; packno <= 11994; ++packno)
29        lsquic_rechist_received(&rechist, packno, 0);
30
31    range = lsquic_rechist_first(&rechist);
32    assert(range);
33    assert(range->high == 11994);
34    assert(range->low == 11946);
35    range = lsquic_rechist_next(&rechist);
36    assert(range);
37    assert(range->high == 11941);
38    assert(range->low == 11917);
39    range = lsquic_rechist_next(&rechist);
40    assert(!range);
41
42    lsquic_rechist_received(&rechist, 11995, 0);
43    lsquic_rechist_received(&rechist, 11996, 0);
44
45    range = lsquic_rechist_first(&rechist);
46    assert(range);
47    assert(range->high == 11996);
48    assert(range->low == 11946);
49    range = lsquic_rechist_next(&rechist);
50    assert(range);
51    assert(range->high == 11941);
52    assert(range->low == 11917);
53    range = lsquic_rechist_next(&rechist);
54    assert(!range);
55
56    lsquic_rechist_received(&rechist, 11912, 0);
57    lsquic_rechist_stop_wait(&rechist, 11860);
58
59    range = lsquic_rechist_first(&rechist);
60    assert(range);
61    assert(range->high == 11996);
62    assert(range->low == 11946);
63    range = lsquic_rechist_next(&rechist);
64    assert(range);
65    assert(range->high == 11941);
66    assert(range->low == 11917);
67    range = lsquic_rechist_next(&rechist);
68    assert(range);
69    assert(range->high == 11912);
70    assert(range->low == 11912);
71    range = lsquic_rechist_next(&rechist);
72    assert(!range);
73
74    for (packno = 12169; packno <= 12193; ++packno)
75        lsquic_rechist_received(&rechist, packno, 0);
76
77    range = lsquic_rechist_first(&rechist);
78    assert(range);
79    assert(range->high == 12193);
80    assert(range->low == 12169);
81    range = lsquic_rechist_next(&rechist);
82    assert(range);
83    assert(range->high == 11996);
84    assert(range->low == 11946);
85    range = lsquic_rechist_next(&rechist);
86    assert(range);
87    assert(range->high == 11941);
88    assert(range->low == 11917);
89    range = lsquic_rechist_next(&rechist);
90    assert(range);
91    assert(range->high == 11912);
92    assert(range->low == 11912);
93    range = lsquic_rechist_next(&rechist);
94    assert(!range);
95
96    lsquic_rechist_cleanup(&rechist);
97}
98
99
100static void
101rechist2str (lsquic_rechist_t *rechist, char *buf, size_t bufsz)
102{
103    const struct lsquic_packno_range *range;
104    size_t off;
105    int n;
106
107    for (off = 0, range = lsquic_rechist_first(rechist);
108            range && off < bufsz;
109                off += n, range = lsquic_rechist_next(rechist))
110    {
111        n = snprintf(buf + off, bufsz - off, "[%"PRIu64"-%"PRIu64"]",
112                                                    range->high, range->low);
113        if (n < 0 || (size_t) n >= bufsz - off)
114            break;
115    }
116}
117
118
119static void
120test5 (void)
121{
122    lsquic_rechist_t rechist;
123    char buf[100];
124
125    lsquic_rechist_init(&rechist, 0, 0);
126
127    lsquic_rechist_received(&rechist, 1, 0);
128    /* Packet 2 omitted because it could not be decrypted */
129    lsquic_rechist_received(&rechist, 3, 0);
130    lsquic_rechist_received(&rechist, 12, 0);
131
132    rechist2str(&rechist, buf, sizeof(buf));
133    assert(0 == strcmp(buf, "[12-12][3-3][1-1]"));
134
135    lsquic_rechist_received(&rechist, 4, 0);
136    lsquic_rechist_received(&rechist, 10, 0);
137
138    rechist2str(&rechist, buf, sizeof(buf));
139    assert(0 == strcmp(buf, "[12-12][10-10][4-3][1-1]"));
140
141    lsquic_rechist_received(&rechist, 6, 0);
142
143    rechist2str(&rechist, buf, sizeof(buf));
144    assert(0 == strcmp(buf, "[12-12][10-10][6-6][4-3][1-1]"));
145
146    lsquic_rechist_received(&rechist, 7, 0);
147    lsquic_rechist_received(&rechist, 8, 0);
148
149    rechist2str(&rechist, buf, sizeof(buf));
150    assert(0 == strcmp(buf, "[12-12][10-10][8-6][4-3][1-1]"));
151
152    lsquic_rechist_received(&rechist, 9, 0);
153
154    rechist2str(&rechist, buf, sizeof(buf));
155    assert(0 == strcmp(buf, "[12-12][10-6][4-3][1-1]"));
156
157    lsquic_rechist_received(&rechist, 5, 0);
158    lsquic_rechist_received(&rechist, 11, 0);
159
160    rechist2str(&rechist, buf, sizeof(buf));
161    assert(0 == strcmp(buf, "[12-3][1-1]"));
162
163    lsquic_rechist_cleanup(&rechist);
164}
165
166
167static void
168test_rand_sequence (unsigned seed, unsigned max)
169{
170    struct lsquic_rechist rechist;
171    const struct lsquic_packno_range *range;
172    lsquic_packno_t prev_low;
173    enum received_st st;
174    unsigned i, count;
175
176    lsquic_rechist_init(&rechist, 1, max);
177    srand(seed);
178
179    for (i = 0; i < 10000; ++i)
180    {
181        st = lsquic_rechist_received(&rechist, (unsigned) rand(), 0);
182        assert(st == REC_ST_OK || st == REC_ST_DUP);
183    }
184
185    range = lsquic_rechist_first(&rechist);
186    assert(range);
187    assert(range->high >= range->low);
188    prev_low = range->low;
189    count = 1;
190
191    while (range = lsquic_rechist_next(&rechist), range != NULL)
192    {
193        ++count;
194        assert(range->high >= range->low);
195        assert(range->high < prev_low);
196        prev_low = range->low;
197    }
198    if (max)
199        assert(count <= max);
200
201    lsquic_rechist_cleanup(&rechist);
202}
203
204
205struct shuffle_elem {
206    unsigned    packno;
207    int         rand;
208};
209
210
211static int
212comp_els (const void *a_p, const void *b_p)
213{
214    const struct shuffle_elem *a = a_p, *b = b_p;
215    if (a->rand < b->rand)
216        return -1;
217    if (a->rand > b->rand)
218        return 1;
219    return (a->packno > b->packno) - (b->packno > a->packno);
220}
221
222
223static void
224test_shuffle_1000 (unsigned seed)
225{
226    struct lsquic_rechist rechist;
227    const struct lsquic_packno_range *range;
228    enum received_st st;
229    unsigned i;
230    struct shuffle_elem *els;
231
232    els = malloc(sizeof(els[0]) * 10000);
233    lsquic_rechist_init(&rechist, 1, 0);
234    srand(seed);
235
236    for (i = 0; i < 10000; ++i)
237    {
238        els[i].packno = i;
239        els[i].rand   = rand();
240    }
241
242    qsort(els, 10000, sizeof(els[0]), comp_els);
243
244    for (i = 0; i < 10000; ++i)
245    {
246        st = lsquic_rechist_received(&rechist, els[i].packno, 0);
247        assert(st == REC_ST_OK || st == REC_ST_DUP);
248    }
249
250    range = lsquic_rechist_first(&rechist);
251    assert(range);
252    assert(range->high == 9999);
253    assert(range->low == 0);
254    range = lsquic_rechist_next(&rechist);
255    assert(!range);
256
257    lsquic_rechist_cleanup(&rechist);
258    free(els);
259}
260
261
262int
263main (void)
264{
265    enum received_st st;
266    lsquic_rechist_t rechist;
267    unsigned i;
268    const struct lsquic_packno_range *range;
269
270    lsquic_rechist_init(&rechist, 0, 0);
271
272    lsquic_time_t now = 1234;
273    st = lsquic_rechist_received(&rechist, 0, now);
274    assert(("inserting packet number zero results in error", st == REC_ST_ERR));
275
276    st = lsquic_rechist_received(&rechist, 1, now);
277    assert(("inserting packet number one is successful", st == REC_ST_OK));
278
279    st = lsquic_rechist_received(&rechist, 1, now);
280    assert(("inserting packet number one again results in duplicate error",
281                                                            st == REC_ST_DUP));
282
283    range = lsquic_rechist_first(&rechist);
284    assert(("first range returned correctly", range));
285    assert(("first range low value checks out", range->low == 1));
286    assert(("first range high value checks out", range->high == 1));
287    range = lsquic_rechist_next(&rechist);
288    assert(("second range does not exist", !range));
289
290    for (i = 3; i <= 5; ++i)
291    {
292        st = lsquic_rechist_received(&rechist, i, now);
293        assert(("inserting packet", st == REC_ST_OK));
294    }
295
296    range = lsquic_rechist_first(&rechist);
297    assert(("first range returned correctly", range));
298    assert(("first range low value checks out", range->low == 3));
299    assert(("first range high value checks out", range->high == 5));
300    range = lsquic_rechist_next(&rechist);
301    assert(("second range returned correctly", range));
302    assert(("second range low value checks out", range->low == 1));
303    assert(("second range high value checks out", range->high == 1));
304    range = lsquic_rechist_next(&rechist);
305    assert(("third range does not exist", !range));
306
307    lsquic_rechist_stop_wait(&rechist, 3);
308
309    st = lsquic_rechist_received(&rechist, 1, now);
310    assert(("inserting packet number one is unsuccessful after cutoff 3",
311                                                            st == REC_ST_DUP));
312
313    range = lsquic_rechist_first(&rechist);
314    assert(("first range returned correctly", range));
315    assert(("first range low value checks out", range->low == 3));
316    assert(("first range high value checks out", range->high == 5));
317    range = lsquic_rechist_next(&rechist);
318    assert(("second range does not exist", !range));
319
320    for (i = 9; i >= 7; --i)
321    {
322        st = lsquic_rechist_received(&rechist, i, now);
323        assert(("inserting packet", st == REC_ST_OK));
324    }
325
326    range = lsquic_rechist_first(&rechist);
327    assert(("first range returned correctly", range));
328    assert(("first range low value checks out", range->low == 7));
329    assert(("first range high value checks out", range->high == 9));
330    range = lsquic_rechist_next(&rechist);
331    assert(("second range returned correctly", range));
332    assert(("second range low value checks out", range->low == 3));
333    assert(("second range high value checks out", range->high == 5));
334    range = lsquic_rechist_next(&rechist);
335    assert(("third range does not exist", !range));
336
337    lsquic_rechist_stop_wait(&rechist, 5);
338
339    range = lsquic_rechist_first(&rechist);
340    range = lsquic_rechist_next(&rechist);
341    assert(("second range returned correctly", range));
342    assert(("second range low value checks out", range->low == 5));
343    assert(("second range high value checks out", range->high == 5));
344    range = lsquic_rechist_next(&rechist);
345    assert(("third range does not exist", !range));
346
347    lsquic_rechist_stop_wait(&rechist, 8);
348
349    range = lsquic_rechist_first(&rechist);
350    assert(("first range returned correctly", range));
351    assert(("first range low value checks out", range->low == 8));
352    assert(("first range high value checks out", range->high == 9));
353    range = lsquic_rechist_next(&rechist);
354    assert(("second range does not exist", !range));
355
356    lsquic_rechist_cleanup(&rechist);
357
358    test4();
359
360    test5();
361
362    for (i = 0; i < 10; ++i)
363        test_rand_sequence(i, 0);
364
365    for (i = 0; i < 10; ++i)
366        test_rand_sequence(i, 111 + i * 3 /* Just something arbitrary */);
367
368    for (i = 0; i < 10; ++i)
369        test_shuffle_1000(i);
370
371    return 0;
372}
373