test_stream.c revision 078f5379
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc.  See LICENSE. */
2#include <assert.h>
3#include <errno.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <sys/queue.h>
8#include <sys/types.h>
9#include <fcntl.h>
10#include <limits.h>
11#ifndef WIN32
12#include <unistd.h>
13#else
14#include <getopt.h>
15#endif
16
17#include "lsquic.h"
18
19#include "lsquic_packet_common.h"
20#include "lsquic_alarmset.h"
21#include "lsquic_packet_in.h"
22#include "lsquic_conn_flow.h"
23#include "lsquic_rtt.h"
24#include "lsquic_sfcw.h"
25#include "lsquic_varint.h"
26#include "lsquic_hq.h"
27#include "lsquic_hash.h"
28#include "lsquic_stream.h"
29#include "lsquic_types.h"
30#include "lsquic_malo.h"
31#include "lsquic_mm.h"
32#include "lsquic_conn_public.h"
33#include "lsquic_logger.h"
34#include "lsquic_parse.h"
35#include "lsquic_conn.h"
36#include "lsquic_engine_public.h"
37#include "lsquic_cubic.h"
38#include "lsquic_pacer.h"
39#include "lsquic_senhist.h"
40#include "lsquic_bw_sampler.h"
41#include "lsquic_minmax.h"
42#include "lsquic_bbr.h"
43#include "lsquic_adaptive_cc.h"
44#include "lsquic_send_ctl.h"
45#include "lsquic_ver_neg.h"
46#include "lsquic_packet_out.h"
47#include "lsquic_enc_sess.h"
48#include "lsqpack.h"
49#include "lsquic_frab_list.h"
50#include "lsquic_qenc_hdl.h"
51#include "lsquic_varint.h"
52#include "lsquic_hq.h"
53#include "lsquic_data_in_if.h"
54
55static const struct parse_funcs *g_pf = select_pf_by_ver(LSQVER_043);
56
57static int g_use_crypto_ctor;
58
59struct test_ctl_settings
60{
61    int     tcs_schedule_stream_packets_immediately;
62    int     tcs_have_delayed_packets;
63    int     tcs_can_send;
64    int     tcs_write_ack;
65    enum buf_packet_type
66            tcs_bp_type;
67    enum packno_bits
68            tcs_guess_packno_bits,
69            tcs_calc_packno_bits;
70};
71
72
73static struct test_ctl_settings g_ctl_settings;
74
75
76static void
77init_buf (void *buf, size_t sz);
78
79
80/* Set values to default */
81static void
82init_test_ctl_settings (struct test_ctl_settings *settings)
83{
84    settings->tcs_schedule_stream_packets_immediately      = 1;
85    settings->tcs_have_delayed_packets = 0;
86    settings->tcs_can_send             = 1;
87    settings->tcs_write_ack            = 0;
88    settings->tcs_bp_type              = BPT_HIGHEST_PRIO;
89    settings->tcs_guess_packno_bits    = GQUIC_PACKNO_LEN_2;
90    settings->tcs_calc_packno_bits     = GQUIC_PACKNO_LEN_2;
91}
92
93
94#if __GNUC__
95__attribute__((unused))
96#endif
97static void
98apply_test_ctl_settings (const struct test_ctl_settings *settings)
99{
100    g_ctl_settings = *settings;
101}
102
103
104enum packno_bits
105lsquic_send_ctl_calc_packno_bits (struct lsquic_send_ctl *ctl)
106{
107    return g_ctl_settings.tcs_calc_packno_bits;
108}
109
110
111int
112lsquic_send_ctl_schedule_stream_packets_immediately (struct lsquic_send_ctl *ctl)
113{
114    return g_ctl_settings.tcs_schedule_stream_packets_immediately;
115}
116
117
118int
119lsquic_send_ctl_have_delayed_packets (const struct lsquic_send_ctl *ctl)
120{
121    return g_ctl_settings.tcs_have_delayed_packets;
122}
123
124
125int
126lsquic_send_ctl_can_send (struct lsquic_send_ctl *ctl)
127{
128    return g_ctl_settings.tcs_can_send;
129}
130
131
132enum packno_bits
133lsquic_send_ctl_guess_packno_bits (struct lsquic_send_ctl *ctl)
134{
135    return g_ctl_settings.tcs_guess_packno_bits;
136}
137
138
139enum buf_packet_type
140lsquic_send_ctl_determine_bpt (struct lsquic_send_ctl *ctl,
141                                        const struct lsquic_stream *stream)
142{
143    return g_ctl_settings.tcs_bp_type;
144}
145
146
147/* This function is only here to avoid crash in the test: */
148void
149lsquic_engine_add_conn_to_tickable (struct lsquic_engine_public *enpub,
150                                    lsquic_conn_t *conn)
151{
152}
153
154
155static unsigned n_closed;
156static enum stream_ctor_flags stream_ctor_flags =
157                                        SCF_CALL_ON_NEW|SCF_DI_AUTOSWITCH;
158
159struct test_ctx {
160    lsquic_stream_t     *stream;
161};
162
163
164static lsquic_stream_ctx_t *
165on_new_stream (void *stream_if_ctx, lsquic_stream_t *stream)
166{
167    struct test_ctx *test_ctx = stream_if_ctx;
168    test_ctx->stream = stream;
169    return NULL;
170}
171
172
173static void
174on_close (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
175{
176    ++n_closed;
177}
178
179
180const struct lsquic_stream_if stream_if = {
181    .on_new_stream          = on_new_stream,
182    .on_close               = on_close,
183};
184
185
186/* This does not do anything beyond just acking the packet: we do not attempt
187 * to update the send controller to have the correct state.
188 */
189static void
190ack_packet (lsquic_send_ctl_t *send_ctl, lsquic_packno_t packno)
191{
192    struct lsquic_packet_out *packet_out;
193    TAILQ_FOREACH(packet_out, &send_ctl->sc_unacked_packets[PNS_APP], po_next)
194        if (packet_out->po_packno == packno)
195        {
196            lsquic_packet_out_ack_streams(packet_out);
197            return;
198        }
199    assert(0);
200}
201
202
203static size_t
204read_from_scheduled_packets (lsquic_send_ctl_t *send_ctl, lsquic_stream_id_t stream_id,
205    unsigned char *const begin, size_t bufsz, uint64_t first_offset, int *p_fin,
206    int fullcheck)
207{
208    const struct parse_funcs *const pf_local = send_ctl->sc_conn_pub->lconn->cn_pf;
209    unsigned char *p = begin;
210    unsigned char *const end = p + bufsz;
211    const struct frame_rec *frec;
212    struct packet_out_frec_iter pofi;
213    struct lsquic_packet_out *packet_out;
214    struct stream_frame frame;
215    enum quic_frame_type expected_type;
216    int len, fin = 0;
217
218    if (g_use_crypto_ctor)
219        expected_type = QUIC_FRAME_CRYPTO;
220    else
221        expected_type = QUIC_FRAME_STREAM;
222
223    TAILQ_FOREACH(packet_out, &send_ctl->sc_scheduled_packets, po_next)
224        for (frec = lsquic_pofi_first(&pofi, packet_out); frec;
225                                                frec = lsquic_pofi_next(&pofi))
226        {
227            if (fullcheck)
228            {
229                assert(frec->fe_frame_type == expected_type);
230                if (packet_out->po_packno != 1)
231                {
232                    /* First packet may contain two stream frames, do not
233                     * check it.
234                     */
235                    assert(!lsquic_pofi_next(&pofi));
236                    if (TAILQ_NEXT(packet_out, po_next))
237                    {
238                        assert(packet_out->po_data_sz == packet_out->po_n_alloc);
239                        assert(frec->fe_len == packet_out->po_data_sz);
240                    }
241                }
242            }
243            if (frec->fe_frame_type == expected_type &&
244                                            frec->fe_stream->id == stream_id)
245            {
246                assert(!fin);
247                if (QUIC_FRAME_STREAM == expected_type)
248                    len = pf_local->pf_parse_stream_frame(packet_out->po_data + frec->fe_off,
249                        packet_out->po_data_sz - frec->fe_off, &frame);
250                else
251                    len = pf_local->pf_parse_crypto_frame(packet_out->po_data + frec->fe_off,
252                        packet_out->po_data_sz - frec->fe_off, &frame);
253                assert(len > 0);
254                if (QUIC_FRAME_STREAM == expected_type)
255                    assert(frame.stream_id == frec->fe_stream->id);
256                else
257                    assert(frame.stream_id == ~0ULL);
258                /* Otherwise not enough to copy to: */
259                assert(end - p >= frame.data_frame.df_size);
260                /* Checks offset ordering: */
261                assert(frame.data_frame.df_offset ==
262                                        first_offset + (uintptr_t) (p - begin));
263                if (frame.data_frame.df_fin)
264                {
265                    assert(!fin);
266                    fin = 1;
267                }
268                memcpy(p, packet_out->po_data + frec->fe_off + len -
269                    frame.data_frame.df_size, frame.data_frame.df_size);
270                p += frame.data_frame.df_size;
271            }
272        }
273
274    if (p_fin)
275        *p_fin = fin;
276    return p + bufsz - end;
277}
278
279
280static struct test_ctx test_ctx;
281
282
283struct test_objs {
284    struct lsquic_conn        lconn;
285    struct lsquic_engine_public eng_pub;
286    struct lsquic_conn_public conn_pub;
287    struct lsquic_send_ctl    send_ctl;
288    struct lsquic_alarmset    alset;
289    void                     *stream_if_ctx;
290    struct ver_neg            ver_neg;
291    const struct lsquic_stream_if *
292                              stream_if;
293    unsigned                  initial_stream_window;
294    enum stream_ctor_flags    ctor_flags;
295    struct qpack_enc_hdl      qeh;
296};
297
298
299static struct network_path network_path;
300
301static struct network_path *
302get_network_path (struct lsquic_conn *lconn, const struct sockaddr *sa)
303{
304    return &network_path;
305}
306
307
308static int
309can_write_ack (struct lsquic_conn *lconn)
310{
311    return g_ctl_settings.tcs_write_ack;
312}
313
314
315static void
316write_ack (struct lsquic_conn *lconn, struct lsquic_packet_out *packet_out)
317{
318    struct test_objs *const tobjs = (void *) lconn;
319    const size_t ack_size = 9;  /* Arbitrary */
320    int s;
321
322    packet_out->po_frame_types |= 1 << QUIC_FRAME_ACK;
323    s = lsquic_packet_out_add_frame(packet_out, &tobjs->eng_pub.enp_mm, 0,
324                            QUIC_FRAME_ACK, packet_out->po_data_sz, ack_size);
325    assert(s == 0);
326    memcpy(packet_out->po_data + packet_out->po_data_sz, "ACKACKACK", 9);
327    lsquic_send_ctl_incr_pack_sz(&tobjs->send_ctl, packet_out, ack_size);
328    packet_out->po_regen_sz += ack_size;
329}
330
331
332static const struct conn_iface our_conn_if =
333{
334    .ci_can_write_ack = can_write_ack,
335    .ci_get_path      = get_network_path,
336    .ci_write_ack     = write_ack,
337};
338
339static struct conn_stats s_conn_stats;
340
341static void
342init_test_objs (struct test_objs *tobjs, unsigned initial_conn_window,
343                unsigned initial_stream_window, const struct parse_funcs *pf)
344{
345    int s;
346    memset(tobjs, 0, sizeof(*tobjs));
347    LSCONN_INITIALIZE(&tobjs->lconn);
348    tobjs->lconn.cn_pf = pf ? pf : g_pf;
349    tobjs->lconn.cn_version = tobjs->lconn.cn_pf == &lsquic_parse_funcs_ietf_v1 ?
350        LSQVER_ID27 : LSQVER_043;
351    tobjs->lconn.cn_esf_c = &lsquic_enc_session_common_gquic_1;
352    network_path.np_pack_size = 1370;
353    tobjs->lconn.cn_if = &our_conn_if;
354    lsquic_mm_init(&tobjs->eng_pub.enp_mm);
355    TAILQ_INIT(&tobjs->conn_pub.sending_streams);
356    TAILQ_INIT(&tobjs->conn_pub.read_streams);
357    TAILQ_INIT(&tobjs->conn_pub.write_streams);
358    TAILQ_INIT(&tobjs->conn_pub.service_streams);
359    lsquic_cfcw_init(&tobjs->conn_pub.cfcw, &tobjs->conn_pub,
360                                                    initial_conn_window);
361    lsquic_conn_cap_init(&tobjs->conn_pub.conn_cap, initial_conn_window);
362    lsquic_alarmset_init(&tobjs->alset, 0);
363    tobjs->conn_pub.mm = &tobjs->eng_pub.enp_mm;
364    tobjs->conn_pub.lconn = &tobjs->lconn;
365    tobjs->conn_pub.enpub = &tobjs->eng_pub;
366    tobjs->conn_pub.send_ctl = &tobjs->send_ctl;
367    tobjs->conn_pub.packet_out_malo =
368                        lsquic_malo_create(sizeof(struct lsquic_packet_out));
369    tobjs->conn_pub.path = &network_path;
370    tobjs->conn_pub.conn_stats = &s_conn_stats;
371    tobjs->initial_stream_window = initial_stream_window;
372    lsquic_send_ctl_init(&tobjs->send_ctl, &tobjs->alset, &tobjs->eng_pub,
373        &tobjs->ver_neg, &tobjs->conn_pub, 0);
374    tobjs->stream_if = &stream_if;
375    tobjs->stream_if_ctx = &test_ctx;
376    tobjs->ctor_flags = stream_ctor_flags;
377    if ((1 << tobjs->lconn.cn_version) & LSQUIC_IETF_VERSIONS)
378    {
379        lsquic_qeh_init(&tobjs->qeh, &tobjs->lconn);
380        s = lsquic_qeh_settings(&tobjs->qeh, 0, 0, 0, 0);
381        assert(0 == s);
382        tobjs->conn_pub.u.ietf.qeh = &tobjs->qeh;
383    }
384}
385
386
387static void
388deinit_test_objs (struct test_objs *tobjs)
389{
390    assert(!lsquic_malo_first(tobjs->eng_pub.enp_mm.malo.stream_frame));
391    lsquic_send_ctl_cleanup(&tobjs->send_ctl);
392    lsquic_malo_destroy(tobjs->conn_pub.packet_out_malo);
393    lsquic_mm_cleanup(&tobjs->eng_pub.enp_mm);
394    if ((1 << tobjs->lconn.cn_version) & LSQUIC_IETF_VERSIONS)
395    {
396        lsquic_qeh_cleanup(&tobjs->qeh);
397    }
398}
399
400
401/* Create a new stream frame.  Each stream frame has a real packet_in to
402 * back it up, just like in real code.  The contents of the packet do
403 * not matter.
404 */
405static stream_frame_t *
406new_frame_in_ext (struct test_objs *tobjs, size_t off, size_t sz, int fin,
407                                                            const void *data)
408{
409    lsquic_packet_in_t *packet_in;
410    stream_frame_t *frame;
411
412    assert(sz <= 1370);
413
414    packet_in = lsquic_mm_get_packet_in(&tobjs->eng_pub.enp_mm);
415    if (data)
416        packet_in->pi_data = (void *) data;
417    else
418    {
419        packet_in->pi_data = lsquic_mm_get_packet_in_buf(&tobjs->eng_pub.enp_mm, 1370);
420        packet_in->pi_flags |= PI_OWN_DATA;
421        memset(packet_in->pi_data, 'A', sz);
422    }
423    /* This is not how stream frame looks in the packet: we have no
424     * header.  In our test case it does not matter, as we only care
425     * about stream frame.
426     */
427    packet_in->pi_data_sz = sz;
428    packet_in->pi_refcnt = 1;
429
430    frame = lsquic_malo_get(tobjs->eng_pub.enp_mm.malo.stream_frame);
431    memset(frame, 0, sizeof(*frame));
432    frame->packet_in = packet_in;
433    frame->data_frame.df_offset = off;
434    frame->data_frame.df_size = sz;
435    frame->data_frame.df_data = &packet_in->pi_data[0];
436    frame->data_frame.df_fin  = fin;
437
438    return frame;
439}
440
441
442static stream_frame_t *
443new_frame_in (struct test_objs *tobjs, size_t off, size_t sz, int fin)
444{
445    return new_frame_in_ext(tobjs, off, sz, fin, NULL);
446}
447
448
449static lsquic_stream_t *
450new_stream_ext (struct test_objs *tobjs, unsigned stream_id, uint64_t send_off)
451{
452    enum stream_ctor_flags ctor_flags;
453
454    if (g_use_crypto_ctor)
455        return lsquic_stream_new_crypto(stream_id, &tobjs->conn_pub,
456            tobjs->stream_if, tobjs->stream_if_ctx,
457            tobjs->ctor_flags | SCF_CRITICAL);
458    else
459    {
460        /* For the purposes of the unit test, consider streams 1 and 3 critical */
461        if (stream_id == 3 || stream_id == 1)
462            ctor_flags = SCF_CRITICAL;
463        else
464            ctor_flags = 0;
465        return lsquic_stream_new(stream_id, &tobjs->conn_pub, tobjs->stream_if,
466            tobjs->stream_if_ctx, tobjs->initial_stream_window, send_off,
467            tobjs->ctor_flags | ctor_flags);
468    }
469}
470
471
472static lsquic_stream_t *
473new_stream (struct test_objs *tobjs, unsigned stream_id)
474{
475    return new_stream_ext(tobjs, stream_id, 16 * 1024);
476}
477
478
479static void
480run_frame_ordering_test (uint64_t run_id /* This is used to make it easier to set breakpoints */,
481                         int *idx, size_t idx_sz, int read_asap)
482{
483    int s;
484    size_t nw = 0, i;
485    char buf[0x1000];
486
487    struct test_objs tobjs;
488
489    init_test_objs(&tobjs, 0x4000, 0x4000, NULL);
490
491    lsquic_stream_t *stream = new_stream(&tobjs, 123);
492    struct lsquic_mm *const mm = &tobjs.eng_pub.enp_mm;
493    struct malo *const frame_malo = mm->malo.stream_frame;
494
495    lsquic_packet_in_t *packet_in = lsquic_mm_get_packet_in(mm);
496    packet_in->pi_data = lsquic_mm_get_packet_in_buf(mm, 1370);
497    packet_in->pi_flags |= PI_OWN_DATA;
498    assert(idx_sz <= 10);
499    memcpy(packet_in->pi_data, "0123456789", 10);
500    packet_in->pi_data_sz = 10;
501    packet_in->pi_refcnt = idx_sz;
502
503    printf("inserting ");
504    for (i = 0; i < idx_sz; ++i)
505    {
506        stream_frame_t *frame;
507        frame = lsquic_malo_get(frame_malo);
508        memset(frame, 0, sizeof(*frame));
509        frame->packet_in = packet_in;
510        frame->data_frame.df_offset = idx[i];
511        if (idx[i] + 1 == (int) idx_sz)
512        {
513            printf("<FIN>");
514            frame->data_frame.df_size = 0;
515            frame->data_frame.df_fin         = 1;
516        }
517        else
518        {
519            printf("%c", packet_in->pi_data[idx[i]]);
520            frame->data_frame.df_size = 1;
521            frame->data_frame.df_data = &packet_in->pi_data[idx[i]];
522        }
523        if (frame->data_frame.df_fin && read_asap && i + 1 == idx_sz)
524        {   /* Last frame is the FIN frame.  Read before inserting zero-sized
525             * FIN frame.
526             */
527            nw = lsquic_stream_read(stream, buf, 10);
528            assert(("Read idx_sz bytes", nw == idx_sz - 1));
529            assert(("Have not reached fin yet (frame has not come in)",
530                -1 == lsquic_stream_read(stream, buf, 1) && errno == EWOULDBLOCK));
531        }
532        s = lsquic_stream_frame_in(stream, frame);
533        assert(("Inserted frame", 0 == s));
534    }
535    printf("\n");
536
537    if (read_asap && nw == idx_sz - 1)
538    {
539        assert(("Reached fin", 0 == lsquic_stream_read(stream, buf, 1)));
540    }
541    else
542    {
543        nw = lsquic_stream_read(stream, buf, 10);
544        assert(("Read idx_sz bytes", nw == idx_sz - 1));
545        assert(("Reached fin", 0 == lsquic_stream_read(stream, buf, 1)));
546    }
547
548    lsquic_stream_destroy(stream);
549
550    assert(("all frames have been released", !lsquic_malo_first(frame_malo)));
551    deinit_test_objs(&tobjs);
552}
553
554
555static void
556permute_and_run (uint64_t run_id,
557                 int mask, int level, int *idx, size_t idx_sz)
558{
559    size_t i;
560    for (i = 0; i < idx_sz; ++i)
561    {
562        if (!(mask & (1 << i)))
563        {
564            idx[level] = i;
565            if (level + 1 == (int) idx_sz)
566            {
567                run_frame_ordering_test(run_id, idx, idx_sz, 0);
568                run_frame_ordering_test(run_id, idx, idx_sz, 1);
569            }
570            else
571                permute_and_run(run_id | (i << (8 * level)),
572                                mask | (1 << i), level + 1, idx, idx_sz);
573        }
574    }
575}
576
577
578/* Client: we send some data and FIN, and remote end sends some data and
579 * FIN.
580 */
581static void
582test_loc_FIN_rem_FIN (struct test_objs *tobjs)
583{
584    lsquic_stream_t *stream;
585    lsquic_packet_out_t *packet_out;
586    char buf_out[0x100];
587    unsigned char buf[0x100];
588    ssize_t n;
589    int s, fin;
590    enum stream_state_sending sss;
591
592    init_buf(buf_out, sizeof(buf_out));
593
594    stream = new_stream(tobjs, 345);
595    n = lsquic_stream_write(stream, buf_out, 100);
596    assert(n == 100);
597    assert(0 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
598
599    s = lsquic_stream_flush(stream);
600    assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
601
602    n = read_from_scheduled_packets(&tobjs->send_ctl, stream->id, buf,
603                                                    sizeof(buf), 0, &fin, 0);
604    assert(100 == n);
605    assert(0 == memcmp(buf_out, buf, 100));
606    assert(!fin);
607
608    /* Pretend we sent out a packet: */
609    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0);
610    lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out);
611
612    s = lsquic_stream_shutdown(stream, 1);
613    assert(s == 0);
614    assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); /* Shutdown performs a flush */
615    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));  /* No need to close stream yet */
616
617    n = read_from_scheduled_packets(&tobjs->send_ctl, stream->id, buf,
618                                                sizeof(buf), 100, &fin, 0);
619    assert(0 == n);
620    assert(fin);
621    sss = lsquic_stream_sending_state(stream);
622    assert(SSS_DATA_SENT == sss);
623
624    /* Pretend we sent out this packet as well: */
625    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0);
626    lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out);
627
628    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));  /* No need to close stream yet */
629
630    s = lsquic_stream_frame_in(stream, new_frame_in(tobjs, 0, 100, 0));
631    assert(0 == s);
632
633    n = lsquic_stream_read(stream, buf, 60);
634    assert(60 == n);
635    n = lsquic_stream_read(stream, buf, 60);
636    assert(40 == n);
637
638    s = lsquic_stream_frame_in(stream, new_frame_in(tobjs, 100, 0, 1));
639    assert(0 == s);
640    n = lsquic_stream_read(stream, buf, 60);
641    assert(0 == n);
642    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
643
644    s = lsquic_stream_shutdown(stream, 0);
645    assert(0 == s);
646    assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
647    assert((stream->sm_qflags & (SMQF_SERVICE_FLAGS)) == (SMQF_CALL_ONCLOSE));
648    ack_packet(&tobjs->send_ctl, 1);
649    ack_packet(&tobjs->send_ctl, 2);
650    assert((stream->sm_qflags & (SMQF_SERVICE_FLAGS)) == (SMQF_CALL_ONCLOSE|SMQF_FREE_STREAM));
651    sss = lsquic_stream_sending_state(stream);
652    assert(SSS_DATA_RECVD == sss);
653
654    lsquic_stream_destroy(stream);
655    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
656
657    assert(100 == tobjs->conn_pub.cfcw.cf_max_recv_off);
658    assert(100 == tobjs->conn_pub.cfcw.cf_read_off);
659}
660
661
662/* Server: we read data and FIN, and then send data and FIN.
663 */
664static void
665test_rem_FIN_loc_FIN (struct test_objs *tobjs)
666{
667    lsquic_stream_t *stream;
668    char buf_out[0x100];
669    unsigned char buf[0x100];
670    size_t n;
671    int s, fin;
672    lsquic_packet_out_t *packet_out;
673
674    stream = new_stream(tobjs, 345);
675
676    s = lsquic_stream_frame_in(stream, new_frame_in(tobjs, 0, 100, 0));
677    assert(0 == s);
678
679    n = lsquic_stream_read(stream, buf, 60);
680    assert(60 == n);
681    n = lsquic_stream_read(stream, buf, 60);
682    assert(40 == n);
683
684    s = lsquic_stream_frame_in(stream, new_frame_in(tobjs, 100, 0, 1));
685    assert(0 == s);
686    n = lsquic_stream_read(stream, buf, 60);
687    assert(0 == n);
688    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
689
690    s = lsquic_stream_shutdown(stream, 0);
691    assert(0 == s);
692    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
693
694    init_buf(buf_out, sizeof(buf_out));
695    n = lsquic_stream_write(stream, buf_out, 100);
696    assert(n == 100);
697    assert(0 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
698
699    s = lsquic_stream_flush(stream);
700    assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
701
702    n = read_from_scheduled_packets(&tobjs->send_ctl, stream->id, buf,
703                                                    sizeof(buf), 0, &fin, 0);
704    assert(100 == n);
705    assert(0 == memcmp(buf_out, buf, 100));
706    assert(!fin);
707
708    /* Pretend we sent out a packet: */
709    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0);
710    lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out);
711
712    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));  /* No need to close stream yet */
713
714    s = lsquic_stream_shutdown(stream, 1);
715    assert(s == 0);
716    assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); /* Shutdown performs a flush */
717
718    /* Now we can call on_close: */
719    assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
720    assert((stream->sm_qflags & (SMQF_SERVICE_FLAGS)) == SMQF_CALL_ONCLOSE);
721
722    n = read_from_scheduled_packets(&tobjs->send_ctl, stream->id, buf,
723                                                sizeof(buf), 100, &fin, 0);
724    assert(0 == n);
725    assert(fin);
726
727    /* Pretend we sent out this packet as well: */
728    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0);
729    lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out);
730
731    /* Cannot free stream yet: packets have not been acked */
732    assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
733    assert((stream->sm_qflags & (SMQF_SERVICE_FLAGS)) == SMQF_CALL_ONCLOSE);
734
735    ack_packet(&tobjs->send_ctl, 1);
736    ack_packet(&tobjs->send_ctl, 2);
737
738    /* Now we can free the stream: */
739    assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
740    assert((stream->sm_qflags & (SMQF_SERVICE_FLAGS)) == (SMQF_CALL_ONCLOSE|SMQF_FREE_STREAM));
741
742    lsquic_stream_destroy(stream);
743    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
744
745    assert(100 == tobjs->conn_pub.cfcw.cf_max_recv_off);
746    assert(100 == tobjs->conn_pub.cfcw.cf_read_off);
747}
748
749
750/* Server: we read data and close the read side before reading FIN, which
751 * results in stream being reset.
752 */
753static void
754test_rem_data_loc_close_and_rst_in (struct test_objs *tobjs)
755{
756    lsquic_stream_t *stream;
757    char buf[0x100];
758    ssize_t n;
759    int s;
760
761    stream = new_stream(tobjs, 345);
762
763    s = lsquic_stream_frame_in(stream, new_frame_in(tobjs, 0, 100, 0));
764    assert(0 == s);
765
766    n = lsquic_stream_read(stream, buf, 60);
767    assert(60 == n);
768
769    s = lsquic_stream_shutdown(stream, 0);
770    assert(0 == s);
771    /* Early read shutdown results in different frames on different QUIC
772     * transports:
773     */
774    if (stream->sm_bflags & SMBF_IETF)
775        assert(stream->sm_qflags & SMQF_SEND_STOP_SENDING);
776    else
777        assert(stream->sm_qflags & SMQF_SEND_RST);
778    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
779    assert(!((stream->sm_qflags & (SMQF_SERVICE_FLAGS)) == SMQF_CALL_ONCLOSE));
780
781    n = lsquic_stream_read(stream, buf, 60);
782    assert(n == -1);    /* Cannot read from closed stream */
783
784    /* Close write side */
785    s = lsquic_stream_shutdown(stream, 1);
786    assert(0 == s);
787
788    assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); /* Shutdown performs a flush */
789    assert(stream->n_unacked == 1);
790
791    assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
792    assert((stream->sm_qflags & (SMQF_SERVICE_FLAGS)) == SMQF_CALL_ONCLOSE);
793
794    s = lsquic_stream_rst_in(stream, 100, 1);
795    assert(0 == s);
796
797    assert(!(stream->sm_qflags & SMQF_FREE_STREAM));    /* Not yet */
798    assert(stream->sm_qflags & SMQF_CALL_ONCLOSE);
799
800    lsquic_stream_rst_frame_sent(stream);
801    stream->n_unacked++;    /* RESET frame take a reference */
802    assert(!(stream->sm_qflags & SMQF_FREE_STREAM));    /* Not yet,
803        because: */ assert(stream->n_unacked == 2);
804
805    lsquic_stream_acked(stream, QUIC_FRAME_STREAM);
806    lsquic_stream_acked(stream, QUIC_FRAME_RST_STREAM);
807    assert(stream->sm_qflags & SMQF_FREE_STREAM);       /* OK, now */
808
809    lsquic_stream_destroy(stream);
810    /* This simply checks that the stream got removed from the queue: */
811    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
812
813    assert(100 == tobjs->conn_pub.cfcw.cf_max_recv_off);
814    assert(100 == tobjs->conn_pub.cfcw.cf_read_off);
815}
816
817
818/* Server: we read data and close the read side before reading FIN.  No
819 * FIN or RST arrive from peer.  This should schedule RST_STREAM to be
820 * sent (this is gQUIC) and add "wait for known FIN" flag.
821 */
822static void
823test_rem_data_loc_close (struct test_objs *tobjs)
824{
825    lsquic_stream_t *stream;
826    char buf[0x100];
827    ssize_t n;
828    int s;
829
830    stream = new_stream(tobjs, 345);
831
832    s = lsquic_stream_frame_in(stream, new_frame_in(tobjs, 0, 100, 0));
833    assert(0 == s);
834
835    n = lsquic_stream_read(stream, buf, 60);
836    assert(60 == n);
837
838    s = lsquic_stream_shutdown(stream, 0);
839    assert(0 == s);
840    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
841    assert(!(stream->sm_qflags & SMQF_CALL_ONCLOSE));
842
843    n = lsquic_stream_read(stream, buf, 60);
844    assert(n == -1);    /* Cannot read from closed stream */
845
846    /* Close write side */
847    s = lsquic_stream_shutdown(stream, 1);
848    assert(0 == s);
849
850    assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); /* Shutdown performs a flush */
851
852    assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
853    assert(stream->sm_qflags & SMQF_CALL_ONCLOSE);
854
855    assert(!(stream->sm_qflags & SMQF_FREE_STREAM));
856    lsquic_stream_acked(stream, QUIC_FRAME_STREAM);
857
858    lsquic_stream_rst_frame_sent(stream);
859    stream->n_unacked++;    /* RESET frame take a reference */
860    assert(!(stream->sm_qflags & SMQF_FREE_STREAM));    /* No */
861
862    lsquic_stream_acked(stream, QUIC_FRAME_RST_STREAM);
863    assert(!(stream->sm_qflags & SMQF_FREE_STREAM));    /* Still no */
864
865    /* Stream will linger until we have the offset: */
866    assert(stream->sm_qflags & SMQF_WAIT_FIN_OFF);
867
868    lsquic_stream_destroy(stream);
869    /* This simply checks that the stream got removed from the queue: */
870    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
871
872    assert(100 == tobjs->conn_pub.cfcw.cf_max_recv_off);
873    assert(100 == tobjs->conn_pub.cfcw.cf_read_off);
874}
875
876
877/* Client: we send some data and FIN, but remote end sends some data and
878 * then resets the stream.  The client gets an error when it reads from
879 * stream, after which it closes and destroys the stream.
880 */
881static void
882test_loc_FIN_rem_RST (struct test_objs *tobjs)
883{
884    lsquic_packet_out_t *packet_out;
885    lsquic_stream_t *stream;
886    char buf_out[0x100];
887    unsigned char buf[0x100];
888    ssize_t n;
889    int s, fin;
890
891    init_buf(buf_out, sizeof(buf_out));
892
893    stream = new_stream(tobjs, 345);
894    n = lsquic_stream_write(stream, buf_out, 100);
895    assert(n == 100);
896    assert(0 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
897
898    s = lsquic_stream_flush(stream);
899    assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
900
901    n = read_from_scheduled_packets(&tobjs->send_ctl, stream->id, buf,
902                                                    sizeof(buf), 0, &fin, 0);
903    assert(100 == n);
904    assert(0 == memcmp(buf_out, buf, 100));
905    assert(!fin);
906
907    /* Pretend we sent out a packet: */
908    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0);
909    lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out);
910
911    s = lsquic_stream_shutdown(stream, 1);
912    assert(s == 0);
913    assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl)); /* Shutdown performs a flush */
914    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));  /* No need to close stream yet */
915
916    n = read_from_scheduled_packets(&tobjs->send_ctl, stream->id, buf,
917                                                    sizeof(buf), 100, &fin, 0);
918    assert(0 == n);
919    assert(fin);
920
921    /* Pretend we sent out this packet as well: */
922    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0);
923    lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out);
924
925    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));  /* No need to close stream yet */
926
927    s = lsquic_stream_frame_in(stream, new_frame_in(tobjs, 0, 100, 0));
928    assert(0 == s);
929    s = lsquic_stream_rst_in(stream, 100, 0);
930    assert(0 == s);
931
932    /* No RST to send, we already sent FIN */
933    assert(0 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
934
935    /* The stream is not yet done: the user code has not closed it yet */
936    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
937    assert(0 == (stream->sm_qflags & (SMQF_SERVICE_FLAGS)));
938    assert(0 == (stream->stream_flags & STREAM_U_READ_DONE));
939
940    s = lsquic_stream_read(stream, buf, sizeof(buf));
941    assert(-1 == s);    /* Error collected */
942    s = lsquic_stream_close(stream);
943    assert(0 == s);     /* Stream closed successfully */
944
945    assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
946    assert((stream->sm_qflags & (SMQF_SERVICE_FLAGS)) == (SMQF_CALL_ONCLOSE));
947
948    ack_packet(&tobjs->send_ctl, 1);
949    ack_packet(&tobjs->send_ctl, 2);
950
951#if 0
952    /* OK, here we pretend that we sent a RESET and it was acked */
953    assert(stream->sm_qflags & SMQF_SEND_RST);
954    stream->sm_qflags |= SMQF_SEND_RST;
955    stream->stream_flags
956#endif
957
958    assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
959    assert((stream->sm_qflags & (SMQF_SERVICE_FLAGS)) == (SMQF_CALL_ONCLOSE|SMQF_FREE_STREAM));
960
961    lsquic_stream_destroy(stream);
962    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
963
964    assert(100 == tobjs->conn_pub.cfcw.cf_max_recv_off);
965    assert(100 == tobjs->conn_pub.cfcw.cf_read_off);
966}
967
968
969/* Client: we send some data (no FIN), and remote end sends some data and
970 * then resets the stream.
971 */
972static void
973test_loc_data_rem_RST (struct test_objs *tobjs)
974{
975    lsquic_packet_out_t *packet_out;
976    lsquic_stream_t *stream;
977    char buf_out[0x100];
978    unsigned char buf[0x100];
979    ssize_t n;
980    int s, fin;
981
982    init_buf(buf_out, sizeof(buf_out));
983
984    stream = new_stream(tobjs, 345);
985    n = lsquic_stream_write(stream, buf_out, 100);
986    assert(n == 100);
987    assert(0 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
988
989    s = lsquic_stream_flush(stream);
990    assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
991
992    n = read_from_scheduled_packets(&tobjs->send_ctl, stream->id, buf,
993                                                    sizeof(buf), 0, &fin, 0);
994    assert(100 == n);
995    assert(0 == memcmp(buf_out, buf, 100));
996    assert(!fin);
997
998    /* Pretend we sent out a packet: */
999    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0);
1000    lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out);
1001
1002    s = lsquic_stream_frame_in(stream, new_frame_in(tobjs, 0, 100, 0));
1003    assert(0 == s);
1004    s = lsquic_stream_rst_in(stream, 200, 0);
1005    assert(0 == s);
1006
1007    ack_packet(&tobjs->send_ctl, 1);
1008
1009    assert(!TAILQ_EMPTY(&tobjs->conn_pub.sending_streams));
1010    assert((stream->sm_qflags & SMQF_SENDING_FLAGS) == SMQF_SEND_RST);
1011
1012    /* Not yet closed: error needs to be collected */
1013    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
1014    assert(0 == (stream->sm_qflags & SMQF_SERVICE_FLAGS));
1015
1016    n = lsquic_stream_write(stream, buf, 100);
1017    assert(-1 == n);    /* Error collected */
1018    s = lsquic_stream_close(stream);
1019    assert(0 == s);     /* Stream successfully closed */
1020
1021    assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
1022    assert((stream->sm_qflags & SMQF_SERVICE_FLAGS) == SMQF_CALL_ONCLOSE);
1023
1024    lsquic_stream_rst_frame_sent(stream);
1025    lsquic_stream_call_on_close(stream);
1026
1027    assert(TAILQ_EMPTY(&tobjs->conn_pub.sending_streams));
1028    assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
1029    assert((stream->sm_qflags & SMQF_SERVICE_FLAGS) == SMQF_FREE_STREAM);
1030
1031    lsquic_stream_destroy(stream);
1032    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
1033
1034    assert(200 == tobjs->conn_pub.cfcw.cf_max_recv_off);
1035    assert(200 == tobjs->conn_pub.cfcw.cf_read_off);
1036}
1037
1038
1039/* We send some data and RST, receive data and FIN
1040 */
1041static void
1042test_loc_RST_rem_FIN (struct test_objs *tobjs)
1043{
1044    lsquic_packet_out_t *packet_out;
1045    lsquic_stream_t *stream;
1046    char buf_out[0x100];
1047    unsigned char buf[0x100];
1048    size_t n;
1049    int s, fin;
1050    enum stream_state_sending sss;
1051
1052    init_buf(buf_out, sizeof(buf_out));
1053
1054    stream = new_stream(tobjs, 345);
1055
1056    n = lsquic_stream_write(stream, buf_out, 100);
1057    assert(n == 100);
1058    assert(0 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
1059
1060    s = lsquic_stream_flush(stream);
1061    assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
1062
1063    n = read_from_scheduled_packets(&tobjs->send_ctl, stream->id, buf,
1064                                                    sizeof(buf), 0, &fin, 0);
1065    assert(100 == n);
1066    assert(0 == memcmp(buf_out, buf, 100));
1067    assert(!fin);
1068
1069    /* Pretend we sent out a packet: */
1070    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0);
1071    lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out);
1072
1073    assert(1 == stream->n_unacked);
1074    ack_packet(&tobjs->send_ctl, 1);
1075    assert(0 == stream->n_unacked);
1076    sss = lsquic_stream_sending_state(stream);
1077    assert(SSS_SEND == sss);
1078
1079    lsquic_stream_reset(stream, 0);
1080    ++stream->n_unacked;    /* Fake sending of packet with RST_STREAM */
1081    assert(!TAILQ_EMPTY(&tobjs->conn_pub.sending_streams));
1082    assert((stream->sm_qflags & SMQF_SENDING_FLAGS) == SMQF_SEND_RST);
1083    sss = lsquic_stream_sending_state(stream);
1084    assert(SSS_DATA_SENT == sss);    /* FIN was packetized */
1085
1086    s = lsquic_stream_frame_in(stream, new_frame_in(tobjs, 0, 90, 1));
1087    assert(s == 0);
1088    assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
1089    assert((stream->sm_qflags & SMQF_SERVICE_FLAGS) == SMQF_CALL_ONCLOSE);
1090
1091    lsquic_stream_rst_frame_sent(stream);
1092    sss = lsquic_stream_sending_state(stream);
1093    assert(SSS_RESET_SENT == sss);
1094
1095    sss = lsquic_stream_sending_state(stream);
1096    assert(SSS_RESET_SENT == sss);
1097    lsquic_stream_acked(stream, QUIC_FRAME_RST_STREAM); /* Fake ack of RST_STREAM packet */
1098    sss = lsquic_stream_sending_state(stream);
1099    assert(SSS_RESET_RECVD == sss);
1100
1101    assert(TAILQ_EMPTY(&tobjs->conn_pub.sending_streams));
1102
1103    lsquic_stream_call_on_close(stream);
1104    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));  /* Not acked yet */
1105    lsquic_stream_acked(stream, QUIC_FRAME_STREAM);
1106
1107    assert(!TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
1108    assert((stream->sm_qflags & SMQF_SERVICE_FLAGS) == SMQF_FREE_STREAM);
1109
1110    lsquic_stream_destroy(stream);
1111    assert(TAILQ_EMPTY(&tobjs->conn_pub.service_streams));
1112
1113    assert(90 == tobjs->conn_pub.cfcw.cf_max_recv_off);
1114    assert(90 == tobjs->conn_pub.cfcw.cf_read_off);
1115}
1116
1117
1118/* Test that when stream frame is elided and the packet is dropped,
1119 * the send controller produces a gapless sequence.
1120 *
1121 * Case "middle": 3 packets with STREAM frames for streams A, B, and A.
1122 *          Stream B is reset.  We should get a gapless sequence
1123 *          of packets 1, 2.
1124 */
1125static void
1126test_gapless_elision_middle (struct test_objs *tobjs)
1127{
1128    lsquic_stream_t *streamA, *streamB;
1129    unsigned char buf[0x1000], buf_out[0x1000];
1130    size_t n, thresh, written_to_A = 0;
1131    int s, fin;
1132    lsquic_packet_out_t *packet_out;
1133
1134    streamA = new_stream(tobjs, 345);
1135    streamB = new_stream(tobjs, 347);
1136
1137    init_buf(buf_out, sizeof(buf_out));
1138    thresh = lsquic_stream_flush_threshold(streamA, 0);
1139    n = lsquic_stream_write(streamA, buf_out, thresh);
1140    assert(n == thresh);
1141    assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
1142    written_to_A += n;
1143
1144    thresh = lsquic_stream_flush_threshold(streamB, 0);
1145    n = lsquic_stream_write(streamB, buf_out, thresh);
1146    assert(n == thresh);
1147    assert(2 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
1148
1149    thresh = lsquic_stream_flush_threshold(streamA, 0);
1150    n = lsquic_stream_write(streamA, buf_out + written_to_A, thresh);
1151    assert(n == thresh);
1152    assert(3 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
1153    written_to_A += n;
1154
1155    /* Verify contents of A: */
1156    n = read_from_scheduled_packets(&tobjs->send_ctl, streamA->id, buf,
1157                                                    sizeof(buf), 0, &fin, 0);
1158    assert(n == written_to_A);
1159    assert(0 == memcmp(buf, buf_out, written_to_A));
1160
1161    /* Now reset stream A: */
1162    s = lsquic_stream_rst_in(streamB, 0, 0);
1163    assert(s == 0);
1164    assert(2 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
1165    /* Verify A again: */
1166    n = read_from_scheduled_packets(&tobjs->send_ctl, streamA->id, buf,
1167                                                    sizeof(buf), 0, &fin, 0);
1168    assert(n == written_to_A);
1169    assert(0 == memcmp(buf, buf_out, written_to_A));
1170
1171    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0);
1172    assert(packet_out->po_packno == 1);
1173    lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out);
1174
1175    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0);
1176    assert(packet_out->po_packno == 2);
1177    lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out);
1178
1179    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0);
1180    assert(!packet_out);
1181
1182    /* Now we can call on_close: */
1183    lsquic_stream_destroy(streamA);
1184    lsquic_stream_destroy(streamB);
1185}
1186
1187
1188/* Test that when stream frame is elided and the packet is dropped,
1189 * the send controller produces a gapless sequence.
1190 *
1191 * Case "beginnig": 3 packets with STREAM frames for streams B, A, and A.
1192 *          Stream B is reset.  We should get a gapless sequence
1193 *          of packets 1, 2.
1194 */
1195static void
1196test_gapless_elision_beginning (struct test_objs *tobjs)
1197{
1198    lsquic_stream_t *streamA, *streamB;
1199    unsigned char buf[0x1000], buf_out[0x1000];
1200    size_t n, thresh, written_to_A = 0;
1201    int s, fin;
1202    lsquic_packet_out_t *packet_out;
1203
1204    streamA = new_stream(tobjs, 345);
1205    streamB = new_stream(tobjs, 347);
1206
1207    init_buf(buf_out, sizeof(buf_out));
1208
1209    thresh = lsquic_stream_flush_threshold(streamB, 0);
1210    n = lsquic_stream_write(streamB, buf_out, thresh);
1211    assert(n == thresh);
1212    assert(1 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
1213
1214    thresh = lsquic_stream_flush_threshold(streamA, 0);
1215    n = lsquic_stream_write(streamA, buf_out, thresh);
1216    assert(n == thresh);
1217    assert(2 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
1218    written_to_A += n;
1219
1220    thresh = lsquic_stream_flush_threshold(streamA, 0);
1221    n = lsquic_stream_write(streamA, buf_out + written_to_A, thresh);
1222    assert(n == thresh);
1223    assert(3 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
1224    written_to_A += n;
1225
1226    /* Verify contents of A: */
1227    n = read_from_scheduled_packets(&tobjs->send_ctl, streamA->id, buf,
1228                                                    sizeof(buf), 0, &fin, 0);
1229    assert(n == written_to_A);
1230    assert(0 == memcmp(buf, buf_out, written_to_A));
1231
1232    /* Now reset stream A: */
1233    s = lsquic_stream_rst_in(streamB, 0, 0);
1234    assert(s == 0);
1235    assert(2 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
1236    /* Verify A again: */
1237    n = read_from_scheduled_packets(&tobjs->send_ctl, streamA->id, buf,
1238                                                    sizeof(buf), 0, &fin, 0);
1239    assert(n == written_to_A);
1240    assert(0 == memcmp(buf, buf_out, written_to_A));
1241
1242    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0);
1243    assert(packet_out->po_packno == 1);
1244    lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out);
1245
1246    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0);
1247    assert(packet_out->po_packno == 2);
1248    lsquic_send_ctl_sent_packet(&tobjs->send_ctl, packet_out);
1249
1250    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs->send_ctl, 0);
1251    assert(!packet_out);
1252
1253    /* Now we can call on_close: */
1254    lsquic_stream_destroy(streamA);
1255    lsquic_stream_destroy(streamB);
1256}
1257
1258
1259
1260/* Write data to the stream, but do not flush: connection cap take a hit.
1261 * After stream is destroyed, connection cap should go back up.
1262 */
1263static void
1264test_reset_stream_with_unflushed_data (struct test_objs *tobjs)
1265{
1266    lsquic_stream_t *stream;
1267    char buf[0x100];
1268    size_t n;
1269    const struct lsquic_conn_cap *const cap = &tobjs->conn_pub.conn_cap;
1270
1271    assert(0x4000 == lsquic_conn_cap_avail(cap));   /* Self-check */
1272    stream = new_stream(tobjs, 345);
1273    n = lsquic_stream_write(stream, buf, 100);
1274    assert(n == 100);
1275
1276    /* Unflushed data counts towards connection cap for connection-limited
1277     * stream:
1278     */
1279    assert(0x4000 - 100 == lsquic_conn_cap_avail(cap));
1280
1281    lsquic_stream_destroy(stream);
1282    assert(0x4000 == lsquic_conn_cap_avail(cap));   /* Goes back up */
1283}
1284
1285
1286/* Write a little data to the stream, flush and then reset it: connection
1287 * cap should NOT go back up.
1288 */
1289static void
1290test_reset_stream_with_flushed_data (struct test_objs *tobjs)
1291{
1292    char buf[0x100];
1293    size_t n;
1294    lsquic_stream_t *stream;
1295    const struct lsquic_conn_cap *const cap = &tobjs->conn_pub.conn_cap;
1296
1297    assert(0x4000 == lsquic_conn_cap_avail(cap));   /* Self-check */
1298    stream = new_stream(tobjs, 345);
1299    n = lsquic_stream_write(stream, buf, 100);
1300    assert(n == 100);
1301
1302    /* Unflushed data counts towards connection cap for
1303     * connection-limited stream:
1304     */
1305    assert(0x4000 - 100 == lsquic_conn_cap_avail(cap));
1306
1307    /* Flush the stream: */
1308    lsquic_stream_flush(stream);
1309    assert(0x4000 - 100 == lsquic_conn_cap_avail(cap));
1310
1311    lsquic_stream_destroy(stream);
1312    assert(0x4000 - 100 == lsquic_conn_cap_avail(cap));   /* Still unchanged */
1313}
1314
1315
1316/* Write data to the handshake stream and flush: this should not affect
1317 * connection cap.
1318 */
1319static void
1320test_unlimited_stream_flush_data (struct test_objs *tobjs)
1321{
1322    char buf[0x100];
1323    size_t n;
1324    lsquic_stream_t *stream;
1325    const struct lsquic_conn_cap *const cap = &tobjs->conn_pub.conn_cap;
1326
1327    assert(0x4000 == lsquic_conn_cap_avail(cap));   /* Self-check */
1328    stream = new_stream(tobjs, 1);
1329    n = lsquic_stream_write(stream, buf, 100);
1330    assert(n == 100);
1331
1332    /* We DO NOT take connection cap hit after stream is flushed: */
1333    lsquic_stream_flush(stream);
1334    assert(0x4000 == lsquic_conn_cap_avail(cap));
1335
1336    lsquic_stream_reset(stream, 0xF00DF00D);
1337    assert(0x4000 == lsquic_conn_cap_avail(cap));   /* Still unchanged */
1338
1339    lsquic_stream_destroy(stream);
1340    assert(0x4000 == lsquic_conn_cap_avail(cap));   /* Still unchanged */
1341}
1342
1343
1344/* Test that data gets flushed when stream is closed. */
1345static void
1346test_data_flush_on_close (struct test_objs *tobjs)
1347{
1348    lsquic_stream_t *stream;
1349    const struct lsquic_conn_cap *const cap = &tobjs->conn_pub.conn_cap;
1350    char buf[0x100];
1351    size_t n;
1352
1353    assert(0x4000 == lsquic_conn_cap_avail(cap));   /* Self-check */
1354    stream = new_stream(tobjs, 345);
1355    n = lsquic_stream_write(stream, buf, 100);
1356    assert(n == 100);
1357    assert(0 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
1358
1359    lsquic_stream_close(stream);
1360    /* Nothing is scheduled because STREAM frames are elided */
1361    assert(0 == lsquic_send_ctl_n_scheduled(&tobjs->send_ctl));
1362
1363    assert(stream->sm_qflags & SMQF_SEND_RST);
1364    assert(!(stream->sm_qflags & SMQF_FREE_STREAM));
1365    assert(stream->sm_qflags & SMQF_WAIT_FIN_OFF);
1366
1367    /* We take connection cap hit after stream is flushed: */
1368    assert(0x4000 - 100 == lsquic_conn_cap_avail(cap)); /* Conn cap hit */
1369
1370    lsquic_stream_destroy(stream);
1371}
1372
1373
1374/* In this function, we test stream termination conditions.  In particular,
1375 * we are interested in when the stream becomes finished (this is when
1376 * connection closes it and starts ignoring frames that come after this):
1377 * we need to test the following scenarios, both normal and abnormal
1378 * termination, initiated both locally and remotely.
1379 *
1380 * We avoid formalities like calling wantread() and wantwrite() and
1381 * dispatching read and write callbacks.
1382 */
1383static void
1384test_termination (void)
1385{
1386    struct test_objs tobjs;
1387    unsigned i;
1388    void (*const test_funcs[])(struct test_objs *) = {
1389        test_loc_FIN_rem_FIN,
1390        test_rem_FIN_loc_FIN,
1391        test_rem_data_loc_close_and_rst_in,
1392        test_rem_data_loc_close,
1393        test_loc_FIN_rem_RST,
1394        test_loc_data_rem_RST,
1395        test_loc_RST_rem_FIN,
1396        test_gapless_elision_beginning,
1397        test_gapless_elision_middle,
1398    };
1399
1400    for (i = 0; i < sizeof(test_funcs) / sizeof(test_funcs[0]); ++i)
1401    {
1402        init_test_ctl_settings(&g_ctl_settings);
1403        g_ctl_settings.tcs_schedule_stream_packets_immediately = 1;
1404        init_test_objs(&tobjs, 0x4000, 0x4000, NULL);
1405        test_funcs[i](&tobjs);
1406        deinit_test_objs(&tobjs);
1407    }
1408}
1409
1410
1411/* Test flush-related corner cases */
1412static void
1413test_flushing (void)
1414{
1415    struct test_objs tobjs;
1416    unsigned i;
1417    void (*const test_funcs[])(struct test_objs *) = {
1418        test_reset_stream_with_unflushed_data,
1419        test_reset_stream_with_flushed_data,
1420        test_unlimited_stream_flush_data,
1421        test_data_flush_on_close,
1422    };
1423
1424    for (i = 0; i < sizeof(test_funcs) / sizeof(test_funcs[0]); ++i)
1425    {
1426        init_test_objs(&tobjs, 0x4000, 0x4000, NULL);
1427        test_funcs[i](&tobjs);
1428        deinit_test_objs(&tobjs);
1429    }
1430}
1431
1432
1433static void
1434test_writev (void)
1435{
1436    unsigned i;
1437    struct test_objs tobjs;
1438    lsquic_stream_t *stream;
1439    ssize_t n;
1440    unsigned char buf_in[0x4000];
1441    unsigned char buf_out[0x4000];
1442    int fin;
1443
1444    struct {
1445        struct iovec iov[0x20];
1446        int          count;
1447    } tests[] = {
1448        { .iov  = {
1449            { .iov_base = buf_in, .iov_len  = 0x4000, },
1450          },
1451          .count = 1,
1452        },
1453        { .iov  = {
1454            { .iov_base = buf_in         , .iov_len  = 0x1000, },
1455            { .iov_base = buf_in + 0x1000, .iov_len  = 0x3000, },
1456          },
1457          .count = 2,
1458        },
1459        { .iov  = {
1460            { .iov_base = buf_in         , .iov_len  = 0x1000, },
1461            { .iov_base = buf_in + 0x1000, .iov_len  = 0x1000, },
1462            { .iov_base = buf_in + 0x2000, .iov_len  = 0x1000, },
1463            { .iov_base = buf_in + 0x3000, .iov_len  = 0x1000, },
1464          },
1465          .count = 4,
1466        },
1467        { .iov  = {
1468            { .iov_base = buf_in         , .iov_len  = 0x1000, },
1469            { .iov_base = buf_in + 0x1000, .iov_len  = 0x1000, },
1470            { .iov_base = buf_in + 0x2000, .iov_len  = 0x1000, },
1471            { .iov_base = buf_in + 0x3000, .iov_len  = 0xFF0,  },
1472            { .iov_base = buf_in + 0x3FF0, .iov_len  = 1,      },
1473            { .iov_base = buf_in + 0x3FF1, .iov_len  = 0,      },
1474            { .iov_base = buf_in + 0x3FF1, .iov_len  = 0,      },
1475            { .iov_base = buf_in + 0x3FF1, .iov_len  = 1,      },
1476            { .iov_base = buf_in + 0x3FF2, .iov_len  = 1,      },
1477            { .iov_base = buf_in + 0x3FF3, .iov_len  = 1,      },
1478            { .iov_base = buf_in + 0x3FF4, .iov_len  = 1,      },
1479            { .iov_base = buf_in + 0x3FF5, .iov_len  = 1,      },
1480            { .iov_base = buf_in + 0x3FF6, .iov_len  = 1,      },
1481            { .iov_base = buf_in + 0x3FF7, .iov_len  = 1,      },
1482            { .iov_base = buf_in + 0x3FF8, .iov_len  = 1,      },
1483            { .iov_base = buf_in + 0x3FF9, .iov_len  = 1,      },
1484            { .iov_base = buf_in + 0x3FFA, .iov_len  = 1,      },
1485            { .iov_base = buf_in + 0x3FFB, .iov_len  = 1,      },
1486            { .iov_base = buf_in + 0x3FFC, .iov_len  = 1,      },
1487            { .iov_base = buf_in + 0x3FFD, .iov_len  = 1,      },
1488            { .iov_base = buf_in + 0x3FFE, .iov_len  = 1,      },
1489            { .iov_base = buf_in + 0x3FFF, .iov_len  = 1,      },
1490          },
1491          .count = 22,
1492        },
1493    };
1494
1495    memset(buf_in,          'A', 0x1000);
1496    memset(buf_in + 0x1000, 'B', 0x1000);
1497    memset(buf_in + 0x2000, 'C', 0x1000);
1498    memset(buf_in + 0x3000, 'D', 0x1000);
1499
1500    for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
1501    {
1502        init_test_objs(&tobjs, UINT_MAX, UINT_MAX, NULL);
1503        stream = new_stream(&tobjs, 12345);
1504        n = lsquic_stream_writev(stream, tests[i].iov, tests[i].count);
1505        assert(0x4000 == n);
1506        lsquic_stream_flush(stream);
1507        n = read_from_scheduled_packets(&tobjs.send_ctl, stream->id, buf_out,
1508                                                sizeof(buf_out), 0, &fin, 0);
1509        assert(0x4000 == n);
1510        assert(0 == memcmp(buf_out, buf_in, 0x1000));
1511        assert(!fin);
1512        lsquic_stream_destroy(stream);
1513        deinit_test_objs(&tobjs);
1514    }
1515}
1516
1517
1518static void
1519test_prio_conversion (void)
1520{
1521    struct test_objs tobjs;
1522    lsquic_stream_t *stream;
1523    unsigned prio;
1524    int s;
1525
1526    init_test_objs(&tobjs, UINT_MAX, UINT_MAX, NULL);
1527    stream = new_stream(&tobjs, 123);
1528
1529    s = lsquic_stream_set_priority(stream, -2);
1530    assert(-1 == s);
1531    s = lsquic_stream_set_priority(stream, 0);
1532    assert(-1 == s);
1533    s = lsquic_stream_set_priority(stream, 257);
1534    assert(-1 == s);
1535
1536    for (prio = 1; prio <= 256; ++prio)
1537    {
1538        s = lsquic_stream_set_priority(stream, prio);
1539        assert(0 == s);
1540        assert(prio == lsquic_stream_priority(stream));
1541    }
1542
1543    lsquic_stream_destroy(stream);
1544    deinit_test_objs(&tobjs);
1545}
1546
1547
1548static void
1549test_read_in_middle (void)
1550{
1551    int s;
1552    size_t nw = 0;
1553    char buf[0x1000];
1554    const char data[] = "AAABBBCCC";
1555    struct test_objs tobjs;
1556    stream_frame_t *frame;
1557    uint64_t n_readable;
1558
1559    init_test_objs(&tobjs, 0x4000, 0x4000, NULL);
1560
1561    lsquic_stream_t *stream = new_stream(&tobjs, 123);
1562
1563    frame = new_frame_in_ext(&tobjs, 0, 3, 0, &data[0]);
1564    s = lsquic_stream_frame_in(stream, frame);
1565    assert(0 == s);
1566    n_readable = stream->data_in->di_if->di_readable_bytes(stream->data_in, 0);
1567    assert(3 == n_readable);
1568
1569    /* Hole */
1570
1571    frame = new_frame_in_ext(&tobjs, 6, 3, 0, &data[6]);
1572    s = lsquic_stream_frame_in(stream, frame);
1573    assert(0 == s);
1574    n_readable = stream->data_in->di_if->di_readable_bytes(stream->data_in, 0);
1575    assert(3 == n_readable);
1576
1577    /* Read up to hole */
1578
1579    nw = lsquic_stream_read(stream, buf, sizeof(buf));
1580    assert(3 == nw);
1581    assert(0 == memcmp(buf, "AAA", 3));
1582    n_readable = stream->data_in->di_if->di_readable_bytes(stream->data_in, 3);
1583    assert(0 == n_readable);
1584
1585    frame = new_frame_in_ext(&tobjs, 3, 3, 0, &data[3]);
1586    s = lsquic_stream_frame_in(stream, frame);
1587    assert(0 == s);
1588    n_readable = stream->data_in->di_if->di_readable_bytes(stream->data_in, 3);
1589    assert(6 == n_readable);
1590
1591    nw = lsquic_stream_read(stream, buf, sizeof(buf));
1592    assert(6 == nw);
1593    assert(0 == memcmp(buf, "BBBCCC", 6));
1594    n_readable = stream->data_in->di_if->di_readable_bytes(stream->data_in, 9);
1595    assert(0 == n_readable);
1596
1597    lsquic_stream_destroy(stream);
1598    deinit_test_objs(&tobjs);
1599}
1600
1601
1602/* Test that connection flow control does not go past the max when both
1603 * connection limited and unlimited streams are used.
1604 */
1605static void
1606test_conn_unlimited (void)
1607{
1608    size_t nw;
1609    struct test_objs tobjs;
1610    lsquic_stream_t *header_stream, *data_stream;
1611
1612    init_test_objs(&tobjs, 0x4000, 0x4000, NULL);
1613
1614    unsigned char *const data = calloc(1, 0x4000);
1615
1616    /* Test 1: first write headers, then data stream */
1617    header_stream = new_stream(&tobjs, 1);
1618    data_stream = new_stream(&tobjs, 123);
1619    nw = lsquic_stream_write(header_stream, data, 98);
1620    assert(98 == nw);
1621    lsquic_stream_flush(header_stream);
1622    nw = lsquic_stream_write(data_stream, data, 0x4000);
1623    assert(0x4000 == nw);
1624    assert(tobjs.conn_pub.conn_cap.cc_sent <= tobjs.conn_pub.conn_cap.cc_max);
1625    lsquic_stream_destroy(header_stream);
1626    lsquic_stream_destroy(data_stream);
1627
1628    /* Test 2: first write data, then headers stream */
1629    header_stream = new_stream(&tobjs, 1);
1630    data_stream = new_stream(&tobjs, 123);
1631    lsquic_conn_cap_init(&tobjs.conn_pub.conn_cap, 0x4000);
1632    nw = lsquic_stream_write(data_stream, data, 0x4000);
1633    assert(0x4000 == nw);
1634    nw = lsquic_stream_write(header_stream, data, 98);
1635    assert(98 == nw);
1636    lsquic_stream_flush(header_stream);
1637    assert(tobjs.conn_pub.conn_cap.cc_sent <= tobjs.conn_pub.conn_cap.cc_max);
1638
1639    lsquic_stream_destroy(header_stream);
1640    lsquic_stream_destroy(data_stream);
1641
1642    deinit_test_objs(&tobjs);
1643    free(data);
1644}
1645
1646
1647static void
1648test_reading_from_stream2 (void)
1649{
1650    struct test_objs tobjs;
1651    char buf[0x1000];
1652    struct iovec iov[2];
1653    lsquic_packet_in_t *packet_in;
1654    lsquic_stream_t *stream;
1655    stream_frame_t *frame;
1656    ssize_t nw;
1657    int s;
1658    enum stream_state_receiving ssr;
1659    const char data[] = "1234567890";
1660
1661    init_test_objs(&tobjs, 0x4000, 0x4000, NULL);
1662    stream = new_stream(&tobjs, 123);
1663    ssr = lsquic_stream_receiving_state(stream);
1664    assert(SSR_RECV == ssr);
1665
1666    frame = new_frame_in_ext(&tobjs, 0, 6, 0, &data[0]);
1667    s = lsquic_stream_frame_in(stream, frame);
1668    assert(("Inserted frame #1", 0 == s));
1669
1670    frame = new_frame_in_ext(&tobjs, 6, 4, 0, &data[6]);
1671    s = lsquic_stream_frame_in(stream, frame);
1672    assert(("Inserted frame #2", 0 == s));
1673
1674    /* Invalid frame: FIN in the middle */
1675    frame = new_frame_in(&tobjs, 6, 0, 1);
1676    s = lsquic_stream_frame_in(stream, frame);
1677    assert(("Invalid frame: FIN in the middle", -1 == s));
1678
1679    /* Test for overlaps and DUPs: */
1680    if (!(stream_ctor_flags & SCF_USE_DI_HASH))
1681    {
1682        int dup;
1683        unsigned offset, length;
1684        for (offset = 0; offset < 7; ++offset)
1685        {
1686            for (length = 1; length <= sizeof(data) - 1 - offset; ++length)
1687            {
1688                dup = (offset == 0 && length == 6)
1689                   || (offset == 6 && length == 4);
1690                frame = new_frame_in_ext(&tobjs, offset, length, 0, data + offset);
1691                s = lsquic_stream_frame_in(stream, frame);
1692                if (dup)
1693                    assert(("Dup OK", 0 == s));
1694                else
1695                    assert(("Overlap OK", 0 == s));
1696            }
1697        }
1698    }
1699
1700    {
1701        uint64_t n_readable;
1702
1703        n_readable = stream->data_in->di_if
1704                                    ->di_readable_bytes(stream->data_in, 0);
1705        assert(10 == n_readable);
1706    }
1707
1708    nw = lsquic_stream_read(stream, buf, 8);
1709    assert(("Read 8 bytes", nw == 8));
1710    assert(("Expected 8 bytes", 0 == memcmp(buf, "12345678", nw)));
1711
1712    /* Insert invalid frame: its offset + length is before the already-read
1713     * offset.
1714     */
1715    frame = new_frame_in_ext(&tobjs, 0, 6, 0, &data[0]);
1716    packet_in = lsquic_packet_in_get(frame->packet_in); /* incref to check for dups below */
1717    assert(2 == packet_in->pi_refcnt);  /* Self-check */
1718    s = lsquic_stream_frame_in(stream, frame);
1719    assert(("Insert frame before already-read offset succeeds (duplicate)",
1720                                                                s == 0));
1721    assert(("Duplicate frame has been thrown out",
1722                                        packet_in->pi_refcnt == 1));
1723    lsquic_packet_in_put(&tobjs.eng_pub.enp_mm, packet_in);
1724    packet_in = NULL;
1725
1726    iov[0].iov_base = buf;
1727    iov[0].iov_len  = 1;
1728    iov[1].iov_base = buf + 1;
1729    iov[1].iov_len  = sizeof(buf) - 1;
1730    nw = lsquic_stream_readv(stream, iov, 2);
1731    assert(("Read 2 bytes", nw == 2));
1732    assert(("Expected 2 bytes", 0 == memcmp(buf, "90", nw)));
1733    nw = lsquic_stream_read(stream, buf, 8);
1734    assert(("Read -1 bytes (EWOULDBLOCK)", -1 == nw && errno == EWOULDBLOCK));
1735    nw = lsquic_stream_read(stream, buf, 8);
1736    assert(("Read -1 bytes again (EWOULDBLOCK)", -1 == nw && errno == EWOULDBLOCK));
1737
1738    /* Insert invalid frame: its offset + length is before the already-read
1739     * offset.  This test is different from before: now there is buffered
1740     * incoming data.
1741     */
1742    frame = new_frame_in_ext(&tobjs, 0, 6, 0, &data[0]);
1743    packet_in = lsquic_packet_in_get(frame->packet_in); /* incref to check for dups below */
1744    assert(2 == packet_in->pi_refcnt);  /* Self-check */
1745    s = lsquic_stream_frame_in(stream, frame);
1746    assert(("Insert frame before already-read offset succeeds (duplicate)",
1747                                                                s == 0));
1748    assert(("Duplicate frame has been thrown out",
1749                                        packet_in->pi_refcnt == 1));
1750    lsquic_packet_in_put(&tobjs.eng_pub.enp_mm, packet_in);
1751    packet_in = NULL;
1752
1753    /* Last frame has no data but has a FIN flag set */
1754    frame = new_frame_in_ext(&tobjs, 10, 0, 1,
1755                (void *) 1234     /* Intentionally invalid: this pointer
1756                                   * should not be used
1757                                   */);
1758    s = lsquic_stream_frame_in(stream, frame);
1759    assert(("Inserted frame #3", 0 == s));
1760    ssr = lsquic_stream_receiving_state(stream);
1761    assert(SSR_DATA_RECVD == ssr);
1762
1763    /* Invalid frame: writing after FIN */
1764    frame = new_frame_in(&tobjs, 10, 2, 0);
1765    s = lsquic_stream_frame_in(stream, frame);
1766    assert(("Invalid frame caught", -1 == s));
1767
1768    /* Duplicate FIN frame */
1769    frame = new_frame_in_ext(&tobjs, 10, 0, 1,
1770                (void *) 1234     /* Intentionally invalid: this pointer
1771                                   * should not be used
1772                                   */);
1773    s = lsquic_stream_frame_in(stream, frame);
1774    assert(("Duplicate FIN frame", 0 == s));
1775
1776    nw = lsquic_stream_read(stream, buf, 1);
1777    assert(("Read 0 bytes (at EOR)", 0 == nw));
1778    ssr = lsquic_stream_receiving_state(stream);
1779    assert(SSR_DATA_READ == ssr);
1780
1781    lsquic_stream_destroy(stream);
1782    deinit_test_objs(&tobjs);
1783}
1784
1785
1786/* This tests stream overlap support */
1787static void
1788test_overlaps (void)
1789{
1790    struct test_objs tobjs;
1791    char buf[0x1000];
1792    lsquic_stream_t *stream;
1793    stream_frame_t *frame;
1794    int s;
1795    const char data[] = "1234567890";
1796
1797    struct frame_spec
1798    {
1799        unsigned    off;
1800        unsigned    len;
1801        signed char fin;
1802    };
1803
1804    struct frame_step
1805    {
1806        struct frame_spec   frame_spec;
1807        int                 insert_res;     /* Expected result */
1808    };
1809
1810    struct overlap_test
1811    {
1812        int                 line;           /* Test identifier */
1813        struct frame_step   steps[10];      /* Sequence of steps */
1814        unsigned            n_steps;
1815        const unsigned char buf[20];        /* Expected result of read */
1816        ssize_t             sz;             /* Expected size of first read */
1817        ssize_t             second_read;    /* Expected size of second read:
1818                                             *   0 means EOS (FIN).
1819                                             */
1820    };
1821
1822    static const struct overlap_test tests[] =
1823    {
1824
1825        {
1826            .line   = __LINE__,
1827            .steps  =
1828            {
1829                {
1830                    .frame_spec = { .off = 0, .len = 10, .fin = 0, },
1831                    .insert_res = 0,
1832                },
1833            },
1834            .n_steps = 1,
1835            .buf = "0123456789",
1836            .sz = 10,
1837            .second_read = -1,
1838        },
1839
1840        {
1841            .line   = __LINE__,
1842            .steps  =
1843            {
1844                {
1845                    .frame_spec = { .off = 0, .len = 5, .fin = 0, },
1846                    .insert_res = 0,
1847                },
1848                {
1849                    .frame_spec = { .off = 0, .len = 10, .fin = 0, },
1850                    .insert_res = 0,
1851                },
1852            },
1853            .n_steps = 2,
1854            .buf = "0123456789",
1855            .sz = 10,
1856            .second_read = -1,
1857        },
1858
1859        {
1860            .line   = __LINE__,
1861            .steps  =
1862            {
1863                {
1864                    .frame_spec = { .off = 1, .len = 9, .fin = 0, },
1865                    .insert_res = 0,
1866                },
1867                {
1868                    .frame_spec = { .off = 1, .len = 9, .fin = 1, },
1869                    .insert_res = 0,
1870                },
1871                {
1872                    .frame_spec = { .off = 0, .len = 2, .fin = 0, },
1873                    .insert_res = 0,
1874                },
1875                {
1876                    .frame_spec = { .off = 2, .len = 6, .fin = 0, },
1877                    .insert_res = 0,
1878                },
1879            },
1880            .n_steps = 4,
1881            .buf = "0123456789",
1882            .sz = 10,
1883            .second_read = 0,
1884        },
1885
1886        {
1887            .line   = __LINE__,
1888            .steps  =
1889            {
1890                {
1891                    .frame_spec = { .off = 1, .len = 9, .fin = 1, },
1892                    .insert_res = 0,
1893                },
1894                {
1895                    .frame_spec = { .off = 0, .len = 2, .fin = 0, },
1896                    .insert_res = 0,
1897                },
1898            },
1899            .n_steps = 2,
1900            .buf = "0123456789",
1901            .sz = 10,
1902            .second_read = 0,
1903        },
1904
1905        {
1906            .line   = __LINE__,
1907            .steps  =
1908            {
1909                { .frame_spec = { .off = 1, .len = 6, .fin = 0, }, .insert_res = 0, },
1910                { .frame_spec = { .off = 2, .len = 1, .fin = 0, }, .insert_res = 0, },
1911                { .frame_spec = { .off = 8, .len = 2, .fin = 1, }, .insert_res = 0, },
1912                { .frame_spec = { .off = 3, .len = 2, .fin = 0, }, .insert_res = 0, },
1913                { .frame_spec = { .off = 4, .len = 1, .fin = 0, }, .insert_res = 0, },
1914                { .frame_spec = { .off = 5, .len = 2, .fin = 0, }, .insert_res = 0, },
1915                { .frame_spec = { .off = 6, .len = 1, .fin = 0, }, .insert_res = 0, },
1916                { .frame_spec = { .off = 7, .len = 3, .fin = 0, }, .insert_res = 0, },
1917                { .frame_spec = { .off = 9, .len = 1, .fin = 1, }, .insert_res = 0, },
1918                { .frame_spec = { .off = 0, .len = 2, .fin = 0, }, .insert_res = 0, },
1919            },
1920            .n_steps = 10,
1921            .buf = "0123456789",
1922            .sz = 10,
1923            .second_read = 0,
1924        },
1925
1926    };
1927
1928    init_test_objs(&tobjs, 0x4000, 0x4000, NULL);
1929
1930    const struct overlap_test *test;
1931    for (test = tests; test < tests + sizeof(tests) / sizeof(tests[0]); ++test)
1932    {
1933        LSQ_NOTICE("executing stream overlap test, line %d", test->line);
1934        stream = new_stream(&tobjs, test->line);
1935
1936        const struct frame_step *step;
1937        for (step = test->steps; step < test->steps + test->n_steps; ++step)
1938        {
1939            frame = new_frame_in_ext(&tobjs, step->frame_spec.off,
1940                step->frame_spec.len, step->frame_spec.fin,
1941                &data[step->frame_spec.off]);
1942            s = lsquic_stream_frame_in(stream, frame);
1943            assert(s == step->insert_res);
1944        }
1945
1946        ssize_t nread = lsquic_stream_read(stream, buf, sizeof(buf));
1947        assert(nread == test->sz);
1948        assert(0 == memcmp(data, buf, test->sz));
1949        nread = lsquic_stream_read(stream, buf, sizeof(buf));
1950        assert(nread == test->second_read);
1951        if (nread < 0)
1952            assert(EWOULDBLOCK == errno);
1953
1954        lsquic_stream_destroy(stream);
1955    }
1956
1957    {
1958        LSQ_NOTICE("Special test on line %d", __LINE__);
1959        stream = new_stream(&tobjs, __LINE__);
1960        frame = new_frame_in_ext(&tobjs, 0, 5, 0, &data[0]);
1961        s = lsquic_stream_frame_in(stream, frame);
1962        assert(0 == s);
1963        ssize_t nread = lsquic_stream_read(stream, buf, sizeof(buf));
1964        assert(nread == 5);
1965        assert(0 == memcmp(data, buf, 5));
1966        nread = lsquic_stream_read(stream, buf, sizeof(buf));
1967        assert(nread < 0);
1968        assert(EWOULDBLOCK == errno);
1969        /* Test that a frame with FIN that ends before the read offset
1970         * results in an error.
1971         */
1972        frame = new_frame_in_ext(&tobjs, 0, 3, 1, &data[0]);
1973        s = lsquic_stream_frame_in(stream, frame);
1974        assert(s < 0);
1975        /* This frame should be a DUP: the next read should still return -1.
1976         */
1977        frame = new_frame_in_ext(&tobjs, 3, 2, 0, &data[3]);
1978        s = lsquic_stream_frame_in(stream, frame);
1979        assert(s == 0);
1980        nread = lsquic_stream_read(stream, buf, sizeof(buf));
1981        assert(nread < 0);
1982        assert(EWOULDBLOCK == errno);
1983        /* This frame should be an overlap: FIN should register and
1984         * the next read should return 0.
1985         */
1986        frame = new_frame_in_ext(&tobjs, 0, 5, 1, &data[0]);
1987        s = lsquic_stream_frame_in(stream, frame);
1988        assert(s == 0);
1989        nread = lsquic_stream_read(stream, buf, sizeof(buf));
1990        assert(nread == 0);
1991        lsquic_stream_destroy(stream);
1992    }
1993
1994    {
1995        LSQ_NOTICE("Special test for bug 106 on line %d", __LINE__);
1996        char *const data = malloc(5862);
1997        init_buf(data, 5862);
1998        assert(data);
1999        stream = new_stream(&tobjs, __LINE__);
2000        /* Insert four frames: */
2001        frame = new_frame_in_ext(&tobjs, 0, 1173, 0, data);
2002        s = lsquic_stream_frame_in(stream, frame);
2003        assert(0 == s);
2004        frame = new_frame_in_ext(&tobjs, 1173, 1173, 0, data + 1173);
2005        s = lsquic_stream_frame_in(stream, frame);
2006        assert(0 == s);
2007        frame = new_frame_in_ext(&tobjs, 2346, 1172, 0, data + 2346);
2008        s = lsquic_stream_frame_in(stream, frame);
2009        assert(0 == s);
2010        frame = new_frame_in_ext(&tobjs, 3518, 578, 0, data + 3518);
2011        s = lsquic_stream_frame_in(stream, frame);
2012        assert(0 == s);
2013        /* Read all data: */
2014        ssize_t nread = lsquic_stream_read(stream, buf, sizeof(buf));
2015        assert(nread == 4096);
2016        assert(0 == memcmp(data, buf, 4096));
2017        nread = lsquic_stream_read(stream, buf, sizeof(buf));
2018        assert(nread < 0);
2019        assert(EWOULDBLOCK == errno);
2020        /* Insert overlapped frame and one more: */
2021        frame = new_frame_in_ext(&tobjs, 3518, 1172, 0, data + 3518);
2022        s = lsquic_stream_frame_in(stream, frame);
2023        assert(0 == s);
2024        frame = new_frame_in_ext(&tobjs, 4690, 1172, 0, data + 4690);
2025        s = lsquic_stream_frame_in(stream, frame);
2026        assert(0 == s);
2027        /* Verify that continued read from offset 4096 succeeds and
2028         * contains expected data:
2029         */
2030        nread = lsquic_stream_read(stream, buf, sizeof(buf));
2031        assert(nread == 5862 - 4096);
2032        assert(0 == memcmp(data + 4096, buf, 5862 - 4096));
2033        lsquic_stream_destroy(stream);
2034        free(data);
2035    }
2036
2037    deinit_test_objs(&tobjs);
2038}
2039
2040
2041static void
2042test_insert_edge_cases (void)
2043{
2044    struct test_objs tobjs;
2045    lsquic_stream_t *stream;
2046    stream_frame_t *frame;
2047    int s;
2048    ssize_t nread;
2049    const char data[] = "1234567890";
2050    enum stream_state_receiving ssr;
2051    unsigned buf[0x1000];
2052
2053    init_test_objs(&tobjs, 0x4000, 0x4000, NULL);
2054
2055    {
2056        stream = new_stream(&tobjs, 123);
2057        frame = new_frame_in_ext(&tobjs, 0, 6, 1, &data[0]);
2058        s = lsquic_stream_frame_in(stream, frame);
2059        assert(("Inserted frame #1", 0 == s));
2060        ssr = lsquic_stream_receiving_state(stream);
2061        assert(SSR_DATA_RECVD == ssr);
2062        /* Invalid frame: different FIN location */
2063        frame = new_frame_in_ext(&tobjs, 3, 2, 1, &data[3]);
2064        s = lsquic_stream_frame_in(stream, frame);
2065        assert(("Invalid frame: different FIN location", -1 == s));
2066        lsquic_stream_destroy(stream);
2067    }
2068
2069    {
2070        stream = new_stream(&tobjs, 123);
2071        frame = new_frame_in_ext(&tobjs, 0, 6, 0, &data[0]);
2072        s = lsquic_stream_frame_in(stream, frame);
2073        assert(("Inserted frame #1", 0 == s));
2074        nread = lsquic_stream_read(stream, buf, sizeof(buf));
2075        assert(6 == nread);
2076        frame = new_frame_in_ext(&tobjs, 6, 0, 0, &data[6]);
2077        s = lsquic_stream_frame_in(stream, frame);
2078        assert(("Duplicate frame", 0 == s));
2079        nread = lsquic_stream_read(stream, buf, sizeof(buf));
2080        assert(nread == -1 && errno == EWOULDBLOCK);
2081        frame = new_frame_in_ext(&tobjs, 6, 0, 1, &data[6]);
2082        s = lsquic_stream_frame_in(stream, frame);
2083        assert(("Frame OK", 0 == s));
2084        nread = lsquic_stream_read(stream, buf, sizeof(buf));
2085        assert(nread == 0); /* Hit EOF */
2086        frame = new_frame_in_ext(&tobjs, 6, 0, 1, &data[6]);
2087        s = lsquic_stream_frame_in(stream, frame);
2088        assert(("Duplicate FIN frame", 0 == s));
2089        lsquic_stream_destroy(stream);
2090    }
2091
2092    {
2093        stream = new_stream(&tobjs, 123);
2094        frame = new_frame_in_ext(&tobjs, 6, 0, 1, &data[6]);
2095        s = lsquic_stream_frame_in(stream, frame);
2096        assert(("Frame OK", 0 == s));
2097        ssr = lsquic_stream_receiving_state(stream);
2098        assert(SSR_SIZE_KNOWN == ssr);
2099        frame = new_frame_in_ext(&tobjs, 0, 6, 0, &data[0]);
2100        s = lsquic_stream_frame_in(stream, frame);
2101        assert(("Inserted frame #1", 0 == s));
2102        nread = lsquic_stream_read(stream, buf, sizeof(buf));
2103        assert(6 == nread);
2104        frame = new_frame_in_ext(&tobjs, 6, 0, 0, &data[6]);
2105        s = lsquic_stream_frame_in(stream, frame);
2106        assert(("Duplicate frame", 0 == s));
2107        nread = lsquic_stream_read(stream, buf, sizeof(buf));
2108        assert(nread == 0); /* Hit EOF */
2109        frame = new_frame_in_ext(&tobjs, 6, 0, 1, &data[6]);
2110        s = lsquic_stream_frame_in(stream, frame);
2111        assert(("Duplicate FIN frame", 0 == s));
2112        lsquic_stream_destroy(stream);
2113    }
2114
2115    {
2116        stream = new_stream(&tobjs, 123);
2117        frame = new_frame_in_ext(&tobjs, 0, 6, 1, &data[0]);
2118        s = lsquic_stream_frame_in(stream, frame);
2119        assert(("Inserted frame #1", 0 == s));
2120        nread = lsquic_stream_read(stream, buf, sizeof(buf));
2121        assert(6 == nread);
2122        nread = lsquic_stream_read(stream, buf, sizeof(buf));
2123        assert(0 == nread); /* Hit EOF */
2124        frame = new_frame_in_ext(&tobjs, 0, 6, 1, &data[0]);
2125        s = lsquic_stream_frame_in(stream, frame);
2126        assert(("Inserted duplicate frame", 0 == s));
2127        lsquic_stream_destroy(stream);
2128    }
2129
2130    deinit_test_objs(&tobjs);
2131}
2132
2133
2134/* When HTTP stream is closed unexpectedly, send a reset instead of creating
2135 * an empty STREAM frame with a FIN bit set.
2136 */
2137static void
2138test_unexpected_http_close (void)
2139{
2140    struct test_objs tobjs;
2141    lsquic_stream_t *stream;
2142    int s;
2143
2144    stream_ctor_flags |= SCF_HTTP;
2145    init_test_objs(&tobjs, 0x4000, 0x4000, NULL);
2146
2147    stream = new_stream(&tobjs, 123);
2148    assert(stream->sm_bflags & SMBF_USE_HEADERS);   /* Self-check */
2149    s = lsquic_stream_close(stream);
2150    assert(s == 0);
2151    assert(stream->sm_qflags & SMQF_SEND_RST);
2152    assert(stream->sm_qflags & SMQF_CALL_ONCLOSE);
2153    assert(!lsquic_send_ctl_has_buffered(&tobjs.send_ctl));
2154
2155    lsquic_stream_destroy(stream);
2156    deinit_test_objs(&tobjs);
2157    stream_ctor_flags &= ~SCF_HTTP;
2158}
2159
2160
2161static void
2162test_writing_to_stream_schedule_stream_packets_immediately (void)
2163{
2164    ssize_t nw;
2165    struct test_objs tobjs;
2166    struct lsquic_conn *const lconn = &tobjs.lconn;
2167    struct lsquic_stream *stream;
2168    int s;
2169    unsigned char buf[0x1000];
2170    struct lsquic_conn_cap *const conn_cap = &tobjs.conn_pub.conn_cap;
2171
2172    init_test_ctl_settings(&g_ctl_settings);
2173    g_ctl_settings.tcs_schedule_stream_packets_immediately = 1;
2174
2175    init_test_objs(&tobjs, 0x4000, 0x4000, NULL);
2176    n_closed = 0;
2177    stream = new_stream(&tobjs, 123);
2178    assert(("Stream initialized", stream));
2179    const struct test_ctx *const test_ctx_local  = tobjs.stream_if_ctx;
2180    assert(("on_new_stream called correctly", stream == test_ctx_local->stream));
2181    assert(LSQUIC_STREAM_DEFAULT_PRIO == lsquic_stream_priority(stream));
2182
2183    assert(lconn == lsquic_stream_conn(stream));
2184
2185    nw = lsquic_stream_write(stream, "Dude, where is", 14);
2186    assert(("14 bytes written correctly", nw == 14));
2187
2188    assert(("not packetized",
2189                        0 == lsquic_send_ctl_n_scheduled(&tobjs.send_ctl)));
2190    /* Cap hit is taken immediately, even for flushed data */
2191    assert(("connection cap is reduced by 14 bytes",
2192                    lsquic_conn_cap_avail(conn_cap) == 0x4000 - 14));
2193    s = lsquic_stream_flush(stream);
2194    assert(0 == s);
2195    assert(("packetized -- 1 packet",
2196                        1 == lsquic_send_ctl_n_scheduled(&tobjs.send_ctl)));
2197
2198    nw = lsquic_stream_write(stream, " my car?!", 9);
2199    assert(("9 bytes written correctly", nw == 9));
2200    s = lsquic_stream_flush(stream);
2201    assert(0 == s);
2202    assert(("packetized -- still 1 packet",
2203                        1 == lsquic_send_ctl_n_scheduled(&tobjs.send_ctl)));
2204
2205    assert(("connection cap is reduced by 23 bytes",
2206                    lsquic_conn_cap_avail(conn_cap) == 0x4000 - 23));
2207
2208    nw = read_from_scheduled_packets(&tobjs.send_ctl, stream->id, buf,
2209                                                    sizeof(buf), 0, NULL, 0);
2210    assert(23 == nw);
2211    assert(0 == memcmp(buf, "Dude, where is my car?!", 23));
2212    assert(("cannot reduce max_send below what's been sent already",
2213                            -1 == lsquic_stream_set_max_send_off(stream, 15)));
2214    assert(("cannot reduce max_send below what's been sent already #2",
2215                            -1 == lsquic_stream_set_max_send_off(stream, 22)));
2216    assert(("can set to the same value...",
2217                             0 == lsquic_stream_set_max_send_off(stream, 23)));
2218    assert(("...or larger",
2219                             0 == lsquic_stream_set_max_send_off(stream, 23000)));
2220    lsquic_stream_destroy(stream);
2221    assert(("on_close called", 1 == n_closed));
2222    deinit_test_objs(&tobjs);
2223}
2224
2225
2226static void
2227test_writing_to_stream_outside_callback (void)
2228{
2229    ssize_t nw;
2230    struct test_objs tobjs;
2231    struct lsquic_conn *const lconn = &tobjs.lconn;
2232    struct lsquic_stream *stream;
2233    int s;
2234    unsigned char buf[0x1000];
2235    struct lsquic_conn_cap *const conn_cap = &tobjs.conn_pub.conn_cap;
2236
2237    init_test_ctl_settings(&g_ctl_settings);
2238    g_ctl_settings.tcs_schedule_stream_packets_immediately = 0;
2239    g_ctl_settings.tcs_bp_type = BPT_OTHER_PRIO;
2240    const struct buf_packet_q *const bpq =
2241            &tobjs.send_ctl.sc_buffered_packets[g_ctl_settings.tcs_bp_type];
2242
2243    init_test_objs(&tobjs, 0x4000, 0x4000, NULL);
2244    n_closed = 0;
2245    stream = new_stream(&tobjs, 123);
2246    assert(("Stream initialized", stream));
2247    const struct test_ctx *const test_ctx_local = tobjs.stream_if_ctx;
2248    assert(("on_new_stream called correctly", stream == test_ctx_local->stream));
2249    assert(LSQUIC_STREAM_DEFAULT_PRIO == lsquic_stream_priority(stream));
2250
2251    assert(lconn == lsquic_stream_conn(stream));
2252
2253    nw = lsquic_stream_write(stream, "Dude, where is", 14);
2254    assert(("14 bytes written correctly", nw == 14));
2255
2256    assert(("not packetized", 0 == bpq->bpq_count));
2257    s = lsquic_stream_flush(stream);
2258    assert(0 == s);
2259    assert(("packetized -- 1 packet", 1 == bpq->bpq_count));
2260
2261    nw = lsquic_stream_write(stream, " my car?!", 9);
2262    assert(("9 bytes written correctly", nw == 9));
2263    s = lsquic_stream_flush(stream);
2264    assert(0 == s);
2265    assert(("packetized -- still 1 packet", 1 == bpq->bpq_count));
2266
2267    assert(("connection cap is reduced by 23 bytes",
2268                    lsquic_conn_cap_avail(conn_cap) == 0x4000 - 23));
2269
2270    /* Now we are magically inside the callback: */
2271    g_ctl_settings.tcs_schedule_stream_packets_immediately = 1;
2272    lsquic_send_ctl_schedule_buffered(&tobjs.send_ctl,
2273                                                g_ctl_settings.tcs_bp_type);
2274    assert(("packetized -- 1 packet",
2275                        1 == lsquic_send_ctl_n_scheduled(&tobjs.send_ctl)));
2276
2277    nw = read_from_scheduled_packets(&tobjs.send_ctl, stream->id, buf,
2278                                                    sizeof(buf), 0, NULL, 0);
2279    assert(23 == nw);
2280    assert(0 == memcmp(buf, "Dude, where is my car?!", 23));
2281    assert(("cannot reduce max_send below what's been sent already",
2282                            -1 == lsquic_stream_set_max_send_off(stream, 15)));
2283    assert(("cannot reduce max_send below what's been sent already #2",
2284                            -1 == lsquic_stream_set_max_send_off(stream, 22)));
2285    assert(("can set to the same value...",
2286                             0 == lsquic_stream_set_max_send_off(stream, 23)));
2287    assert(("...or larger",
2288                             0 == lsquic_stream_set_max_send_off(stream, 23000)));
2289    lsquic_stream_destroy(stream);
2290    assert(("on_close called", 1 == n_closed));
2291    deinit_test_objs(&tobjs);
2292}
2293
2294
2295static void
2296verify_ack (struct lsquic_packet_out *packet_out)
2297{
2298    struct packet_out_frec_iter pofi;
2299    const struct frame_rec *frec;
2300    unsigned short regen_sz;
2301    enum quic_ft_bit frame_types;
2302
2303    assert(packet_out->po_regen_sz > 0);
2304    assert(packet_out->po_frame_types & (1 << QUIC_FRAME_ACK));
2305
2306    regen_sz = 0;
2307    frame_types = 0;
2308    for (frec = lsquic_pofi_first(&pofi, packet_out); frec;
2309                                                frec = lsquic_pofi_next(&pofi))
2310    {
2311        frame_types |= 1 << frec->fe_frame_type;
2312        if (frec->fe_frame_type == QUIC_FRAME_ACK)
2313        {
2314            assert(frec->fe_len == 9);
2315            assert(0 == memcmp(packet_out->po_data + frec->fe_off, "ACKACKACK", 9));
2316            assert(regen_sz == frec->fe_off);
2317            regen_sz += frec->fe_len;
2318        }
2319    }
2320
2321    assert(frame_types & (1 << QUIC_FRAME_ACK));
2322    assert(regen_sz == packet_out->po_regen_sz);
2323}
2324
2325
2326/* Write to buffered streams: first to low-priority, then high-priority.  This
2327 * should trigger ACK generation and move.
2328 */
2329static void
2330test_stealing_ack (void)
2331{
2332    ssize_t nw;
2333    struct test_objs tobjs;
2334    struct lsquic_conn *const lconn = &tobjs.lconn;
2335    struct lsquic_stream *lo_stream, *hi_stream;;
2336    int s;
2337    const struct buf_packet_q *bpq;
2338
2339    init_test_ctl_settings(&g_ctl_settings);
2340    g_ctl_settings.tcs_schedule_stream_packets_immediately = 0;
2341    g_ctl_settings.tcs_write_ack = 1;
2342    g_ctl_settings.tcs_bp_type = BPT_OTHER_PRIO;
2343
2344    init_test_objs(&tobjs, 0x4000, 0x4000, NULL);
2345
2346    lo_stream = new_stream(&tobjs, 123);
2347    assert(("Stream initialized", lo_stream));
2348    assert(LSQUIC_STREAM_DEFAULT_PRIO == lsquic_stream_priority(lo_stream));
2349    assert(lconn == lsquic_stream_conn(lo_stream));
2350    nw = lsquic_stream_write(lo_stream, "Dude, where is", 14);
2351    assert(("14 bytes written correctly", nw == 14));
2352    s = lsquic_stream_flush(lo_stream);
2353    assert(0 == s);
2354
2355    bpq = &tobjs.send_ctl.sc_buffered_packets[g_ctl_settings.tcs_bp_type];
2356    verify_ack(TAILQ_FIRST(&bpq->bpq_packets));
2357
2358    g_ctl_settings.tcs_bp_type = BPT_HIGHEST_PRIO;
2359
2360    hi_stream = new_stream(&tobjs, 1);
2361    assert(("Stream initialized", hi_stream));
2362    assert(lconn == lsquic_stream_conn(hi_stream));
2363    nw = lsquic_stream_write(hi_stream, "DATA", 4);
2364    assert(("4 bytes written correctly", nw == 4));
2365    s = lsquic_stream_flush(hi_stream);
2366    assert(0 == s);
2367
2368    /* ACK is moved (stolen) from low-priority stream to high-priority stream */
2369    /* Check old packet */
2370    assert(!(TAILQ_FIRST(&bpq->bpq_packets)->po_frame_types & (1 << QUIC_FRAME_ACK)));
2371    /* Check new packet */
2372    bpq = &tobjs.send_ctl.sc_buffered_packets[g_ctl_settings.tcs_bp_type];
2373    verify_ack(TAILQ_FIRST(&bpq->bpq_packets));
2374
2375    /* And now chop regen, see if we hit any asserts there */
2376    lsquic_packet_out_chop_regen(TAILQ_FIRST(&bpq->bpq_packets));
2377    /* And now verify that ACK is gone */
2378    assert(!(TAILQ_FIRST(&bpq->bpq_packets)->po_frame_types & (1 << QUIC_FRAME_ACK)));
2379
2380    lsquic_stream_destroy(lo_stream);
2381    lsquic_stream_destroy(hi_stream);
2382    deinit_test_objs(&tobjs);
2383}
2384
2385
2386static void
2387test_changing_pack_size (void)
2388{
2389    ssize_t nw;
2390    struct test_objs tobjs;
2391    struct lsquic_conn *lconn = &tobjs.lconn;
2392    struct lsquic_stream *stream;
2393    int s, i;
2394    unsigned char buf[0x2000];
2395    size_t len;
2396
2397    init_buf(buf, sizeof(buf));
2398
2399    enum lsquic_version versions_to_test[3] =
2400    {
2401        LSQVER_046,
2402        LSQVER_ID27,
2403    };
2404
2405    for (i = 0; i < 3; i++)
2406    {
2407        g_pf = select_pf_by_ver(versions_to_test[i]);
2408
2409        init_test_ctl_settings(&g_ctl_settings);
2410        g_ctl_settings.tcs_schedule_stream_packets_immediately = 0;
2411        g_ctl_settings.tcs_bp_type = BPT_OTHER_PRIO;
2412        const struct buf_packet_q *const bpq =
2413                &tobjs.send_ctl.sc_buffered_packets[g_ctl_settings.tcs_bp_type];
2414        init_test_objs(&tobjs, 0x4000, 0x4000, NULL);
2415        n_closed = 0;
2416        if ((1 << versions_to_test[i]) & LSQUIC_IETF_VERSIONS)
2417        {
2418            tobjs.ctor_flags |= SCF_IETF;
2419            lconn->cn_flags |= LSCONN_IETF;
2420            network_path.np_pack_size = 4096;
2421        }
2422        stream = new_stream(&tobjs, 5);
2423        assert(("Stream initialized", stream));
2424        const struct test_ctx *const test_ctx_local = tobjs.stream_if_ctx;
2425        assert(("on_new_stream called correctly", stream == test_ctx_local->stream));
2426
2427        len = ((1 << versions_to_test[i]) & LSQUIC_IETF_VERSIONS) ? 2048 : 1024;
2428        nw = lsquic_stream_write(stream, buf, len);
2429        assert(("n bytes written correctly", (size_t)nw == len));
2430
2431        assert(("not packetized", 0 == bpq->bpq_count));
2432
2433        /* IETF: shrink packet size before a flush */
2434        if ((1 << versions_to_test[i]) & LSQUIC_IETF_VERSIONS)
2435            network_path.np_pack_size = 1370;
2436
2437        s = lsquic_stream_flush(stream);
2438        assert(0 == s);
2439
2440        if ((1 << versions_to_test[i]) & LSQUIC_IETF_VERSIONS)
2441            assert(("packetized -- 2 packets", 2 == bpq->bpq_count));
2442        else
2443            assert(("packetized -- 1 packets", 1 == bpq->bpq_count));
2444
2445        /* IETF: expand packet size before a write */
2446        if ((1 << versions_to_test[i]) & LSQUIC_IETF_VERSIONS)
2447            network_path.np_pack_size = 4096;
2448
2449        len = ((1 << versions_to_test[i]) & LSQUIC_IETF_VERSIONS) ? 2048 : 1024;
2450        nw = lsquic_stream_write(stream, buf, len);
2451        assert(("n bytes written correctly", (size_t)nw == len));
2452        if ((1 << versions_to_test[i]) & LSQUIC_IETF_VERSIONS)
2453            assert(("packetized -- 3 packets", 3 == bpq->bpq_count));
2454        else
2455            assert(("packetized -- 1 packets", 1 == bpq->bpq_count));
2456
2457        s = lsquic_stream_flush(stream);
2458        assert(0 == s);
2459        if ((1 << versions_to_test[i]) & LSQUIC_IETF_VERSIONS)
2460            assert(("packetized -- 3 packets", 3 == bpq->bpq_count));
2461        else
2462            assert(("packetized -- 2 packets", 2 == bpq->bpq_count));
2463
2464        lsquic_stream_destroy(stream);
2465        assert(("on_close called", 1 == n_closed));
2466        deinit_test_objs(&tobjs);
2467    }
2468    g_pf = select_pf_by_ver(LSQVER_043);
2469}
2470
2471
2472/* This tests what happens when a stream data is buffered using one packet
2473 * size, but then packet size get smaller (which is what happens when an RTO
2474 * occurs), and then more data is written.
2475 *
2476 * In particular, the write sizes in this tests are structured to make
2477 * maybe_resize_threshold() change the threshold.
2478 */
2479static void
2480test_reducing_pack_size (void)
2481{
2482    ssize_t nw;
2483    struct test_objs tobjs;
2484    struct lsquic_conn *lconn = &tobjs.lconn;
2485    struct lsquic_stream *stream;
2486    int s;
2487    unsigned i;
2488    unsigned char buf[0x4000];
2489
2490    init_buf(buf, sizeof(buf));
2491
2492    enum lsquic_version versions_to_test[] =
2493    {
2494        LSQVER_050,
2495        LSQVER_ID29,
2496    };
2497
2498    /* Particular versions should not matter as this is tests the logic in
2499     * stream only, but we do it for completeness.
2500     */
2501    for (i = 0; i < sizeof(versions_to_test) / sizeof(versions_to_test[0]); i++)
2502    {
2503        g_pf = select_pf_by_ver(versions_to_test[i]);
2504
2505        init_test_ctl_settings(&g_ctl_settings);
2506        g_ctl_settings.tcs_schedule_stream_packets_immediately = 1;
2507        g_ctl_settings.tcs_bp_type = BPT_OTHER_PRIO;
2508        init_test_objs(&tobjs, 0x4000, 0x4000, NULL);
2509        n_closed = 0;
2510        if ((1 << versions_to_test[i]) & LSQUIC_IETF_VERSIONS)
2511        {
2512            tobjs.ctor_flags |= SCF_IETF;
2513            lconn->cn_flags |= LSCONN_IETF;
2514        }
2515        network_path.np_pack_size = 2000;
2516        stream = new_stream(&tobjs, 5);
2517        assert(("Stream initialized", stream));
2518        const struct test_ctx *const test_ctx_local = tobjs.stream_if_ctx;
2519        assert(("on_new_stream called correctly", stream == test_ctx_local->stream));
2520
2521        nw = lsquic_stream_write(stream, buf, 1400);
2522        assert(stream->sm_n_allocated <= 2000);
2523        assert(stream->sm_n_buffered > 0);
2524        assert(("n bytes written correctly", (size_t)nw == 1400));
2525
2526        /* Shrink packet size */
2527        network_path.np_pack_size = 1300;
2528
2529        nw = lsquic_stream_write(stream, buf, 3000);
2530        assert(stream->sm_n_allocated <= 1300);
2531        assert(stream->sm_n_buffered > 0);
2532        assert(("n bytes written correctly", (size_t)nw == 3000));
2533
2534        s = lsquic_stream_flush(stream);
2535        assert(stream->sm_n_buffered == 0);
2536        assert(0 == s);
2537
2538        lsquic_stream_destroy(stream);
2539        assert(("on_close called", 1 == n_closed));
2540        deinit_test_objs(&tobjs);
2541    }
2542    g_pf = select_pf_by_ver(LSQVER_043);
2543}
2544
2545
2546/* Test window update logic, connection-limited */
2547static void
2548test_window_update1 (void)
2549{
2550    ssize_t nw;
2551    struct test_objs tobjs;
2552    struct lsquic_stream *stream;
2553    unsigned char buf[0x1000];
2554    lsquic_packet_out_t *packet_out;
2555    struct lsquic_conn_cap *const conn_cap = &tobjs.conn_pub.conn_cap;
2556    int s;
2557
2558    init_test_ctl_settings(&g_ctl_settings);
2559    g_ctl_settings.tcs_schedule_stream_packets_immediately = 1;
2560
2561    init_test_objs(&tobjs, 0x4000, 0x4000, NULL);
2562    n_closed = 0;
2563    stream = new_stream_ext(&tobjs, 123, 3);
2564    nw = lsquic_stream_write(stream, "1234567890", 10);
2565    assert(("lsquic_stream_write is limited by the send window", 3 == nw));
2566    assert(("cc_tosend is updated immediately",
2567                                            3 == conn_cap->cc_sent));
2568    s = lsquic_stream_flush(stream);
2569    assert(0 == s);
2570    assert(("cc_tosend is updated when limited by connection",
2571                                            3 == conn_cap->cc_sent));
2572    nw = read_from_scheduled_packets(&tobjs.send_ctl, stream->id, buf,
2573                                                    sizeof(buf), 0, NULL, 0);
2574    assert(nw == 3);
2575    assert(0 == memcmp(buf, "123", 3));
2576
2577    /* Pretend we sent out a packet: */
2578    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs.send_ctl, 0);
2579    lsquic_send_ctl_sent_packet(&tobjs.send_ctl, packet_out);
2580
2581    lsquic_stream_window_update(stream, 20);
2582    nw = lsquic_stream_write(stream, "4567890", 7);
2583    assert(("lsquic_stream_write: wrote remainig 7 bytes", 7 == nw));
2584    s = lsquic_stream_flush(stream);
2585    assert(0 == s);
2586
2587    /* Verify written data: */
2588    nw = read_from_scheduled_packets(&tobjs.send_ctl, stream->id, buf,
2589                                                    sizeof(buf), 3, NULL, 0);
2590    assert(nw == 7);
2591    assert(0 == memcmp(buf, "4567890", 7));
2592
2593    lsquic_stream_destroy(stream);
2594    assert(("on_close called", 1 == n_closed));
2595    deinit_test_objs(&tobjs);
2596}
2597
2598
2599/* Test two: large frame in the middle */
2600static void
2601test_bad_packbits_guess_2 (void)
2602{
2603    lsquic_packet_out_t *packet_out;
2604    ssize_t nw;
2605    struct test_objs tobjs;
2606    struct lsquic_stream *streams[3];
2607    char buf[0x1000];
2608    unsigned char buf_out[0x1000];
2609    int s, fin;
2610
2611    init_buf(buf, sizeof(buf));
2612
2613    init_test_ctl_settings(&g_ctl_settings);
2614    g_ctl_settings.tcs_schedule_stream_packets_immediately = 0;
2615    g_ctl_settings.tcs_guess_packno_bits = GQUIC_PACKNO_LEN_1;
2616
2617    init_test_objs(&tobjs, 0x1000, 0x1000, NULL);
2618    streams[0] = new_stream(&tobjs, 5);
2619    streams[1] = new_stream(&tobjs, 7);
2620    streams[2] = new_stream(&tobjs, 9);
2621
2622    /* Perfrom writes on the three streams.  This is tuned to fill a single
2623     * packet completely -- we check this later in this function.
2624     */
2625    s = lsquic_stream_shutdown(streams[0], 1);
2626    assert(s == 0);
2627    nw = lsquic_stream_write(streams[1], buf, 1337);
2628    assert(nw == 1337);
2629    s = lsquic_stream_flush(streams[1]);
2630    assert(0 == s);
2631    nw = lsquic_stream_write(streams[2], buf + 1337, 1);
2632    assert(nw == 1);
2633    s = lsquic_stream_shutdown(streams[2], 1);
2634    assert(s == 0);
2635
2636    /* Verify that we got one packet filled to the top: */
2637    const struct buf_packet_q *const bpq =
2638            &tobjs.send_ctl.sc_buffered_packets[g_ctl_settings.tcs_bp_type];
2639    assert(("packetized -- 1 packet", 1 == bpq->bpq_count));
2640    packet_out = TAILQ_FIRST(&bpq->bpq_packets);
2641    assert(0 == lsquic_packet_out_avail(packet_out));
2642
2643    assert(1 == streams[0]->n_unacked);
2644    assert(1 == streams[1]->n_unacked);
2645    assert(1 == streams[2]->n_unacked);
2646
2647    g_ctl_settings.tcs_schedule_stream_packets_immediately = 1;
2648    g_ctl_settings.tcs_calc_packno_bits = GQUIC_PACKNO_LEN_6;
2649    s = lsquic_send_ctl_schedule_buffered(&tobjs.send_ctl,
2650                                                g_ctl_settings.tcs_bp_type);
2651    assert(2 == lsquic_send_ctl_n_scheduled(&tobjs.send_ctl));
2652
2653    /* Verify written data: */
2654    nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[0]->id, buf_out,
2655                                                sizeof(buf_out), 0, &fin, 0);
2656    assert(nw == 0);
2657    assert(fin);
2658    nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[1]->id, buf_out,
2659                                                sizeof(buf_out), 0, &fin, 0);
2660    assert(nw == 1337);
2661    assert(!fin);
2662    assert(0 == memcmp(buf, buf_out, 1337));
2663    nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[2]->id, buf_out,
2664                                                sizeof(buf_out), 0, &fin, 0);
2665    assert(nw == 1);
2666    assert(fin);
2667    assert(0 == memcmp(buf + 1337, buf_out, 1));
2668
2669    /* Verify packets */
2670    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs.send_ctl, 0);
2671    assert(lsquic_packet_out_packno_bits(packet_out) == GQUIC_PACKNO_LEN_6);
2672    assert(1 == packet_out->po_packno);
2673    assert(packet_out->po_frame_types & (1 << QUIC_FRAME_STREAM));
2674    lsquic_send_ctl_sent_packet(&tobjs.send_ctl, packet_out);
2675    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs.send_ctl, 0);
2676    assert(lsquic_packet_out_packno_bits(packet_out) == GQUIC_PACKNO_LEN_6);
2677    assert(2 == packet_out->po_packno);
2678    assert(packet_out->po_frame_types & (1 << QUIC_FRAME_STREAM));
2679    lsquic_send_ctl_sent_packet(&tobjs.send_ctl, packet_out);
2680
2681    assert(1 == streams[0]->n_unacked);
2682    assert(1 == streams[1]->n_unacked);
2683    assert(1 == streams[2]->n_unacked);
2684    ack_packet(&tobjs.send_ctl, 1);
2685    assert(0 == streams[0]->n_unacked);
2686    assert(0 == streams[1]->n_unacked);
2687    assert(1 == streams[2]->n_unacked);
2688    ack_packet(&tobjs.send_ctl, 2);
2689    assert(0 == streams[0]->n_unacked);
2690    assert(0 == streams[1]->n_unacked);
2691    assert(0 == streams[2]->n_unacked);
2692
2693    lsquic_stream_destroy(streams[0]);
2694    lsquic_stream_destroy(streams[1]);
2695    lsquic_stream_destroy(streams[2]);
2696    deinit_test_objs(&tobjs);
2697}
2698
2699
2700/* Test three: split large STREAM frame into two halves.  The second half
2701 * goes into new packet.
2702 */
2703static void
2704test_bad_packbits_guess_3 (void)
2705{
2706    lsquic_packet_out_t *packet_out;
2707    ssize_t nw;
2708    struct test_objs tobjs;
2709    struct lsquic_stream *streams[1];
2710    char buf[0x1000];
2711    unsigned char buf_out[0x1000];
2712    int s, fin;
2713
2714    init_buf(buf, sizeof(buf));
2715
2716    init_test_ctl_settings(&g_ctl_settings);
2717    g_ctl_settings.tcs_schedule_stream_packets_immediately = 0;
2718    g_ctl_settings.tcs_guess_packno_bits = GQUIC_PACKNO_LEN_1;
2719
2720    init_test_objs(&tobjs, 0x1000, 0x1000, NULL);
2721    streams[0] = new_stream(&tobjs, 5);
2722
2723    nw = lsquic_stream_write(streams[0], buf,
2724                /* Use odd number to test halving logic: */ 1343);
2725    assert(nw == 1343);
2726    s = lsquic_stream_shutdown(streams[0], 1);
2727    assert(s == 0);
2728
2729    /* Verify that we got one packet filled to the top (minus one byte) */
2730    const struct buf_packet_q *const bpq =
2731            &tobjs.send_ctl.sc_buffered_packets[g_ctl_settings.tcs_bp_type];
2732    assert(("packetized -- 1 packet", 1 == bpq->bpq_count));
2733    packet_out = TAILQ_FIRST(&bpq->bpq_packets);
2734    assert(1 == lsquic_packet_out_avail(packet_out));
2735
2736    assert(1 == streams[0]->n_unacked);
2737
2738    g_ctl_settings.tcs_schedule_stream_packets_immediately = 1;
2739    g_ctl_settings.tcs_calc_packno_bits = GQUIC_PACKNO_LEN_6;
2740    s = lsquic_send_ctl_schedule_buffered(&tobjs.send_ctl,
2741                                                g_ctl_settings.tcs_bp_type);
2742    assert(2 == lsquic_send_ctl_n_scheduled(&tobjs.send_ctl));
2743
2744    /* Verify written data: */
2745    nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[0]->id, buf_out,
2746                                                sizeof(buf_out), 0, &fin, 0);
2747    assert(nw == 1343);
2748    assert(fin);
2749    assert(0 == memcmp(buf, buf_out, 1343));
2750
2751    /* Verify packets */
2752    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs.send_ctl, 0);
2753    assert(lsquic_packet_out_packno_bits(packet_out) == GQUIC_PACKNO_LEN_6);
2754    assert(1 == packet_out->po_packno);
2755    assert(packet_out->po_frame_types & (1 << QUIC_FRAME_STREAM));
2756    lsquic_send_ctl_sent_packet(&tobjs.send_ctl, packet_out);
2757    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs.send_ctl, 0);
2758    assert(lsquic_packet_out_packno_bits(packet_out) == GQUIC_PACKNO_LEN_6);
2759    assert(2 == packet_out->po_packno);
2760    assert(packet_out->po_frame_types & (1 << QUIC_FRAME_STREAM));
2761    lsquic_send_ctl_sent_packet(&tobjs.send_ctl, packet_out);
2762
2763    assert(2 == streams[0]->n_unacked);
2764    ack_packet(&tobjs.send_ctl, 1);
2765    assert(1 == streams[0]->n_unacked);
2766    ack_packet(&tobjs.send_ctl, 2);
2767    assert(0 == streams[0]->n_unacked);
2768
2769    lsquic_stream_destroy(streams[0]);
2770    deinit_test_objs(&tobjs);
2771}
2772
2773
2774/* Test resizing of buffered packets:
2775 *  1. Write data to buffered packets
2776 *  2. Reduce packet size
2777 *  3. Resize buffered packets
2778 *  4. Schedule them
2779 *  5. Check contents
2780 */
2781static void
2782test_resize_buffered (void)
2783{
2784    ssize_t nw;
2785    struct test_objs tobjs;
2786    struct lsquic_stream *streams[1];
2787    const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_ID27);
2788    char buf[0x10000];
2789    unsigned char buf_out[0x10000];
2790    int s, fin;
2791    unsigned packet_counts[2];
2792
2793    init_buf(buf, sizeof(buf));
2794
2795    lsquic_send_ctl_set_max_bpq_count(UINT_MAX);
2796    init_test_ctl_settings(&g_ctl_settings);
2797    g_ctl_settings.tcs_schedule_stream_packets_immediately = 0;
2798
2799    init_test_objs(&tobjs, 0x100000, 0x100000, pf);
2800    tobjs.send_ctl.sc_flags |= SC_IETF; /* work around asserts lsquic_send_ctl_resize() */
2801    network_path.np_pack_size = 4096;
2802    streams[0] = new_stream_ext(&tobjs, 7, 0x100000);
2803
2804    nw = lsquic_stream_write(streams[0], buf, sizeof(buf));
2805    assert(nw == sizeof(buf));
2806    s = lsquic_stream_shutdown(streams[0], 1);
2807    assert(s == 0);
2808    packet_counts[0] = tobjs.send_ctl.sc_buffered_packets[g_ctl_settings.tcs_bp_type].bpq_count;
2809
2810    assert(streams[0]->n_unacked > 0);
2811
2812    network_path.np_pack_size = 1234;
2813    lsquic_send_ctl_resize(&tobjs.send_ctl);
2814    packet_counts[1] = tobjs.send_ctl.sc_buffered_packets[g_ctl_settings.tcs_bp_type].bpq_count;
2815    assert(packet_counts[1] > packet_counts[0]);
2816
2817    g_ctl_settings.tcs_schedule_stream_packets_immediately = 1;
2818    s = lsquic_send_ctl_schedule_buffered(&tobjs.send_ctl,
2819                                                g_ctl_settings.tcs_bp_type);
2820    assert(lsquic_send_ctl_n_scheduled(&tobjs.send_ctl) > 0);
2821
2822    /* Verify written data: */
2823    nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[0]->id, buf_out,
2824                                                sizeof(buf_out), 0, &fin, 0);
2825    assert(nw == sizeof(buf));
2826    assert(fin);
2827    assert(0 == memcmp(buf, buf_out, nw));
2828
2829    lsquic_stream_destroy(streams[0]);
2830    deinit_test_objs(&tobjs);
2831    lsquic_send_ctl_set_max_bpq_count(10);
2832}
2833
2834
2835/* Test resizing of buffered packets:
2836 *  1. Write data to buffered packets
2837 *  2. Schedule them
2838 *  3. Reduce packet size
2839 *  4. Resize packets
2840 *  5. Check contents
2841 */
2842static void
2843test_resize_scheduled (void)
2844{
2845    ssize_t nw;
2846    struct test_objs tobjs;
2847    struct lsquic_stream *streams[1];
2848    const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_ID27);
2849    char buf[0x10000];
2850    unsigned char buf_out[0x10000];
2851    int s, fin;
2852    unsigned packet_counts[2];
2853
2854    init_buf(buf, sizeof(buf));
2855
2856    lsquic_send_ctl_set_max_bpq_count(UINT_MAX);
2857    init_test_ctl_settings(&g_ctl_settings);
2858    g_ctl_settings.tcs_schedule_stream_packets_immediately = 0;
2859
2860    init_test_objs(&tobjs, 0x100000, 0x100000, pf);
2861    tobjs.send_ctl.sc_flags |= SC_IETF; /* work around asserts lsquic_send_ctl_resize() */
2862    network_path.np_pack_size = 4096;
2863    streams[0] = new_stream_ext(&tobjs, 7, 0x100000);
2864
2865    nw = lsquic_stream_write(streams[0], buf, sizeof(buf));
2866    assert(nw == sizeof(buf));
2867    s = lsquic_stream_shutdown(streams[0], 1);
2868    assert(s == 0);
2869
2870    assert(streams[0]->n_unacked > 0);
2871
2872    g_ctl_settings.tcs_schedule_stream_packets_immediately = 1;
2873    s = lsquic_send_ctl_schedule_buffered(&tobjs.send_ctl,
2874                                                g_ctl_settings.tcs_bp_type);
2875    packet_counts[0] = lsquic_send_ctl_n_scheduled(&tobjs.send_ctl);
2876    assert(packet_counts[0] > 0);
2877
2878    network_path.np_pack_size = 1234;
2879    lsquic_send_ctl_resize(&tobjs.send_ctl);
2880    packet_counts[1] = lsquic_send_ctl_n_scheduled(&tobjs.send_ctl);
2881    assert(packet_counts[1] > packet_counts[0]);
2882
2883    /* Verify written data: */
2884    nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[0]->id, buf_out,
2885                                                sizeof(buf_out), 0, &fin, 0);
2886    assert(nw == sizeof(buf));
2887    assert(fin);
2888    assert(0 == memcmp(buf, buf_out, nw));
2889
2890    lsquic_stream_destroy(streams[0]);
2891    deinit_test_objs(&tobjs);
2892    lsquic_send_ctl_set_max_bpq_count(10);
2893}
2894
2895
2896struct packetization_test_stream_ctx
2897{
2898    const unsigned char    *buf;
2899    unsigned                len, off, write_size;
2900};
2901
2902
2903static lsquic_stream_ctx_t *
2904packetization_on_new_stream (void *stream_if_ctx, lsquic_stream_t *stream)
2905{
2906    lsquic_stream_wantwrite(stream, 1);
2907    return stream_if_ctx;
2908}
2909
2910
2911static void
2912packetization_on_close (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
2913{
2914}
2915
2916
2917#define RANDOM_WRITE_SIZE ~0U
2918
2919static unsigned
2920calc_n_to_write (unsigned write_size)
2921{
2922    if (write_size == RANDOM_WRITE_SIZE)
2923        return rand() % 1000 + 1;
2924    else
2925        return write_size;
2926}
2927
2928
2929static void
2930packetization_write_as_much_as_you_can (lsquic_stream_t *stream,
2931                                         lsquic_stream_ctx_t *ctx)
2932{
2933    struct packetization_test_stream_ctx *const pack_ctx = (void *) ctx;
2934    unsigned n_to_write;
2935    ssize_t n_written;
2936    int s;
2937
2938    while (pack_ctx->off < pack_ctx->len)
2939    {
2940        n_to_write = calc_n_to_write(pack_ctx->write_size);
2941        if (n_to_write > pack_ctx->len - pack_ctx->off)
2942            n_to_write = pack_ctx->len - pack_ctx->off;
2943        n_written = lsquic_stream_write(stream, pack_ctx->buf + pack_ctx->off,
2944                                        n_to_write);
2945        assert(n_written >= 0);
2946        if (n_written == 0)
2947            break;
2948        pack_ctx->off += n_written;
2949    }
2950
2951    s = lsquic_stream_flush(stream);
2952    assert(s == 0);
2953    lsquic_stream_wantwrite(stream, 0);
2954}
2955
2956
2957static void
2958packetization_perform_one_write (lsquic_stream_t *stream,
2959                                         lsquic_stream_ctx_t *ctx)
2960{
2961    struct packetization_test_stream_ctx *const pack_ctx = (void *) ctx;
2962    unsigned n_to_write;
2963    ssize_t n_written;
2964
2965    n_to_write = calc_n_to_write(pack_ctx->write_size);
2966    if (n_to_write > pack_ctx->len - pack_ctx->off)
2967        n_to_write = pack_ctx->len - pack_ctx->off;
2968    n_written = lsquic_stream_write(stream, pack_ctx->buf + pack_ctx->off,
2969                                    n_to_write);
2970    assert(n_written >= 0);
2971    pack_ctx->off += n_written;
2972    if (n_written == 0)
2973        lsquic_stream_wantwrite(stream, 0);
2974}
2975
2976
2977static const struct lsquic_stream_if packetization_inside_once_stream_if = {
2978    .on_new_stream          = packetization_on_new_stream,
2979    .on_close               = packetization_on_close,
2980    .on_write               = packetization_write_as_much_as_you_can,
2981};
2982
2983
2984static const struct lsquic_stream_if packetization_inside_many_stream_if = {
2985    .on_new_stream          = packetization_on_new_stream,
2986    .on_close               = packetization_on_close,
2987    .on_write               = packetization_perform_one_write,
2988};
2989
2990
2991static void
2992test_packetization (int schedule_stream_packets_immediately, int dispatch_once,
2993                    unsigned write_size, unsigned first_stream_sz)
2994{
2995    struct test_objs tobjs;
2996    struct lsquic_stream *streams[2];
2997    size_t nw;
2998    int fin;
2999    unsigned stream_ids[2];
3000    unsigned char buf[0x8000];
3001    unsigned char buf_out[0x8000];
3002
3003    struct packetization_test_stream_ctx packet_stream_ctx =
3004    {
3005        .buf = buf,
3006        .off = 0,
3007        .len = sizeof(buf),
3008        .write_size = write_size,
3009    };
3010
3011    init_buf(buf, sizeof(buf));
3012
3013    init_test_ctl_settings(&g_ctl_settings);
3014    g_ctl_settings.tcs_schedule_stream_packets_immediately = schedule_stream_packets_immediately;
3015
3016    init_test_objs(&tobjs,
3017        /* Test limits a bit while we are at it: */
3018        sizeof(buf) - 1, sizeof(buf) - 1, NULL);
3019    tobjs.stream_if_ctx = &packet_stream_ctx;
3020
3021    if (schedule_stream_packets_immediately)
3022    {
3023        if (dispatch_once)
3024        {
3025            tobjs.stream_if = &packetization_inside_once_stream_if;
3026            tobjs.ctor_flags |= SCF_DISP_RW_ONCE;
3027        }
3028        else
3029            tobjs.stream_if = &packetization_inside_many_stream_if;
3030    }
3031    else
3032        /* Need this for on_new_stream() callback not to mess with
3033         * the context, otherwise this is not used.
3034         */
3035        tobjs.stream_if = &packetization_inside_many_stream_if;
3036
3037    if (g_use_crypto_ctor)
3038    {
3039        stream_ids[0] = ENC_LEV_CLEAR;
3040        stream_ids[1] = ENC_LEV_INIT;
3041    }
3042    else
3043    {
3044        stream_ids[0] = 7;
3045        stream_ids[1] = 5;
3046    }
3047
3048    streams[0] = new_stream(&tobjs, stream_ids[0]);
3049    streams[1] = new_stream_ext(&tobjs, stream_ids[1], sizeof(buf) - 1);
3050
3051    if (first_stream_sz)
3052    {
3053        lsquic_stream_write(streams[0], buf, first_stream_sz);
3054        lsquic_stream_flush(streams[0]);
3055    }
3056
3057    if (schedule_stream_packets_immediately)
3058    {
3059        lsquic_stream_dispatch_write_events(streams[1]);
3060        lsquic_stream_flush(streams[1]);
3061    }
3062    else
3063    {
3064        packetization_write_as_much_as_you_can(streams[1],
3065                                                (void *) &packet_stream_ctx);
3066        g_ctl_settings.tcs_schedule_stream_packets_immediately = 1;
3067        lsquic_send_ctl_schedule_buffered(&tobjs.send_ctl, BPT_HIGHEST_PRIO);
3068        g_ctl_settings.tcs_schedule_stream_packets_immediately = 0;
3069    }
3070
3071    if (!g_use_crypto_ctor)
3072        assert(packet_stream_ctx.off == packet_stream_ctx.len - first_stream_sz - 1);
3073
3074    /* Verify written data: */
3075    nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[1]->id, buf_out,
3076                                     sizeof(buf_out), 0, &fin, 1);
3077    if (!g_use_crypto_ctor)
3078    {
3079        assert(nw == sizeof(buf) - first_stream_sz - 1);
3080        assert(!fin);
3081        assert(0 == memcmp(buf, buf_out, sizeof(buf) - first_stream_sz - 1));
3082    }
3083    else
3084    {
3085        assert(sizeof(buf) == nw);
3086        assert(0 == memcmp(buf, buf_out, nw));
3087    }
3088
3089    lsquic_stream_destroy(streams[0]);
3090    lsquic_stream_destroy(streams[1]);
3091    deinit_test_objs(&tobjs);
3092}
3093
3094
3095/* Test condition when the room necessary to write a STREAM frame to a packet
3096 * is miscalculated and a brand-new packet has to be allocated.
3097 *
3098 * This does not affect IETF QUIC because the STREAM frame uses varint data
3099 * length representation and thus uses just a single byte to represent the
3100 * length of a 1-byte stream data chunk.
3101 */
3102static void
3103test_cant_fit_frame (const struct parse_funcs *pf)
3104{
3105    struct test_objs tobjs;
3106    struct lsquic_stream *streams[2];
3107    struct lsquic_packet_out *packet_out;
3108    size_t pad_len, rem, nr;
3109    int fin, s;
3110    const char dude[] = "Dude, where is my car?!";
3111    unsigned char buf_out[100];
3112
3113    init_test_ctl_settings(&g_ctl_settings);
3114    g_ctl_settings.tcs_schedule_stream_packets_immediately = 0;
3115
3116    init_test_objs(&tobjs, 0x8000, 0x8000, pf);
3117
3118    streams[0] = new_stream(&tobjs, 5);
3119    streams[1] = new_stream(&tobjs, 7);
3120
3121    /* Allocate a packet and pad it so just a few bytes remain to trigger
3122     * the condition we're after.
3123     */
3124    lsquic_stream_write(streams[0], dude, sizeof(dude) - 1);
3125    lsquic_stream_flush(streams[0]);
3126
3127    rem = pf->pf_calc_stream_frame_header_sz(streams[1]->id, 0, 1)
3128        + 1 /* We'll write one byte */
3129        + 1 /* This triggers the refit condition */
3130        ;
3131
3132    packet_out = TAILQ_FIRST(&tobjs.send_ctl.sc_buffered_packets[0].bpq_packets);
3133    assert(NULL == TAILQ_NEXT(packet_out, po_next));
3134    pad_len = packet_out->po_n_alloc - packet_out->po_data_sz - rem;
3135    memset(packet_out->po_data + packet_out->po_data_sz, 0, pad_len);
3136    packet_out->po_data_sz += pad_len;
3137
3138    lsquic_stream_write(streams[1], "A", 1);
3139    s = lsquic_stream_flush(streams[1]);
3140    assert(0 == s);
3141    /* Allocated another packet */
3142    assert(TAILQ_NEXT(packet_out, po_next));
3143
3144    g_ctl_settings.tcs_schedule_stream_packets_immediately = 1;
3145    lsquic_send_ctl_schedule_buffered(&tobjs.send_ctl, BPT_HIGHEST_PRIO);
3146    g_ctl_settings.tcs_schedule_stream_packets_immediately = 0;
3147
3148    /* Verify written data: */
3149    nr = read_from_scheduled_packets(&tobjs.send_ctl, streams[0]->id, buf_out,
3150                                     sizeof(buf_out), 0, &fin, 1);
3151    assert(nr == sizeof(dude) - 1);
3152    assert(!fin);
3153    assert(0 == memcmp(dude, buf_out, sizeof(dude) - 1));
3154    nr = read_from_scheduled_packets(&tobjs.send_ctl, streams[1]->id, buf_out,
3155                                     sizeof(buf_out), 0, &fin, 1);
3156    assert(nr == 1);
3157    assert(!fin);
3158    assert(buf_out[0] == 'A');
3159
3160    lsquic_stream_destroy(streams[0]);
3161    lsquic_stream_destroy(streams[1]);
3162    deinit_test_objs(&tobjs);
3163}
3164
3165
3166/* Test window update logic, not connection limited */
3167static void
3168test_window_update2 (void)
3169{
3170    ssize_t nw;
3171    int s;
3172    struct test_objs tobjs;
3173    struct lsquic_stream *stream;
3174    lsquic_packet_out_t *packet_out;
3175    struct lsquic_conn_cap *const conn_cap = &tobjs.conn_pub.conn_cap;
3176    unsigned char buf[0x1000];
3177
3178    init_test_objs(&tobjs, 0x4000, 0x4000, NULL);
3179    n_closed = 0;
3180    stream = new_stream_ext(&tobjs, 1, 3);
3181    nw = lsquic_stream_write(stream, "1234567890", 10);
3182    lsquic_stream_flush(stream);
3183    assert(("lsquic_stream_write is limited by the send window", 3 == nw));
3184    s = lsquic_stream_flush(stream);
3185    assert(0 == s);
3186    assert(("cc_tosend is not updated when not limited by connection",
3187                                            0 == conn_cap->cc_sent));
3188    assert(stream->sm_qflags & SMQF_SEND_BLOCKED);
3189    nw = read_from_scheduled_packets(&tobjs.send_ctl, stream->id, buf,
3190                                                    sizeof(buf), 0, NULL, 0);
3191    assert(nw == 3);
3192    assert(0 == memcmp(buf, "123", 3));
3193
3194    /* Pretend we sent out a packet: */
3195    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs.send_ctl, 0);
3196    lsquic_send_ctl_sent_packet(&tobjs.send_ctl, packet_out);
3197
3198    lsquic_stream_window_update(stream, 20);
3199    nw = lsquic_stream_write(stream, "4567890", 7);
3200    assert(("lsquic_stream_write: wrote remainig 7 bytes", 7 == nw));
3201    s = lsquic_stream_flush(stream);
3202    assert(0 == s);
3203
3204    /* Verify written data: */
3205    nw = read_from_scheduled_packets(&tobjs.send_ctl, stream->id, buf,
3206                                                    sizeof(buf), 3, NULL, 0);
3207    assert(nw == 7);
3208    assert(0 == memcmp(buf, "4567890", 7));
3209
3210    lsquic_stream_destroy(stream);
3211    assert(("on_close called", 1 == n_closed));
3212
3213    deinit_test_objs(&tobjs);
3214}
3215
3216
3217/* Test that stream is marked as both stream- and connection-blocked */
3218static void
3219test_blocked_flags (void)
3220{
3221    ssize_t nw;
3222    struct test_objs tobjs;
3223    struct lsquic_stream *stream;
3224    struct lsquic_conn_cap *const conn_cap = &tobjs.conn_pub.conn_cap;
3225    int s;
3226
3227    init_test_ctl_settings(&g_ctl_settings);
3228    g_ctl_settings.tcs_schedule_stream_packets_immediately = 1;
3229
3230    init_test_objs(&tobjs, 3, 3, NULL);
3231    stream = new_stream_ext(&tobjs, 123, 3);
3232    nw = lsquic_stream_write(stream, "1234567890", 10);
3233    assert(("lsquic_stream_write is limited by the send window", 3 == nw));
3234    assert(("cc_tosend is updated immediately",
3235                                            3 == conn_cap->cc_sent));
3236    assert(1 == lsquic_send_ctl_n_scheduled(&tobjs.send_ctl)); /* Flush occurred already */
3237    s = lsquic_stream_flush(stream);
3238    assert(0 == s);
3239    assert(("cc_tosend is updated when limited by connection",
3240                                            3 == conn_cap->cc_sent));
3241    assert(stream->sm_qflags & SMQF_SEND_BLOCKED);
3242    assert(3 == stream->blocked_off);
3243    assert(tobjs.lconn.cn_flags & LSCONN_SEND_BLOCKED);
3244    assert(3 == conn_cap->cc_blocked);
3245
3246    lsquic_stream_destroy(stream);
3247    deinit_test_objs(&tobjs);
3248}
3249
3250
3251static void
3252test_forced_flush_when_conn_blocked (void)
3253{
3254    ssize_t nw;
3255    struct test_objs tobjs;
3256    struct lsquic_stream *stream;
3257    struct lsquic_conn_cap *const conn_cap = &tobjs.conn_pub.conn_cap;
3258    enum stream_state_sending sss;
3259
3260    init_test_ctl_settings(&g_ctl_settings);
3261    g_ctl_settings.tcs_schedule_stream_packets_immediately = 1;
3262
3263    init_test_objs(&tobjs, 3, 0x1000, NULL);
3264    stream = new_stream(&tobjs, 123);
3265    sss = lsquic_stream_sending_state(stream);
3266    assert(SSS_READY == sss);
3267    nw = lsquic_stream_write(stream, "1234567890", 10);
3268    assert(("lsquic_stream_write is limited by the send window", 3 == nw));
3269    assert(("cc_tosend is updated immediately",
3270                                            3 == conn_cap->cc_sent));
3271    assert(1 == lsquic_send_ctl_n_scheduled(&tobjs.send_ctl)); /* Flush occurred */
3272    sss = lsquic_stream_sending_state(stream);
3273    assert(SSS_SEND == sss);
3274    assert(tobjs.lconn.cn_flags & LSCONN_SEND_BLOCKED);
3275    assert(3 == conn_cap->cc_blocked);
3276
3277    lsquic_stream_destroy(stream);
3278    deinit_test_objs(&tobjs);
3279}
3280
3281
3282static int
3283my_gen_stream_frame_err (unsigned char *buf, size_t bufsz,
3284                         lsquic_stream_id_t stream_id, uint64_t offset,
3285                         int fin, size_t size, gsf_read_f read,
3286                         void *stream)
3287{
3288    return -1;
3289}
3290
3291
3292static void
3293test_conn_abort (void)
3294{
3295    ssize_t nw;
3296    struct test_objs tobjs;
3297    struct lsquic_stream *stream;
3298    struct parse_funcs my_pf;
3299    int s;
3300
3301    init_test_ctl_settings(&g_ctl_settings);
3302    g_ctl_settings.tcs_schedule_stream_packets_immediately = 1;
3303
3304    init_test_objs(&tobjs, 0x1000, 0x1000, NULL);
3305    my_pf = *tobjs.lconn.cn_pf;
3306    my_pf.pf_gen_stream_frame = my_gen_stream_frame_err;
3307    tobjs.lconn.cn_pf = &my_pf;
3308
3309    stream = new_stream(&tobjs, 123);
3310    nw = lsquic_stream_write(stream, "1234567890", 10);
3311    assert(10 == nw);   /* No error yet */
3312    s = lsquic_stream_flush(stream);
3313    assert(s < 0);
3314    assert(stream->sm_qflags & SMQF_ABORT_CONN);
3315    assert(!TAILQ_EMPTY(&tobjs.conn_pub.service_streams));
3316
3317    lsquic_stream_destroy(stream);
3318    deinit_test_objs(&tobjs);
3319}
3320
3321
3322/* Test one: large frame first, followed by small frames to finish off
3323 * the packet.
3324 */
3325static void
3326test_bad_packbits_guess_1 (void)
3327{
3328    lsquic_packet_out_t *packet_out;
3329    ssize_t nw;
3330    struct test_objs tobjs;
3331    struct lsquic_stream *streams[3];
3332    char buf[0x1000];
3333    unsigned char buf_out[0x1000];
3334    int s, fin;
3335
3336    init_buf(buf, sizeof(buf));
3337
3338    init_test_ctl_settings(&g_ctl_settings);
3339    g_ctl_settings.tcs_schedule_stream_packets_immediately = 0;
3340    g_ctl_settings.tcs_guess_packno_bits = GQUIC_PACKNO_LEN_1;
3341
3342    init_test_objs(&tobjs, 0x1000, 0x1000, NULL);
3343    streams[0] = new_stream(&tobjs, 5);
3344    streams[1] = new_stream(&tobjs, 7);
3345    streams[2] = new_stream(&tobjs, 9);
3346
3347    /* Perfrom writes on the three streams.  This is tuned to fill a single
3348     * packet completely -- we check this later in this function.
3349     */
3350    nw = lsquic_stream_write(streams[0], buf, 1337);
3351    assert(nw == 1337);
3352    s = lsquic_stream_flush(streams[0]);
3353    assert(0 == s);
3354    s = lsquic_stream_shutdown(streams[1], 1);
3355    assert(s == 0);
3356    nw = lsquic_stream_write(streams[2], buf + 1337, 1);
3357    assert(nw == 1);
3358    s = lsquic_stream_shutdown(streams[2], 1);
3359    assert(s == 0);
3360
3361    /* Verify that we got one packet filled to the top: */
3362    const struct buf_packet_q *const bpq =
3363            &tobjs.send_ctl.sc_buffered_packets[g_ctl_settings.tcs_bp_type];
3364    assert(("packetized -- 1 packet", 1 == bpq->bpq_count));
3365    packet_out = TAILQ_FIRST(&bpq->bpq_packets);
3366    assert(0 == lsquic_packet_out_avail(packet_out));
3367
3368    assert(1 == streams[0]->n_unacked);
3369    assert(1 == streams[1]->n_unacked);
3370    assert(1 == streams[2]->n_unacked);
3371
3372    g_ctl_settings.tcs_schedule_stream_packets_immediately = 1;
3373    g_ctl_settings.tcs_calc_packno_bits = GQUIC_PACKNO_LEN_6;
3374    s = lsquic_send_ctl_schedule_buffered(&tobjs.send_ctl,
3375                                                g_ctl_settings.tcs_bp_type);
3376    assert(2 == lsquic_send_ctl_n_scheduled(&tobjs.send_ctl));
3377
3378    /* Verify written data: */
3379    nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[0]->id, buf_out,
3380                                                sizeof(buf_out), 0, &fin, 0);
3381    assert(nw == 1337);
3382    assert(!fin);
3383    assert(0 == memcmp(buf, buf_out, 1337));
3384    nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[1]->id, buf_out,
3385                                                sizeof(buf_out), 0, &fin, 0);
3386    assert(nw == 0);
3387    assert(fin);
3388    nw = read_from_scheduled_packets(&tobjs.send_ctl, streams[2]->id, buf_out,
3389                                                sizeof(buf_out), 0, &fin, 0);
3390    assert(nw == 1);
3391    assert(fin);
3392    assert(0 == memcmp(buf + 1337, buf_out, 1));
3393
3394    /* Verify packets */
3395    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs.send_ctl, 0);
3396    assert(lsquic_packet_out_packno_bits(packet_out) == GQUIC_PACKNO_LEN_6);
3397    assert(1 == packet_out->po_packno);
3398    assert(packet_out->po_frame_types & (1 << QUIC_FRAME_STREAM));
3399    lsquic_send_ctl_sent_packet(&tobjs.send_ctl, packet_out);
3400    packet_out = lsquic_send_ctl_next_packet_to_send(&tobjs.send_ctl, 0);
3401    assert(lsquic_packet_out_packno_bits(packet_out) == GQUIC_PACKNO_LEN_6);
3402    assert(2 == packet_out->po_packno);
3403    assert(packet_out->po_frame_types & (1 << QUIC_FRAME_STREAM));
3404    lsquic_send_ctl_sent_packet(&tobjs.send_ctl, packet_out);
3405
3406    assert(1 == streams[0]->n_unacked);
3407    assert(1 == streams[1]->n_unacked);
3408    assert(1 == streams[2]->n_unacked);
3409    ack_packet(&tobjs.send_ctl, 1);
3410    assert(0 == streams[0]->n_unacked);
3411    assert(1 == streams[1]->n_unacked);
3412    assert(1 == streams[2]->n_unacked);
3413    ack_packet(&tobjs.send_ctl, 2);
3414    assert(0 == streams[0]->n_unacked);
3415    assert(0 == streams[1]->n_unacked);
3416    assert(0 == streams[2]->n_unacked);
3417
3418    lsquic_stream_destroy(streams[0]);
3419    lsquic_stream_destroy(streams[1]);
3420    lsquic_stream_destroy(streams[2]);
3421    deinit_test_objs(&tobjs);
3422}
3423
3424
3425static void
3426main_test_packetization (void)
3427{
3428    const unsigned fp_sizes[] = { 0, 10, 100, 501, 1290, };
3429    unsigned i;
3430    for (i = 0; i < sizeof(fp_sizes) / sizeof(fp_sizes[0]); ++i)
3431    {
3432        int once;
3433        unsigned write_size;
3434        if (!g_use_crypto_ctor) /* No buffered packets for CRYPTO frames */
3435        {
3436            for (write_size = 1; write_size < GQUIC_MAX_PACKET_SZ; ++write_size)
3437                test_packetization(0, 0, write_size, fp_sizes[i]);
3438            srand(7891);
3439            for (write_size = 1; write_size < GQUIC_MAX_PACKET_SZ * 10; ++write_size)
3440                test_packetization(0, 0, RANDOM_WRITE_SIZE, fp_sizes[i]);
3441        }
3442        for (once = 0; once < 2; ++once)
3443        {
3444            for (write_size = 1; write_size < GQUIC_MAX_PACKET_SZ; ++write_size)
3445                test_packetization(1, once, write_size, fp_sizes[i]);
3446            srand(7891);
3447            for (write_size = 1; write_size < GQUIC_MAX_PACKET_SZ * 10; ++write_size)
3448                test_packetization(1, once, RANDOM_WRITE_SIZE, fp_sizes[i]);
3449        }
3450    }
3451}
3452
3453
3454int
3455main (int argc, char **argv)
3456{
3457    int opt;
3458
3459    lsquic_global_init(LSQUIC_GLOBAL_SERVER);
3460
3461    while (-1 != (opt = getopt(argc, argv, "Ahl:")))
3462    {
3463        switch (opt)
3464        {
3465        case 'A':
3466            stream_ctor_flags &= ~SCF_DI_AUTOSWITCH;
3467            break;
3468        case 'h':
3469            stream_ctor_flags |= SCF_USE_DI_HASH;
3470            break;
3471        case 'l':
3472            lsquic_log_to_fstream(stderr, 0);
3473            lsquic_logger_lopt(optarg);
3474            break;
3475        default:
3476            exit(1);
3477        }
3478    }
3479
3480    init_test_ctl_settings(&g_ctl_settings);
3481
3482    test_writing_to_stream_schedule_stream_packets_immediately();
3483    test_writing_to_stream_outside_callback();
3484    test_stealing_ack();
3485    test_changing_pack_size();
3486    test_reducing_pack_size();
3487    test_window_update1();
3488    test_window_update2();
3489    test_forced_flush_when_conn_blocked();
3490    test_blocked_flags();
3491    test_reading_from_stream2();
3492    test_overlaps();
3493    test_insert_edge_cases();
3494    test_unexpected_http_close();
3495
3496    {
3497        int idx[6];
3498        permute_and_run(0, 0, 0, idx, sizeof(idx) / sizeof(idx[0]));
3499    }
3500
3501    test_termination();
3502
3503    test_writev();
3504
3505    test_prio_conversion();
3506
3507    test_read_in_middle();
3508
3509    test_conn_unlimited();
3510
3511    test_flushing();
3512
3513    test_conn_abort();
3514
3515    test_bad_packbits_guess_1();
3516    test_bad_packbits_guess_2();
3517    test_bad_packbits_guess_3();
3518
3519    test_resize_buffered();
3520    test_resize_scheduled();
3521
3522    main_test_packetization();
3523
3524    enum lsquic_version ver;
3525    for (ver = 0; ver < N_LSQVER; ++ver)
3526        if (!((1 << ver) & LSQUIC_IETF_VERSIONS))
3527            test_cant_fit_frame(select_pf_by_ver(ver));
3528
3529    /* Redo some tests using crypto streams and frames */
3530    g_use_crypto_ctor = 1;
3531    g_pf = select_pf_by_ver(LSQVER_ID27);
3532    main_test_packetization();
3533
3534    return 0;
3535}
3536
3537static const char on_being_idle[] =
3538"ON BEING IDLE."
3539""
3540"Now, this is a subject on which I flatter myself I really am _au fait_."
3541"The gentleman who, when I was young, bathed me at wisdom's font for nine"
3542"guineas a term--no extras--used to say he never knew a boy who could"
3543"do less work in more time; and I remember my poor grandmother once"
3544"incidentally observing, in the course of an instruction upon the use"
3545"of the Prayer-book, that it was highly improbable that I should ever do"
3546"much that I ought not to do, but that she felt convinced beyond a doubt"
3547"that I should leave undone pretty well everything that I ought to do."
3548""
3549"I am afraid I have somewhat belied half the dear old lady's prophecy."
3550"Heaven help me! I have done a good many things that I ought not to have"
3551"done, in spite of my laziness. But I have fully confirmed the accuracy"
3552"of her judgment so far as neglecting much that I ought not to have"
3553"neglected is concerned. Idling always has been my strong point. I take"
3554"no credit to myself in the matter--it is a gift. Few possess it. There"
3555"are plenty of lazy people and plenty of slow-coaches, but a genuine"
3556"idler is a rarity. He is not a man who slouches about with his hands in"
3557"his pockets. On the contrary, his most startling characteristic is that"
3558"he is always intensely busy."
3559""
3560"It is impossible to enjoy idling thoroughly unless one has plenty of"
3561"work to do. There is no fun in doing nothing when you have nothing to"
3562"do. Wasting time is merely an occupation then, and a most exhausting"
3563"one. Idleness, like kisses, to be sweet must be stolen."
3564""
3565"Many years ago, when I was a young man, I was taken very ill--I never"
3566"could see myself that much was the matter with me, except that I had"
3567"a beastly cold. But I suppose it was something very serious, for the"
3568"doctor said that I ought to have come to him a month before, and that"
3569"if it (whatever it was) had gone on for another week he would not have"
3570"answered for the consequences. It is an extraordinary thing, but I"
3571"never knew a doctor called into any case yet but what it transpired"
3572"that another day's delay would have rendered cure hopeless. Our medical"
3573"guide, philosopher, and friend is like the hero in a melodrama--he"
3574"always comes upon the scene just, and only just, in the nick of time. It"
3575"is Providence, that is what it is."
3576""
3577"Well, as I was saying, I was very ill and was ordered to Buxton for a"
3578"month, with strict injunctions to do nothing whatever all the while"
3579"that I was there. \"Rest is what you require,\" said the doctor, \"perfect"
3580"rest.\""
3581""
3582"It seemed a delightful prospect. \"This man evidently understands my"
3583"complaint,\" said I, and I pictured to myself a glorious time--a four"
3584"weeks' _dolce far niente_ with a dash of illness in it. Not too much"
3585"illness, but just illness enough--just sufficient to give it the flavor"
3586"of suffering and make it poetical. I should get up late, sip chocolate,"
3587"and have my breakfast in slippers and a dressing-gown. I should lie out"
3588"in the garden in a hammock and read sentimental novels with a melancholy"
3589"ending, until the books should fall from my listless hand, and I should"
3590"recline there, dreamily gazing into the deep blue of the firmament,"
3591"watching the fleecy clouds floating like white-sailed ships across"
3592"its depths, and listening to the joyous song of the birds and the low"
3593"rustling of the trees. Or, on becoming too weak to go out of doors,"
3594"I should sit propped up with pillows at the open window of the"
3595"ground-floor front, and look wasted and interesting, so that all the"
3596"pretty girls would sigh as they passed by."
3597""
3598"And twice a day I should go down in a Bath chair to the Colonnade to"
3599"drink the waters. Oh, those waters! I knew nothing about them then,"
3600"and was rather taken with the idea. \"Drinking the waters\" sounded"
3601"fashionable and Queen Anne-fied, and I thought I should like them. But,"
3602"ugh! after the first three or four mornings! Sam Weller's description of"
3603"them as \"having a taste of warm flat-irons\" conveys only a faint idea of"
3604"their hideous nauseousness. If anything could make a sick man get well"
3605"quickly, it would be the knowledge that he must drink a glassful of them"
3606"every day until he was recovered. I drank them neat for six consecutive"
3607"days, and they nearly killed me; but after then I adopted the plan of"
3608"taking a stiff glass of brandy-and-water immediately on the top of them,"
3609"and found much relief thereby. I have been informed since, by various"
3610"eminent medical gentlemen, that the alcohol must have entirely"
3611"counteracted the effects of the chalybeate properties contained in the"
3612"water. I am glad I was lucky enough to hit upon the right thing."
3613;
3614
3615static void
3616init_buf (void *buf, size_t sz)
3617{
3618    unsigned char *p = buf;
3619    unsigned char *const end = (unsigned char*)buf + sz;
3620    size_t n;
3621
3622    while (p < end)
3623    {
3624        n = end - p;
3625        if (sizeof(on_being_idle) - 1 < n)
3626            n = sizeof(on_being_idle) - 1;
3627        memcpy(p, on_being_idle, n);
3628        p +=n;
3629    }
3630
3631    assert(p == end);
3632}
3633