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