quic_stream_test.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. /*
  2. * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include "internal/packet.h"
  10. #include "internal/quic_stream.h"
  11. #include "testutil.h"
  12. static int compare_iov(const unsigned char *ref, size_t ref_len,
  13. const OSSL_QTX_IOVEC *iov, size_t iov_len)
  14. {
  15. size_t i, total_len = 0;
  16. const unsigned char *cur = ref;
  17. for (i = 0; i < iov_len; ++i)
  18. total_len += iov[i].buf_len;
  19. if (ref_len != total_len)
  20. return 0;
  21. for (i = 0; i < iov_len; ++i) {
  22. if (memcmp(cur, iov[i].buf, iov[i].buf_len))
  23. return 0;
  24. cur += iov[i].buf_len;
  25. }
  26. return 1;
  27. }
  28. static const unsigned char data_1[] = {
  29. 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
  30. 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f
  31. };
  32. static int test_sstream_simple(void)
  33. {
  34. int testresult = 0;
  35. QUIC_SSTREAM *sstream = NULL;
  36. OSSL_QUIC_FRAME_STREAM hdr;
  37. OSSL_QTX_IOVEC iov[2];
  38. size_t num_iov = 0, wr = 0, i, init_size = 8192;
  39. if (!TEST_ptr(sstream = ossl_quic_sstream_new(init_size)))
  40. goto err;
  41. /* Should not have any data yet */
  42. num_iov = OSSL_NELEM(iov);
  43. if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
  44. &num_iov)))
  45. goto err;
  46. /* Append data */
  47. if (!TEST_true(ossl_quic_sstream_append(sstream, data_1, sizeof(data_1),
  48. &wr))
  49. || !TEST_size_t_eq(wr, sizeof(data_1)))
  50. goto err;
  51. /* Read data */
  52. num_iov = OSSL_NELEM(iov);
  53. if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
  54. &num_iov))
  55. || !TEST_size_t_gt(num_iov, 0)
  56. || !TEST_uint64_t_eq(hdr.offset, 0)
  57. || !TEST_uint64_t_eq(hdr.len, sizeof(data_1))
  58. || !TEST_false(hdr.is_fin))
  59. goto err;
  60. if (!TEST_true(compare_iov(data_1, sizeof(data_1), iov, num_iov)))
  61. goto err;
  62. /* Mark data as half transmitted */
  63. if (!TEST_true(ossl_quic_sstream_mark_transmitted(sstream, 0, 7)))
  64. goto err;
  65. /* Read data */
  66. num_iov = OSSL_NELEM(iov);
  67. if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
  68. &num_iov))
  69. || !TEST_size_t_gt(num_iov, 0)
  70. || !TEST_uint64_t_eq(hdr.offset, 8)
  71. || !TEST_uint64_t_eq(hdr.len, sizeof(data_1) - 8)
  72. || !TEST_false(hdr.is_fin))
  73. goto err;
  74. if (!TEST_true(compare_iov(data_1 + 8, sizeof(data_1) - 8, iov, num_iov)))
  75. goto err;
  76. if (!TEST_true(ossl_quic_sstream_mark_transmitted(sstream, 8, 15)))
  77. goto err;
  78. /* Read more data; should not be any more */
  79. num_iov = OSSL_NELEM(iov);
  80. if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
  81. &num_iov)))
  82. goto err;
  83. /* Now we have lost bytes 4-6 */
  84. if (!TEST_true(ossl_quic_sstream_mark_lost(sstream, 4, 6)))
  85. goto err;
  86. /* Should be able to read them */
  87. num_iov = OSSL_NELEM(iov);
  88. if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
  89. &num_iov))
  90. || !TEST_size_t_gt(num_iov, 0)
  91. || !TEST_uint64_t_eq(hdr.offset, 4)
  92. || !TEST_uint64_t_eq(hdr.len, 3)
  93. || !TEST_false(hdr.is_fin))
  94. goto err;
  95. if (!TEST_true(compare_iov(data_1 + 4, 3, iov, num_iov)))
  96. goto err;
  97. /* Retransmit */
  98. if (!TEST_true(ossl_quic_sstream_mark_transmitted(sstream, 4, 6)))
  99. goto err;
  100. /* Read more data; should not be any more */
  101. num_iov = OSSL_NELEM(iov);
  102. if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
  103. &num_iov)))
  104. goto err;
  105. if (!TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), 16))
  106. goto err;
  107. /* Data has been acknowledged, space should be not be freed yet */
  108. if (!TEST_true(ossl_quic_sstream_mark_acked(sstream, 1, 7))
  109. || !TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), 16))
  110. goto err;
  111. /* Now data should be freed */
  112. if (!TEST_true(ossl_quic_sstream_mark_acked(sstream, 0, 0))
  113. || !TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), 8))
  114. goto err;
  115. if (!TEST_true(ossl_quic_sstream_mark_acked(sstream, 0, 15))
  116. || !TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), 0))
  117. goto err;
  118. /* Now FIN */
  119. ossl_quic_sstream_fin(sstream);
  120. /* Get FIN frame */
  121. for (i = 0; i < 2; ++i) {
  122. num_iov = OSSL_NELEM(iov);
  123. if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
  124. &num_iov))
  125. || !TEST_uint64_t_eq(hdr.offset, 16)
  126. || !TEST_uint64_t_eq(hdr.len, 0)
  127. || !TEST_true(hdr.is_fin)
  128. || !TEST_size_t_eq(num_iov, 0))
  129. goto err;
  130. }
  131. if (!TEST_true(ossl_quic_sstream_mark_transmitted_fin(sstream, 16)))
  132. goto err;
  133. /* Read more data; FIN should not be returned any more */
  134. num_iov = OSSL_NELEM(iov);
  135. if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
  136. &num_iov)))
  137. goto err;
  138. /* Lose FIN frame */
  139. if (!TEST_true(ossl_quic_sstream_mark_lost_fin(sstream)))
  140. goto err;
  141. /* Get FIN frame */
  142. for (i = 0; i < 2; ++i) {
  143. num_iov = OSSL_NELEM(iov);
  144. if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
  145. &num_iov))
  146. || !TEST_uint64_t_eq(hdr.offset, 16)
  147. || !TEST_uint64_t_eq(hdr.len, 0)
  148. || !TEST_true(hdr.is_fin)
  149. || !TEST_size_t_eq(num_iov, 0))
  150. goto err;
  151. }
  152. if (!TEST_true(ossl_quic_sstream_mark_transmitted_fin(sstream, 16)))
  153. goto err;
  154. /* Read more data; FIN should not be returned any more */
  155. num_iov = OSSL_NELEM(iov);
  156. if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
  157. &num_iov)))
  158. goto err;
  159. /* Acknowledge fin. */
  160. if (!TEST_true(ossl_quic_sstream_mark_acked_fin(sstream)))
  161. goto err;
  162. testresult = 1;
  163. err:
  164. ossl_quic_sstream_free(sstream);
  165. return testresult;
  166. }
  167. static int test_sstream_bulk(int idx)
  168. {
  169. int testresult = 0;
  170. QUIC_SSTREAM *sstream = NULL;
  171. OSSL_QUIC_FRAME_STREAM hdr;
  172. OSSL_QTX_IOVEC iov[2];
  173. size_t i, num_iov = 0, init_size = 8192, l;
  174. size_t consumed = 0, rd, expected = 0;
  175. unsigned char *src_buf = NULL, *dst_buf = NULL;
  176. unsigned char *ref_src_buf = NULL, *ref_dst_buf = NULL;
  177. unsigned char *ref_dst_cur, *ref_src_cur, *dst_cur;
  178. if (!TEST_ptr(sstream = ossl_quic_sstream_new(init_size)))
  179. goto err;
  180. if (!TEST_size_t_eq(ossl_quic_sstream_get_buffer_size(sstream), init_size))
  181. goto err;
  182. if (!TEST_ptr(src_buf = OPENSSL_zalloc(init_size)))
  183. goto err;
  184. if (!TEST_ptr(dst_buf = OPENSSL_malloc(init_size)))
  185. goto err;
  186. if (!TEST_ptr(ref_src_buf = OPENSSL_malloc(init_size)))
  187. goto err;
  188. if (!TEST_ptr(ref_dst_buf = OPENSSL_malloc(init_size)))
  189. goto err;
  190. /*
  191. * Append a preliminary buffer to allow later code to exercise wraparound.
  192. */
  193. if (!TEST_true(ossl_quic_sstream_append(sstream, src_buf, init_size / 2,
  194. &consumed))
  195. || !TEST_size_t_eq(consumed, init_size / 2)
  196. || !TEST_true(ossl_quic_sstream_mark_transmitted(sstream, 0,
  197. init_size / 2 - 1))
  198. || !TEST_true(ossl_quic_sstream_mark_acked(sstream, 0,
  199. init_size / 2 - 1)))
  200. goto err;
  201. /* Generate a random buffer. */
  202. for (i = 0; i < init_size; ++i)
  203. src_buf[i] = (unsigned char)(test_random() & 0xFF);
  204. /* Append bytes into the buffer in chunks of random length. */
  205. ref_src_cur = ref_src_buf;
  206. do {
  207. l = (test_random() % init_size) + 1;
  208. if (!TEST_true(ossl_quic_sstream_append(sstream, src_buf, l, &consumed)))
  209. goto err;
  210. memcpy(ref_src_cur, src_buf, consumed);
  211. ref_src_cur += consumed;
  212. } while (consumed > 0);
  213. if (!TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), init_size)
  214. || !TEST_size_t_eq(ossl_quic_sstream_get_buffer_avail(sstream), 0))
  215. goto err;
  216. /*
  217. * Randomly select bytes out of the buffer by marking them as transmitted.
  218. * Record the remaining bytes, which should be the sequence of bytes
  219. * returned.
  220. */
  221. ref_src_cur = ref_src_buf;
  222. ref_dst_cur = ref_dst_buf;
  223. for (i = 0; i < consumed; ++i) {
  224. if ((test_random() & 1) != 0) {
  225. *ref_dst_cur++ = *ref_src_cur;
  226. ++expected;
  227. } else if (!TEST_true(ossl_quic_sstream_mark_transmitted(sstream, i, i)))
  228. goto err;
  229. ++ref_src_cur;
  230. }
  231. /* Exercise resize. */
  232. if (!TEST_true(ossl_quic_sstream_set_buffer_size(sstream, init_size * 2))
  233. || !TEST_true(ossl_quic_sstream_set_buffer_size(sstream, init_size)))
  234. goto err;
  235. /* Readout and verification. */
  236. dst_cur = dst_buf;
  237. for (i = 0, rd = 0; rd < expected; ++i) {
  238. num_iov = OSSL_NELEM(iov);
  239. if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, i, &hdr, iov,
  240. &num_iov)))
  241. goto err;
  242. for (i = 0; i < num_iov; ++i) {
  243. if (!TEST_size_t_le(iov[i].buf_len + rd, expected))
  244. goto err;
  245. memcpy(dst_cur, iov[i].buf, iov[i].buf_len);
  246. dst_cur += iov[i].buf_len;
  247. rd += iov[i].buf_len;
  248. }
  249. if (!TEST_uint64_t_eq(rd, hdr.len))
  250. goto err;
  251. }
  252. if (!TEST_mem_eq(dst_buf, rd, ref_dst_buf, expected))
  253. goto err;
  254. testresult = 1;
  255. err:
  256. OPENSSL_free(src_buf);
  257. OPENSSL_free(dst_buf);
  258. OPENSSL_free(ref_src_buf);
  259. OPENSSL_free(ref_dst_buf);
  260. ossl_quic_sstream_free(sstream);
  261. return testresult;
  262. }
  263. static const unsigned char simple_data[] =
  264. "Hello world! And thank you for all the fish!";
  265. static int test_rstream_simple(void)
  266. {
  267. QUIC_RSTREAM *rstream = NULL;
  268. int ret = 0;
  269. unsigned char buf[sizeof(simple_data)];
  270. size_t readbytes = 0, avail = 0;
  271. int fin = 0;
  272. if (!TEST_ptr(rstream = ossl_quic_rstream_new(NULL, NULL, NULL)))
  273. goto err;
  274. if (!TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, 5,
  275. simple_data + 5, 10, 0))
  276. || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL,
  277. sizeof(simple_data) - 1,
  278. simple_data + sizeof(simple_data) - 1,
  279. 1, 1))
  280. || !TEST_true(ossl_quic_rstream_peek(rstream, buf, sizeof(buf),
  281. &readbytes, &fin))
  282. || !TEST_false(fin)
  283. || !TEST_size_t_eq(readbytes, 0)
  284. || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL,
  285. sizeof(simple_data) - 10,
  286. simple_data + sizeof(simple_data) - 10,
  287. 10, 1))
  288. || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, 0,
  289. simple_data, 1, 0))
  290. || !TEST_true(ossl_quic_rstream_peek(rstream, buf, sizeof(buf),
  291. &readbytes, &fin))
  292. || !TEST_false(fin)
  293. || !TEST_size_t_eq(readbytes, 1)
  294. || !TEST_mem_eq(buf, 1, simple_data, 1)
  295. || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL,
  296. 0, simple_data,
  297. 10, 0))
  298. || !TEST_true(ossl_quic_rstream_peek(rstream, buf, sizeof(buf),
  299. &readbytes, &fin))
  300. || !TEST_false(fin)
  301. || !TEST_size_t_eq(readbytes, 15)
  302. || !TEST_mem_eq(buf, 15, simple_data, 15)
  303. || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL,
  304. 15,
  305. simple_data + 15,
  306. sizeof(simple_data) - 15, 1))
  307. || !TEST_true(ossl_quic_rstream_available(rstream, &avail, &fin))
  308. || !TEST_true(fin)
  309. || !TEST_size_t_eq(avail, sizeof(simple_data))
  310. || !TEST_true(ossl_quic_rstream_read(rstream, buf, 12,
  311. &readbytes, &fin))
  312. || !TEST_false(fin)
  313. || !TEST_size_t_eq(readbytes, 12)
  314. || !TEST_mem_eq(buf, 12, simple_data, 12)
  315. || !TEST_true(ossl_quic_rstream_read(rstream, buf + 12, sizeof(buf) - 12,
  316. &readbytes, &fin))
  317. || !TEST_true(fin)
  318. || !TEST_size_t_eq(readbytes, sizeof(buf) - 12)
  319. || !TEST_mem_eq(buf, sizeof(buf), simple_data, sizeof(simple_data))
  320. || !TEST_true(ossl_quic_rstream_read(rstream, buf, sizeof(buf),
  321. &readbytes, &fin))
  322. || !TEST_true(fin)
  323. || !TEST_size_t_eq(readbytes, 0))
  324. goto err;
  325. ret = 1;
  326. err:
  327. ossl_quic_rstream_free(rstream);
  328. return ret;
  329. }
  330. static int test_rstream_random(int idx)
  331. {
  332. unsigned char *bulk_data = NULL;
  333. unsigned char *read_buf = NULL;
  334. QUIC_RSTREAM *rstream = NULL;
  335. size_t i, read_off, queued_min;
  336. const size_t data_size = 10000;
  337. int r, s, fin;
  338. int ret = 0;
  339. size_t readbytes = 0;
  340. if (!TEST_ptr(bulk_data = OPENSSL_malloc(data_size))
  341. || !TEST_ptr(read_buf = OPENSSL_malloc(data_size))
  342. || !TEST_ptr(rstream = ossl_quic_rstream_new(NULL, NULL, NULL)))
  343. goto err;
  344. for (i = 0; i < data_size; ++i)
  345. bulk_data[i] = (unsigned char)(test_random() & 0xFF);
  346. read_off = queued_min = 0;
  347. for (r = 0; r < 100; ++r) {
  348. for (s = 0; s < 10; ++s) {
  349. size_t off = (r * 10 + s) * 10, size = 10;
  350. if (test_random() % 5 == 0)
  351. /* drop packet */
  352. continue;
  353. if (off <= queued_min && off + size > queued_min)
  354. queued_min = off + size;
  355. if (!TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, off,
  356. bulk_data + off,
  357. size, 0)))
  358. goto err;
  359. if (test_random() % 5 != 0)
  360. continue;
  361. /* random overlapping retransmit */
  362. off = read_off + test_random() % 50;
  363. if (off > 50)
  364. off -= 50;
  365. size = test_random() % 100;
  366. if (off + size > data_size)
  367. off = data_size - size;
  368. if (off <= queued_min && off + size > queued_min)
  369. queued_min = off + size;
  370. if (!TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, off,
  371. bulk_data + off,
  372. size, 0)))
  373. goto err;
  374. }
  375. if (!TEST_true(ossl_quic_rstream_read(rstream, read_buf,
  376. data_size,
  377. &readbytes, &fin)))
  378. goto err;
  379. if (!TEST_size_t_ge(readbytes, queued_min - read_off)
  380. || !TEST_size_t_le(readbytes + read_off, data_size)
  381. || !TEST_mem_eq(read_buf, readbytes, bulk_data + read_off,
  382. readbytes))
  383. goto err;
  384. read_off += readbytes;
  385. queued_min = read_off;
  386. }
  387. TEST_info("Total read bytes: %zu", read_off);
  388. ret = 1;
  389. err:
  390. OPENSSL_free(bulk_data);
  391. OPENSSL_free(read_buf);
  392. ossl_quic_rstream_free(rstream);
  393. return ret;
  394. }
  395. int setup_tests(void)
  396. {
  397. ADD_TEST(test_sstream_simple);
  398. ADD_ALL_TESTS(test_sstream_bulk, 100);
  399. ADD_TEST(test_rstream_simple);
  400. ADD_ALL_TESTS(test_rstream_random, 100);
  401. return 1;
  402. }