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