1*e7be843bSPierre Pronchery /*
2*e7be843bSPierre Pronchery * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
3*e7be843bSPierre Pronchery *
4*e7be843bSPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
5*e7be843bSPierre Pronchery * this file except in compliance with the License. You can obtain a copy
6*e7be843bSPierre Pronchery * in the file LICENSE in the source distribution or at
7*e7be843bSPierre Pronchery * https://www.openssl.org/source/license.html
8*e7be843bSPierre Pronchery */
9*e7be843bSPierre Pronchery #include "internal/packet.h"
10*e7be843bSPierre Pronchery #include "internal/quic_stream.h"
11*e7be843bSPierre Pronchery #include "testutil.h"
12*e7be843bSPierre Pronchery
compare_iov(const unsigned char * ref,size_t ref_len,const OSSL_QTX_IOVEC * iov,size_t iov_len)13*e7be843bSPierre Pronchery static int compare_iov(const unsigned char *ref, size_t ref_len,
14*e7be843bSPierre Pronchery const OSSL_QTX_IOVEC *iov, size_t iov_len)
15*e7be843bSPierre Pronchery {
16*e7be843bSPierre Pronchery size_t i, total_len = 0;
17*e7be843bSPierre Pronchery const unsigned char *cur = ref;
18*e7be843bSPierre Pronchery
19*e7be843bSPierre Pronchery for (i = 0; i < iov_len; ++i)
20*e7be843bSPierre Pronchery total_len += iov[i].buf_len;
21*e7be843bSPierre Pronchery
22*e7be843bSPierre Pronchery if (ref_len != total_len)
23*e7be843bSPierre Pronchery return 0;
24*e7be843bSPierre Pronchery
25*e7be843bSPierre Pronchery for (i = 0; i < iov_len; ++i) {
26*e7be843bSPierre Pronchery if (memcmp(cur, iov[i].buf, iov[i].buf_len))
27*e7be843bSPierre Pronchery return 0;
28*e7be843bSPierre Pronchery
29*e7be843bSPierre Pronchery cur += iov[i].buf_len;
30*e7be843bSPierre Pronchery }
31*e7be843bSPierre Pronchery
32*e7be843bSPierre Pronchery return 1;
33*e7be843bSPierre Pronchery }
34*e7be843bSPierre Pronchery
35*e7be843bSPierre Pronchery static const unsigned char data_1[] = {
36*e7be843bSPierre Pronchery 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
37*e7be843bSPierre Pronchery 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f
38*e7be843bSPierre Pronchery };
39*e7be843bSPierre Pronchery
test_sstream_simple(void)40*e7be843bSPierre Pronchery static int test_sstream_simple(void)
41*e7be843bSPierre Pronchery {
42*e7be843bSPierre Pronchery int testresult = 0;
43*e7be843bSPierre Pronchery QUIC_SSTREAM *sstream = NULL;
44*e7be843bSPierre Pronchery OSSL_QUIC_FRAME_STREAM hdr;
45*e7be843bSPierre Pronchery OSSL_QTX_IOVEC iov[2];
46*e7be843bSPierre Pronchery size_t num_iov = 0, wr = 0, i, init_size = 8192;
47*e7be843bSPierre Pronchery
48*e7be843bSPierre Pronchery if (!TEST_ptr(sstream = ossl_quic_sstream_new(init_size)))
49*e7be843bSPierre Pronchery goto err;
50*e7be843bSPierre Pronchery
51*e7be843bSPierre Pronchery /* A stream with nothing yet appended is totally acked */
52*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_is_totally_acked(sstream)))
53*e7be843bSPierre Pronchery goto err;
54*e7be843bSPierre Pronchery
55*e7be843bSPierre Pronchery /* Should not have any data yet */
56*e7be843bSPierre Pronchery num_iov = OSSL_NELEM(iov);
57*e7be843bSPierre Pronchery if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
58*e7be843bSPierre Pronchery &num_iov)))
59*e7be843bSPierre Pronchery goto err;
60*e7be843bSPierre Pronchery
61*e7be843bSPierre Pronchery /* Append data */
62*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_append(sstream, data_1, sizeof(data_1),
63*e7be843bSPierre Pronchery &wr))
64*e7be843bSPierre Pronchery || !TEST_size_t_eq(wr, sizeof(data_1)))
65*e7be843bSPierre Pronchery goto err;
66*e7be843bSPierre Pronchery
67*e7be843bSPierre Pronchery /* No longer totally acked */
68*e7be843bSPierre Pronchery if (!TEST_false(ossl_quic_sstream_is_totally_acked(sstream)))
69*e7be843bSPierre Pronchery goto err;
70*e7be843bSPierre Pronchery
71*e7be843bSPierre Pronchery /* Read data */
72*e7be843bSPierre Pronchery num_iov = OSSL_NELEM(iov);
73*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
74*e7be843bSPierre Pronchery &num_iov))
75*e7be843bSPierre Pronchery || !TEST_size_t_gt(num_iov, 0)
76*e7be843bSPierre Pronchery || !TEST_uint64_t_eq(hdr.offset, 0)
77*e7be843bSPierre Pronchery || !TEST_uint64_t_eq(hdr.len, sizeof(data_1))
78*e7be843bSPierre Pronchery || !TEST_false(hdr.is_fin))
79*e7be843bSPierre Pronchery goto err;
80*e7be843bSPierre Pronchery
81*e7be843bSPierre Pronchery if (!TEST_true(compare_iov(data_1, sizeof(data_1), iov, num_iov)))
82*e7be843bSPierre Pronchery goto err;
83*e7be843bSPierre Pronchery
84*e7be843bSPierre Pronchery /* Mark data as half transmitted */
85*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_mark_transmitted(sstream, 0, 7)))
86*e7be843bSPierre Pronchery goto err;
87*e7be843bSPierre Pronchery
88*e7be843bSPierre Pronchery /* Read data */
89*e7be843bSPierre Pronchery num_iov = OSSL_NELEM(iov);
90*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
91*e7be843bSPierre Pronchery &num_iov))
92*e7be843bSPierre Pronchery || !TEST_size_t_gt(num_iov, 0)
93*e7be843bSPierre Pronchery || !TEST_uint64_t_eq(hdr.offset, 8)
94*e7be843bSPierre Pronchery || !TEST_uint64_t_eq(hdr.len, sizeof(data_1) - 8)
95*e7be843bSPierre Pronchery || !TEST_false(hdr.is_fin))
96*e7be843bSPierre Pronchery goto err;
97*e7be843bSPierre Pronchery
98*e7be843bSPierre Pronchery if (!TEST_true(compare_iov(data_1 + 8, sizeof(data_1) - 8, iov, num_iov)))
99*e7be843bSPierre Pronchery goto err;
100*e7be843bSPierre Pronchery
101*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_mark_transmitted(sstream, 8, 15)))
102*e7be843bSPierre Pronchery goto err;
103*e7be843bSPierre Pronchery
104*e7be843bSPierre Pronchery /* Read more data; should not be any more */
105*e7be843bSPierre Pronchery num_iov = OSSL_NELEM(iov);
106*e7be843bSPierre Pronchery if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
107*e7be843bSPierre Pronchery &num_iov)))
108*e7be843bSPierre Pronchery goto err;
109*e7be843bSPierre Pronchery
110*e7be843bSPierre Pronchery /* Now we have lost bytes 4-6 */
111*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_mark_lost(sstream, 4, 6)))
112*e7be843bSPierre Pronchery goto err;
113*e7be843bSPierre Pronchery
114*e7be843bSPierre Pronchery /* Should be able to read them */
115*e7be843bSPierre Pronchery num_iov = OSSL_NELEM(iov);
116*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
117*e7be843bSPierre Pronchery &num_iov))
118*e7be843bSPierre Pronchery || !TEST_size_t_gt(num_iov, 0)
119*e7be843bSPierre Pronchery || !TEST_uint64_t_eq(hdr.offset, 4)
120*e7be843bSPierre Pronchery || !TEST_uint64_t_eq(hdr.len, 3)
121*e7be843bSPierre Pronchery || !TEST_false(hdr.is_fin))
122*e7be843bSPierre Pronchery goto err;
123*e7be843bSPierre Pronchery
124*e7be843bSPierre Pronchery if (!TEST_true(compare_iov(data_1 + 4, 3, iov, num_iov)))
125*e7be843bSPierre Pronchery goto err;
126*e7be843bSPierre Pronchery
127*e7be843bSPierre Pronchery /* Retransmit */
128*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_mark_transmitted(sstream, 4, 6)))
129*e7be843bSPierre Pronchery goto err;
130*e7be843bSPierre Pronchery
131*e7be843bSPierre Pronchery /* Read more data; should not be any more */
132*e7be843bSPierre Pronchery num_iov = OSSL_NELEM(iov);
133*e7be843bSPierre Pronchery if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
134*e7be843bSPierre Pronchery &num_iov)))
135*e7be843bSPierre Pronchery goto err;
136*e7be843bSPierre Pronchery
137*e7be843bSPierre Pronchery if (!TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), 16))
138*e7be843bSPierre Pronchery goto err;
139*e7be843bSPierre Pronchery
140*e7be843bSPierre Pronchery /* Data has been acknowledged, space should be not be freed yet */
141*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_mark_acked(sstream, 1, 7))
142*e7be843bSPierre Pronchery || !TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), 16))
143*e7be843bSPierre Pronchery goto err;
144*e7be843bSPierre Pronchery
145*e7be843bSPierre Pronchery /* Now data should be freed */
146*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_mark_acked(sstream, 0, 0))
147*e7be843bSPierre Pronchery || !TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), 8))
148*e7be843bSPierre Pronchery goto err;
149*e7be843bSPierre Pronchery
150*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_mark_acked(sstream, 0, 15))
151*e7be843bSPierre Pronchery || !TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), 0))
152*e7be843bSPierre Pronchery goto err;
153*e7be843bSPierre Pronchery
154*e7be843bSPierre Pronchery /* Now FIN */
155*e7be843bSPierre Pronchery ossl_quic_sstream_fin(sstream);
156*e7be843bSPierre Pronchery
157*e7be843bSPierre Pronchery /* Get FIN frame */
158*e7be843bSPierre Pronchery for (i = 0; i < 2; ++i) {
159*e7be843bSPierre Pronchery num_iov = OSSL_NELEM(iov);
160*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
161*e7be843bSPierre Pronchery &num_iov))
162*e7be843bSPierre Pronchery || !TEST_uint64_t_eq(hdr.offset, 16)
163*e7be843bSPierre Pronchery || !TEST_uint64_t_eq(hdr.len, 0)
164*e7be843bSPierre Pronchery || !TEST_true(hdr.is_fin)
165*e7be843bSPierre Pronchery || !TEST_size_t_eq(num_iov, 0))
166*e7be843bSPierre Pronchery goto err;
167*e7be843bSPierre Pronchery }
168*e7be843bSPierre Pronchery
169*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_mark_transmitted_fin(sstream, 16)))
170*e7be843bSPierre Pronchery goto err;
171*e7be843bSPierre Pronchery
172*e7be843bSPierre Pronchery /* Read more data; FIN should not be returned any more */
173*e7be843bSPierre Pronchery num_iov = OSSL_NELEM(iov);
174*e7be843bSPierre Pronchery if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
175*e7be843bSPierre Pronchery &num_iov)))
176*e7be843bSPierre Pronchery goto err;
177*e7be843bSPierre Pronchery
178*e7be843bSPierre Pronchery /* Lose FIN frame */
179*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_mark_lost_fin(sstream)))
180*e7be843bSPierre Pronchery goto err;
181*e7be843bSPierre Pronchery
182*e7be843bSPierre Pronchery /* Get FIN frame */
183*e7be843bSPierre Pronchery for (i = 0; i < 2; ++i) {
184*e7be843bSPierre Pronchery num_iov = OSSL_NELEM(iov);
185*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
186*e7be843bSPierre Pronchery &num_iov))
187*e7be843bSPierre Pronchery || !TEST_uint64_t_eq(hdr.offset, 16)
188*e7be843bSPierre Pronchery || !TEST_uint64_t_eq(hdr.len, 0)
189*e7be843bSPierre Pronchery || !TEST_true(hdr.is_fin)
190*e7be843bSPierre Pronchery || !TEST_size_t_eq(num_iov, 0))
191*e7be843bSPierre Pronchery goto err;
192*e7be843bSPierre Pronchery }
193*e7be843bSPierre Pronchery
194*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_mark_transmitted_fin(sstream, 16)))
195*e7be843bSPierre Pronchery goto err;
196*e7be843bSPierre Pronchery
197*e7be843bSPierre Pronchery /* Read more data; FIN should not be returned any more */
198*e7be843bSPierre Pronchery num_iov = OSSL_NELEM(iov);
199*e7be843bSPierre Pronchery if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
200*e7be843bSPierre Pronchery &num_iov)))
201*e7be843bSPierre Pronchery goto err;
202*e7be843bSPierre Pronchery
203*e7be843bSPierre Pronchery /* Acknowledge fin. */
204*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_mark_acked_fin(sstream)))
205*e7be843bSPierre Pronchery goto err;
206*e7be843bSPierre Pronchery
207*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_is_totally_acked(sstream)))
208*e7be843bSPierre Pronchery goto err;
209*e7be843bSPierre Pronchery
210*e7be843bSPierre Pronchery testresult = 1;
211*e7be843bSPierre Pronchery err:
212*e7be843bSPierre Pronchery ossl_quic_sstream_free(sstream);
213*e7be843bSPierre Pronchery return testresult;
214*e7be843bSPierre Pronchery }
215*e7be843bSPierre Pronchery
test_sstream_bulk(int idx)216*e7be843bSPierre Pronchery static int test_sstream_bulk(int idx)
217*e7be843bSPierre Pronchery {
218*e7be843bSPierre Pronchery int testresult = 0;
219*e7be843bSPierre Pronchery QUIC_SSTREAM *sstream = NULL;
220*e7be843bSPierre Pronchery OSSL_QUIC_FRAME_STREAM hdr;
221*e7be843bSPierre Pronchery OSSL_QTX_IOVEC iov[2];
222*e7be843bSPierre Pronchery size_t i, j, num_iov = 0, init_size = 8192, l;
223*e7be843bSPierre Pronchery size_t consumed = 0, total_written = 0, rd, cur_rd, expected = 0, start_at;
224*e7be843bSPierre Pronchery unsigned char *src_buf = NULL, *dst_buf = NULL;
225*e7be843bSPierre Pronchery unsigned char *ref_src_buf = NULL, *ref_dst_buf = NULL;
226*e7be843bSPierre Pronchery unsigned char *ref_dst_cur, *ref_src_cur, *dst_cur;
227*e7be843bSPierre Pronchery
228*e7be843bSPierre Pronchery if (!TEST_ptr(sstream = ossl_quic_sstream_new(init_size)))
229*e7be843bSPierre Pronchery goto err;
230*e7be843bSPierre Pronchery
231*e7be843bSPierre Pronchery if (!TEST_size_t_eq(ossl_quic_sstream_get_buffer_size(sstream), init_size))
232*e7be843bSPierre Pronchery goto err;
233*e7be843bSPierre Pronchery
234*e7be843bSPierre Pronchery if (!TEST_ptr(src_buf = OPENSSL_zalloc(init_size)))
235*e7be843bSPierre Pronchery goto err;
236*e7be843bSPierre Pronchery
237*e7be843bSPierre Pronchery if (!TEST_ptr(dst_buf = OPENSSL_malloc(init_size)))
238*e7be843bSPierre Pronchery goto err;
239*e7be843bSPierre Pronchery
240*e7be843bSPierre Pronchery if (!TEST_ptr(ref_src_buf = OPENSSL_malloc(init_size)))
241*e7be843bSPierre Pronchery goto err;
242*e7be843bSPierre Pronchery
243*e7be843bSPierre Pronchery if (!TEST_ptr(ref_dst_buf = OPENSSL_malloc(init_size)))
244*e7be843bSPierre Pronchery goto err;
245*e7be843bSPierre Pronchery
246*e7be843bSPierre Pronchery /*
247*e7be843bSPierre Pronchery * Append a preliminary buffer to allow later code to exercise wraparound.
248*e7be843bSPierre Pronchery */
249*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_append(sstream, src_buf, init_size / 2,
250*e7be843bSPierre Pronchery &consumed))
251*e7be843bSPierre Pronchery || !TEST_size_t_eq(consumed, init_size / 2)
252*e7be843bSPierre Pronchery || !TEST_true(ossl_quic_sstream_mark_transmitted(sstream, 0,
253*e7be843bSPierre Pronchery init_size / 2 - 1))
254*e7be843bSPierre Pronchery || !TEST_true(ossl_quic_sstream_mark_acked(sstream, 0,
255*e7be843bSPierre Pronchery init_size / 2 - 1)))
256*e7be843bSPierre Pronchery goto err;
257*e7be843bSPierre Pronchery
258*e7be843bSPierre Pronchery start_at = init_size / 2;
259*e7be843bSPierre Pronchery
260*e7be843bSPierre Pronchery /* Generate a random buffer. */
261*e7be843bSPierre Pronchery for (i = 0; i < init_size; ++i)
262*e7be843bSPierre Pronchery src_buf[i] = (unsigned char)(test_random() & 0xFF);
263*e7be843bSPierre Pronchery
264*e7be843bSPierre Pronchery /* Append bytes into the buffer in chunks of random length. */
265*e7be843bSPierre Pronchery ref_src_cur = ref_src_buf;
266*e7be843bSPierre Pronchery do {
267*e7be843bSPierre Pronchery l = (test_random() % init_size) + 1;
268*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_append(sstream, src_buf, l, &consumed)))
269*e7be843bSPierre Pronchery goto err;
270*e7be843bSPierre Pronchery
271*e7be843bSPierre Pronchery memcpy(ref_src_cur, src_buf, consumed);
272*e7be843bSPierre Pronchery ref_src_cur += consumed;
273*e7be843bSPierre Pronchery total_written += consumed;
274*e7be843bSPierre Pronchery } while (consumed > 0);
275*e7be843bSPierre Pronchery
276*e7be843bSPierre Pronchery if (!TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), init_size)
277*e7be843bSPierre Pronchery || !TEST_size_t_eq(ossl_quic_sstream_get_buffer_avail(sstream), 0))
278*e7be843bSPierre Pronchery goto err;
279*e7be843bSPierre Pronchery
280*e7be843bSPierre Pronchery /*
281*e7be843bSPierre Pronchery * Randomly select bytes out of the buffer by marking them as transmitted.
282*e7be843bSPierre Pronchery * Record the remaining bytes, which should be the sequence of bytes
283*e7be843bSPierre Pronchery * returned.
284*e7be843bSPierre Pronchery */
285*e7be843bSPierre Pronchery ref_src_cur = ref_src_buf;
286*e7be843bSPierre Pronchery ref_dst_cur = ref_dst_buf;
287*e7be843bSPierre Pronchery for (i = 0; i < total_written; ++i) {
288*e7be843bSPierre Pronchery if ((test_random() & 1) != 0) {
289*e7be843bSPierre Pronchery *ref_dst_cur++ = *ref_src_cur;
290*e7be843bSPierre Pronchery ++expected;
291*e7be843bSPierre Pronchery } else if (!TEST_true(ossl_quic_sstream_mark_transmitted(sstream,
292*e7be843bSPierre Pronchery start_at + i,
293*e7be843bSPierre Pronchery start_at + i)))
294*e7be843bSPierre Pronchery goto err;
295*e7be843bSPierre Pronchery
296*e7be843bSPierre Pronchery ++ref_src_cur;
297*e7be843bSPierre Pronchery }
298*e7be843bSPierre Pronchery
299*e7be843bSPierre Pronchery /* Exercise resize. */
300*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_set_buffer_size(sstream, init_size * 2))
301*e7be843bSPierre Pronchery || !TEST_true(ossl_quic_sstream_set_buffer_size(sstream, init_size)))
302*e7be843bSPierre Pronchery goto err;
303*e7be843bSPierre Pronchery
304*e7be843bSPierre Pronchery /* Readout and verification. */
305*e7be843bSPierre Pronchery dst_cur = dst_buf;
306*e7be843bSPierre Pronchery for (i = 0, rd = 0; rd < expected; ++i) {
307*e7be843bSPierre Pronchery num_iov = OSSL_NELEM(iov);
308*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, i, &hdr, iov,
309*e7be843bSPierre Pronchery &num_iov)))
310*e7be843bSPierre Pronchery goto err;
311*e7be843bSPierre Pronchery
312*e7be843bSPierre Pronchery cur_rd = 0;
313*e7be843bSPierre Pronchery for (j = 0; j < num_iov; ++j) {
314*e7be843bSPierre Pronchery if (!TEST_size_t_le(iov[j].buf_len + rd, expected))
315*e7be843bSPierre Pronchery goto err;
316*e7be843bSPierre Pronchery
317*e7be843bSPierre Pronchery memcpy(dst_cur, iov[j].buf, iov[j].buf_len);
318*e7be843bSPierre Pronchery dst_cur += iov[j].buf_len;
319*e7be843bSPierre Pronchery cur_rd += iov[j].buf_len;
320*e7be843bSPierre Pronchery }
321*e7be843bSPierre Pronchery
322*e7be843bSPierre Pronchery if (!TEST_uint64_t_eq(cur_rd, hdr.len))
323*e7be843bSPierre Pronchery goto err;
324*e7be843bSPierre Pronchery
325*e7be843bSPierre Pronchery rd += cur_rd;
326*e7be843bSPierre Pronchery }
327*e7be843bSPierre Pronchery
328*e7be843bSPierre Pronchery if (!TEST_mem_eq(dst_buf, rd, ref_dst_buf, expected))
329*e7be843bSPierre Pronchery goto err;
330*e7be843bSPierre Pronchery
331*e7be843bSPierre Pronchery testresult = 1;
332*e7be843bSPierre Pronchery err:
333*e7be843bSPierre Pronchery OPENSSL_free(src_buf);
334*e7be843bSPierre Pronchery OPENSSL_free(dst_buf);
335*e7be843bSPierre Pronchery OPENSSL_free(ref_src_buf);
336*e7be843bSPierre Pronchery OPENSSL_free(ref_dst_buf);
337*e7be843bSPierre Pronchery ossl_quic_sstream_free(sstream);
338*e7be843bSPierre Pronchery return testresult;
339*e7be843bSPierre Pronchery }
340*e7be843bSPierre Pronchery
test_single_copy_read(QUIC_RSTREAM * qrs,unsigned char * buf,size_t size,size_t * readbytes,int * fin)341*e7be843bSPierre Pronchery static int test_single_copy_read(QUIC_RSTREAM *qrs,
342*e7be843bSPierre Pronchery unsigned char *buf, size_t size,
343*e7be843bSPierre Pronchery size_t *readbytes, int *fin)
344*e7be843bSPierre Pronchery {
345*e7be843bSPierre Pronchery const unsigned char *record;
346*e7be843bSPierre Pronchery size_t rec_len;
347*e7be843bSPierre Pronchery
348*e7be843bSPierre Pronchery *readbytes = 0;
349*e7be843bSPierre Pronchery
350*e7be843bSPierre Pronchery for (;;) {
351*e7be843bSPierre Pronchery if (!ossl_quic_rstream_get_record(qrs, &record, &rec_len, fin))
352*e7be843bSPierre Pronchery return 0;
353*e7be843bSPierre Pronchery if (rec_len == 0)
354*e7be843bSPierre Pronchery break;
355*e7be843bSPierre Pronchery if (rec_len > size) {
356*e7be843bSPierre Pronchery rec_len = size;
357*e7be843bSPierre Pronchery *fin = 0;
358*e7be843bSPierre Pronchery }
359*e7be843bSPierre Pronchery memcpy(buf, record, rec_len);
360*e7be843bSPierre Pronchery size -= rec_len;
361*e7be843bSPierre Pronchery *readbytes += rec_len;
362*e7be843bSPierre Pronchery buf += rec_len;
363*e7be843bSPierre Pronchery
364*e7be843bSPierre Pronchery if (!ossl_quic_rstream_release_record(qrs, rec_len))
365*e7be843bSPierre Pronchery return 0;
366*e7be843bSPierre Pronchery if (*fin || size == 0)
367*e7be843bSPierre Pronchery break;
368*e7be843bSPierre Pronchery }
369*e7be843bSPierre Pronchery
370*e7be843bSPierre Pronchery return 1;
371*e7be843bSPierre Pronchery }
372*e7be843bSPierre Pronchery
373*e7be843bSPierre Pronchery static const unsigned char simple_data[] =
374*e7be843bSPierre Pronchery "Hello world! And thank you for all the fish!";
375*e7be843bSPierre Pronchery
test_rstream_simple(int idx)376*e7be843bSPierre Pronchery static int test_rstream_simple(int idx)
377*e7be843bSPierre Pronchery {
378*e7be843bSPierre Pronchery QUIC_RSTREAM *rstream = NULL;
379*e7be843bSPierre Pronchery int ret = 0;
380*e7be843bSPierre Pronchery unsigned char buf[sizeof(simple_data)];
381*e7be843bSPierre Pronchery size_t readbytes = 0, avail = 0;
382*e7be843bSPierre Pronchery int fin = 0;
383*e7be843bSPierre Pronchery int use_rbuf = idx > 1;
384*e7be843bSPierre Pronchery int use_sc = idx % 2;
385*e7be843bSPierre Pronchery int (* read_fn)(QUIC_RSTREAM *, unsigned char *, size_t, size_t *,
386*e7be843bSPierre Pronchery int *) = use_sc ? test_single_copy_read
387*e7be843bSPierre Pronchery : ossl_quic_rstream_read;
388*e7be843bSPierre Pronchery
389*e7be843bSPierre Pronchery if (!TEST_ptr(rstream = ossl_quic_rstream_new(NULL, NULL, 0)))
390*e7be843bSPierre Pronchery goto err;
391*e7be843bSPierre Pronchery
392*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, 5,
393*e7be843bSPierre Pronchery simple_data + 5, 10, 0))
394*e7be843bSPierre Pronchery || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL,
395*e7be843bSPierre Pronchery sizeof(simple_data) - 1,
396*e7be843bSPierre Pronchery simple_data + sizeof(simple_data) - 1,
397*e7be843bSPierre Pronchery 1, 1))
398*e7be843bSPierre Pronchery || !TEST_true(ossl_quic_rstream_peek(rstream, buf, sizeof(buf),
399*e7be843bSPierre Pronchery &readbytes, &fin))
400*e7be843bSPierre Pronchery || !TEST_false(fin)
401*e7be843bSPierre Pronchery || !TEST_size_t_eq(readbytes, 0)
402*e7be843bSPierre Pronchery || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL,
403*e7be843bSPierre Pronchery sizeof(simple_data) - 10,
404*e7be843bSPierre Pronchery simple_data + sizeof(simple_data) - 10,
405*e7be843bSPierre Pronchery 10, 1))
406*e7be843bSPierre Pronchery || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, 0,
407*e7be843bSPierre Pronchery simple_data, 1, 0))
408*e7be843bSPierre Pronchery || !TEST_true(ossl_quic_rstream_peek(rstream, buf, sizeof(buf),
409*e7be843bSPierre Pronchery &readbytes, &fin))
410*e7be843bSPierre Pronchery || !TEST_false(fin)
411*e7be843bSPierre Pronchery || !TEST_size_t_eq(readbytes, 1)
412*e7be843bSPierre Pronchery || !TEST_mem_eq(buf, 1, simple_data, 1)
413*e7be843bSPierre Pronchery || (use_rbuf && !TEST_false(ossl_quic_rstream_move_to_rbuf(rstream)))
414*e7be843bSPierre Pronchery || (use_rbuf
415*e7be843bSPierre Pronchery && !TEST_true(ossl_quic_rstream_resize_rbuf(rstream,
416*e7be843bSPierre Pronchery sizeof(simple_data))))
417*e7be843bSPierre Pronchery || (use_rbuf && !TEST_true(ossl_quic_rstream_move_to_rbuf(rstream)))
418*e7be843bSPierre Pronchery || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL,
419*e7be843bSPierre Pronchery 0, simple_data,
420*e7be843bSPierre Pronchery 10, 0))
421*e7be843bSPierre Pronchery || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL,
422*e7be843bSPierre Pronchery sizeof(simple_data),
423*e7be843bSPierre Pronchery NULL,
424*e7be843bSPierre Pronchery 0, 1))
425*e7be843bSPierre Pronchery || !TEST_true(ossl_quic_rstream_peek(rstream, buf, sizeof(buf),
426*e7be843bSPierre Pronchery &readbytes, &fin))
427*e7be843bSPierre Pronchery || !TEST_false(fin)
428*e7be843bSPierre Pronchery || !TEST_size_t_eq(readbytes, 15)
429*e7be843bSPierre Pronchery || !TEST_mem_eq(buf, 15, simple_data, 15)
430*e7be843bSPierre Pronchery || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL,
431*e7be843bSPierre Pronchery 15,
432*e7be843bSPierre Pronchery simple_data + 15,
433*e7be843bSPierre Pronchery sizeof(simple_data) - 15, 1))
434*e7be843bSPierre Pronchery || !TEST_true(ossl_quic_rstream_available(rstream, &avail, &fin))
435*e7be843bSPierre Pronchery || !TEST_true(fin)
436*e7be843bSPierre Pronchery || !TEST_size_t_eq(avail, sizeof(simple_data))
437*e7be843bSPierre Pronchery || !TEST_true(read_fn(rstream, buf, 2, &readbytes, &fin))
438*e7be843bSPierre Pronchery || !TEST_false(fin)
439*e7be843bSPierre Pronchery || !TEST_size_t_eq(readbytes, 2)
440*e7be843bSPierre Pronchery || !TEST_mem_eq(buf, 2, simple_data, 2)
441*e7be843bSPierre Pronchery || !TEST_true(read_fn(rstream, buf + 2, 12, &readbytes, &fin))
442*e7be843bSPierre Pronchery || !TEST_false(fin)
443*e7be843bSPierre Pronchery || !TEST_size_t_eq(readbytes, 12)
444*e7be843bSPierre Pronchery || !TEST_mem_eq(buf + 2, 12, simple_data + 2, 12)
445*e7be843bSPierre Pronchery || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL,
446*e7be843bSPierre Pronchery sizeof(simple_data),
447*e7be843bSPierre Pronchery NULL,
448*e7be843bSPierre Pronchery 0, 1))
449*e7be843bSPierre Pronchery || (use_rbuf
450*e7be843bSPierre Pronchery && !TEST_true(ossl_quic_rstream_resize_rbuf(rstream,
451*e7be843bSPierre Pronchery 2 * sizeof(simple_data))))
452*e7be843bSPierre Pronchery || (use_rbuf && !TEST_true(ossl_quic_rstream_move_to_rbuf(rstream)))
453*e7be843bSPierre Pronchery || !TEST_true(read_fn(rstream, buf + 14, 5, &readbytes, &fin))
454*e7be843bSPierre Pronchery || !TEST_false(fin)
455*e7be843bSPierre Pronchery || !TEST_size_t_eq(readbytes, 5)
456*e7be843bSPierre Pronchery || !TEST_mem_eq(buf, 14 + 5, simple_data, 14 + 5)
457*e7be843bSPierre Pronchery || !TEST_true(read_fn(rstream, buf + 14 + 5, sizeof(buf) - 14 - 5,
458*e7be843bSPierre Pronchery &readbytes, &fin))
459*e7be843bSPierre Pronchery || !TEST_true(fin)
460*e7be843bSPierre Pronchery || !TEST_size_t_eq(readbytes, sizeof(buf) - 14 - 5)
461*e7be843bSPierre Pronchery || !TEST_mem_eq(buf, sizeof(buf), simple_data, sizeof(simple_data))
462*e7be843bSPierre Pronchery || (use_rbuf && !TEST_true(ossl_quic_rstream_move_to_rbuf(rstream)))
463*e7be843bSPierre Pronchery || !TEST_true(read_fn(rstream, buf, sizeof(buf), &readbytes, &fin))
464*e7be843bSPierre Pronchery || !TEST_true(fin)
465*e7be843bSPierre Pronchery || !TEST_size_t_eq(readbytes, 0))
466*e7be843bSPierre Pronchery goto err;
467*e7be843bSPierre Pronchery
468*e7be843bSPierre Pronchery ret = 1;
469*e7be843bSPierre Pronchery
470*e7be843bSPierre Pronchery err:
471*e7be843bSPierre Pronchery ossl_quic_rstream_free(rstream);
472*e7be843bSPierre Pronchery return ret;
473*e7be843bSPierre Pronchery }
474*e7be843bSPierre Pronchery
test_rstream_random(int idx)475*e7be843bSPierre Pronchery static int test_rstream_random(int idx)
476*e7be843bSPierre Pronchery {
477*e7be843bSPierre Pronchery unsigned char *bulk_data = NULL;
478*e7be843bSPierre Pronchery unsigned char *read_buf = NULL;
479*e7be843bSPierre Pronchery QUIC_RSTREAM *rstream = NULL;
480*e7be843bSPierre Pronchery size_t i, read_off, queued_min, queued_max;
481*e7be843bSPierre Pronchery const size_t data_size = 10000;
482*e7be843bSPierre Pronchery int r, s, fin = 0, fin_set = 0;
483*e7be843bSPierre Pronchery int ret = 0;
484*e7be843bSPierre Pronchery size_t readbytes = 0;
485*e7be843bSPierre Pronchery
486*e7be843bSPierre Pronchery if (!TEST_ptr(bulk_data = OPENSSL_malloc(data_size))
487*e7be843bSPierre Pronchery || !TEST_ptr(read_buf = OPENSSL_malloc(data_size))
488*e7be843bSPierre Pronchery || !TEST_ptr(rstream = ossl_quic_rstream_new(NULL, NULL, 0)))
489*e7be843bSPierre Pronchery goto err;
490*e7be843bSPierre Pronchery
491*e7be843bSPierre Pronchery if (idx % 3 == 0)
492*e7be843bSPierre Pronchery ossl_quic_rstream_set_cleanse(rstream, 1);
493*e7be843bSPierre Pronchery
494*e7be843bSPierre Pronchery for (i = 0; i < data_size; ++i)
495*e7be843bSPierre Pronchery bulk_data[i] = (unsigned char)(test_random() & 0xFF);
496*e7be843bSPierre Pronchery
497*e7be843bSPierre Pronchery read_off = queued_min = queued_max = 0;
498*e7be843bSPierre Pronchery for (r = 0; r < 100; ++r) {
499*e7be843bSPierre Pronchery for (s = 0; s < 10; ++s) {
500*e7be843bSPierre Pronchery size_t off = (r * 10 + s) * 10, size = 10;
501*e7be843bSPierre Pronchery
502*e7be843bSPierre Pronchery if (test_random() % 10 == 0)
503*e7be843bSPierre Pronchery /* drop packet */
504*e7be843bSPierre Pronchery continue;
505*e7be843bSPierre Pronchery
506*e7be843bSPierre Pronchery if (off <= queued_min && off + size > queued_min)
507*e7be843bSPierre Pronchery queued_min = off + size;
508*e7be843bSPierre Pronchery
509*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, off,
510*e7be843bSPierre Pronchery bulk_data + off,
511*e7be843bSPierre Pronchery size, 0)))
512*e7be843bSPierre Pronchery goto err;
513*e7be843bSPierre Pronchery if (queued_max < off + size)
514*e7be843bSPierre Pronchery queued_max = off + size;
515*e7be843bSPierre Pronchery
516*e7be843bSPierre Pronchery if (test_random() % 5 != 0)
517*e7be843bSPierre Pronchery continue;
518*e7be843bSPierre Pronchery
519*e7be843bSPierre Pronchery /* random overlapping retransmit */
520*e7be843bSPierre Pronchery off = read_off + test_random() % 50;
521*e7be843bSPierre Pronchery if (off > 50)
522*e7be843bSPierre Pronchery off -= 50;
523*e7be843bSPierre Pronchery size = test_random() % 100 + 1;
524*e7be843bSPierre Pronchery if (off + size > data_size)
525*e7be843bSPierre Pronchery off = data_size - size;
526*e7be843bSPierre Pronchery if (off <= queued_min && off + size > queued_min)
527*e7be843bSPierre Pronchery queued_min = off + size;
528*e7be843bSPierre Pronchery
529*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, off,
530*e7be843bSPierre Pronchery bulk_data + off,
531*e7be843bSPierre Pronchery size, 0)))
532*e7be843bSPierre Pronchery goto err;
533*e7be843bSPierre Pronchery if (queued_max < off + size)
534*e7be843bSPierre Pronchery queued_max = off + size;
535*e7be843bSPierre Pronchery }
536*e7be843bSPierre Pronchery if (idx % 2 == 0) {
537*e7be843bSPierre Pronchery if (!TEST_true(test_single_copy_read(rstream, read_buf, data_size,
538*e7be843bSPierre Pronchery &readbytes, &fin)))
539*e7be843bSPierre Pronchery goto err;
540*e7be843bSPierre Pronchery } else if (!TEST_true(ossl_quic_rstream_read(rstream, read_buf,
541*e7be843bSPierre Pronchery data_size,
542*e7be843bSPierre Pronchery &readbytes, &fin))) {
543*e7be843bSPierre Pronchery goto err;
544*e7be843bSPierre Pronchery }
545*e7be843bSPierre Pronchery if (!TEST_size_t_ge(readbytes, queued_min - read_off)
546*e7be843bSPierre Pronchery || !TEST_size_t_le(readbytes + read_off, data_size)
547*e7be843bSPierre Pronchery || (idx % 3 != 0
548*e7be843bSPierre Pronchery && !TEST_mem_eq(read_buf, readbytes, bulk_data + read_off,
549*e7be843bSPierre Pronchery readbytes)))
550*e7be843bSPierre Pronchery goto err;
551*e7be843bSPierre Pronchery read_off += readbytes;
552*e7be843bSPierre Pronchery queued_min = read_off;
553*e7be843bSPierre Pronchery if (test_random() % 50 == 0)
554*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_rstream_resize_rbuf(rstream,
555*e7be843bSPierre Pronchery queued_max - read_off + 1))
556*e7be843bSPierre Pronchery || !TEST_true(ossl_quic_rstream_move_to_rbuf(rstream)))
557*e7be843bSPierre Pronchery goto err;
558*e7be843bSPierre Pronchery if (!fin_set && queued_max >= data_size - test_random() % 200) {
559*e7be843bSPierre Pronchery fin_set = 1;
560*e7be843bSPierre Pronchery /* Queue empty fin frame */
561*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, data_size,
562*e7be843bSPierre Pronchery NULL, 0, 1)))
563*e7be843bSPierre Pronchery goto err;
564*e7be843bSPierre Pronchery }
565*e7be843bSPierre Pronchery }
566*e7be843bSPierre Pronchery
567*e7be843bSPierre Pronchery TEST_info("Total read bytes: %zu Fin rcvd: %d", read_off, fin);
568*e7be843bSPierre Pronchery
569*e7be843bSPierre Pronchery if (idx % 3 == 0)
570*e7be843bSPierre Pronchery for (i = 0; i < read_off; i++)
571*e7be843bSPierre Pronchery if (!TEST_uchar_eq(bulk_data[i], 0))
572*e7be843bSPierre Pronchery goto err;
573*e7be843bSPierre Pronchery
574*e7be843bSPierre Pronchery if (read_off == data_size && fin_set && !fin) {
575*e7be843bSPierre Pronchery /* We might still receive the final empty frame */
576*e7be843bSPierre Pronchery if (idx % 2 == 0) {
577*e7be843bSPierre Pronchery if (!TEST_true(test_single_copy_read(rstream, read_buf, data_size,
578*e7be843bSPierre Pronchery &readbytes, &fin)))
579*e7be843bSPierre Pronchery goto err;
580*e7be843bSPierre Pronchery } else if (!TEST_true(ossl_quic_rstream_read(rstream, read_buf,
581*e7be843bSPierre Pronchery data_size,
582*e7be843bSPierre Pronchery &readbytes, &fin))) {
583*e7be843bSPierre Pronchery goto err;
584*e7be843bSPierre Pronchery }
585*e7be843bSPierre Pronchery if (!TEST_size_t_eq(readbytes, 0) || !TEST_true(fin))
586*e7be843bSPierre Pronchery goto err;
587*e7be843bSPierre Pronchery }
588*e7be843bSPierre Pronchery
589*e7be843bSPierre Pronchery ret = 1;
590*e7be843bSPierre Pronchery
591*e7be843bSPierre Pronchery err:
592*e7be843bSPierre Pronchery ossl_quic_rstream_free(rstream);
593*e7be843bSPierre Pronchery OPENSSL_free(bulk_data);
594*e7be843bSPierre Pronchery OPENSSL_free(read_buf);
595*e7be843bSPierre Pronchery return ret;
596*e7be843bSPierre Pronchery }
597*e7be843bSPierre Pronchery
setup_tests(void)598*e7be843bSPierre Pronchery int setup_tests(void)
599*e7be843bSPierre Pronchery {
600*e7be843bSPierre Pronchery ADD_TEST(test_sstream_simple);
601*e7be843bSPierre Pronchery ADD_ALL_TESTS(test_sstream_bulk, 100);
602*e7be843bSPierre Pronchery ADD_ALL_TESTS(test_rstream_simple, 4);
603*e7be843bSPierre Pronchery ADD_ALL_TESTS(test_rstream_random, 100);
604*e7be843bSPierre Pronchery return 1;
605*e7be843bSPierre Pronchery }
606