2 * nghttp2 - HTTP/2 C Library
4 * Copyright (c) 2013 Tatsuhiro Tsujikawa
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #include "nghttp2_session_test.h"
30 #include <CUnit/CUnit.h>
32 #include "nghttp2_session.h"
33 #include "nghttp2_stream.h"
34 #include "nghttp2_net.h"
35 #include "nghttp2_helper.h"
36 #include "nghttp2_test_helper.h"
37 #include "nghttp2_priority_spec.h"
39 #define OB_CTRL(ITEM) nghttp2_outbound_item_get_ctrl_frame(ITEM)
40 #define OB_CTRL_TYPE(ITEM) nghttp2_outbound_item_get_ctrl_frame_type(ITEM)
41 #define OB_DATA(ITEM) nghttp2_outbound_item_get_data_frame(ITEM)
58 scripted_data_feed *df;
59 int frame_recv_cb_called, invalid_frame_recv_cb_called;
60 uint8_t recv_frame_type;
61 int frame_send_cb_called;
62 uint8_t sent_frame_type;
63 int frame_not_send_cb_called;
64 uint8_t not_sent_frame_type;
66 int stream_close_cb_called;
67 size_t data_source_length;
70 int data_chunk_recv_cb_called;
71 const nghttp2_frame *frame;
74 int begin_headers_cb_called;
76 size_t data_chunk_len;
78 int begin_frame_cb_called;
81 static void scripted_data_feed_init2(scripted_data_feed *df,
83 nghttp2_buf_chain *ci;
88 memset(df, 0, sizeof(scripted_data_feed));
92 for (ci = bufs->head; ci; ci = ci->next) {
94 ptr = nghttp2_cpymem(ptr, buf->pos, nghttp2_buf_len(buf));
95 len += nghttp2_buf_len(buf);
98 df->datamark = df->data;
99 df->datalimit = df->data + len;
100 df->feedseq[0] = len;
103 static ssize_t null_send_callback(nghttp2_session *session _U_,
104 const uint8_t *data _U_, size_t len,
105 int flags _U_, void *user_data _U_) {
109 static ssize_t fail_send_callback(nghttp2_session *session _U_,
110 const uint8_t *data _U_, size_t len _U_,
111 int flags _U_, void *user_data _U_) {
112 return NGHTTP2_ERR_CALLBACK_FAILURE;
115 static ssize_t fixed_bytes_send_callback(nghttp2_session *session _U_,
116 const uint8_t *data _U_, size_t len,
117 int flags _U_, void *user_data) {
118 size_t fixed_sendlen = ((my_user_data *)user_data)->fixed_sendlen;
119 return fixed_sendlen < len ? fixed_sendlen : len;
122 static ssize_t scripted_recv_callback(nghttp2_session *session _U_,
123 uint8_t *data, size_t len, int flags _U_,
125 scripted_data_feed *df = ((my_user_data *)user_data)->df;
126 size_t wlen = df->feedseq[df->seqidx] > len ? len : df->feedseq[df->seqidx];
127 memcpy(data, df->datamark, wlen);
128 df->datamark += wlen;
129 df->feedseq[df->seqidx] -= wlen;
130 if (df->feedseq[df->seqidx] == 0) {
136 static ssize_t eof_recv_callback(nghttp2_session *session _U_,
137 uint8_t *data _U_, size_t len _U_,
138 int flags _U_, void *user_data _U_) {
139 return NGHTTP2_ERR_EOF;
142 static ssize_t accumulator_send_callback(nghttp2_session *session _U_,
143 const uint8_t *buf, size_t len,
144 int flags _U_, void *user_data) {
145 accumulator *acc = ((my_user_data *)user_data)->acc;
146 assert(acc->length + len < sizeof(acc->buf));
147 memcpy(acc->buf + acc->length, buf, len);
152 static int on_begin_frame_callback(nghttp2_session *session _U_,
153 const nghttp2_frame_hd *hd _U_,
155 my_user_data *ud = (my_user_data *)user_data;
156 ++ud->begin_frame_cb_called;
160 static int on_frame_recv_callback(nghttp2_session *session _U_,
161 const nghttp2_frame *frame, void *user_data) {
162 my_user_data *ud = (my_user_data *)user_data;
163 ++ud->frame_recv_cb_called;
164 ud->recv_frame_type = frame->hd.type;
168 static int on_invalid_frame_recv_callback(nghttp2_session *session _U_,
169 const nghttp2_frame *frame _U_,
170 nghttp2_error_code error_code _U_,
172 my_user_data *ud = (my_user_data *)user_data;
173 ++ud->invalid_frame_recv_cb_called;
177 static int on_frame_send_callback(nghttp2_session *session _U_,
178 const nghttp2_frame *frame, void *user_data) {
179 my_user_data *ud = (my_user_data *)user_data;
180 ++ud->frame_send_cb_called;
181 ud->sent_frame_type = frame->hd.type;
185 static int on_frame_not_send_callback(nghttp2_session *session _U_,
186 const nghttp2_frame *frame, int lib_error,
188 my_user_data *ud = (my_user_data *)user_data;
189 ++ud->frame_not_send_cb_called;
190 ud->not_sent_frame_type = frame->hd.type;
191 ud->not_sent_error = lib_error;
195 static int on_data_chunk_recv_callback(nghttp2_session *session _U_,
196 uint8_t flags _U_, int32_t stream_id _U_,
197 const uint8_t *data _U_, size_t len,
199 my_user_data *ud = (my_user_data *)user_data;
200 ++ud->data_chunk_recv_cb_called;
201 ud->data_chunk_len = len;
205 static int pause_on_data_chunk_recv_callback(nghttp2_session *session _U_,
207 int32_t stream_id _U_,
208 const uint8_t *data _U_,
209 size_t len _U_, void *user_data) {
210 my_user_data *ud = (my_user_data *)user_data;
211 ++ud->data_chunk_recv_cb_called;
212 return NGHTTP2_ERR_PAUSE;
215 static ssize_t select_padding_callback(nghttp2_session *session _U_,
216 const nghttp2_frame *frame,
217 size_t max_payloadlen, void *user_data) {
218 my_user_data *ud = (my_user_data *)user_data;
219 return nghttp2_min(max_payloadlen, frame->hd.length + ud->padlen);
222 static ssize_t too_large_data_source_length_callback(
223 nghttp2_session *session _U_, uint8_t frame_type _U_, int32_t stream_id _U_,
224 int32_t session_remote_window_size _U_,
225 int32_t stream_remote_window_size _U_, uint32_t remote_max_frame_size _U_,
226 void *user_data _U_) {
227 return NGHTTP2_MAX_FRAME_SIZE_MAX + 1;
230 static ssize_t smallest_length_data_source_length_callback(
231 nghttp2_session *session _U_, uint8_t frame_type _U_, int32_t stream_id _U_,
232 int32_t session_remote_window_size _U_,
233 int32_t stream_remote_window_size _U_, uint32_t remote_max_frame_size _U_,
234 void *user_data _U_) {
238 static ssize_t fixed_length_data_source_read_callback(
239 nghttp2_session *session _U_, int32_t stream_id _U_, uint8_t *buf _U_,
240 size_t len, uint32_t *data_flags, nghttp2_data_source *source _U_,
242 my_user_data *ud = (my_user_data *)user_data;
244 if (len < ud->data_source_length) {
247 wlen = ud->data_source_length;
249 ud->data_source_length -= wlen;
250 if (ud->data_source_length == 0) {
251 *data_flags |= NGHTTP2_DATA_FLAG_EOF;
256 static ssize_t temporal_failure_data_source_read_callback(
257 nghttp2_session *session _U_, int32_t stream_id _U_, uint8_t *buf _U_,
258 size_t len _U_, uint32_t *data_flags _U_, nghttp2_data_source *source _U_,
259 void *user_data _U_) {
260 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
263 static ssize_t fail_data_source_read_callback(nghttp2_session *session _U_,
264 int32_t stream_id _U_,
265 uint8_t *buf _U_, size_t len _U_,
266 uint32_t *data_flags _U_,
267 nghttp2_data_source *source _U_,
268 void *user_data _U_) {
269 return NGHTTP2_ERR_CALLBACK_FAILURE;
272 /* static void no_stream_user_data_stream_close_callback */
273 /* (nghttp2_session *session, */
274 /* int32_t stream_id, */
275 /* nghttp2_error_code error_code, */
276 /* void *user_data) */
278 /* my_user_data* my_data = (my_user_data*)user_data; */
279 /* ++my_data->stream_close_cb_called; */
282 static ssize_t block_count_send_callback(nghttp2_session *session _U_,
283 const uint8_t *data _U_, size_t len,
284 int flags _U_, void *user_data) {
285 my_user_data *ud = (my_user_data *)user_data;
287 if (ud->block_count == 0) {
288 r = NGHTTP2_ERR_WOULDBLOCK;
296 static int on_header_callback(nghttp2_session *session _U_,
297 const nghttp2_frame *frame, const uint8_t *name,
298 size_t namelen, const uint8_t *value,
299 size_t valuelen, uint8_t flags _U_,
301 my_user_data *ud = (my_user_data *)user_data;
302 ++ud->header_cb_called;
303 ud->nv.name = (uint8_t *)name;
304 ud->nv.namelen = namelen;
305 ud->nv.value = (uint8_t *)value;
306 ud->nv.valuelen = valuelen;
312 static int pause_on_header_callback(nghttp2_session *session,
313 const nghttp2_frame *frame,
314 const uint8_t *name, size_t namelen,
315 const uint8_t *value, size_t valuelen,
316 uint8_t flags, void *user_data) {
317 on_header_callback(session, frame, name, namelen, value, valuelen, flags,
319 return NGHTTP2_ERR_PAUSE;
322 static int temporal_failure_on_header_callback(
323 nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name,
324 size_t namelen, const uint8_t *value, size_t valuelen, uint8_t flags,
326 on_header_callback(session, frame, name, namelen, value, valuelen, flags,
328 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
331 static int on_begin_headers_callback(nghttp2_session *session _U_,
332 const nghttp2_frame *frame _U_,
334 my_user_data *ud = (my_user_data *)user_data;
335 ++ud->begin_headers_cb_called;
339 static ssize_t defer_data_source_read_callback(nghttp2_session *session _U_,
340 int32_t stream_id _U_,
341 uint8_t *buf _U_, size_t len _U_,
342 uint32_t *data_flags _U_,
343 nghttp2_data_source *source _U_,
344 void *user_data _U_) {
345 return NGHTTP2_ERR_DEFERRED;
348 static int on_stream_close_callback(nghttp2_session *session _U_,
349 int32_t stream_id _U_,
350 nghttp2_error_code error_code _U_,
352 my_user_data *my_data = (my_user_data *)user_data;
353 ++my_data->stream_close_cb_called;
358 static nghttp2_settings_entry *dup_iv(const nghttp2_settings_entry *iv,
360 return nghttp2_frame_iv_copy(iv, niv, nghttp2_mem_default());
363 static nghttp2_priority_spec pri_spec_default = {0, NGHTTP2_DEFAULT_WEIGHT, 0};
365 void test_nghttp2_session_recv(void) {
366 nghttp2_session *session;
367 nghttp2_session_callbacks callbacks;
368 scripted_data_feed df;
369 my_user_data user_data;
370 const nghttp2_nv nv[] = {MAKE_NV("url", "/")};
375 nghttp2_outbound_item *item;
378 nghttp2_hd_deflater deflater;
382 mem = nghttp2_mem_default();
383 frame_pack_bufs_init(&bufs);
385 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
386 callbacks.send_callback = null_send_callback;
387 callbacks.recv_callback = scripted_recv_callback;
388 callbacks.on_frame_recv_callback = on_frame_recv_callback;
389 callbacks.on_begin_frame_callback = on_begin_frame_callback;
393 nghttp2_session_server_new(&session, &callbacks, &user_data);
394 nghttp2_hd_deflate_init(&deflater, mem);
397 nghttp2_nv_array_copy(&nva, nv, nvlen, mem);
398 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
399 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
400 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
404 scripted_data_feed_init2(&df, &bufs);
406 framelen = nghttp2_bufs_len(&bufs);
408 /* Send 1 byte per each read */
409 for (i = 0; i < framelen; ++i) {
413 nghttp2_frame_headers_free(&frame.headers, mem);
415 user_data.frame_recv_cb_called = 0;
416 user_data.begin_frame_cb_called = 0;
418 while ((ssize_t)df.seqidx < framelen) {
419 CU_ASSERT(0 == nghttp2_session_recv(session));
421 CU_ASSERT(1 == user_data.frame_recv_cb_called);
422 CU_ASSERT(1 == user_data.begin_frame_cb_called);
424 nghttp2_bufs_reset(&bufs);
426 /* Received HEADERS without header block, which is valid */
427 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 5,
428 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
429 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
433 nghttp2_frame_headers_free(&frame.headers, mem);
435 scripted_data_feed_init2(&df, &bufs);
436 user_data.frame_recv_cb_called = 0;
437 user_data.begin_frame_cb_called = 0;
439 CU_ASSERT(0 == nghttp2_session_recv(session));
440 CU_ASSERT(1 == user_data.frame_recv_cb_called);
441 CU_ASSERT(1 == user_data.begin_frame_cb_called);
443 nghttp2_bufs_reset(&bufs);
445 /* Receive PRIORITY */
446 nghttp2_frame_priority_init(&frame.priority, 5, &pri_spec_default);
448 rv = nghttp2_frame_pack_priority(&bufs, &frame.priority);
452 nghttp2_frame_priority_free(&frame.priority);
454 scripted_data_feed_init2(&df, &bufs);
456 user_data.frame_recv_cb_called = 0;
457 user_data.begin_frame_cb_called = 0;
459 CU_ASSERT(0 == nghttp2_session_recv(session));
460 CU_ASSERT(1 == user_data.frame_recv_cb_called);
461 CU_ASSERT(1 == user_data.begin_frame_cb_called);
463 nghttp2_bufs_reset(&bufs);
465 nghttp2_hd_deflate_free(&deflater);
466 nghttp2_session_del(session);
468 /* Some tests for frame too large */
469 nghttp2_session_server_new(&session, &callbacks, &user_data);
471 /* Receive PING with too large payload */
472 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
474 rv = nghttp2_frame_pack_ping(&bufs, &frame.ping);
478 /* Add extra 16 bytes */
479 nghttp2_bufs_seek_last_present(&bufs);
480 assert(nghttp2_buf_len(&bufs.cur->buf) >= 16);
482 bufs.cur->buf.last += 16;
483 nghttp2_put_uint32be(
485 (uint32_t)(((frame.hd.length + 16) << 8) + bufs.cur->buf.pos[3]));
487 nghttp2_frame_ping_free(&frame.ping);
489 scripted_data_feed_init2(&df, &bufs);
490 user_data.frame_recv_cb_called = 0;
491 user_data.begin_frame_cb_called = 0;
493 CU_ASSERT(0 == nghttp2_session_recv(session));
494 CU_ASSERT(0 == user_data.frame_recv_cb_called);
495 CU_ASSERT(0 == user_data.begin_frame_cb_called);
497 item = nghttp2_session_get_next_ob_item(session);
498 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
499 CU_ASSERT(NGHTTP2_FRAME_SIZE_ERROR == item->frame.goaway.error_code);
500 CU_ASSERT(0 == nghttp2_session_send(session));
502 nghttp2_bufs_free(&bufs);
503 nghttp2_session_del(session);
506 void test_nghttp2_session_recv_invalid_stream_id(void) {
507 nghttp2_session *session;
508 nghttp2_session_callbacks callbacks;
509 scripted_data_feed df;
510 my_user_data user_data;
513 nghttp2_hd_deflater deflater;
517 mem = nghttp2_mem_default();
518 frame_pack_bufs_init(&bufs);
520 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
521 callbacks.recv_callback = scripted_recv_callback;
522 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
525 user_data.invalid_frame_recv_cb_called = 0;
526 nghttp2_session_server_new(&session, &callbacks, &user_data);
527 nghttp2_hd_deflate_init(&deflater, mem);
529 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
530 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
531 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
534 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
536 scripted_data_feed_init2(&df, &bufs);
537 nghttp2_frame_headers_free(&frame.headers, mem);
539 CU_ASSERT(0 == nghttp2_session_recv(session));
540 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
542 nghttp2_bufs_free(&bufs);
543 nghttp2_hd_deflate_free(&deflater);
544 nghttp2_session_del(session);
547 void test_nghttp2_session_recv_invalid_frame(void) {
548 nghttp2_session *session;
549 nghttp2_session_callbacks callbacks;
550 scripted_data_feed df;
551 my_user_data user_data;
552 const nghttp2_nv nv[] = {MAKE_NV("url", "/")};
557 nghttp2_hd_deflater deflater;
561 mem = nghttp2_mem_default();
562 frame_pack_bufs_init(&bufs);
564 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
565 callbacks.recv_callback = scripted_recv_callback;
566 callbacks.send_callback = null_send_callback;
567 callbacks.on_frame_send_callback = on_frame_send_callback;
570 user_data.frame_send_cb_called = 0;
571 nghttp2_session_server_new(&session, &callbacks, &user_data);
572 nghttp2_hd_deflate_init(&deflater, mem);
574 nghttp2_nv_array_copy(&nva, nv, nvlen, mem);
575 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
576 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
577 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
580 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
582 scripted_data_feed_init2(&df, &bufs);
584 CU_ASSERT(0 == nghttp2_session_recv(session));
585 CU_ASSERT(0 == nghttp2_session_send(session));
586 CU_ASSERT(0 == user_data.frame_send_cb_called);
588 /* Receive exactly same bytes of HEADERS is treated as subsequent
589 HEADERS (e.g., trailers */
590 scripted_data_feed_init2(&df, &bufs);
592 CU_ASSERT(0 == nghttp2_session_recv(session));
593 CU_ASSERT(0 == nghttp2_session_send(session));
594 CU_ASSERT(0 == user_data.frame_send_cb_called);
596 nghttp2_bufs_free(&bufs);
597 nghttp2_frame_headers_free(&frame.headers, mem);
599 nghttp2_hd_deflate_free(&deflater);
600 nghttp2_session_del(session);
603 void test_nghttp2_session_recv_eof(void) {
604 nghttp2_session *session;
605 nghttp2_session_callbacks callbacks;
607 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
608 callbacks.send_callback = null_send_callback;
609 callbacks.recv_callback = eof_recv_callback;
611 nghttp2_session_client_new(&session, &callbacks, NULL);
612 CU_ASSERT(NGHTTP2_ERR_EOF == nghttp2_session_recv(session));
614 nghttp2_session_del(session);
617 void test_nghttp2_session_recv_data(void) {
618 nghttp2_session *session;
619 nghttp2_session_callbacks callbacks;
623 nghttp2_outbound_item *item;
624 nghttp2_stream *stream;
628 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
629 callbacks.send_callback = null_send_callback;
630 callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
631 callbacks.on_frame_recv_callback = on_frame_recv_callback;
633 nghttp2_session_client_new(&session, &callbacks, &ud);
635 /* Create DATA frame with length 4KiB */
636 memset(data, 0, sizeof(data));
638 hd.type = NGHTTP2_DATA;
639 hd.flags = NGHTTP2_FLAG_NONE;
641 nghttp2_frame_pack_frame_hd(data, &hd);
643 /* stream 1 is not opened, so it must be responded with connection
644 error. This is not mandated by the spec */
645 ud.data_chunk_recv_cb_called = 0;
646 ud.frame_recv_cb_called = 0;
647 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
648 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
650 CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
651 CU_ASSERT(0 == ud.frame_recv_cb_called);
652 item = nghttp2_session_get_next_ob_item(session);
653 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
655 nghttp2_session_del(session);
657 nghttp2_session_client_new(&session, &callbacks, &ud);
659 /* Create stream 1 with CLOSING state. DATA is ignored. */
660 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
662 NGHTTP2_STREAM_CLOSING, NULL);
663 /* Set initial window size 16383 to check stream flow control,
664 isolating it from the conneciton flow control */
665 stream->local_window_size = 16383;
667 ud.data_chunk_recv_cb_called = 0;
668 ud.frame_recv_cb_called = 0;
669 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
670 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
672 CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
673 CU_ASSERT(0 == ud.frame_recv_cb_called);
674 item = nghttp2_session_get_next_ob_item(session);
675 CU_ASSERT(NULL == item);
677 /* This is normal case. DATA is acceptable. */
678 stream->state = NGHTTP2_STREAM_OPENED;
680 ud.data_chunk_recv_cb_called = 0;
681 ud.frame_recv_cb_called = 0;
682 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
683 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
685 CU_ASSERT(1 == ud.data_chunk_recv_cb_called);
686 CU_ASSERT(1 == ud.frame_recv_cb_called);
688 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
690 ud.data_chunk_recv_cb_called = 0;
691 ud.frame_recv_cb_called = 0;
692 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
693 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
695 /* Now we got data more than initial-window-size / 2, WINDOW_UPDATE
697 CU_ASSERT(1 == ud.data_chunk_recv_cb_called);
698 CU_ASSERT(1 == ud.frame_recv_cb_called);
699 item = nghttp2_session_get_next_ob_item(session);
700 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
701 CU_ASSERT(1 == item->frame.window_update.hd.stream_id);
702 CU_ASSERT(0 == nghttp2_session_send(session));
704 /* Set initial window size to 1MiB, so that we can check connection
705 flow control individually */
706 stream->local_window_size = 1 << 20;
707 /* Connection flow control takes into account DATA which is received
708 in the error condition. We have received 4096 * 4 bytes of
709 DATA. Additional 4 DATA frames, connection flow control will kick
711 for (i = 0; i < 5; ++i) {
712 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
713 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
715 item = nghttp2_session_get_next_ob_item(session);
716 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
717 CU_ASSERT(0 == item->frame.window_update.hd.stream_id);
718 CU_ASSERT(0 == nghttp2_session_send(session));
720 /* Reception of DATA with stream ID = 0 causes connection error */
722 hd.type = NGHTTP2_DATA;
723 hd.flags = NGHTTP2_FLAG_NONE;
725 nghttp2_frame_pack_frame_hd(data, &hd);
727 ud.data_chunk_recv_cb_called = 0;
728 ud.frame_recv_cb_called = 0;
729 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
730 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
732 CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
733 CU_ASSERT(0 == ud.frame_recv_cb_called);
734 item = nghttp2_session_get_next_ob_item(session);
735 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
736 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
738 nghttp2_session_del(session);
741 void test_nghttp2_session_recv_continuation(void) {
742 nghttp2_session *session;
743 nghttp2_session_callbacks callbacks;
744 const nghttp2_nv nv1[] = {MAKE_NV("method", "GET"), MAKE_NV("path", "/")};
752 nghttp2_hd_deflater deflater;
755 nghttp2_frame_hd cont_hd;
756 nghttp2_priority_spec pri_spec;
759 mem = nghttp2_mem_default();
760 frame_pack_bufs_init(&bufs);
762 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
763 callbacks.on_header_callback = on_header_callback;
764 callbacks.on_begin_headers_callback = on_begin_headers_callback;
765 callbacks.on_begin_frame_callback = on_begin_frame_callback;
767 nghttp2_session_server_new(&session, &callbacks, &ud);
769 nghttp2_hd_deflate_init(&deflater, mem);
771 /* Make 1 HEADERS and insert CONTINUATION header */
773 nghttp2_nv_array_copy(&nva, nv1, nvlen, mem);
774 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1,
775 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
776 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
779 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
781 /* make sure that all data is in the first buf */
782 buf = &bufs.head->buf;
783 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
785 nghttp2_frame_headers_free(&frame.headers, mem);
787 /* HEADERS's payload is 1 byte */
788 memcpy(data, buf->pos, NGHTTP2_FRAME_HDLEN + 1);
789 datalen = NGHTTP2_FRAME_HDLEN + 1;
790 buf->pos += NGHTTP2_FRAME_HDLEN + 1;
792 nghttp2_put_uint32be(data, (1 << 8) + data[3]);
794 /* First CONTINUATION, 2 bytes */
795 nghttp2_frame_hd_init(&cont_hd, 2, NGHTTP2_CONTINUATION, NGHTTP2_FLAG_NONE,
798 nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
799 datalen += NGHTTP2_FRAME_HDLEN;
801 memcpy(data + datalen, buf->pos, cont_hd.length);
802 datalen += cont_hd.length;
803 buf->pos += cont_hd.length;
805 /* Second CONTINUATION, rest of the bytes */
806 nghttp2_frame_hd_init(&cont_hd, nghttp2_buf_len(buf), NGHTTP2_CONTINUATION,
807 NGHTTP2_FLAG_END_HEADERS, 1);
809 nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
810 datalen += NGHTTP2_FRAME_HDLEN;
812 memcpy(data + datalen, buf->pos, cont_hd.length);
813 datalen += cont_hd.length;
814 buf->pos += cont_hd.length;
816 CU_ASSERT(0 == nghttp2_buf_len(buf));
818 ud.header_cb_called = 0;
819 ud.begin_frame_cb_called = 0;
821 rv = nghttp2_session_mem_recv(session, data, datalen);
822 CU_ASSERT((ssize_t)datalen == rv);
823 CU_ASSERT(2 == ud.header_cb_called);
824 CU_ASSERT(3 == ud.begin_frame_cb_called);
826 nghttp2_hd_deflate_free(&deflater);
827 nghttp2_session_del(session);
829 /* Expecting CONTINUATION, but get the other frame */
830 nghttp2_session_server_new(&session, &callbacks, &ud);
832 nghttp2_hd_deflate_init(&deflater, mem);
834 /* HEADERS without END_HEADERS flag */
836 nghttp2_nv_array_copy(&nva, nv1, nvlen, mem);
837 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1,
838 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
839 nghttp2_bufs_reset(&bufs);
840 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
843 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
845 nghttp2_frame_headers_free(&frame.headers, mem);
847 /* make sure that all data is in the first buf */
848 buf = &bufs.head->buf;
849 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
851 memcpy(data, buf->pos, nghttp2_buf_len(buf));
852 datalen = nghttp2_buf_len(buf);
854 /* Followed by PRIORITY */
855 nghttp2_priority_spec_default_init(&pri_spec);
857 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
858 nghttp2_bufs_reset(&bufs);
860 rv = nghttp2_frame_pack_priority(&bufs, &frame.priority);
863 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
865 memcpy(data + datalen, buf->pos, nghttp2_buf_len(buf));
866 datalen += nghttp2_buf_len(buf);
868 ud.begin_headers_cb_called = 0;
869 rv = nghttp2_session_mem_recv(session, data, datalen);
870 CU_ASSERT((ssize_t)datalen == rv);
872 CU_ASSERT(1 == ud.begin_headers_cb_called);
873 CU_ASSERT(NGHTTP2_GOAWAY ==
874 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
876 nghttp2_bufs_free(&bufs);
877 nghttp2_hd_deflate_free(&deflater);
878 nghttp2_session_del(session);
881 void test_nghttp2_session_recv_headers_with_priority(void) {
882 nghttp2_session *session;
883 nghttp2_session_callbacks callbacks;
884 const nghttp2_nv nv1[] = {MAKE_NV("method", "GET"), MAKE_NV("path", "/")};
892 nghttp2_hd_deflater deflater;
893 nghttp2_outbound_item *item;
894 nghttp2_priority_spec pri_spec;
895 nghttp2_stream *stream;
898 mem = nghttp2_mem_default();
899 frame_pack_bufs_init(&bufs);
901 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
902 callbacks.on_frame_recv_callback = on_frame_recv_callback;
904 nghttp2_session_server_new(&session, &callbacks, &ud);
906 nghttp2_hd_deflate_init(&deflater, mem);
908 open_stream(session, 1);
910 /* With NGHTTP2_FLAG_PRIORITY without exclusive flag set */
912 nghttp2_nv_array_copy(&nva, nv1, nvlen, mem);
914 nghttp2_priority_spec_init(&pri_spec, 1, 99, 0);
916 nghttp2_frame_headers_init(&frame.headers,
917 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
918 3, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
920 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
923 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
925 nghttp2_frame_headers_free(&frame.headers, mem);
927 buf = &bufs.head->buf;
928 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
930 ud.frame_recv_cb_called = 0;
932 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
934 CU_ASSERT(nghttp2_buf_len(buf) == rv);
935 CU_ASSERT(1 == ud.frame_recv_cb_called);
937 stream = nghttp2_session_get_stream(session, 3);
939 CU_ASSERT(99 == stream->weight);
940 CU_ASSERT(1 == stream->dep_prev->stream_id);
942 nghttp2_bufs_reset(&bufs);
944 /* With NGHTTP2_FLAG_PRIORITY, but cut last 1 byte to make it
947 nghttp2_nv_array_copy(&nva, nv1, nvlen, mem);
949 nghttp2_priority_spec_init(&pri_spec, 0, 99, 0);
951 nghttp2_frame_headers_init(&frame.headers,
952 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
953 5, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
955 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
958 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 5 + 2 == nghttp2_bufs_len(&bufs));
960 nghttp2_frame_headers_free(&frame.headers, mem);
962 buf = &bufs.head->buf;
963 /* Make payload shorter than required length to store priroty
965 nghttp2_put_uint32be(buf->pos, (4 << 8) + buf->pos[3]);
967 ud.frame_recv_cb_called = 0;
969 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
971 CU_ASSERT(nghttp2_buf_len(buf) == rv);
972 CU_ASSERT(0 == ud.frame_recv_cb_called);
974 stream = nghttp2_session_get_stream(session, 5);
976 CU_ASSERT(NULL == stream);
978 item = nghttp2_session_get_next_ob_item(session);
979 CU_ASSERT(NULL != item);
980 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
981 CU_ASSERT(NGHTTP2_FRAME_SIZE_ERROR == item->frame.goaway.error_code);
983 nghttp2_bufs_reset(&bufs);
985 nghttp2_hd_deflate_free(&deflater);
986 nghttp2_session_del(session);
988 /* Check dep_stream_id == stream_id */
989 nghttp2_session_server_new(&session, &callbacks, &ud);
991 nghttp2_hd_deflate_init(&deflater, mem);
994 nghttp2_nv_array_copy(&nva, nv1, nvlen, mem);
996 nghttp2_priority_spec_init(&pri_spec, 1, 0, 0);
998 nghttp2_frame_headers_init(&frame.headers,
999 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1000 1, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
1002 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1005 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1007 nghttp2_frame_headers_free(&frame.headers, mem);
1009 buf = &bufs.head->buf;
1010 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1012 ud.frame_recv_cb_called = 0;
1014 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1016 CU_ASSERT(nghttp2_buf_len(buf) == rv);
1017 CU_ASSERT(0 == ud.frame_recv_cb_called);
1019 stream = nghttp2_session_get_stream(session, 1);
1021 CU_ASSERT(NULL == stream);
1023 item = nghttp2_session_get_next_ob_item(session);
1024 CU_ASSERT(NULL != item);
1025 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1026 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
1028 nghttp2_bufs_reset(&bufs);
1030 nghttp2_bufs_free(&bufs);
1031 nghttp2_hd_deflate_free(&deflater);
1032 nghttp2_session_del(session);
1035 void test_nghttp2_session_recv_premature_headers(void) {
1036 nghttp2_session *session;
1037 nghttp2_session_callbacks callbacks;
1038 const nghttp2_nv nv1[] = {MAKE_NV("method", "GET"), MAKE_NV("path", "/")};
1041 nghttp2_frame frame;
1046 nghttp2_hd_deflater deflater;
1047 nghttp2_outbound_item *item;
1050 mem = nghttp2_mem_default();
1051 frame_pack_bufs_init(&bufs);
1053 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1055 nghttp2_session_server_new(&session, &callbacks, &ud);
1057 nghttp2_hd_deflate_init(&deflater, mem);
1059 nvlen = ARRLEN(nv1);
1060 nghttp2_nv_array_copy(&nva, nv1, nvlen, mem);
1061 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
1062 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1063 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1066 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1068 nghttp2_frame_headers_free(&frame.headers, mem);
1070 buf = &bufs.head->buf;
1071 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1073 /* Intentionally feed payload cutting last 1 byte off */
1074 nghttp2_put_uint32be(buf->pos,
1075 (uint32_t)(((frame.hd.length - 1) << 8) + buf->pos[3]));
1076 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf) - 1);
1078 CU_ASSERT((ssize_t)(nghttp2_buf_len(buf) - 1) == rv);
1080 item = nghttp2_session_get_next_ob_item(session);
1081 CU_ASSERT(NULL != item);
1082 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
1083 CU_ASSERT(NGHTTP2_COMPRESSION_ERROR == item->frame.rst_stream.error_code);
1085 nghttp2_bufs_free(&bufs);
1086 nghttp2_hd_deflate_free(&deflater);
1087 nghttp2_session_del(session);
1090 void test_nghttp2_session_recv_unknown_frame(void) {
1091 nghttp2_session *session;
1092 nghttp2_session_callbacks callbacks;
1094 uint8_t data[16384];
1096 nghttp2_frame_hd hd;
1099 nghttp2_frame_hd_init(&hd, 16000, 99, NGHTTP2_FLAG_NONE, 0);
1101 nghttp2_frame_pack_frame_hd(data, &hd);
1102 datalen = NGHTTP2_FRAME_HDLEN + hd.length;
1104 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1105 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1107 nghttp2_session_server_new(&session, &callbacks, &ud);
1109 ud.frame_recv_cb_called = 0;
1111 /* Unknown frame must be ignored */
1112 rv = nghttp2_session_mem_recv(session, data, datalen);
1114 CU_ASSERT(rv == (ssize_t)datalen);
1115 CU_ASSERT(0 == ud.frame_recv_cb_called);
1116 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
1118 nghttp2_session_del(session);
1121 void test_nghttp2_session_recv_unexpected_continuation(void) {
1122 nghttp2_session *session;
1123 nghttp2_session_callbacks callbacks;
1125 uint8_t data[16384];
1127 nghttp2_frame_hd hd;
1129 nghttp2_outbound_item *item;
1131 nghttp2_frame_hd_init(&hd, 16000, NGHTTP2_CONTINUATION,
1132 NGHTTP2_FLAG_END_HEADERS, 1);
1134 nghttp2_frame_pack_frame_hd(data, &hd);
1135 datalen = NGHTTP2_FRAME_HDLEN + hd.length;
1137 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1138 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1140 nghttp2_session_server_new(&session, &callbacks, &ud);
1142 open_stream(session, 1);
1144 ud.frame_recv_cb_called = 0;
1146 /* unexpected CONTINUATION must be treated as connection error */
1147 rv = nghttp2_session_mem_recv(session, data, datalen);
1149 CU_ASSERT(rv == (ssize_t)datalen);
1150 CU_ASSERT(0 == ud.frame_recv_cb_called);
1152 item = nghttp2_session_get_next_ob_item(session);
1154 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1156 nghttp2_session_del(session);
1159 void test_nghttp2_session_recv_settings_header_table_size(void) {
1160 nghttp2_session *session;
1161 nghttp2_session_callbacks callbacks;
1162 nghttp2_frame frame;
1167 nghttp2_settings_entry iv[3];
1168 nghttp2_nv nv = MAKE_NV(":authority", "example.org");
1171 mem = nghttp2_mem_default();
1172 frame_pack_bufs_init(&bufs);
1174 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1175 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1176 callbacks.send_callback = null_send_callback;
1178 nghttp2_session_client_new(&session, &callbacks, &ud);
1180 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
1183 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
1184 iv[1].value = 16384;
1186 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
1189 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
1192 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1194 nghttp2_frame_settings_free(&frame.settings, mem);
1196 buf = &bufs.head->buf;
1197 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1199 ud.frame_recv_cb_called = 0;
1201 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1203 CU_ASSERT(rv == nghttp2_buf_len(buf));
1204 CU_ASSERT(1 == ud.frame_recv_cb_called);
1206 CU_ASSERT(3000 == session->remote_settings.header_table_size);
1207 CU_ASSERT(16384 == session->remote_settings.initial_window_size);
1209 nghttp2_bufs_reset(&bufs);
1211 /* 2 SETTINGS_HEADER_TABLE_SIZE */
1212 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
1215 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
1216 iv[1].value = 16383;
1218 iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
1221 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
1224 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
1227 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1229 nghttp2_frame_settings_free(&frame.settings, mem);
1231 buf = &bufs.head->buf;
1232 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1234 ud.frame_recv_cb_called = 0;
1236 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1238 CU_ASSERT(rv == nghttp2_buf_len(buf));
1239 CU_ASSERT(1 == ud.frame_recv_cb_called);
1241 CU_ASSERT(3001 == session->remote_settings.header_table_size);
1242 CU_ASSERT(16383 == session->remote_settings.initial_window_size);
1244 nghttp2_bufs_reset(&bufs);
1246 /* 2 SETTINGS_HEADER_TABLE_SIZE; first entry clears dynamic header
1249 nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL);
1250 nghttp2_session_send(session);
1252 CU_ASSERT(0 < session->hd_deflater.ctx.hd_table.len);
1254 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
1257 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
1258 iv[1].value = 16382;
1260 iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
1263 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
1266 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
1269 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1271 nghttp2_frame_settings_free(&frame.settings, mem);
1273 buf = &bufs.head->buf;
1274 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1276 ud.frame_recv_cb_called = 0;
1278 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1280 CU_ASSERT(rv == nghttp2_buf_len(buf));
1281 CU_ASSERT(1 == ud.frame_recv_cb_called);
1283 CU_ASSERT(4096 == session->remote_settings.header_table_size);
1284 CU_ASSERT(16382 == session->remote_settings.initial_window_size);
1285 CU_ASSERT(0 == session->hd_deflater.ctx.hd_table.len);
1287 nghttp2_bufs_reset(&bufs);
1289 /* 2 SETTINGS_HEADER_TABLE_SIZE; second entry clears dynamic header
1292 nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL);
1293 nghttp2_session_send(session);
1295 CU_ASSERT(0 < session->hd_deflater.ctx.hd_table.len);
1297 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
1300 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
1301 iv[1].value = 16381;
1303 iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
1306 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
1309 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
1312 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1314 nghttp2_frame_settings_free(&frame.settings, mem);
1316 buf = &bufs.head->buf;
1317 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1319 ud.frame_recv_cb_called = 0;
1321 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1323 CU_ASSERT(rv == nghttp2_buf_len(buf));
1324 CU_ASSERT(1 == ud.frame_recv_cb_called);
1326 CU_ASSERT(0 == session->remote_settings.header_table_size);
1327 CU_ASSERT(16381 == session->remote_settings.initial_window_size);
1328 CU_ASSERT(0 == session->hd_deflater.ctx.hd_table.len);
1330 nghttp2_bufs_reset(&bufs);
1332 nghttp2_bufs_free(&bufs);
1333 nghttp2_session_del(session);
1336 void test_nghttp2_session_recv_too_large_frame_length(void) {
1337 nghttp2_session *session;
1338 nghttp2_session_callbacks callbacks;
1339 uint8_t buf[NGHTTP2_FRAME_HDLEN];
1340 nghttp2_outbound_item *item;
1341 nghttp2_frame_hd hd;
1343 /* Initial max frame size is NGHTTP2_MAX_FRAME_SIZE_MIN */
1344 nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN + 1, NGHTTP2_HEADERS,
1345 NGHTTP2_FLAG_NONE, 1);
1347 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1349 nghttp2_session_server_new(&session, &callbacks, NULL);
1351 nghttp2_frame_pack_frame_hd(buf, &hd);
1353 CU_ASSERT(sizeof(buf) == nghttp2_session_mem_recv(session, buf, sizeof(buf)));
1355 item = nghttp2_session_get_next_ob_item(session);
1357 CU_ASSERT(item != NULL);
1358 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1360 nghttp2_session_del(session);
1363 void test_nghttp2_session_continue(void) {
1364 nghttp2_session *session;
1365 nghttp2_session_callbacks callbacks;
1366 my_user_data user_data;
1367 const nghttp2_nv nv1[] = {MAKE_NV(":method", "GET"), MAKE_NV(":path", "/")};
1368 const nghttp2_nv nv2[] = {MAKE_NV("user-agent", "nghttp2/1.0.0"),
1369 MAKE_NV("alpha", "bravo")};
1372 size_t framelen1, framelen2;
1374 uint8_t buffer[4096];
1375 nghttp2_buf databuf;
1376 nghttp2_frame frame;
1379 const nghttp2_frame *recv_frame;
1380 nghttp2_frame_hd data_hd;
1381 nghttp2_hd_deflater deflater;
1384 mem = nghttp2_mem_default();
1385 frame_pack_bufs_init(&bufs);
1386 nghttp2_buf_wrap_init(&databuf, buffer, sizeof(buffer));
1388 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1389 callbacks.send_callback = null_send_callback;
1390 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1391 callbacks.on_data_chunk_recv_callback = pause_on_data_chunk_recv_callback;
1392 callbacks.on_header_callback = pause_on_header_callback;
1393 callbacks.on_begin_headers_callback = on_begin_headers_callback;
1395 nghttp2_session_server_new(&session, &callbacks, &user_data);
1397 nghttp2_hd_deflate_init(&deflater, mem);
1399 /* Make 2 HEADERS frames */
1400 nvlen = ARRLEN(nv1);
1401 nghttp2_nv_array_copy(&nva, nv1, nvlen, mem);
1402 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
1403 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1404 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1407 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1409 nghttp2_frame_headers_free(&frame.headers, mem);
1411 buf = &bufs.head->buf;
1412 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1414 framelen1 = nghttp2_buf_len(buf);
1415 databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf));
1417 nvlen = ARRLEN(nv2);
1418 nghttp2_nv_array_copy(&nva, nv2, nvlen, mem);
1419 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
1420 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1421 nghttp2_bufs_reset(&bufs);
1422 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1425 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1427 nghttp2_frame_headers_free(&frame.headers, mem);
1429 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1431 framelen2 = nghttp2_buf_len(buf);
1432 databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf));
1434 /* Receive 1st HEADERS and pause */
1435 user_data.begin_headers_cb_called = 0;
1436 user_data.header_cb_called = 0;
1438 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
1443 recv_frame = user_data.frame;
1444 CU_ASSERT(NGHTTP2_HEADERS == recv_frame->hd.type);
1445 CU_ASSERT(framelen1 - NGHTTP2_FRAME_HDLEN == recv_frame->hd.length);
1447 CU_ASSERT(1 == user_data.begin_headers_cb_called);
1448 CU_ASSERT(1 == user_data.header_cb_called);
1450 CU_ASSERT(nghttp2_nv_equal(&nv1[0], &user_data.nv));
1452 /* get 2nd header field */
1453 user_data.begin_headers_cb_called = 0;
1454 user_data.header_cb_called = 0;
1456 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
1461 CU_ASSERT(0 == user_data.begin_headers_cb_called);
1462 CU_ASSERT(1 == user_data.header_cb_called);
1464 CU_ASSERT(nghttp2_nv_equal(&nv1[1], &user_data.nv));
1466 /* will call end_headers_callback and receive 2nd HEADERS and pause */
1467 user_data.begin_headers_cb_called = 0;
1468 user_data.header_cb_called = 0;
1470 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
1475 recv_frame = user_data.frame;
1476 CU_ASSERT(NGHTTP2_HEADERS == recv_frame->hd.type);
1477 CU_ASSERT(framelen2 - NGHTTP2_FRAME_HDLEN == recv_frame->hd.length);
1479 CU_ASSERT(1 == user_data.begin_headers_cb_called);
1480 CU_ASSERT(1 == user_data.header_cb_called);
1482 CU_ASSERT(nghttp2_nv_equal(&nv2[0], &user_data.nv));
1484 /* get 2nd header field */
1485 user_data.begin_headers_cb_called = 0;
1486 user_data.header_cb_called = 0;
1488 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
1493 CU_ASSERT(0 == user_data.begin_headers_cb_called);
1494 CU_ASSERT(1 == user_data.header_cb_called);
1496 CU_ASSERT(nghttp2_nv_equal(&nv2[1], &user_data.nv));
1498 /* No input data, frame_recv_callback is called */
1499 user_data.begin_headers_cb_called = 0;
1500 user_data.header_cb_called = 0;
1501 user_data.frame_recv_cb_called = 0;
1503 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
1508 CU_ASSERT(0 == user_data.begin_headers_cb_called);
1509 CU_ASSERT(0 == user_data.header_cb_called);
1510 CU_ASSERT(1 == user_data.frame_recv_cb_called);
1513 nghttp2_frame_hd_init(&data_hd, 16, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 1);
1515 nghttp2_buf_reset(&databuf);
1516 nghttp2_frame_pack_frame_hd(databuf.pos, &data_hd);
1518 /* Intentionally specify larger buffer size to see pause is kicked
1520 databuf.last = databuf.end;
1522 user_data.frame_recv_cb_called = 0;
1524 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
1526 CU_ASSERT(16 + NGHTTP2_FRAME_HDLEN == rv);
1527 CU_ASSERT(0 == user_data.frame_recv_cb_called);
1529 /* Next nghttp2_session_mem_recv invokes on_frame_recv_callback and
1530 pause again in on_data_chunk_recv_callback since we pass same
1532 user_data.frame_recv_cb_called = 0;
1534 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
1535 CU_ASSERT(16 + NGHTTP2_FRAME_HDLEN == rv);
1536 CU_ASSERT(1 == user_data.frame_recv_cb_called);
1538 /* And finally call on_frame_recv_callback with 0 size input */
1539 user_data.frame_recv_cb_called = 0;
1540 rv = nghttp2_session_mem_recv(session, NULL, 0);
1542 CU_ASSERT(1 == user_data.frame_recv_cb_called);
1544 nghttp2_bufs_free(&bufs);
1545 nghttp2_hd_deflate_free(&deflater);
1546 nghttp2_session_del(session);
1549 void test_nghttp2_session_add_frame(void) {
1550 nghttp2_session *session;
1551 nghttp2_session_callbacks callbacks;
1553 my_user_data user_data;
1554 const nghttp2_nv nv[] = {MAKE_NV("method", "GET"), MAKE_NV("scheme", "https"),
1555 MAKE_NV("url", "/"), MAKE_NV("version", "HTTP/1.1")};
1556 nghttp2_outbound_item *item;
1557 nghttp2_frame *frame;
1562 mem = nghttp2_mem_default();
1563 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1564 callbacks.send_callback = accumulator_send_callback;
1567 user_data.acc = &acc;
1569 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &user_data));
1571 item = malloc(sizeof(nghttp2_outbound_item));
1573 nghttp2_session_outbound_item_init(session, item);
1575 frame = &item->frame;
1578 nghttp2_nv_array_copy(&nva, nv, nvlen, mem);
1580 nghttp2_frame_headers_init(
1581 &frame->headers, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1582 session->next_stream_id, NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
1584 session->next_stream_id += 2;
1586 CU_ASSERT(0 == nghttp2_session_add_item(session, item));
1587 CU_ASSERT(0 == nghttp2_pq_empty(&session->ob_ss_pq));
1588 CU_ASSERT(0 == nghttp2_session_send(session));
1589 CU_ASSERT(NGHTTP2_HEADERS == acc.buf[3]);
1590 CU_ASSERT((NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY) == acc.buf[4]);
1591 /* check stream id */
1592 CU_ASSERT(1 == nghttp2_get_uint32(&acc.buf[5]));
1594 nghttp2_session_del(session);
1597 void test_nghttp2_session_on_request_headers_received(void) {
1598 nghttp2_session *session;
1599 nghttp2_session_callbacks callbacks;
1600 my_user_data user_data;
1601 nghttp2_frame frame;
1602 nghttp2_stream *stream;
1603 int32_t stream_id = 1;
1604 nghttp2_nv malformed_nva[] = {MAKE_NV(":path", "\x01")};
1607 nghttp2_priority_spec pri_spec;
1610 mem = nghttp2_mem_default();
1611 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1612 callbacks.on_begin_headers_callback = on_begin_headers_callback;
1613 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
1615 nghttp2_session_server_new(&session, &callbacks, &user_data);
1617 nghttp2_priority_spec_init(&pri_spec, 0, 255, 0);
1619 nghttp2_frame_headers_init(
1620 &frame.headers, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1621 stream_id, NGHTTP2_HCAT_REQUEST, &pri_spec, NULL, 0);
1623 user_data.begin_headers_cb_called = 0;
1624 user_data.invalid_frame_recv_cb_called = 0;
1626 CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
1627 CU_ASSERT(1 == user_data.begin_headers_cb_called);
1628 stream = nghttp2_session_get_stream(session, stream_id);
1629 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
1630 CU_ASSERT(255 == stream->weight);
1632 nghttp2_frame_headers_free(&frame.headers, mem);
1634 /* More than un-ACKed max concurrent streams leads REFUSED_STREAM */
1635 session->pending_local_max_concurrent_stream = 1;
1636 nghttp2_frame_headers_init(&frame.headers,
1637 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1638 3, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
1639 user_data.invalid_frame_recv_cb_called = 0;
1640 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1641 nghttp2_session_on_request_headers_received(session, &frame));
1642 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
1643 CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
1645 nghttp2_frame_headers_free(&frame.headers, mem);
1646 session->local_settings.max_concurrent_streams =
1647 NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS;
1649 /* Stream ID less than or equal to the previouly received request
1650 HEADERS is just ignored due to race condition */
1651 nghttp2_frame_headers_init(&frame.headers,
1652 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1653 3, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
1654 user_data.invalid_frame_recv_cb_called = 0;
1655 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1656 nghttp2_session_on_request_headers_received(session, &frame));
1657 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
1658 CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
1660 nghttp2_frame_headers_free(&frame.headers, mem);
1662 /* Stream ID is our side and it is idle stream ID, then treat it as
1664 nghttp2_frame_headers_init(&frame.headers,
1665 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1666 2, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
1667 user_data.invalid_frame_recv_cb_called = 0;
1668 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1669 nghttp2_session_on_request_headers_received(session, &frame));
1670 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
1671 CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
1673 nghttp2_frame_headers_free(&frame.headers, mem);
1675 nghttp2_session_del(session);
1677 /* Check malformed headers. The library accept it. */
1678 nghttp2_session_server_new(&session, &callbacks, &user_data);
1680 nvlen = ARRLEN(malformed_nva);
1681 nghttp2_nv_array_copy(&nva, malformed_nva, nvlen, mem);
1682 nghttp2_frame_headers_init(&frame.headers,
1683 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1684 1, NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1685 user_data.begin_headers_cb_called = 0;
1686 user_data.invalid_frame_recv_cb_called = 0;
1687 CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
1688 CU_ASSERT(1 == user_data.begin_headers_cb_called);
1689 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
1691 nghttp2_frame_headers_free(&frame.headers, mem);
1693 nghttp2_session_del(session);
1695 /* Check client side */
1696 nghttp2_session_client_new(&session, &callbacks, &user_data);
1698 /* Receiving peer's idle stream ID is subject to connection error */
1699 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
1700 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
1702 user_data.invalid_frame_recv_cb_called = 0;
1703 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1704 nghttp2_session_on_request_headers_received(session, &frame));
1705 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
1706 CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
1708 nghttp2_frame_headers_free(&frame.headers, mem);
1710 nghttp2_session_del(session);
1712 nghttp2_session_client_new(&session, &callbacks, &user_data);
1714 /* Receiving our's idle stream ID is subject to connection error */
1715 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
1716 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
1718 user_data.invalid_frame_recv_cb_called = 0;
1719 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1720 nghttp2_session_on_request_headers_received(session, &frame));
1721 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
1722 CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
1724 nghttp2_frame_headers_free(&frame.headers, mem);
1726 nghttp2_session_del(session);
1728 nghttp2_session_client_new(&session, &callbacks, &user_data);
1730 session->next_stream_id = 5;
1732 /* Stream ID which is not idle and not in stream map is just
1734 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
1735 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
1737 user_data.invalid_frame_recv_cb_called = 0;
1738 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1739 nghttp2_session_on_request_headers_received(session, &frame));
1740 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
1741 CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
1743 nghttp2_frame_headers_free(&frame.headers, mem);
1745 nghttp2_session_del(session);
1747 nghttp2_session_server_new(&session, &callbacks, &user_data);
1749 /* Stream ID which is equal to local_last_stream_id is ok. */
1750 session->local_last_stream_id = 3;
1752 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
1753 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
1755 CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
1757 nghttp2_frame_headers_free(&frame.headers, mem);
1759 /* If GOAWAY has been sent, new stream is ignored */
1760 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 5,
1761 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
1763 session->goaway_flags |= NGHTTP2_GOAWAY_SENT;
1764 user_data.invalid_frame_recv_cb_called = 0;
1765 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1766 nghttp2_session_on_request_headers_received(session, &frame));
1767 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
1768 CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
1770 nghttp2_frame_headers_free(&frame.headers, mem);
1772 nghttp2_session_del(session);
1775 void test_nghttp2_session_on_response_headers_received(void) {
1776 nghttp2_session *session;
1777 nghttp2_session_callbacks callbacks;
1778 my_user_data user_data;
1779 nghttp2_frame frame;
1780 nghttp2_stream *stream;
1783 mem = nghttp2_mem_default();
1784 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1785 callbacks.on_begin_headers_callback = on_begin_headers_callback;
1786 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
1788 nghttp2_session_client_new(&session, &callbacks, &user_data);
1789 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
1791 NGHTTP2_STREAM_OPENING, NULL);
1792 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
1793 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
1795 user_data.begin_headers_cb_called = 0;
1796 user_data.invalid_frame_recv_cb_called = 0;
1798 CU_ASSERT(0 == nghttp2_session_on_response_headers_received(session, &frame,
1800 CU_ASSERT(1 == user_data.begin_headers_cb_called);
1801 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
1803 nghttp2_frame_headers_free(&frame.headers, mem);
1804 nghttp2_session_del(session);
1807 void test_nghttp2_session_on_headers_received(void) {
1808 nghttp2_session *session;
1809 nghttp2_session_callbacks callbacks;
1810 my_user_data user_data;
1811 nghttp2_frame frame;
1812 nghttp2_stream *stream;
1815 mem = nghttp2_mem_default();
1816 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1817 callbacks.on_begin_headers_callback = on_begin_headers_callback;
1818 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
1820 nghttp2_session_client_new(&session, &callbacks, &user_data);
1821 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
1822 &pri_spec_default, NGHTTP2_STREAM_OPENED,
1824 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
1825 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
1826 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
1828 user_data.begin_headers_cb_called = 0;
1829 user_data.invalid_frame_recv_cb_called = 0;
1831 CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
1832 CU_ASSERT(1 == user_data.begin_headers_cb_called);
1833 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
1836 frame.hd.flags |= NGHTTP2_FLAG_END_STREAM;
1838 CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
1839 CU_ASSERT(2 == user_data.begin_headers_cb_called);
1841 /* Check to see when NGHTTP2_STREAM_CLOSING, incoming HEADERS is
1843 stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
1845 NGHTTP2_STREAM_CLOSING, NULL);
1846 frame.hd.stream_id = 3;
1847 frame.hd.flags = NGHTTP2_FLAG_END_HEADERS;
1848 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1849 nghttp2_session_on_headers_received(session, &frame, stream));
1850 /* See no counters are updated */
1851 CU_ASSERT(2 == user_data.begin_headers_cb_called);
1852 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
1854 /* Server initiated stream */
1855 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
1857 NGHTTP2_STREAM_OPENING, NULL);
1859 /* half closed (remote) */
1860 frame.hd.flags = NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM;
1861 frame.hd.stream_id = 2;
1863 CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
1864 CU_ASSERT(3 == user_data.begin_headers_cb_called);
1865 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
1867 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
1869 /* Further reception of HEADERS is subject to stream error */
1870 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1871 nghttp2_session_on_headers_received(session, &frame, stream));
1872 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
1874 nghttp2_frame_headers_free(&frame.headers, mem);
1876 nghttp2_session_del(session);
1879 void test_nghttp2_session_on_push_response_headers_received(void) {
1880 nghttp2_session *session;
1881 nghttp2_session_callbacks callbacks;
1882 my_user_data user_data;
1883 nghttp2_frame frame;
1884 nghttp2_stream *stream;
1885 nghttp2_outbound_item *item;
1888 mem = nghttp2_mem_default();
1889 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1890 callbacks.send_callback = null_send_callback;
1891 callbacks.on_begin_headers_callback = on_begin_headers_callback;
1892 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
1894 nghttp2_session_client_new(&session, &callbacks, &user_data);
1895 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
1897 NGHTTP2_STREAM_RESERVED, NULL);
1898 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
1899 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
1900 /* nghttp2_session_on_push_response_headers_received assumes
1901 stream's state is NGHTTP2_STREAM_RESERVED and session->server is
1904 user_data.begin_headers_cb_called = 0;
1905 user_data.invalid_frame_recv_cb_called = 0;
1907 CU_ASSERT(0 == nghttp2_session_on_push_response_headers_received(
1908 session, &frame, stream));
1909 CU_ASSERT(1 == user_data.begin_headers_cb_called);
1910 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
1911 CU_ASSERT(1 == session->num_incoming_streams);
1913 /* If un-ACKed max concurrent streams limit is exceeded,
1915 session->pending_local_max_concurrent_stream = 1;
1916 stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
1918 NGHTTP2_STREAM_RESERVED, NULL);
1919 frame.hd.stream_id = 4;
1920 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1921 nghttp2_session_on_push_response_headers_received(session, &frame,
1923 item = nghttp2_session_get_next_ob_item(session);
1924 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
1925 CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
1926 CU_ASSERT(1 == session->num_incoming_streams);
1928 CU_ASSERT(0 == nghttp2_session_send(session));
1929 CU_ASSERT(1 == session->num_incoming_streams);
1931 /* If ACKed max concurrent streams limit is exceeded, GOAWAY is
1933 session->local_settings.max_concurrent_streams = 1;
1935 stream = nghttp2_session_open_stream(session, 6, NGHTTP2_STREAM_FLAG_NONE,
1937 NGHTTP2_STREAM_RESERVED, NULL);
1938 frame.hd.stream_id = 6;
1940 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1941 nghttp2_session_on_push_response_headers_received(session, &frame,
1943 item = nghttp2_session_get_next_ob_item(session);
1944 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1945 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
1946 CU_ASSERT(1 == session->num_incoming_streams);
1948 nghttp2_frame_headers_free(&frame.headers, mem);
1949 nghttp2_session_del(session);
1952 void test_nghttp2_session_on_priority_received(void) {
1953 nghttp2_session *session;
1954 nghttp2_session_callbacks callbacks;
1955 my_user_data user_data;
1956 nghttp2_frame frame;
1957 nghttp2_stream *stream, *dep_stream;
1958 nghttp2_priority_spec pri_spec;
1959 nghttp2_outbound_item *item;
1961 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1962 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1963 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
1965 nghttp2_session_server_new(&session, &callbacks, &user_data);
1966 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
1968 NGHTTP2_STREAM_OPENING, NULL);
1970 nghttp2_priority_spec_init(&pri_spec, 0, 2, 0);
1972 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
1974 /* depend on stream 0 */
1975 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
1977 CU_ASSERT(2 == stream->weight);
1979 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
1981 NGHTTP2_STREAM_OPENING, NULL);
1983 dep_stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
1985 NGHTTP2_STREAM_OPENING, NULL);
1987 frame.hd.stream_id = 2;
1989 /* using dependency stream */
1990 nghttp2_priority_spec_init(&frame.priority.pri_spec, 3, 1, 0);
1992 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
1993 CU_ASSERT(dep_stream == stream->dep_prev);
1995 /* PRIORITY against idle stream */
1997 frame.hd.stream_id = 100;
1999 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
2001 stream = nghttp2_session_get_stream_raw(session, frame.hd.stream_id);
2003 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
2004 CU_ASSERT(dep_stream == stream->dep_prev);
2006 nghttp2_frame_priority_free(&frame.priority);
2007 nghttp2_session_del(session);
2009 /* Check dep_stream_id == stream_id case */
2010 nghttp2_session_server_new(&session, &callbacks, &user_data);
2011 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2012 &pri_spec_default, NGHTTP2_STREAM_OPENED, NULL);
2014 nghttp2_priority_spec_init(&pri_spec, 1, 0, 0);
2016 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
2018 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
2020 item = nghttp2_session_get_next_ob_item(session);
2022 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2024 nghttp2_frame_priority_free(&frame.priority);
2025 nghttp2_session_del(session);
2028 void test_nghttp2_session_on_rst_stream_received(void) {
2029 nghttp2_session *session;
2030 nghttp2_session_callbacks callbacks;
2031 my_user_data user_data;
2032 nghttp2_frame frame;
2033 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2034 nghttp2_session_server_new(&session, &callbacks, &user_data);
2035 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2036 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
2038 nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_PROTOCOL_ERROR);
2040 CU_ASSERT(0 == nghttp2_session_on_rst_stream_received(session, &frame));
2041 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
2043 nghttp2_frame_rst_stream_free(&frame.rst_stream);
2044 nghttp2_session_del(session);
2047 void test_nghttp2_session_on_settings_received(void) {
2048 nghttp2_session *session;
2049 nghttp2_session_callbacks callbacks;
2050 my_user_data user_data;
2051 nghttp2_stream *stream1, *stream2;
2052 nghttp2_frame frame;
2053 const size_t niv = 5;
2054 nghttp2_settings_entry iv[255];
2055 nghttp2_outbound_item *item;
2056 nghttp2_nv nv = MAKE_NV(":authority", "example.org");
2059 mem = nghttp2_mem_default();
2061 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
2064 iv[1].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
2065 iv[1].value = 1000000009;
2067 iv[2].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2068 iv[2].value = 64 * 1024;
2070 iv[3].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2073 iv[4].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
2076 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2077 callbacks.send_callback = null_send_callback;
2079 nghttp2_session_client_new(&session, &callbacks, &user_data);
2080 session->remote_settings.initial_window_size = 16 * 1024;
2082 stream1 = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2084 NGHTTP2_STREAM_OPENING, NULL);
2085 stream2 = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
2087 NGHTTP2_STREAM_OPENING, NULL);
2088 /* Set window size for each streams and will see how settings
2089 updates these values */
2090 stream1->remote_window_size = 16 * 1024;
2091 stream2->remote_window_size = -48 * 1024;
2093 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE,
2094 dup_iv(iv, niv), niv);
2096 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
2097 CU_ASSERT(1000000009 == session->remote_settings.max_concurrent_streams);
2098 CU_ASSERT(64 * 1024 == session->remote_settings.initial_window_size);
2099 CU_ASSERT(1024 == session->remote_settings.header_table_size);
2100 CU_ASSERT(0 == session->remote_settings.enable_push);
2102 CU_ASSERT(64 * 1024 == stream1->remote_window_size);
2103 CU_ASSERT(0 == stream2->remote_window_size);
2105 frame.settings.iv[2].value = 16 * 1024;
2107 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
2109 CU_ASSERT(16 * 1024 == stream1->remote_window_size);
2110 CU_ASSERT(-48 * 1024 == stream2->remote_window_size);
2112 CU_ASSERT(16 * 1024 == nghttp2_session_get_stream_remote_window_size(
2113 session, stream1->stream_id));
2114 CU_ASSERT(0 == nghttp2_session_get_stream_remote_window_size(
2115 session, stream2->stream_id));
2117 nghttp2_frame_settings_free(&frame.settings, mem);
2119 nghttp2_session_del(session);
2121 /* Check ACK with niv > 0 */
2122 nghttp2_session_server_new(&session, &callbacks, NULL);
2123 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, dup_iv(iv, 1),
2125 /* Specify inflight_iv deliberately */
2126 session->inflight_iv = frame.settings.iv;
2127 session->inflight_niv = frame.settings.niv;
2129 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
2130 item = nghttp2_session_get_next_ob_item(session);
2131 CU_ASSERT(item != NULL);
2132 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2134 session->inflight_iv = NULL;
2135 session->inflight_niv = -1;
2137 nghttp2_frame_settings_free(&frame.settings, mem);
2138 nghttp2_session_del(session);
2140 /* Check ACK against no inflight SETTINGS */
2141 nghttp2_session_server_new(&session, &callbacks, NULL);
2142 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
2144 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
2145 item = nghttp2_session_get_next_ob_item(session);
2146 CU_ASSERT(item != NULL);
2147 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2149 nghttp2_frame_settings_free(&frame.settings, mem);
2150 nghttp2_session_del(session);
2152 /* Check that 2 SETTINGS_HEADER_TABLE_SIZE 0 and 4096 are included
2153 and header table size is once cleared to 0. */
2154 nghttp2_session_client_new(&session, &callbacks, NULL);
2156 nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL);
2158 nghttp2_session_send(session);
2160 CU_ASSERT(session->hd_deflater.ctx.hd_table.len > 0);
2162 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2165 iv[1].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2168 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
2171 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
2173 CU_ASSERT(0 == session->hd_deflater.ctx.hd_table.len);
2174 CU_ASSERT(2048 == session->hd_deflater.ctx.hd_table_bufsize_max);
2175 CU_ASSERT(2048 == session->remote_settings.header_table_size);
2177 nghttp2_frame_settings_free(&frame.settings, mem);
2178 nghttp2_session_del(session);
2180 /* Check too large SETTINGS_MAX_FRAME_SIZE */
2181 nghttp2_session_server_new(&session, &callbacks, NULL);
2183 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_FRAME_SIZE;
2184 iv[0].value = NGHTTP2_MAX_FRAME_SIZE_MAX + 1;
2186 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
2189 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
2191 item = nghttp2_session_get_next_ob_item(session);
2193 CU_ASSERT(item != NULL);
2194 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2196 nghttp2_frame_settings_free(&frame.settings, mem);
2197 nghttp2_session_del(session);
2200 void test_nghttp2_session_on_push_promise_received(void) {
2201 nghttp2_session *session;
2202 nghttp2_session_callbacks callbacks;
2203 my_user_data user_data;
2204 nghttp2_frame frame;
2205 nghttp2_stream *stream, *promised_stream;
2206 nghttp2_outbound_item *item;
2207 nghttp2_nv malformed_nva[] = {MAKE_NV(":path", "\x01")};
2212 mem = nghttp2_mem_default();
2213 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2214 callbacks.send_callback = null_send_callback;
2215 callbacks.on_begin_headers_callback = on_begin_headers_callback;
2216 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
2218 nghttp2_session_client_new(&session, &callbacks, &user_data);
2220 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2222 NGHTTP2_STREAM_OPENING, NULL);
2223 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
2226 user_data.begin_headers_cb_called = 0;
2227 user_data.invalid_frame_recv_cb_called = 0;
2229 CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
2231 CU_ASSERT(1 == user_data.begin_headers_cb_called);
2232 promised_stream = nghttp2_session_get_stream(session, 2);
2233 CU_ASSERT(NGHTTP2_STREAM_RESERVED == promised_stream->state);
2234 CU_ASSERT(2 == session->last_recv_stream_id);
2236 /* Attempt to PUSH_PROMISE against half close (remote) */
2237 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
2238 frame.push_promise.promised_stream_id = 4;
2240 user_data.begin_headers_cb_called = 0;
2241 user_data.invalid_frame_recv_cb_called = 0;
2242 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2243 nghttp2_session_on_push_promise_received(session, &frame));
2245 CU_ASSERT(0 == user_data.begin_headers_cb_called);
2246 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
2247 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 4));
2248 item = nghttp2_session_get_next_ob_item(session);
2249 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
2250 CU_ASSERT(4 == item->frame.hd.stream_id);
2251 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.rst_stream.error_code);
2252 CU_ASSERT(0 == nghttp2_session_send(session));
2253 CU_ASSERT(4 == session->last_recv_stream_id);
2255 /* Attempt to PUSH_PROMISE against stream in closing state */
2256 stream->shut_flags = NGHTTP2_SHUT_NONE;
2257 stream->state = NGHTTP2_STREAM_CLOSING;
2258 frame.push_promise.promised_stream_id = 6;
2260 user_data.begin_headers_cb_called = 0;
2261 user_data.invalid_frame_recv_cb_called = 0;
2262 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2263 nghttp2_session_on_push_promise_received(session, &frame));
2265 CU_ASSERT(0 == user_data.begin_headers_cb_called);
2266 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 6));
2267 item = nghttp2_session_get_next_ob_item(session);
2268 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
2269 CU_ASSERT(6 == item->frame.hd.stream_id);
2270 CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
2271 CU_ASSERT(0 == nghttp2_session_send(session));
2273 /* Attempt to PUSH_PROMISE against non-existent stream */
2274 frame.hd.stream_id = 3;
2275 frame.push_promise.promised_stream_id = 8;
2277 user_data.begin_headers_cb_called = 0;
2278 user_data.invalid_frame_recv_cb_called = 0;
2279 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2280 nghttp2_session_on_push_promise_received(session, &frame));
2282 CU_ASSERT(0 == user_data.begin_headers_cb_called);
2283 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 8));
2284 item = nghttp2_session_get_next_ob_item(session);
2285 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2286 CU_ASSERT(0 == item->frame.hd.stream_id);
2287 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
2288 CU_ASSERT(0 == nghttp2_session_send(session));
2290 nghttp2_session_del(session);
2292 nghttp2_session_client_new(&session, &callbacks, &user_data);
2294 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2296 NGHTTP2_STREAM_OPENING, NULL);
2299 stream->state = NGHTTP2_STREAM_OPENING;
2301 user_data.begin_headers_cb_called = 0;
2302 user_data.invalid_frame_recv_cb_called = 0;
2303 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2304 nghttp2_session_on_push_promise_received(session, &frame));
2306 CU_ASSERT(0 == user_data.begin_headers_cb_called);
2307 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 8));
2308 item = nghttp2_session_get_next_ob_item(session);
2309 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2310 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
2311 CU_ASSERT(0 == nghttp2_session_send(session));
2313 /* After GOAWAY, PUSH_PROMISE will be discarded */
2314 frame.push_promise.promised_stream_id = 10;
2316 user_data.begin_headers_cb_called = 0;
2317 user_data.invalid_frame_recv_cb_called = 0;
2318 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2319 nghttp2_session_on_push_promise_received(session, &frame));
2321 CU_ASSERT(0 == user_data.begin_headers_cb_called);
2322 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 10));
2323 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
2325 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
2326 nghttp2_session_del(session);
2328 nghttp2_session_client_new(&session, &callbacks, &user_data);
2330 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
2332 NGHTTP2_STREAM_RESERVED, NULL);
2333 /* Attempt to PUSH_PROMISE against reserved (remote) stream */
2334 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
2337 user_data.begin_headers_cb_called = 0;
2338 user_data.invalid_frame_recv_cb_called = 0;
2339 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2340 nghttp2_session_on_push_promise_received(session, &frame));
2342 CU_ASSERT(0 == user_data.begin_headers_cb_called);
2343 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
2345 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
2346 nghttp2_session_del(session);
2349 nghttp2_session_client_new(&session, &callbacks, &user_data);
2351 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2353 NGHTTP2_STREAM_OPENING, NULL);
2355 session->local_settings.enable_push = 0;
2357 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
2360 user_data.begin_headers_cb_called = 0;
2361 user_data.invalid_frame_recv_cb_called = 0;
2362 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2363 nghttp2_session_on_push_promise_received(session, &frame));
2365 CU_ASSERT(0 == user_data.begin_headers_cb_called);
2366 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
2368 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
2369 nghttp2_session_del(session);
2371 /* Check malformed headers. We accept malformed headers */
2372 nghttp2_session_client_new(&session, &callbacks, &user_data);
2374 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2376 NGHTTP2_STREAM_OPENING, NULL);
2377 nvlen = ARRLEN(malformed_nva);
2378 nghttp2_nv_array_copy(&nva, malformed_nva, nvlen, mem);
2379 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
2381 user_data.begin_headers_cb_called = 0;
2382 user_data.invalid_frame_recv_cb_called = 0;
2383 CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
2385 CU_ASSERT(1 == user_data.begin_headers_cb_called);
2386 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
2388 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
2389 nghttp2_session_del(session);
2392 void test_nghttp2_session_on_ping_received(void) {
2393 nghttp2_session *session;
2394 nghttp2_session_callbacks callbacks;
2395 my_user_data user_data;
2396 nghttp2_frame frame;
2397 nghttp2_outbound_item *top;
2398 const uint8_t opaque_data[] = "01234567";
2400 user_data.frame_recv_cb_called = 0;
2401 user_data.invalid_frame_recv_cb_called = 0;
2403 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2404 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2405 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
2407 nghttp2_session_client_new(&session, &callbacks, &user_data);
2408 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_ACK, opaque_data);
2410 CU_ASSERT(0 == nghttp2_session_on_ping_received(session, &frame));
2411 CU_ASSERT(1 == user_data.frame_recv_cb_called);
2413 /* Since this ping frame has PONG flag set, no further action is
2415 CU_ASSERT(NULL == nghttp2_session_get_ob_pq_top(session));
2417 /* Clear the flag, and receive it again */
2418 frame.hd.flags = NGHTTP2_FLAG_NONE;
2420 CU_ASSERT(0 == nghttp2_session_on_ping_received(session, &frame));
2421 CU_ASSERT(2 == user_data.frame_recv_cb_called);
2422 top = nghttp2_session_get_ob_pq_top(session);
2423 CU_ASSERT(NGHTTP2_PING == top->frame.hd.type);
2424 CU_ASSERT(NGHTTP2_FLAG_ACK == top->frame.hd.flags);
2425 CU_ASSERT(memcmp(opaque_data, top->frame.ping.opaque_data, 8) == 0);
2427 nghttp2_frame_ping_free(&frame.ping);
2428 nghttp2_session_del(session);
2431 void test_nghttp2_session_on_goaway_received(void) {
2432 nghttp2_session *session;
2433 nghttp2_session_callbacks callbacks;
2434 my_user_data user_data;
2435 nghttp2_frame frame;
2439 mem = nghttp2_mem_default();
2440 user_data.frame_recv_cb_called = 0;
2441 user_data.invalid_frame_recv_cb_called = 0;
2443 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2444 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2445 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
2446 callbacks.on_stream_close_callback = on_stream_close_callback;
2448 nghttp2_session_client_new(&session, &callbacks, &user_data);
2450 for (i = 1; i <= 7; ++i) {
2451 open_stream(session, i);
2454 nghttp2_frame_goaway_init(&frame.goaway, 3, NGHTTP2_PROTOCOL_ERROR, NULL, 0);
2456 user_data.stream_close_cb_called = 0;
2458 CU_ASSERT(0 == nghttp2_session_on_goaway_received(session, &frame));
2460 CU_ASSERT(1 == user_data.frame_recv_cb_called);
2461 CU_ASSERT(3 == session->remote_last_stream_id);
2462 /* on_stream_close should be callsed for 2 times (stream 5 and 7) */
2463 CU_ASSERT(2 == user_data.stream_close_cb_called);
2465 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 1));
2466 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 2));
2467 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 3));
2468 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 4));
2469 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 5));
2470 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 6));
2471 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 7));
2473 nghttp2_frame_goaway_free(&frame.goaway, mem);
2474 nghttp2_session_del(session);
2477 void test_nghttp2_session_on_window_update_received(void) {
2478 nghttp2_session *session;
2479 nghttp2_session_callbacks callbacks;
2480 my_user_data user_data;
2481 nghttp2_frame frame;
2482 nghttp2_stream *stream;
2483 nghttp2_outbound_item *data_item;
2484 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2485 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2486 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
2487 user_data.frame_recv_cb_called = 0;
2488 user_data.invalid_frame_recv_cb_called = 0;
2490 nghttp2_session_client_new(&session, &callbacks, &user_data);
2492 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2493 &pri_spec_default, NGHTTP2_STREAM_OPENED,
2496 data_item = create_data_ob_item();
2498 CU_ASSERT(0 == nghttp2_stream_attach_item(stream, data_item, session));
2500 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
2503 CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
2504 CU_ASSERT(1 == user_data.frame_recv_cb_called);
2505 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 16 * 1024 ==
2506 stream->remote_window_size);
2509 nghttp2_stream_defer_item(
2510 stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, session));
2512 CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
2513 CU_ASSERT(2 == user_data.frame_recv_cb_called);
2514 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 16 * 1024 * 2 ==
2515 stream->remote_window_size);
2516 CU_ASSERT(0 == (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL));
2518 nghttp2_frame_window_update_free(&frame.window_update);
2520 /* Receiving WINDOW_UPDATE on reserved (remote) stream is a
2522 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
2524 NGHTTP2_STREAM_RESERVED, NULL);
2526 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2,
2529 CU_ASSERT(!(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
2530 CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
2531 CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
2533 nghttp2_frame_window_update_free(&frame.window_update);
2535 nghttp2_session_del(session);
2537 /* Receiving WINDOW_UPDATE on reserved (local) stream is allowed */
2538 nghttp2_session_server_new(&session, &callbacks, &user_data);
2540 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
2542 NGHTTP2_STREAM_RESERVED, NULL);
2544 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2,
2547 CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
2548 CU_ASSERT(!(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
2550 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 4096 == stream->remote_window_size);
2552 nghttp2_frame_window_update_free(&frame.window_update);
2554 nghttp2_session_del(session);
2557 void test_nghttp2_session_on_data_received(void) {
2558 nghttp2_session *session;
2559 nghttp2_session_callbacks callbacks;
2560 my_user_data user_data;
2561 nghttp2_outbound_item *top;
2562 nghttp2_stream *stream;
2563 nghttp2_frame frame;
2565 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2567 nghttp2_session_client_new(&session, &callbacks, &user_data);
2568 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
2570 NGHTTP2_STREAM_OPENING, NULL);
2572 nghttp2_frame_hd_init(&frame.hd, 4096, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 2);
2574 CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
2575 CU_ASSERT(0 == stream->shut_flags);
2577 frame.hd.flags = NGHTTP2_FLAG_END_STREAM;
2579 CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
2580 CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
2582 /* If NGHTTP2_STREAM_CLOSING state, DATA frame is discarded. */
2583 stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
2585 NGHTTP2_STREAM_CLOSING, NULL);
2587 frame.hd.flags = NGHTTP2_FLAG_NONE;
2588 frame.hd.stream_id = 4;
2590 CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
2591 CU_ASSERT(NULL == nghttp2_session_get_ob_pq_top(session));
2593 /* Check INVALID_STREAM case: DATA frame with stream ID which does
2596 frame.hd.stream_id = 6;
2598 CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
2599 top = nghttp2_session_get_ob_pq_top(session);
2600 /* DATA against nonexistent stream is just ignored for now */
2601 CU_ASSERT(top == NULL);
2602 /* CU_ASSERT(NGHTTP2_RST_STREAM == top->frame.hd.type); */
2603 /* CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == top->frame.rst_stream.error_code); */
2605 nghttp2_session_del(session);
2608 void test_nghttp2_session_send_headers_start_stream(void) {
2609 nghttp2_session *session;
2610 nghttp2_session_callbacks callbacks;
2611 nghttp2_outbound_item *item;
2612 nghttp2_frame *frame;
2613 nghttp2_stream *stream;
2615 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2616 callbacks.send_callback = null_send_callback;
2618 nghttp2_session_client_new(&session, &callbacks, NULL);
2620 item = malloc(sizeof(nghttp2_outbound_item));
2622 nghttp2_session_outbound_item_init(session, item);
2624 frame = &item->frame;
2626 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS,
2627 session->next_stream_id, NGHTTP2_HCAT_REQUEST,
2629 session->next_stream_id += 2;
2631 nghttp2_session_add_item(session, item);
2632 CU_ASSERT(0 == nghttp2_session_send(session));
2633 stream = nghttp2_session_get_stream(session, 1);
2634 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
2636 nghttp2_session_del(session);
2639 void test_nghttp2_session_send_headers_reply(void) {
2640 nghttp2_session *session;
2641 nghttp2_session_callbacks callbacks;
2642 nghttp2_outbound_item *item;
2643 nghttp2_frame *frame;
2644 nghttp2_stream *stream;
2646 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2647 callbacks.send_callback = null_send_callback;
2649 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
2650 nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
2651 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
2653 item = malloc(sizeof(nghttp2_outbound_item));
2655 nghttp2_session_outbound_item_init(session, item);
2657 frame = &item->frame;
2659 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 2,
2660 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
2661 nghttp2_session_add_item(session, item);
2662 CU_ASSERT(0 == nghttp2_session_send(session));
2663 stream = nghttp2_session_get_stream(session, 2);
2664 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
2666 nghttp2_session_del(session);
2669 void test_nghttp2_session_send_headers_frame_size_error(void) {
2670 nghttp2_session *session;
2671 nghttp2_session_callbacks callbacks;
2672 nghttp2_outbound_item *item;
2673 nghttp2_frame *frame;
2676 size_t vallen = NGHTTP2_HD_MAX_NV;
2678 size_t nnv = ARRLEN(nv);
2683 mem = nghttp2_mem_default();
2685 for (i = 0; i < nnv; ++i) {
2686 nv[i].name = (uint8_t *)"header";
2687 nv[i].namelen = strlen((const char *)nv[i].name);
2688 nv[i].value = malloc(vallen + 1);
2689 memset(nv[i].value, '0' + (int)i, vallen);
2690 nv[i].value[vallen] = '\0';
2691 nv[i].valuelen = vallen;
2692 nv[i].flags = NGHTTP2_NV_FLAG_NONE;
2695 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2696 callbacks.send_callback = null_send_callback;
2697 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
2699 nghttp2_session_client_new(&session, &callbacks, &ud);
2701 nghttp2_nv_array_copy(&nva, nv, nvlen, mem);
2703 item = malloc(sizeof(nghttp2_outbound_item));
2705 nghttp2_session_outbound_item_init(session, item);
2707 frame = &item->frame;
2709 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS,
2710 session->next_stream_id, NGHTTP2_HCAT_REQUEST,
2713 session->next_stream_id += 2;
2715 nghttp2_session_add_item(session, item);
2717 ud.frame_not_send_cb_called = 0;
2719 CU_ASSERT(0 == nghttp2_session_send(session));
2721 CU_ASSERT(1 == ud.frame_not_send_cb_called);
2722 CU_ASSERT(NGHTTP2_HEADERS == ud.not_sent_frame_type);
2723 CU_ASSERT(NGHTTP2_ERR_FRAME_SIZE_ERROR == ud.not_sent_error);
2725 for (i = 0; i < nnv; ++i) {
2728 nghttp2_session_del(session);
2731 void test_nghttp2_session_send_headers_push_reply(void) {
2732 nghttp2_session *session;
2733 nghttp2_session_callbacks callbacks;
2734 nghttp2_outbound_item *item;
2735 nghttp2_frame *frame;
2736 nghttp2_stream *stream;
2738 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2739 callbacks.send_callback = null_send_callback;
2741 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL));
2742 nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
2743 &pri_spec_default, NGHTTP2_STREAM_RESERVED, NULL);
2745 item = malloc(sizeof(nghttp2_outbound_item));
2747 nghttp2_session_outbound_item_init(session, item);
2749 frame = &item->frame;
2751 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 2,
2752 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
2753 nghttp2_session_add_item(session, item);
2754 CU_ASSERT(0 == session->num_outgoing_streams);
2755 CU_ASSERT(0 == nghttp2_session_send(session));
2756 CU_ASSERT(1 == session->num_outgoing_streams);
2757 stream = nghttp2_session_get_stream(session, 2);
2758 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
2760 nghttp2_session_del(session);
2763 void test_nghttp2_session_send_rst_stream(void) {
2764 nghttp2_session *session;
2765 nghttp2_session_callbacks callbacks;
2766 my_user_data user_data;
2767 nghttp2_outbound_item *item;
2768 nghttp2_frame *frame;
2770 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2771 callbacks.send_callback = null_send_callback;
2772 nghttp2_session_client_new(&session, &callbacks, &user_data);
2773 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2774 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
2776 item = malloc(sizeof(nghttp2_outbound_item));
2778 nghttp2_session_outbound_item_init(session, item);
2780 frame = &item->frame;
2782 nghttp2_frame_rst_stream_init(&frame->rst_stream, 1, NGHTTP2_PROTOCOL_ERROR);
2783 nghttp2_session_add_item(session, item);
2784 CU_ASSERT(0 == nghttp2_session_send(session));
2786 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
2788 nghttp2_session_del(session);
2791 void test_nghttp2_session_send_push_promise(void) {
2792 nghttp2_session *session;
2793 nghttp2_session_callbacks callbacks;
2794 nghttp2_outbound_item *item;
2795 nghttp2_frame *frame;
2796 nghttp2_stream *stream;
2797 nghttp2_settings_entry iv;
2801 mem = nghttp2_mem_default();
2802 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2803 callbacks.send_callback = null_send_callback;
2804 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
2806 nghttp2_session_server_new(&session, &callbacks, &ud);
2807 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2808 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
2810 item = malloc(sizeof(nghttp2_outbound_item));
2812 nghttp2_session_outbound_item_init(session, item);
2814 frame = &item->frame;
2816 nghttp2_frame_push_promise_init(&frame->push_promise,
2817 NGHTTP2_FLAG_END_HEADERS, 1,
2818 session->next_stream_id, NULL, 0);
2820 session->next_stream_id += 2;
2822 nghttp2_session_add_item(session, item);
2824 CU_ASSERT(0 == nghttp2_session_send(session));
2825 stream = nghttp2_session_get_stream(session, 2);
2826 CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state);
2828 /* Received ENABLE_PUSH = 0 */
2829 iv.settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
2831 frame = malloc(sizeof(nghttp2_frame));
2832 nghttp2_frame_settings_init(&frame->settings, NGHTTP2_FLAG_NONE,
2834 nghttp2_session_on_settings_received(session, frame, 1);
2835 nghttp2_frame_settings_free(&frame->settings, mem);
2838 item = malloc(sizeof(nghttp2_outbound_item));
2840 nghttp2_session_outbound_item_init(session, item);
2842 frame = &item->frame;
2844 nghttp2_frame_push_promise_init(&frame->push_promise,
2845 NGHTTP2_FLAG_END_HEADERS, 1, -1, NULL, 0);
2846 nghttp2_session_add_item(session, item);
2848 ud.frame_not_send_cb_called = 0;
2849 CU_ASSERT(0 == nghttp2_session_send(session));
2851 CU_ASSERT(1 == ud.frame_not_send_cb_called);
2852 CU_ASSERT(NGHTTP2_PUSH_PROMISE == ud.not_sent_frame_type);
2853 CU_ASSERT(NGHTTP2_ERR_PUSH_DISABLED == ud.not_sent_error);
2855 nghttp2_session_del(session);
2857 /* PUSH_PROMISE from client is error */
2858 nghttp2_session_client_new(&session, &callbacks, &ud);
2859 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2860 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
2861 item = malloc(sizeof(nghttp2_outbound_item));
2863 nghttp2_session_outbound_item_init(session, item);
2865 frame = &item->frame;
2867 nghttp2_frame_push_promise_init(&frame->push_promise,
2868 NGHTTP2_FLAG_END_HEADERS, 1, -1, NULL, 0);
2869 nghttp2_session_add_item(session, item);
2871 CU_ASSERT(0 == nghttp2_session_send(session));
2872 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 3));
2874 nghttp2_session_del(session);
2877 void test_nghttp2_session_is_my_stream_id(void) {
2878 nghttp2_session *session;
2879 nghttp2_session_callbacks callbacks;
2880 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2881 nghttp2_session_server_new(&session, &callbacks, NULL);
2883 CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 0));
2884 CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 1));
2885 CU_ASSERT(1 == nghttp2_session_is_my_stream_id(session, 2));
2887 nghttp2_session_del(session);
2889 nghttp2_session_client_new(&session, &callbacks, NULL);
2891 CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 0));
2892 CU_ASSERT(1 == nghttp2_session_is_my_stream_id(session, 1));
2893 CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 2));
2895 nghttp2_session_del(session);
2898 void test_nghttp2_session_upgrade(void) {
2899 nghttp2_session *session;
2900 nghttp2_session_callbacks callbacks;
2901 uint8_t settings_payload[128];
2902 size_t settings_payloadlen;
2903 nghttp2_settings_entry iv[16];
2904 nghttp2_stream *stream;
2905 nghttp2_outbound_item *item;
2907 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2908 callbacks.send_callback = null_send_callback;
2909 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
2911 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2913 settings_payloadlen = nghttp2_pack_settings_payload(
2914 settings_payload, sizeof(settings_payload), iv, 2);
2916 /* Check client side */
2917 nghttp2_session_client_new(&session, &callbacks, NULL);
2918 CU_ASSERT(0 == nghttp2_session_upgrade(session, settings_payload,
2919 settings_payloadlen, &callbacks));
2920 stream = nghttp2_session_get_stream(session, 1);
2921 CU_ASSERT(stream != NULL);
2922 CU_ASSERT(&callbacks == stream->stream_user_data);
2923 CU_ASSERT(NGHTTP2_SHUT_WR == stream->shut_flags);
2924 item = nghttp2_session_get_next_ob_item(session);
2925 CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type);
2926 CU_ASSERT(2 == item->frame.settings.niv);
2927 CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
2928 item->frame.settings.iv[0].settings_id);
2929 CU_ASSERT(1 == item->frame.settings.iv[0].value);
2930 CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE ==
2931 item->frame.settings.iv[1].settings_id);
2932 CU_ASSERT(4095 == item->frame.settings.iv[1].value);
2934 /* Call nghttp2_session_upgrade() again is error */
2935 CU_ASSERT(NGHTTP2_ERR_PROTO ==
2936 nghttp2_session_upgrade(session, settings_payload,
2937 settings_payloadlen, &callbacks));
2938 nghttp2_session_del(session);
2940 /* Check server side */
2941 nghttp2_session_server_new(&session, &callbacks, NULL);
2942 CU_ASSERT(0 == nghttp2_session_upgrade(session, settings_payload,
2943 settings_payloadlen, &callbacks));
2944 stream = nghttp2_session_get_stream(session, 1);
2945 CU_ASSERT(stream != NULL);
2946 CU_ASSERT(NULL == stream->stream_user_data);
2947 CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
2948 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
2949 CU_ASSERT(1 == session->remote_settings.max_concurrent_streams);
2950 CU_ASSERT(4095 == session->remote_settings.initial_window_size);
2951 /* Call nghttp2_session_upgrade() again is error */
2952 CU_ASSERT(NGHTTP2_ERR_PROTO ==
2953 nghttp2_session_upgrade(session, settings_payload,
2954 settings_payloadlen, &callbacks));
2955 nghttp2_session_del(session);
2957 /* Empty SETTINGS is OK */
2958 settings_payloadlen = nghttp2_pack_settings_payload(
2959 settings_payload, sizeof(settings_payload), NULL, 0);
2961 nghttp2_session_client_new(&session, &callbacks, NULL);
2962 CU_ASSERT(0 == nghttp2_session_upgrade(session, settings_payload,
2963 settings_payloadlen, NULL));
2964 nghttp2_session_del(session);
2967 void test_nghttp2_session_reprioritize_stream(void) {
2968 nghttp2_session *session;
2969 nghttp2_session_callbacks callbacks;
2971 nghttp2_stream *stream;
2972 nghttp2_stream *dep_stream;
2973 nghttp2_priority_spec pri_spec;
2975 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2976 callbacks.send_callback = block_count_send_callback;
2978 nghttp2_session_server_new(&session, &callbacks, &ud);
2980 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2982 NGHTTP2_STREAM_OPENING, NULL);
2984 nghttp2_priority_spec_init(&pri_spec, 0, 10, 0);
2986 nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
2988 CU_ASSERT(10 == stream->weight);
2989 CU_ASSERT(NULL == stream->dep_prev);
2991 /* If depenency to idle stream which is not in depdenency tree yet */
2993 nghttp2_priority_spec_init(&pri_spec, 3, 99, 0);
2995 nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
2997 CU_ASSERT(99 == stream->weight);
2998 CU_ASSERT(3 == stream->dep_prev->stream_id);
3000 dep_stream = nghttp2_session_get_stream_raw(session, 3);
3002 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == dep_stream->weight);
3004 dep_stream = open_stream(session, 3);
3007 pri_spec.weight = 128;
3009 nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
3011 CU_ASSERT(128 == stream->weight);
3012 CU_ASSERT(dep_stream == stream->dep_prev);
3014 /* Test circular dependency; stream 1 is first removed and becomes
3015 root. Then stream 3 depends on it. */
3016 nghttp2_priority_spec_init(&pri_spec, 1, 1, 0);
3018 nghttp2_session_reprioritize_stream(session, dep_stream, &pri_spec);
3020 CU_ASSERT(1 == dep_stream->weight);
3021 CU_ASSERT(stream == dep_stream->dep_prev);
3023 /* Making priority to closed stream will result in default
3025 session->last_recv_stream_id = 9;
3027 nghttp2_priority_spec_init(&pri_spec, 5, 5, 0);
3029 nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
3031 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
3033 nghttp2_session_del(session);
3036 void test_nghttp2_session_reprioritize_stream_with_idle_stream_dep(void) {
3037 nghttp2_session *session;
3038 nghttp2_session_callbacks callbacks;
3039 nghttp2_stream *stream;
3040 nghttp2_priority_spec pri_spec;
3042 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3043 callbacks.send_callback = block_count_send_callback;
3045 nghttp2_session_server_new(&session, &callbacks, NULL);
3047 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3049 NGHTTP2_STREAM_OPENING, NULL);
3051 session->pending_local_max_concurrent_stream = 1;
3053 nghttp2_priority_spec_init(&pri_spec, 101, 10, 0);
3055 nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
3057 /* idle stream is not counteed to max concurrent streams */
3059 CU_ASSERT(10 == stream->weight);
3060 CU_ASSERT(101 == stream->dep_prev->stream_id);
3062 stream = nghttp2_session_get_stream_raw(session, 101);
3064 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
3066 nghttp2_session_del(session);
3069 void test_nghttp2_submit_data(void) {
3070 nghttp2_session *session;
3071 nghttp2_session_callbacks callbacks;
3072 nghttp2_data_provider data_prd;
3074 nghttp2_frame *frame;
3075 nghttp2_frame_hd hd;
3076 nghttp2_active_outbound_item *aob;
3077 nghttp2_bufs *framebufs;
3080 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3081 callbacks.send_callback = block_count_send_callback;
3083 data_prd.read_callback = fixed_length_data_source_read_callback;
3084 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
3085 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3086 aob = &session->aob;
3087 framebufs = &aob->framebufs;
3089 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3090 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
3092 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
3095 CU_ASSERT(0 == nghttp2_session_send(session));
3096 frame = &aob->item->frame;
3098 buf = &framebufs->head->buf;
3099 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
3101 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
3102 CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
3103 /* aux_data.data.flags has these flags */
3104 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
3106 nghttp2_session_del(session);
3109 void test_nghttp2_submit_data_read_length_too_large(void) {
3110 nghttp2_session *session;
3111 nghttp2_session_callbacks callbacks;
3112 nghttp2_data_provider data_prd;
3114 nghttp2_frame *frame;
3115 nghttp2_frame_hd hd;
3116 nghttp2_active_outbound_item *aob;
3117 nghttp2_bufs *framebufs;
3121 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3122 callbacks.send_callback = block_count_send_callback;
3123 callbacks.read_length_callback = too_large_data_source_length_callback;
3125 data_prd.read_callback = fixed_length_data_source_read_callback;
3126 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
3127 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3128 aob = &session->aob;
3129 framebufs = &aob->framebufs;
3131 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3132 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
3134 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
3137 CU_ASSERT(0 == nghttp2_session_send(session));
3138 frame = &aob->item->frame;
3140 buf = &framebufs->head->buf;
3141 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
3143 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
3144 CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
3145 CU_ASSERT(16384 == hd.length)
3146 /* aux_data.data.flags has these flags */
3147 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
3149 nghttp2_session_del(session);
3151 /* Check that buffers are expanded */
3152 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3154 ud.data_source_length = NGHTTP2_MAX_FRAME_SIZE_MAX;
3156 session->remote_settings.max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MAX;
3158 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3159 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
3161 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
3164 CU_ASSERT(0 == nghttp2_session_send(session));
3166 aob = &session->aob;
3168 frame = &aob->item->frame;
3170 framebufs = &aob->framebufs;
3172 buf = &framebufs->head->buf;
3173 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
3175 payloadlen = nghttp2_min(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE,
3176 NGHTTP2_INITIAL_WINDOW_SIZE);
3178 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 1 + payloadlen ==
3179 (size_t)nghttp2_buf_cap(buf));
3180 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
3181 CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
3182 CU_ASSERT(payloadlen == hd.length);
3183 /* aux_data.data.flags has these flags */
3184 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
3186 nghttp2_session_del(session);
3189 void test_nghttp2_submit_data_read_length_smallest(void) {
3190 nghttp2_session *session;
3191 nghttp2_session_callbacks callbacks;
3192 nghttp2_data_provider data_prd;
3194 nghttp2_frame *frame;
3195 nghttp2_frame_hd hd;
3196 nghttp2_active_outbound_item *aob;
3197 nghttp2_bufs *framebufs;
3200 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3201 callbacks.send_callback = block_count_send_callback;
3202 callbacks.read_length_callback = smallest_length_data_source_length_callback;
3204 data_prd.read_callback = fixed_length_data_source_read_callback;
3205 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
3206 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3207 aob = &session->aob;
3208 framebufs = &aob->framebufs;
3210 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3211 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
3213 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
3216 CU_ASSERT(0 == nghttp2_session_send(session));
3217 frame = &aob->item->frame;
3219 buf = &framebufs->head->buf;
3220 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
3222 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
3223 CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
3224 CU_ASSERT(1 == hd.length)
3225 /* aux_data.data.flags has these flags */
3226 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
3228 nghttp2_session_del(session);
3231 static ssize_t submit_data_twice_data_source_read_callback(
3232 nghttp2_session *session _U_, int32_t stream_id _U_, uint8_t *buf _U_,
3233 size_t len, uint32_t *data_flags, nghttp2_data_source *source _U_,
3234 void *user_data _U_) {
3235 *data_flags |= NGHTTP2_DATA_FLAG_EOF;
3236 return nghttp2_min(len, 16);
3239 static int submit_data_twice_on_frame_send_callback(nghttp2_session *session,
3240 const nghttp2_frame *frame,
3241 void *user_data _U_) {
3242 static int called = 0;
3244 nghttp2_data_provider data_prd;
3249 data_prd.read_callback = submit_data_twice_data_source_read_callback;
3251 rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM,
3252 frame->hd.stream_id, &data_prd);
3259 void test_nghttp2_submit_data_twice(void) {
3260 nghttp2_session *session;
3261 nghttp2_session_callbacks callbacks;
3262 nghttp2_data_provider data_prd;
3266 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3267 callbacks.send_callback = accumulator_send_callback;
3268 callbacks.on_frame_send_callback = submit_data_twice_on_frame_send_callback;
3270 data_prd.read_callback = submit_data_twice_data_source_read_callback;
3275 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3277 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3278 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
3280 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &data_prd));
3282 CU_ASSERT(0 == nghttp2_session_send(session));
3284 /* We should have sent 2 DATA frame with 16 bytes payload each */
3285 CU_ASSERT(NGHTTP2_FRAME_HDLEN * 2 + 16 * 2 == acc.length);
3287 nghttp2_session_del(session);
3290 void test_nghttp2_submit_request_with_data(void) {
3291 nghttp2_session *session;
3292 nghttp2_session_callbacks callbacks;
3293 nghttp2_nv nva[] = {MAKE_NV(":version", "HTTP/1.1")};
3294 nghttp2_data_provider data_prd;
3296 nghttp2_outbound_item *item;
3298 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3299 callbacks.send_callback = null_send_callback;
3301 data_prd.read_callback = fixed_length_data_source_read_callback;
3302 ud.data_source_length = 64 * 1024 - 1;
3303 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3304 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, nva, ARRLEN(nva),
3306 item = nghttp2_session_get_next_ob_item(session);
3307 CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0]));
3308 CU_ASSERT(0 == nghttp2_session_send(session));
3309 CU_ASSERT(0 == ud.data_source_length);
3311 nghttp2_session_del(session);
3314 void test_nghttp2_submit_request_without_data(void) {
3315 nghttp2_session *session;
3316 nghttp2_session_callbacks callbacks;
3318 nghttp2_nv nva[] = {MAKE_NV(":version", "HTTP/1.1")};
3319 nghttp2_data_provider data_prd = {{-1}, NULL};
3320 nghttp2_outbound_item *item;
3322 nghttp2_frame frame;
3323 nghttp2_hd_inflater inflater;
3328 mem = nghttp2_mem_default();
3329 frame_pack_bufs_init(&bufs);
3334 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3335 callbacks.send_callback = accumulator_send_callback;
3336 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3338 nghttp2_hd_inflate_init(&inflater, mem);
3339 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, nva, ARRLEN(nva),
3341 item = nghttp2_session_get_next_ob_item(session);
3342 CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0]));
3343 CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
3345 CU_ASSERT(0 == nghttp2_session_send(session));
3346 CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
3348 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
3349 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN);
3351 CU_ASSERT(nvnameeq(":version", &out.nva[0]));
3352 nghttp2_frame_headers_free(&frame.headers, mem);
3353 nva_out_reset(&out);
3355 nghttp2_bufs_free(&bufs);
3356 nghttp2_hd_inflate_free(&inflater);
3357 nghttp2_session_del(session);
3360 void test_nghttp2_submit_response_with_data(void) {
3361 nghttp2_session *session;
3362 nghttp2_session_callbacks callbacks;
3363 nghttp2_nv nva[] = {MAKE_NV(":version", "HTTP/1.1")};
3364 nghttp2_data_provider data_prd;
3366 nghttp2_outbound_item *item;
3368 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3369 callbacks.send_callback = null_send_callback;
3371 data_prd.read_callback = fixed_length_data_source_read_callback;
3372 ud.data_source_length = 64 * 1024 - 1;
3373 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
3374 nghttp2_session_open_stream(session, 1, NGHTTP2_FLAG_END_STREAM,
3375 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
3377 nghttp2_submit_response(session, 1, nva, ARRLEN(nva), &data_prd));
3378 item = nghttp2_session_get_next_ob_item(session);
3379 CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0]));
3380 CU_ASSERT(0 == nghttp2_session_send(session));
3381 CU_ASSERT(0 == ud.data_source_length);
3383 nghttp2_session_del(session);
3386 void test_nghttp2_submit_response_without_data(void) {
3387 nghttp2_session *session;
3388 nghttp2_session_callbacks callbacks;
3390 nghttp2_nv nva[] = {MAKE_NV(":version", "HTTP/1.1")};
3391 nghttp2_data_provider data_prd = {{-1}, NULL};
3392 nghttp2_outbound_item *item;
3394 nghttp2_frame frame;
3395 nghttp2_hd_inflater inflater;
3400 mem = nghttp2_mem_default();
3401 frame_pack_bufs_init(&bufs);
3406 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3407 callbacks.send_callback = accumulator_send_callback;
3408 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
3410 nghttp2_hd_inflate_init(&inflater, mem);
3411 nghttp2_session_open_stream(session, 1, NGHTTP2_FLAG_END_STREAM,
3412 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
3414 nghttp2_submit_response(session, 1, nva, ARRLEN(nva), &data_prd));
3415 item = nghttp2_session_get_next_ob_item(session);
3416 CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0]));
3417 CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
3419 CU_ASSERT(0 == nghttp2_session_send(session));
3420 CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
3422 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
3423 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN);
3425 CU_ASSERT(nvnameeq(":version", &out.nva[0]));
3427 nva_out_reset(&out);
3428 nghttp2_bufs_free(&bufs);
3429 nghttp2_frame_headers_free(&frame.headers, mem);
3430 nghttp2_hd_inflate_free(&inflater);
3431 nghttp2_session_del(session);
3434 void test_nghttp2_submit_headers_start_stream(void) {
3435 nghttp2_session *session;
3436 nghttp2_session_callbacks callbacks;
3437 const nghttp2_nv nv[] = {MAKE_NV(":version", "HTTP/1.1")};
3438 nghttp2_outbound_item *item;
3440 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3441 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
3442 CU_ASSERT(1 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
3443 NULL, nv, ARRLEN(nv), NULL));
3444 item = nghttp2_session_get_next_ob_item(session);
3445 CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0]));
3446 CU_ASSERT((NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM) ==
3447 item->frame.hd.flags);
3448 CU_ASSERT(0 == (item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY));
3450 nghttp2_session_del(session);
3453 void test_nghttp2_submit_headers_reply(void) {
3454 nghttp2_session *session;
3455 nghttp2_session_callbacks callbacks;
3456 const nghttp2_nv nv[] = {MAKE_NV(":version", "HTTP/1.1")};
3458 nghttp2_outbound_item *item;
3459 nghttp2_stream *stream;
3461 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3462 callbacks.send_callback = null_send_callback;
3463 callbacks.on_frame_send_callback = on_frame_send_callback;
3465 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
3466 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
3467 NULL, nv, ARRLEN(nv), NULL));
3468 item = nghttp2_session_get_next_ob_item(session);
3469 CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0]));
3470 CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
3471 item->frame.hd.flags);
3473 ud.frame_send_cb_called = 0;
3474 ud.sent_frame_type = 0;
3475 /* The transimission will be canceled because the stream 1 is not
3477 CU_ASSERT(0 == nghttp2_session_send(session));
3478 CU_ASSERT(0 == ud.frame_send_cb_called);
3480 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3482 NGHTTP2_STREAM_OPENING, NULL);
3484 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
3485 NULL, nv, ARRLEN(nv), NULL));
3486 CU_ASSERT(0 == nghttp2_session_send(session));
3487 CU_ASSERT(1 == ud.frame_send_cb_called);
3488 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
3489 CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
3491 nghttp2_session_del(session);
3494 void test_nghttp2_submit_headers_push_reply(void) {
3495 nghttp2_session *session;
3496 nghttp2_session_callbacks callbacks;
3497 const nghttp2_nv nv[] = {MAKE_NV(":version", "HTTP/1.1")};
3499 nghttp2_stream *stream;
3502 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3503 callbacks.send_callback = null_send_callback;
3504 callbacks.on_frame_send_callback = on_frame_send_callback;
3506 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
3507 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
3509 NGHTTP2_STREAM_RESERVED, NULL);
3510 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL, nv,
3513 ud.frame_send_cb_called = 0;
3514 ud.sent_frame_type = 0;
3515 CU_ASSERT(0 == nghttp2_session_send(session));
3516 CU_ASSERT(1 == ud.frame_send_cb_called);
3517 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
3518 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
3519 CU_ASSERT(&foo == stream->stream_user_data);
3521 nghttp2_session_del(session);
3523 /* Sending HEADERS from client against stream in reserved state is
3525 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3526 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
3528 NGHTTP2_STREAM_RESERVED, NULL);
3529 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL, nv,
3532 ud.frame_send_cb_called = 0;
3533 ud.sent_frame_type = 0;
3534 CU_ASSERT(0 == nghttp2_session_send(session));
3535 CU_ASSERT(0 == ud.frame_send_cb_called);
3537 nghttp2_session_del(session);
3540 void test_nghttp2_submit_headers(void) {
3541 nghttp2_session *session;
3542 nghttp2_session_callbacks callbacks;
3543 const nghttp2_nv nv[] = {MAKE_NV(":version", "HTTP/1.1")};
3545 nghttp2_outbound_item *item;
3546 nghttp2_stream *stream;
3548 nghttp2_frame frame;
3549 nghttp2_hd_inflater inflater;
3554 mem = nghttp2_mem_default();
3555 frame_pack_bufs_init(&bufs);
3560 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3561 callbacks.send_callback = accumulator_send_callback;
3562 callbacks.on_frame_send_callback = on_frame_send_callback;
3564 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3566 nghttp2_hd_inflate_init(&inflater, mem);
3567 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
3568 NULL, nv, ARRLEN(nv), NULL));
3569 item = nghttp2_session_get_next_ob_item(session);
3570 CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0]));
3571 CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
3572 item->frame.hd.flags);
3574 ud.frame_send_cb_called = 0;
3575 ud.sent_frame_type = 0;
3576 /* The transimission will be canceled because the stream 1 is not
3578 CU_ASSERT(0 == nghttp2_session_send(session));
3579 CU_ASSERT(0 == ud.frame_send_cb_called);
3581 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3583 NGHTTP2_STREAM_OPENING, NULL);
3585 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
3586 NULL, nv, ARRLEN(nv), NULL));
3587 CU_ASSERT(0 == nghttp2_session_send(session));
3588 CU_ASSERT(1 == ud.frame_send_cb_called);
3589 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
3590 CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
3592 CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
3594 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
3595 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN);
3597 CU_ASSERT(nvnameeq(":version", &out.nva[0]));
3599 nva_out_reset(&out);
3600 nghttp2_bufs_free(&bufs);
3601 nghttp2_frame_headers_free(&frame.headers, mem);
3603 nghttp2_hd_inflate_free(&inflater);
3604 nghttp2_session_del(session);
3607 void test_nghttp2_submit_headers_continuation(void) {
3608 nghttp2_session *session;
3609 nghttp2_session_callbacks callbacks;
3611 MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
3612 MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
3615 nghttp2_outbound_item *item;
3620 memset(data, '0', sizeof(data));
3621 for (i = 0; i < ARRLEN(nv); ++i) {
3622 nv[i].valuelen = sizeof(data);
3626 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3627 callbacks.send_callback = null_send_callback;
3628 callbacks.on_frame_send_callback = on_frame_send_callback;
3630 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3631 CU_ASSERT(1 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
3632 NULL, nv, ARRLEN(nv), NULL));
3633 item = nghttp2_session_get_next_ob_item(session);
3634 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
3635 CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
3636 item->frame.hd.flags);
3637 CU_ASSERT(0 == (item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY));
3639 ud.frame_send_cb_called = 0;
3640 CU_ASSERT(0 == nghttp2_session_send(session));
3641 CU_ASSERT(1 == ud.frame_send_cb_called);
3643 nghttp2_session_del(session);
3646 void test_nghttp2_submit_priority(void) {
3647 nghttp2_session *session;
3648 nghttp2_session_callbacks callbacks;
3649 nghttp2_stream *stream;
3651 nghttp2_priority_spec pri_spec;
3653 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3654 callbacks.send_callback = null_send_callback;
3655 callbacks.on_frame_send_callback = on_frame_send_callback;
3657 nghttp2_session_client_new(&session, &callbacks, &ud);
3658 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3660 NGHTTP2_STREAM_OPENING, NULL);
3662 nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
3664 /* depends on stream 0 */
3666 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
3667 CU_ASSERT(0 == nghttp2_session_send(session));
3668 CU_ASSERT(3 == stream->weight);
3670 /* submit against idle stream */
3672 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 3, &pri_spec));
3674 ud.frame_send_cb_called = 0;
3675 CU_ASSERT(0 == nghttp2_session_send(session));
3676 CU_ASSERT(1 == ud.frame_send_cb_called);
3678 nghttp2_session_del(session);
3681 void test_nghttp2_submit_settings(void) {
3682 nghttp2_session *session;
3683 nghttp2_session_callbacks callbacks;
3685 nghttp2_outbound_item *item;
3686 nghttp2_frame *frame;
3687 nghttp2_settings_entry iv[7];
3688 nghttp2_frame ack_frame;
3689 const int32_t UNKNOWN_ID = 1000000007;
3692 mem = nghttp2_mem_default();
3694 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
3697 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3698 iv[1].value = 16 * 1024;
3700 iv[2].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
3703 iv[3].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3706 iv[4].settings_id = UNKNOWN_ID;
3709 iv[5].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3710 iv[5].value = (uint32_t)NGHTTP2_MAX_WINDOW_SIZE + 1;
3712 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3713 callbacks.send_callback = null_send_callback;
3714 callbacks.on_frame_send_callback = on_frame_send_callback;
3715 nghttp2_session_server_new(&session, &callbacks, &ud);
3717 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
3718 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 6));
3720 /* Make sure that local settings are not changed */
3721 CU_ASSERT(NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS ==
3722 session->local_settings.max_concurrent_streams);
3723 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
3724 session->local_settings.initial_window_size);
3726 /* Now sends without 6th one */
3727 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 5));
3729 item = nghttp2_session_get_next_ob_item(session);
3731 CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type);
3733 frame = &item->frame;
3734 CU_ASSERT(5 == frame->settings.niv);
3735 CU_ASSERT(5 == frame->settings.iv[0].value);
3736 CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
3737 frame->settings.iv[0].settings_id);
3739 CU_ASSERT(16 * 1024 == frame->settings.iv[1].value);
3740 CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE ==
3741 frame->settings.iv[1].settings_id);
3743 CU_ASSERT(UNKNOWN_ID == frame->settings.iv[4].settings_id);
3744 CU_ASSERT(999 == frame->settings.iv[4].value);
3746 ud.frame_send_cb_called = 0;
3747 CU_ASSERT(0 == nghttp2_session_send(session));
3748 CU_ASSERT(1 == ud.frame_send_cb_called);
3750 CU_ASSERT(50 == session->pending_local_max_concurrent_stream);
3752 nghttp2_frame_settings_init(&ack_frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
3753 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
3754 nghttp2_frame_settings_free(&ack_frame.settings, mem);
3756 CU_ASSERT(16 * 1024 == session->local_settings.initial_window_size);
3757 CU_ASSERT(0 == session->hd_inflater.ctx.hd_table_bufsize_max);
3758 CU_ASSERT(50 == session->local_settings.max_concurrent_streams);
3759 CU_ASSERT(NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS ==
3760 session->pending_local_max_concurrent_stream);
3762 nghttp2_session_del(session);
3765 void test_nghttp2_submit_settings_update_local_window_size(void) {
3766 nghttp2_session *session;
3767 nghttp2_session_callbacks callbacks;
3768 nghttp2_outbound_item *item;
3769 nghttp2_settings_entry iv[4];
3770 nghttp2_stream *stream;
3771 nghttp2_frame ack_frame;
3774 mem = nghttp2_mem_default();
3775 nghttp2_frame_settings_init(&ack_frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
3777 iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3778 iv[0].value = 16 * 1024;
3780 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3781 callbacks.send_callback = null_send_callback;
3783 nghttp2_session_server_new(&session, &callbacks, NULL);
3785 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3786 &pri_spec_default, NGHTTP2_STREAM_OPENED,
3788 stream->local_window_size = NGHTTP2_INITIAL_WINDOW_SIZE + 100;
3789 stream->recv_window_size = 32768;
3791 stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
3792 &pri_spec_default, NGHTTP2_STREAM_OPENED,
3795 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
3796 CU_ASSERT(0 == nghttp2_session_send(session));
3797 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
3799 stream = nghttp2_session_get_stream(session, 1);
3800 CU_ASSERT(0 == stream->recv_window_size);
3801 CU_ASSERT(16 * 1024 + 100 == stream->local_window_size);
3803 stream = nghttp2_session_get_stream(session, 3);
3804 CU_ASSERT(16 * 1024 == stream->local_window_size);
3806 item = nghttp2_session_get_next_ob_item(session);
3807 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
3808 CU_ASSERT(32768 == item->frame.window_update.window_size_increment);
3810 nghttp2_session_del(session);
3812 /* Check overflow case */
3813 iv[0].value = 128 * 1024;
3814 nghttp2_session_server_new(&session, &callbacks, NULL);
3815 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3816 &pri_spec_default, NGHTTP2_STREAM_OPENED,
3818 stream->local_window_size = NGHTTP2_MAX_WINDOW_SIZE;
3820 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
3821 CU_ASSERT(0 == nghttp2_session_send(session));
3822 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
3824 item = nghttp2_session_get_next_ob_item(session);
3825 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3826 CU_ASSERT(NGHTTP2_FLOW_CONTROL_ERROR == item->frame.goaway.error_code);
3828 nghttp2_session_del(session);
3829 nghttp2_frame_settings_free(&ack_frame.settings, mem);
3832 void test_nghttp2_submit_push_promise(void) {
3833 nghttp2_session *session;
3834 nghttp2_session_callbacks callbacks;
3835 const nghttp2_nv nv[] = {MAKE_NV(":version", "HTTP/1.1")};
3837 nghttp2_stream *stream;
3839 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3840 callbacks.send_callback = null_send_callback;
3841 callbacks.on_frame_send_callback = on_frame_send_callback;
3843 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
3844 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3845 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
3846 CU_ASSERT(2 == nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, nv,
3849 ud.frame_send_cb_called = 0;
3850 ud.sent_frame_type = 0;
3851 CU_ASSERT(0 == nghttp2_session_send(session));
3852 CU_ASSERT(1 == ud.frame_send_cb_called);
3853 CU_ASSERT(NGHTTP2_PUSH_PROMISE == ud.sent_frame_type);
3854 stream = nghttp2_session_get_stream(session, 2);
3855 CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state);
3856 CU_ASSERT(&ud == nghttp2_session_get_stream_user_data(session, 2));
3858 nghttp2_session_del(session);
3861 void test_nghttp2_submit_window_update(void) {
3862 nghttp2_session *session;
3863 nghttp2_session_callbacks callbacks;
3865 nghttp2_outbound_item *item;
3866 nghttp2_stream *stream;
3868 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3869 callbacks.send_callback = null_send_callback;
3871 nghttp2_session_client_new(&session, &callbacks, &ud);
3872 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
3873 &pri_spec_default, NGHTTP2_STREAM_OPENED,
3875 stream->recv_window_size = 4096;
3878 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 1024));
3879 item = nghttp2_session_get_next_ob_item(session);
3880 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
3881 CU_ASSERT(1024 == item->frame.window_update.window_size_increment);
3882 CU_ASSERT(0 == nghttp2_session_send(session));
3883 CU_ASSERT(3072 == stream->recv_window_size);
3886 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 4096));
3887 item = nghttp2_session_get_next_ob_item(session);
3888 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
3889 CU_ASSERT(4096 == item->frame.window_update.window_size_increment);
3890 CU_ASSERT(0 == nghttp2_session_send(session));
3891 CU_ASSERT(0 == stream->recv_window_size);
3894 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 4096));
3895 item = nghttp2_session_get_next_ob_item(session);
3896 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
3897 CU_ASSERT(4096 == item->frame.window_update.window_size_increment);
3898 CU_ASSERT(0 == nghttp2_session_send(session));
3899 CU_ASSERT(0 == stream->recv_window_size);
3902 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 0));
3903 /* It is ok if stream is closed or does not exist at the call
3906 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 4, 4096));
3908 nghttp2_session_del(session);
3911 void test_nghttp2_submit_window_update_local_window_size(void) {
3912 nghttp2_session *session;
3913 nghttp2_session_callbacks callbacks;
3914 nghttp2_outbound_item *item;
3915 nghttp2_stream *stream;
3917 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3918 callbacks.send_callback = null_send_callback;
3920 nghttp2_session_client_new(&session, &callbacks, NULL);
3921 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
3922 &pri_spec_default, NGHTTP2_STREAM_OPENED,
3924 stream->recv_window_size = 4096;
3926 CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
3927 stream->recv_window_size + 1));
3928 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1 == stream->local_window_size);
3929 CU_ASSERT(0 == stream->recv_window_size);
3930 item = nghttp2_session_get_next_ob_item(session);
3931 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
3932 CU_ASSERT(4097 == item->frame.window_update.window_size_increment);
3934 CU_ASSERT(0 == nghttp2_session_send(session));
3936 /* Let's decrement local window size */
3937 stream->recv_window_size = 4096;
3938 CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
3939 -stream->local_window_size / 2));
3940 CU_ASSERT(32768 == stream->local_window_size);
3941 CU_ASSERT(-28672 == stream->recv_window_size);
3942 CU_ASSERT(32768 == stream->recv_reduction);
3944 item = nghttp2_session_get_next_ob_item(session);
3945 CU_ASSERT(item == NULL);
3947 /* Increase local window size */
3949 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 16384));
3950 CU_ASSERT(49152 == stream->local_window_size);
3951 CU_ASSERT(-12288 == stream->recv_window_size);
3952 CU_ASSERT(16384 == stream->recv_reduction);
3953 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
3955 CU_ASSERT(NGHTTP2_ERR_FLOW_CONTROL ==
3956 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
3957 NGHTTP2_MAX_WINDOW_SIZE));
3959 CU_ASSERT(0 == nghttp2_session_send(session));
3961 /* Check connection-level flow control */
3962 session->recv_window_size = 4096;
3963 CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
3964 session->recv_window_size + 1));
3965 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
3966 session->local_window_size);
3967 CU_ASSERT(0 == session->recv_window_size);
3968 item = nghttp2_session_get_next_ob_item(session);
3969 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
3970 CU_ASSERT(4097 == item->frame.window_update.window_size_increment);
3972 CU_ASSERT(0 == nghttp2_session_send(session));
3974 /* Go decrement part */
3975 session->recv_window_size = 4096;
3976 CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
3977 -session->local_window_size / 2));
3978 CU_ASSERT(32768 == session->local_window_size);
3979 CU_ASSERT(-28672 == session->recv_window_size);
3980 CU_ASSERT(32768 == session->recv_reduction);
3981 item = nghttp2_session_get_next_ob_item(session);
3982 CU_ASSERT(item == NULL);
3984 /* Increase local window size */
3986 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 16384));
3987 CU_ASSERT(49152 == session->local_window_size);
3988 CU_ASSERT(-12288 == session->recv_window_size);
3989 CU_ASSERT(16384 == session->recv_reduction);
3990 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
3992 CU_ASSERT(NGHTTP2_ERR_FLOW_CONTROL ==
3993 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
3994 NGHTTP2_MAX_WINDOW_SIZE));
3996 nghttp2_session_del(session);
3999 void test_nghttp2_submit_shutdown_notice(void) {
4000 nghttp2_session *session;
4001 nghttp2_session_callbacks callbacks;
4004 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4005 callbacks.send_callback = null_send_callback;
4006 callbacks.on_frame_send_callback = on_frame_send_callback;
4007 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
4009 nghttp2_session_server_new(&session, &callbacks, &ud);
4011 CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
4013 ud.frame_send_cb_called = 0;
4015 nghttp2_session_send(session);
4017 CU_ASSERT(1 == ud.frame_send_cb_called);
4018 CU_ASSERT(NGHTTP2_GOAWAY == ud.sent_frame_type);
4019 CU_ASSERT((1u << 31) - 1 == session->local_last_stream_id);
4021 /* After another GOAWAY, nghttp2_submit_shutdown_notice() is
4023 CU_ASSERT(0 == nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR));
4025 ud.frame_send_cb_called = 0;
4027 nghttp2_session_send(session);
4029 CU_ASSERT(1 == ud.frame_send_cb_called);
4030 CU_ASSERT(NGHTTP2_GOAWAY == ud.sent_frame_type);
4031 CU_ASSERT(0 == session->local_last_stream_id);
4033 CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
4035 ud.frame_send_cb_called = 0;
4036 ud.frame_not_send_cb_called = 0;
4038 nghttp2_session_send(session);
4040 CU_ASSERT(0 == ud.frame_send_cb_called);
4041 CU_ASSERT(0 == ud.frame_not_send_cb_called);
4043 nghttp2_session_del(session);
4045 /* Using nghttp2_submit_shutdown_notice() with client side session
4047 nghttp2_session_client_new(&session, &callbacks, NULL);
4049 CU_ASSERT(NGHTTP2_ERR_INVALID_STATE ==
4050 nghttp2_submit_shutdown_notice(session));
4052 nghttp2_session_del(session);
4055 void test_nghttp2_submit_invalid_nv(void) {
4056 nghttp2_session *session;
4057 nghttp2_session_callbacks callbacks;
4058 nghttp2_nv empty_name_nv[] = {MAKE_NV("Version", "HTTP/1.1"),
4059 MAKE_NV("", "empty name")};
4061 /* Now invalid header name/value pair in HTTP/1.1 is accepted in
4064 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4066 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL));
4068 /* nghttp2_submit_request */
4069 CU_ASSERT(0 < nghttp2_submit_request(session, NULL, empty_name_nv,
4070 ARRLEN(empty_name_nv), NULL, NULL));
4072 /* nghttp2_submit_response */
4073 CU_ASSERT(0 == nghttp2_submit_response(session, 2, empty_name_nv,
4074 ARRLEN(empty_name_nv), NULL));
4076 /* nghttp2_submit_headers */
4077 CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL,
4078 empty_name_nv, ARRLEN(empty_name_nv),
4081 /* nghttp2_submit_push_promise */
4082 open_stream(session, 1);
4084 CU_ASSERT(0 < nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1,
4086 ARRLEN(empty_name_nv), NULL));
4088 nghttp2_session_del(session);
4091 void test_nghttp2_session_open_stream(void) {
4092 nghttp2_session *session;
4093 nghttp2_session_callbacks callbacks;
4094 nghttp2_stream *stream;
4095 nghttp2_priority_spec pri_spec;
4097 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4098 nghttp2_session_server_new(&session, &callbacks, NULL);
4100 nghttp2_priority_spec_init(&pri_spec, 0, 245, 0);
4102 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4103 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
4104 CU_ASSERT(1 == session->num_incoming_streams);
4105 CU_ASSERT(0 == session->num_outgoing_streams);
4106 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
4107 CU_ASSERT(245 == stream->weight);
4108 CU_ASSERT(NULL == stream->dep_prev);
4109 CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags);
4111 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
4113 NGHTTP2_STREAM_OPENING, NULL);
4114 CU_ASSERT(1 == session->num_incoming_streams);
4115 CU_ASSERT(1 == session->num_outgoing_streams);
4116 CU_ASSERT(NULL == stream->dep_prev);
4117 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
4118 CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags);
4120 stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
4122 NGHTTP2_STREAM_RESERVED, NULL);
4123 CU_ASSERT(1 == session->num_incoming_streams);
4124 CU_ASSERT(1 == session->num_outgoing_streams);
4125 CU_ASSERT(NULL == stream->dep_prev);
4126 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
4127 CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
4129 nghttp2_priority_spec_init(&pri_spec, 1, 17, 1);
4131 stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
4132 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
4133 CU_ASSERT(17 == stream->weight);
4134 CU_ASSERT(1 == stream->dep_prev->stream_id);
4136 /* Dependency to idle stream */
4137 nghttp2_priority_spec_init(&pri_spec, 1000000007, 240, 1);
4139 stream = nghttp2_session_open_stream(session, 5, NGHTTP2_STREAM_FLAG_NONE,
4140 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
4141 CU_ASSERT(240 == stream->weight);
4142 CU_ASSERT(1000000007 == stream->dep_prev->stream_id);
4144 stream = nghttp2_session_get_stream_raw(session, 1000000007);
4146 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
4147 CU_ASSERT(NULL != stream->root_next);
4149 /* Dependency to closed stream which is not in dependency tree */
4150 session->last_recv_stream_id = 7;
4152 nghttp2_priority_spec_init(&pri_spec, 7, 10, 0);
4154 stream = nghttp2_session_open_stream(session, 9, NGHTTP2_FLAG_NONE, &pri_spec,
4155 NGHTTP2_STREAM_OPENED, NULL);
4157 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
4159 nghttp2_session_del(session);
4161 nghttp2_session_client_new(&session, &callbacks, NULL);
4162 stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
4164 NGHTTP2_STREAM_RESERVED, NULL);
4165 CU_ASSERT(0 == session->num_incoming_streams);
4166 CU_ASSERT(0 == session->num_outgoing_streams);
4167 CU_ASSERT(NULL == stream->dep_prev);
4168 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
4169 CU_ASSERT(NGHTTP2_SHUT_WR == stream->shut_flags);
4171 nghttp2_session_del(session);
4174 void test_nghttp2_session_open_stream_with_idle_stream_dep(void) {
4175 nghttp2_session *session;
4176 nghttp2_session_callbacks callbacks;
4177 nghttp2_stream *stream;
4178 nghttp2_priority_spec pri_spec;
4180 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4181 nghttp2_session_server_new(&session, &callbacks, NULL);
4183 /* Dependency to idle stream */
4184 nghttp2_priority_spec_init(&pri_spec, 101, 245, 0);
4186 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4187 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
4189 CU_ASSERT(245 == stream->weight);
4190 CU_ASSERT(101 == stream->dep_prev->stream_id);
4192 stream = nghttp2_session_get_stream_raw(session, 101);
4194 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
4195 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
4197 nghttp2_priority_spec_init(&pri_spec, 211, 1, 0);
4199 /* stream 101 was already created as idle. */
4200 stream = nghttp2_session_open_stream(session, 101, NGHTTP2_STREAM_FLAG_NONE,
4201 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
4203 CU_ASSERT(1 == stream->weight);
4204 CU_ASSERT(211 == stream->dep_prev->stream_id);
4206 stream = nghttp2_session_get_stream_raw(session, 211);
4208 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
4209 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
4211 nghttp2_session_del(session);
4214 void test_nghttp2_session_get_next_ob_item(void) {
4215 nghttp2_session *session;
4216 nghttp2_session_callbacks callbacks;
4217 nghttp2_priority_spec pri_spec;
4219 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4220 callbacks.send_callback = null_send_callback;
4222 nghttp2_session_server_new(&session, &callbacks, NULL);
4223 session->remote_settings.max_concurrent_streams = 2;
4225 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
4226 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
4227 CU_ASSERT(NGHTTP2_PING ==
4228 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
4230 nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL);
4231 CU_ASSERT(NGHTTP2_PING ==
4232 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
4234 CU_ASSERT(0 == nghttp2_session_send(session));
4235 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
4237 /* Incoming stream does not affect the number of outgoing max
4238 concurrent streams. */
4239 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4240 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
4242 nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
4244 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
4245 CU_ASSERT(NGHTTP2_HEADERS ==
4246 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
4247 CU_ASSERT(0 == nghttp2_session_send(session));
4249 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
4250 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
4252 session->remote_settings.max_concurrent_streams = 3;
4254 CU_ASSERT(NGHTTP2_HEADERS ==
4255 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
4257 nghttp2_session_del(session);
4260 void test_nghttp2_session_pop_next_ob_item(void) {
4261 nghttp2_session *session;
4262 nghttp2_session_callbacks callbacks;
4263 nghttp2_outbound_item *item;
4264 nghttp2_priority_spec pri_spec;
4265 nghttp2_stream *stream;
4268 mem = nghttp2_mem_default();
4269 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4270 callbacks.send_callback = null_send_callback;
4272 nghttp2_session_server_new(&session, &callbacks, NULL);
4273 session->remote_settings.max_concurrent_streams = 1;
4275 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
4277 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
4279 nghttp2_priority_spec_init(&pri_spec, 0, 254, 0);
4281 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
4283 item = nghttp2_session_pop_next_ob_item(session);
4284 CU_ASSERT(NGHTTP2_PING == item->frame.hd.type);
4285 nghttp2_outbound_item_free(item, mem);
4288 item = nghttp2_session_pop_next_ob_item(session);
4289 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
4290 nghttp2_outbound_item_free(item, mem);
4293 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
4295 /* Incoming stream does not affect the number of outgoing max
4296 concurrent streams. */
4297 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4298 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
4299 /* In-flight outgoing stream */
4300 nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
4301 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
4303 nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
4305 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
4306 nghttp2_submit_response(session, 1, NULL, 0, NULL);
4308 item = nghttp2_session_pop_next_ob_item(session);
4309 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
4310 CU_ASSERT(1 == item->frame.hd.stream_id);
4312 stream = nghttp2_session_get_stream(session, 1);
4314 nghttp2_stream_detach_item(stream, session);
4316 nghttp2_outbound_item_free(item, mem);
4319 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
4321 session->remote_settings.max_concurrent_streams = 2;
4323 item = nghttp2_session_pop_next_ob_item(session);
4324 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
4325 nghttp2_outbound_item_free(item, mem);
4328 nghttp2_session_del(session);
4330 /* Check that push reply HEADERS are queued into ob_ss_pq */
4331 nghttp2_session_server_new(&session, &callbacks, NULL);
4332 session->remote_settings.max_concurrent_streams = 0;
4333 nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
4334 &pri_spec_default, NGHTTP2_STREAM_RESERVED, NULL);
4335 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2,
4336 NULL, NULL, 0, NULL));
4337 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
4338 CU_ASSERT(1 == nghttp2_pq_size(&session->ob_ss_pq));
4339 nghttp2_session_del(session);
4342 void test_nghttp2_session_reply_fail(void) {
4343 nghttp2_session *session;
4344 nghttp2_session_callbacks callbacks;
4345 nghttp2_data_provider data_prd;
4348 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4349 callbacks.send_callback = fail_send_callback;
4351 data_prd.read_callback = fixed_length_data_source_read_callback;
4352 ud.data_source_length = 4 * 1024;
4353 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
4354 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4355 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
4356 CU_ASSERT(0 == nghttp2_submit_response(session, 1, NULL, 0, &data_prd));
4357 CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session));
4358 nghttp2_session_del(session);
4361 void test_nghttp2_session_max_concurrent_streams(void) {
4362 nghttp2_session *session;
4363 nghttp2_session_callbacks callbacks;
4364 nghttp2_frame frame;
4365 nghttp2_outbound_item *item;
4368 mem = nghttp2_mem_default();
4369 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4370 callbacks.send_callback = null_send_callback;
4372 nghttp2_session_server_new(&session, &callbacks, NULL);
4373 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4374 &pri_spec_default, NGHTTP2_STREAM_OPENED, NULL);
4376 /* Check un-ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
4377 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
4378 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
4379 session->pending_local_max_concurrent_stream = 1;
4381 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4382 nghttp2_session_on_request_headers_received(session, &frame));
4384 item = nghttp2_session_get_ob_pq_top(session);
4385 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
4386 CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
4388 CU_ASSERT(0 == nghttp2_session_send(session));
4390 /* Check ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
4391 session->local_settings.max_concurrent_streams = 1;
4392 frame.hd.stream_id = 5;
4394 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4395 nghttp2_session_on_request_headers_received(session, &frame));
4397 item = nghttp2_session_get_ob_pq_top(session);
4398 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
4399 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
4401 nghttp2_frame_headers_free(&frame.headers, mem);
4402 nghttp2_session_del(session);
4406 * Check that on_stream_close_callback is called when server pushed
4407 * HEADERS have NGHTTP2_FLAG_END_STREAM.
4409 void test_nghttp2_session_stream_close_on_headers_push(void) {
4410 /* nghttp2_session *session; */
4411 /* nghttp2_session_callbacks callbacks; */
4412 /* const char *nv[] = { NULL }; */
4413 /* my_user_data ud; */
4414 /* nghttp2_frame frame; */
4416 /* memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); */
4417 /* callbacks.on_stream_close_callback = */
4418 /* no_stream_user_data_stream_close_callback; */
4419 /* ud.stream_close_cb_called = 0; */
4421 /* nghttp2_session_client_new(&session, NGHTTP2_PROTO_SPDY2, &callbacks, &ud);
4423 /* nghttp2_session_open_stream(session, 1, NGHTTP2_CTRL_FLAG_NONE, 3, */
4424 /* NGHTTP2_STREAM_OPENING, NULL); */
4425 /* nghttp2_frame_syn_stream_init(&frame.syn_stream, NGHTTP2_PROTO_SPDY2, */
4426 /* NGHTTP2_CTRL_FLAG_FIN | */
4427 /* NGHTTP2_CTRL_FLAG_UNIDIRECTIONAL, */
4428 /* 2, 1, 3, dup_nv(nv)); */
4430 /* CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session,
4433 /* nghttp2_frame_syn_stream_free(&frame.syn_stream); */
4434 /* nghttp2_session_del(session); */
4437 void test_nghttp2_session_stop_data_with_rst_stream(void) {
4438 nghttp2_session *session;
4439 nghttp2_session_callbacks callbacks;
4441 nghttp2_data_provider data_prd;
4442 nghttp2_frame frame;
4444 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4445 callbacks.on_frame_send_callback = on_frame_send_callback;
4446 callbacks.send_callback = block_count_send_callback;
4447 data_prd.read_callback = fixed_length_data_source_read_callback;
4449 ud.frame_send_cb_called = 0;
4450 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
4452 nghttp2_session_server_new(&session, &callbacks, &ud);
4453 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4454 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
4455 nghttp2_submit_response(session, 1, NULL, 0, &data_prd);
4458 /* Sends response HEADERS + DATA[0] */
4459 CU_ASSERT(0 == nghttp2_session_send(session));
4460 CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
4461 /* data for DATA[1] is read from data_prd but it is not sent */
4462 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
4464 nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
4465 CU_ASSERT(0 == nghttp2_session_on_rst_stream_received(session, &frame));
4466 nghttp2_frame_rst_stream_free(&frame.rst_stream);
4468 /* Big enough number to send all DATA frames potentially. */
4469 ud.block_count = 100;
4470 /* Nothing will be sent in the following call. */
4471 CU_ASSERT(0 == nghttp2_session_send(session));
4472 /* With RST_STREAM, stream is canceled and further DATA on that
4473 stream are not sent. */
4474 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
4476 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
4478 nghttp2_session_del(session);
4481 void test_nghttp2_session_defer_data(void) {
4482 nghttp2_session *session;
4483 nghttp2_session_callbacks callbacks;
4485 nghttp2_data_provider data_prd;
4486 nghttp2_outbound_item *item;
4488 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4489 callbacks.on_frame_send_callback = on_frame_send_callback;
4490 callbacks.send_callback = block_count_send_callback;
4491 data_prd.read_callback = defer_data_source_read_callback;
4493 ud.frame_send_cb_called = 0;
4494 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
4496 nghttp2_session_server_new(&session, &callbacks, &ud);
4497 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4498 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
4499 nghttp2_submit_response(session, 1, NULL, 0, &data_prd);
4502 /* Sends HEADERS reply */
4503 CU_ASSERT(0 == nghttp2_session_send(session));
4504 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
4505 /* No data is read */
4506 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 4);
4509 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
4511 CU_ASSERT(0 == nghttp2_session_send(session));
4512 CU_ASSERT(NGHTTP2_PING == ud.sent_frame_type);
4514 /* Resume deferred DATA */
4515 CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
4516 item = (nghttp2_outbound_item *)nghttp2_pq_top(&session->ob_da_pq);
4517 item->aux_data.data.data_prd.read_callback =
4518 fixed_length_data_source_read_callback;
4520 /* Reads 2 DATA chunks */
4521 CU_ASSERT(0 == nghttp2_session_send(session));
4522 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
4524 /* Deferred again */
4525 item->aux_data.data.data_prd.read_callback = defer_data_source_read_callback;
4526 /* This is needed since 4KiB block is already read and waiting to be
4527 sent. No read_callback invocation. */
4529 CU_ASSERT(0 == nghttp2_session_send(session));
4530 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
4532 /* Resume deferred DATA */
4533 CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
4534 item = (nghttp2_outbound_item *)nghttp2_pq_top(&session->ob_da_pq);
4535 item->aux_data.data.data_prd.read_callback =
4536 fixed_length_data_source_read_callback;
4538 /* Reads 2 4KiB blocks */
4539 CU_ASSERT(0 == nghttp2_session_send(session));
4540 CU_ASSERT(ud.data_source_length == 0);
4542 nghttp2_session_del(session);
4545 void test_nghttp2_session_flow_control(void) {
4546 nghttp2_session *session;
4547 nghttp2_session_callbacks callbacks;
4549 nghttp2_data_provider data_prd;
4550 nghttp2_frame frame;
4551 nghttp2_stream *stream;
4552 int32_t new_initial_window_size;
4553 nghttp2_settings_entry iv[1];
4554 nghttp2_frame settings_frame;
4557 mem = nghttp2_mem_default();
4558 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4559 callbacks.send_callback = fixed_bytes_send_callback;
4560 callbacks.on_frame_send_callback = on_frame_send_callback;
4561 data_prd.read_callback = fixed_length_data_source_read_callback;
4563 ud.frame_send_cb_called = 0;
4564 ud.data_source_length = 128 * 1024;
4565 /* Use smaller emission count so that we can check outbound flow
4566 control window calculation is correct. */
4567 ud.fixed_sendlen = 2 * 1024;
4569 /* Initial window size to 64KiB - 1*/
4570 nghttp2_session_client_new(&session, &callbacks, &ud);
4571 /* Change it to 64KiB for easy calculation */
4572 session->remote_window_size = 64 * 1024;
4573 session->remote_settings.initial_window_size = 64 * 1024;
4575 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
4577 /* Sends 64KiB - 1 data */
4578 CU_ASSERT(0 == nghttp2_session_send(session));
4579 CU_ASSERT(64 * 1024 == ud.data_source_length);
4581 /* Back 32KiB in stream window */
4582 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
4584 nghttp2_session_on_window_update_received(session, &frame);
4586 /* Send nothing because of connection-level window */
4587 CU_ASSERT(0 == nghttp2_session_send(session));
4588 CU_ASSERT(64 * 1024 == ud.data_source_length);
4590 /* Back 32KiB in connection-level window */
4591 frame.hd.stream_id = 0;
4592 nghttp2_session_on_window_update_received(session, &frame);
4594 /* Sends another 32KiB data */
4595 CU_ASSERT(0 == nghttp2_session_send(session));
4596 CU_ASSERT(32 * 1024 == ud.data_source_length);
4598 stream = nghttp2_session_get_stream(session, 1);
4599 /* Change initial window size to 16KiB. The window_size becomes
4601 new_initial_window_size = 16 * 1024;
4602 stream->remote_window_size =
4603 new_initial_window_size - (session->remote_settings.initial_window_size -
4604 stream->remote_window_size);
4605 session->remote_settings.initial_window_size = new_initial_window_size;
4606 CU_ASSERT(-48 * 1024 == stream->remote_window_size);
4608 /* Back 48KiB to stream window */
4609 frame.hd.stream_id = 1;
4610 frame.window_update.window_size_increment = 48 * 1024;
4611 nghttp2_session_on_window_update_received(session, &frame);
4613 /* Nothing is sent because window_size is 0 */
4614 CU_ASSERT(0 == nghttp2_session_send(session));
4615 CU_ASSERT(32 * 1024 == ud.data_source_length);
4617 /* Back 16KiB in stream window */
4618 frame.hd.stream_id = 1;
4619 frame.window_update.window_size_increment = 16 * 1024;
4620 nghttp2_session_on_window_update_received(session, &frame);
4622 /* Back 24KiB in connection-level window */
4623 frame.hd.stream_id = 0;
4624 frame.window_update.window_size_increment = 24 * 1024;
4625 nghttp2_session_on_window_update_received(session, &frame);
4627 /* Sends another 16KiB data */
4628 CU_ASSERT(0 == nghttp2_session_send(session));
4629 CU_ASSERT(16 * 1024 == ud.data_source_length);
4631 /* Increase initial window size to 32KiB */
4632 iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
4633 iv[0].value = 32 * 1024;
4635 nghttp2_frame_settings_init(&settings_frame.settings, NGHTTP2_FLAG_NONE,
4637 nghttp2_session_on_settings_received(session, &settings_frame, 1);
4638 nghttp2_frame_settings_free(&settings_frame.settings, mem);
4640 /* Sends another 8KiB data */
4641 CU_ASSERT(0 == nghttp2_session_send(session));
4642 CU_ASSERT(8 * 1024 == ud.data_source_length);
4644 /* Back 8KiB in connection-level window */
4645 frame.hd.stream_id = 0;
4646 frame.window_update.window_size_increment = 8 * 1024;
4647 nghttp2_session_on_window_update_received(session, &frame);
4649 /* Sends last 8KiB data */
4650 CU_ASSERT(0 == nghttp2_session_send(session));
4651 CU_ASSERT(0 == ud.data_source_length);
4652 CU_ASSERT(nghttp2_session_get_stream(session, 1)->shut_flags &
4655 nghttp2_frame_window_update_free(&frame.window_update);
4656 nghttp2_session_del(session);
4659 void test_nghttp2_session_flow_control_data_recv(void) {
4660 nghttp2_session *session;
4661 nghttp2_session_callbacks callbacks;
4662 uint8_t data[64 * 1024 + 16];
4663 nghttp2_frame_hd hd;
4664 nghttp2_outbound_item *item;
4665 nghttp2_stream *stream;
4667 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4668 callbacks.send_callback = null_send_callback;
4670 /* Initial window size to 64KiB - 1*/
4671 nghttp2_session_client_new(&session, &callbacks, NULL);
4673 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4674 &pri_spec_default, NGHTTP2_STREAM_OPENED,
4677 session->next_stream_id = 3;
4679 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
4681 session->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
4682 stream->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
4684 /* Create DATA frame */
4685 memset(data, 0, sizeof(data));
4686 nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_PAYLOADLEN, NGHTTP2_DATA,
4687 NGHTTP2_FLAG_END_STREAM, 1);
4689 nghttp2_frame_pack_frame_hd(data, &hd);
4690 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN ==
4691 nghttp2_session_mem_recv(session, data, NGHTTP2_MAX_PAYLOADLEN +
4692 NGHTTP2_FRAME_HDLEN));
4694 item = nghttp2_session_get_next_ob_item(session);
4695 /* Since this is the last frame, stream-level WINDOW_UPDATE is not
4696 issued, but connection-level is. */
4697 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
4698 CU_ASSERT(0 == item->frame.hd.stream_id);
4699 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
4700 item->frame.window_update.window_size_increment);
4702 CU_ASSERT(0 == nghttp2_session_send(session));
4704 /* Receive DATA for closed stream. They are still subject to under
4705 connection-level flow control, since this situation arises when
4706 RST_STREAM is issued by the remote, but the local side keeps
4707 sending DATA frames. Without calculating connection-level window,
4708 the subsequent flow control gets confused. */
4709 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN ==
4710 nghttp2_session_mem_recv(session, data, NGHTTP2_MAX_PAYLOADLEN +
4711 NGHTTP2_FRAME_HDLEN));
4713 item = nghttp2_session_get_next_ob_item(session);
4714 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
4715 CU_ASSERT(0 == item->frame.hd.stream_id);
4716 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
4717 item->frame.window_update.window_size_increment);
4719 nghttp2_session_del(session);
4722 void test_nghttp2_session_flow_control_data_with_padding_recv(void) {
4723 nghttp2_session *session;
4724 nghttp2_session_callbacks callbacks;
4726 nghttp2_frame_hd hd;
4727 nghttp2_stream *stream;
4728 nghttp2_option *option;
4730 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4731 callbacks.send_callback = null_send_callback;
4733 nghttp2_option_new(&option);
4734 /* Disable auto window update so that we can check padding is
4735 consumed automatically */
4736 nghttp2_option_set_no_auto_window_update(option, 1);
4738 /* Initial window size to 64KiB - 1*/
4739 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
4741 nghttp2_option_del(option);
4743 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4744 &pri_spec_default, NGHTTP2_STREAM_OPENED,
4747 /* Create DATA frame */
4748 memset(data, 0, sizeof(data));
4749 nghttp2_frame_hd_init(&hd, 357, NGHTTP2_DATA,
4750 NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_PADDED, 1);
4752 nghttp2_frame_pack_frame_hd(data, &hd);
4753 /* Set Pad Length field, which itself is padding */
4754 data[NGHTTP2_FRAME_HDLEN] = 255;
4757 (ssize_t)(NGHTTP2_FRAME_HDLEN + hd.length) ==
4758 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + hd.length));
4760 CU_ASSERT((int32_t)hd.length == session->recv_window_size);
4761 CU_ASSERT((int32_t)hd.length == stream->recv_window_size);
4762 CU_ASSERT(256 == session->consumed_size);
4763 CU_ASSERT(256 == stream->consumed_size);
4765 nghttp2_session_del(session);
4768 void test_nghttp2_session_data_read_temporal_failure(void) {
4769 nghttp2_session *session;
4770 nghttp2_session_callbacks callbacks;
4772 nghttp2_data_provider data_prd;
4773 nghttp2_frame frame;
4774 nghttp2_stream *stream;
4775 size_t data_size = 128 * 1024;
4777 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4778 callbacks.send_callback = null_send_callback;
4779 callbacks.on_frame_send_callback = on_frame_send_callback;
4780 data_prd.read_callback = fixed_length_data_source_read_callback;
4782 ud.data_source_length = data_size;
4784 /* Initial window size is 64KiB - 1 */
4785 nghttp2_session_client_new(&session, &callbacks, &ud);
4786 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
4788 /* Sends NGHTTP2_INITIAL_WINDOW_SIZE data, assuming, it is equal to
4789 or smaller than NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE */
4790 CU_ASSERT(0 == nghttp2_session_send(session));
4791 CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
4793 stream = nghttp2_session_get_stream(session, 1);
4794 CU_ASSERT(nghttp2_stream_check_deferred_by_flow_control(stream));
4795 CU_ASSERT(NGHTTP2_DATA == stream->item->frame.hd.type);
4797 stream->item->aux_data.data.data_prd.read_callback =
4798 temporal_failure_data_source_read_callback;
4800 /* Back NGHTTP2_INITIAL_WINDOW_SIZE to both connection-level and
4801 stream-wise window */
4802 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
4803 NGHTTP2_INITIAL_WINDOW_SIZE);
4804 nghttp2_session_on_window_update_received(session, &frame);
4805 frame.hd.stream_id = 0;
4806 nghttp2_session_on_window_update_received(session, &frame);
4807 nghttp2_frame_window_update_free(&frame.window_update);
4809 /* Sending data will fail (soft fail) and treated as stream error */
4810 ud.frame_send_cb_called = 0;
4811 CU_ASSERT(0 == nghttp2_session_send(session));
4812 CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
4814 CU_ASSERT(1 == ud.frame_send_cb_called);
4815 CU_ASSERT(NGHTTP2_RST_STREAM == ud.sent_frame_type);
4817 data_prd.read_callback = fail_data_source_read_callback;
4818 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
4819 /* Sending data will fail (hard fail) and session tear down */
4820 CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session));
4822 nghttp2_session_del(session);
4825 void test_nghttp2_session_on_stream_close(void) {
4826 nghttp2_session *session;
4827 nghttp2_session_callbacks callbacks;
4828 my_user_data user_data;
4829 nghttp2_stream *stream;
4831 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4832 callbacks.on_stream_close_callback = on_stream_close_callback;
4833 user_data.stream_close_cb_called = 0;
4835 nghttp2_session_client_new(&session, &callbacks, &user_data);
4836 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4837 &pri_spec_default, NGHTTP2_STREAM_OPENED,
4839 CU_ASSERT(stream != NULL);
4840 CU_ASSERT(nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR) == 0);
4841 CU_ASSERT(user_data.stream_close_cb_called == 1);
4842 nghttp2_session_del(session);
4845 void test_nghttp2_session_on_ctrl_not_send(void) {
4846 nghttp2_session *session;
4847 nghttp2_session_callbacks callbacks;
4848 my_user_data user_data;
4849 nghttp2_stream *stream;
4851 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4852 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
4853 callbacks.send_callback = null_send_callback;
4854 user_data.frame_not_send_cb_called = 0;
4855 user_data.not_sent_frame_type = 0;
4856 user_data.not_sent_error = 0;
4858 nghttp2_session_server_new(&session, &callbacks, &user_data);
4859 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4861 NGHTTP2_STREAM_OPENING, &user_data);
4863 /* Check response HEADERS */
4864 /* Send bogus stream ID */
4865 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 3,
4866 NULL, NULL, 0, NULL));
4867 CU_ASSERT(0 == nghttp2_session_send(session));
4868 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
4869 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
4870 CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSED == user_data.not_sent_error);
4872 user_data.frame_not_send_cb_called = 0;
4873 /* Shutdown transmission */
4874 stream->shut_flags |= NGHTTP2_SHUT_WR;
4875 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
4876 NULL, NULL, 0, NULL));
4877 CU_ASSERT(0 == nghttp2_session_send(session));
4878 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
4879 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
4880 CU_ASSERT(NGHTTP2_ERR_STREAM_SHUT_WR == user_data.not_sent_error);
4882 stream->shut_flags = NGHTTP2_SHUT_NONE;
4883 user_data.frame_not_send_cb_called = 0;
4884 /* Queue RST_STREAM */
4885 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
4886 NULL, NULL, 0, NULL));
4887 CU_ASSERT(0 == nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
4888 NGHTTP2_INTERNAL_ERROR));
4889 CU_ASSERT(0 == nghttp2_session_send(session));
4890 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
4891 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
4892 CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSING == user_data.not_sent_error);
4894 nghttp2_session_del(session);
4896 /* Check request HEADERS */
4897 user_data.frame_not_send_cb_called = 0;
4898 CU_ASSERT(nghttp2_session_client_new(&session, &callbacks, &user_data) == 0);
4899 /* Maximum Stream ID is reached */
4900 session->next_stream_id = (1u << 31) + 1;
4901 CU_ASSERT(NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE ==
4902 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1, NULL,
4905 user_data.frame_not_send_cb_called = 0;
4906 /* GOAWAY received */
4907 session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
4908 session->next_stream_id = 9;
4910 CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
4911 NULL, NULL, 0, NULL));
4912 CU_ASSERT(0 == nghttp2_session_send(session));
4913 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
4914 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
4915 CU_ASSERT(NGHTTP2_ERR_START_STREAM_NOT_ALLOWED == user_data.not_sent_error);
4917 nghttp2_session_del(session);
4920 void test_nghttp2_session_get_outbound_queue_size(void) {
4921 nghttp2_session *session;
4922 nghttp2_session_callbacks callbacks;
4924 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4925 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
4926 CU_ASSERT(0 == nghttp2_session_get_outbound_queue_size(session));
4928 CU_ASSERT(0 == nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL));
4929 CU_ASSERT(1 == nghttp2_session_get_outbound_queue_size(session));
4931 CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 2,
4932 NGHTTP2_NO_ERROR, NULL, 0));
4933 CU_ASSERT(2 == nghttp2_session_get_outbound_queue_size(session));
4935 nghttp2_session_del(session);
4938 void test_nghttp2_session_get_effective_local_window_size(void) {
4939 nghttp2_session *session;
4940 nghttp2_session_callbacks callbacks;
4941 nghttp2_stream *stream;
4943 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4944 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
4946 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4947 &pri_spec_default, NGHTTP2_STREAM_OPENED,
4950 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE ==
4951 nghttp2_session_get_effective_local_window_size(session));
4952 CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
4954 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
4955 nghttp2_session_get_stream_effective_local_window_size(session, 1));
4957 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
4959 /* Check connection flow control */
4960 session->recv_window_size = 100;
4961 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 1100);
4963 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
4964 nghttp2_session_get_effective_local_window_size(session));
4965 CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
4967 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, -50);
4968 /* Now session->recv_window_size = -50 */
4969 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950 ==
4970 nghttp2_session_get_effective_local_window_size(session));
4971 CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
4973 session->recv_window_size += 50;
4974 /* Now session->recv_window_size = 0 */
4975 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 100);
4976 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1050 ==
4977 nghttp2_session_get_effective_local_window_size(session));
4978 CU_ASSERT(50 == nghttp2_session_get_effective_recv_data_length(session));
4980 /* Check stream flow control */
4981 stream->recv_window_size = 100;
4982 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 1100);
4984 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
4985 nghttp2_session_get_stream_effective_local_window_size(session, 1));
4987 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
4989 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, -50);
4990 /* Now stream->recv_window_size = -50 */
4991 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 950 ==
4992 nghttp2_session_get_stream_effective_local_window_size(session, 1));
4994 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
4996 stream->recv_window_size += 50;
4997 /* Now stream->recv_window_size = 0 */
4998 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 100);
4999 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1050 ==
5000 nghttp2_session_get_stream_effective_local_window_size(session, 1));
5002 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
5004 nghttp2_session_del(session);
5007 void test_nghttp2_session_set_option(void) {
5008 nghttp2_session *session;
5009 nghttp2_session_callbacks callbacks;
5010 nghttp2_option *option;
5012 nghttp2_option_new(&option);
5014 nghttp2_option_set_no_auto_window_update(option, 1);
5016 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5017 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
5019 CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE);
5021 nghttp2_session_del(session);
5023 nghttp2_option_set_peer_max_concurrent_streams(option, 100);
5025 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
5027 CU_ASSERT(100 == session->remote_settings.max_concurrent_streams);
5028 nghttp2_session_del(session);
5030 nghttp2_option_del(option);
5033 void test_nghttp2_session_data_backoff_by_high_pri_frame(void) {
5034 nghttp2_session *session;
5035 nghttp2_session_callbacks callbacks;
5037 nghttp2_data_provider data_prd;
5038 nghttp2_stream *stream;
5040 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5041 callbacks.send_callback = block_count_send_callback;
5042 callbacks.on_frame_send_callback = on_frame_send_callback;
5043 data_prd.read_callback = fixed_length_data_source_read_callback;
5045 ud.frame_send_cb_called = 0;
5046 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
5048 nghttp2_session_client_new(&session, &callbacks, &ud);
5049 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
5052 /* Sends request HEADERS + DATA[0] */
5053 CU_ASSERT(0 == nghttp2_session_send(session));
5054 CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
5055 /* data for DATA[1] is read from data_prd but it is not sent */
5056 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
5058 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
5060 /* Sends DATA[1] + PING, PING is interleaved in DATA sequence */
5061 CU_ASSERT(0 == nghttp2_session_send(session));
5062 CU_ASSERT(NGHTTP2_PING == ud.sent_frame_type);
5063 /* data for DATA[2] is read from data_prd but it is not sent */
5064 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN);
5067 /* Sends DATA[2..3] */
5068 CU_ASSERT(0 == nghttp2_session_send(session));
5070 stream = nghttp2_session_get_stream(session, 1);
5071 CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
5073 nghttp2_session_del(session);
5076 static void check_session_recv_data_with_padding(nghttp2_bufs *bufs,
5078 nghttp2_session *session;
5080 nghttp2_session_callbacks callbacks;
5084 memset(&callbacks, 0, sizeof(callbacks));
5085 callbacks.on_frame_recv_callback = on_frame_recv_callback;
5086 callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
5087 nghttp2_session_server_new(&session, &callbacks, &ud);
5089 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
5090 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
5092 inlen = nghttp2_bufs_remove(bufs, &in);
5094 ud.frame_recv_cb_called = 0;
5095 ud.data_chunk_len = 0;
5097 CU_ASSERT((ssize_t)inlen == nghttp2_session_mem_recv(session, in, inlen));
5099 CU_ASSERT(1 == ud.frame_recv_cb_called);
5100 CU_ASSERT(datalen == ud.data_chunk_len);
5103 nghttp2_session_del(session);
5106 void test_nghttp2_session_pack_data_with_padding(void) {
5107 nghttp2_session *session;
5109 nghttp2_session_callbacks callbacks;
5110 nghttp2_data_provider data_prd;
5111 nghttp2_frame *frame;
5112 size_t datalen = 55;
5114 memset(&callbacks, 0, sizeof(callbacks));
5115 callbacks.send_callback = block_count_send_callback;
5116 callbacks.on_frame_send_callback = on_frame_send_callback;
5117 callbacks.select_padding_callback = select_padding_callback;
5119 data_prd.read_callback = fixed_length_data_source_read_callback;
5121 nghttp2_session_client_new(&session, &callbacks, &ud);
5125 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
5127 ud.data_source_length = datalen;
5129 CU_ASSERT(0 == nghttp2_session_send(session));
5130 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
5132 frame = &session->aob.item->frame;
5134 CU_ASSERT(ud.padlen == frame->data.padlen);
5135 CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PADDED);
5137 /* Check reception of this DATA frame */
5138 check_session_recv_data_with_padding(&session->aob.framebufs, datalen);
5140 nghttp2_session_del(session);
5143 void test_nghttp2_session_pack_headers_with_padding(void) {
5144 nghttp2_session *session, *sv_session;
5147 nghttp2_session_callbacks callbacks;
5148 nghttp2_nv nv = MAKE_NV(":path", "/");
5150 memset(&callbacks, 0, sizeof(callbacks));
5151 callbacks.send_callback = accumulator_send_callback;
5152 callbacks.on_frame_send_callback = on_frame_send_callback;
5153 callbacks.select_padding_callback = select_padding_callback;
5154 callbacks.on_frame_recv_callback = on_frame_recv_callback;
5159 nghttp2_session_client_new(&session, &callbacks, &ud);
5160 nghttp2_session_server_new(&sv_session, &callbacks, &ud);
5164 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL));
5165 CU_ASSERT(0 == nghttp2_session_send(session));
5167 CU_ASSERT(acc.length < NGHTTP2_MAX_PAYLOADLEN);
5168 ud.frame_recv_cb_called = 0;
5169 CU_ASSERT((ssize_t)acc.length ==
5170 nghttp2_session_mem_recv(sv_session, acc.buf, acc.length));
5171 CU_ASSERT(1 == ud.frame_recv_cb_called);
5172 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(sv_session));
5174 nghttp2_session_del(sv_session);
5175 nghttp2_session_del(session);
5178 void test_nghttp2_pack_settings_payload(void) {
5179 nghttp2_settings_entry iv[2];
5182 nghttp2_settings_entry *resiv;
5186 mem = nghttp2_mem_default();
5188 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
5190 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
5193 len = nghttp2_pack_settings_payload(buf, sizeof(buf), iv, 2);
5194 CU_ASSERT(2 * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH == len);
5195 CU_ASSERT(0 == nghttp2_frame_unpack_settings_payload2(&resiv, &resniv, buf,
5197 CU_ASSERT(2 == resniv);
5198 CU_ASSERT(NGHTTP2_SETTINGS_HEADER_TABLE_SIZE == resiv[0].settings_id);
5199 CU_ASSERT(1023 == resiv[0].value);
5200 CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE == resiv[1].settings_id);
5201 CU_ASSERT(4095 == resiv[1].value);
5205 len = nghttp2_pack_settings_payload(buf, 9 /* too small */, iv, 2);
5206 CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == len);
5209 #define check_stream_dep_sib(STREAM, DEP_PREV, DEP_NEXT, SIB_PREV, SIB_NEXT) \
5211 CU_ASSERT(DEP_PREV == STREAM->dep_prev); \
5212 CU_ASSERT(DEP_NEXT == STREAM->dep_next); \
5213 CU_ASSERT(SIB_PREV == STREAM->sib_prev); \
5214 CU_ASSERT(SIB_NEXT == STREAM->sib_next); \
5217 /* nghttp2_stream_dep_add() and its families functions should be
5218 tested in nghttp2_stream_test.c, but it is easier to use
5219 nghttp2_session_open_stream(). Therefore, we test them here. */
5220 void test_nghttp2_session_stream_dep_add(void) {
5221 nghttp2_session *session;
5222 nghttp2_session_callbacks callbacks;
5223 nghttp2_stream *a, *b, *c, *d, *e;
5225 memset(&callbacks, 0, sizeof(callbacks));
5227 nghttp2_session_server_new(&session, &callbacks, NULL);
5229 a = open_stream(session, 1);
5231 c = open_stream_with_dep(session, 5, a);
5232 b = open_stream_with_dep(session, 3, a);
5233 d = open_stream_with_dep(session, 7, c);
5242 CU_ASSERT(4 == a->num_substreams);
5243 CU_ASSERT(1 == b->num_substreams);
5244 CU_ASSERT(2 == c->num_substreams);
5245 CU_ASSERT(1 == d->num_substreams);
5247 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
5248 CU_ASSERT(0 == b->sum_dep_weight);
5249 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5250 CU_ASSERT(0 == d->sum_dep_weight);
5252 check_stream_dep_sib(a, NULL, b, NULL, NULL);
5253 check_stream_dep_sib(b, a, NULL, NULL, c);
5254 check_stream_dep_sib(c, NULL, d, b, NULL);
5255 check_stream_dep_sib(d, c, NULL, NULL, NULL);
5257 CU_ASSERT(4 == session->roots.num_streams);
5258 CU_ASSERT(a == session->roots.head);
5259 CU_ASSERT(NULL == a->root_next);
5261 e = open_stream_with_dep_excl(session, 9, a);
5272 CU_ASSERT(5 == a->num_substreams);
5273 CU_ASSERT(4 == e->num_substreams);
5274 CU_ASSERT(1 == b->num_substreams);
5275 CU_ASSERT(2 == c->num_substreams);
5276 CU_ASSERT(1 == d->num_substreams);
5278 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
5279 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == e->sum_dep_weight);
5280 CU_ASSERT(0 == b->sum_dep_weight);
5281 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5282 CU_ASSERT(0 == d->sum_dep_weight);
5284 check_stream_dep_sib(a, NULL, e, NULL, NULL);
5285 check_stream_dep_sib(e, a, b, NULL, NULL);
5286 check_stream_dep_sib(b, e, NULL, NULL, c);
5287 check_stream_dep_sib(c, NULL, d, b, NULL);
5288 check_stream_dep_sib(d, c, NULL, NULL, NULL);
5290 CU_ASSERT(5 == session->roots.num_streams);
5291 CU_ASSERT(a == session->roots.head);
5292 CU_ASSERT(NULL == a->root_next);
5294 nghttp2_session_del(session);
5297 void test_nghttp2_session_stream_dep_remove(void) {
5298 nghttp2_session *session;
5299 nghttp2_session_callbacks callbacks;
5300 nghttp2_stream *a, *b, *c, *d, *e, *f;
5302 memset(&callbacks, 0, sizeof(callbacks));
5305 nghttp2_session_server_new(&session, &callbacks, NULL);
5307 a = open_stream(session, 1);
5308 b = open_stream_with_dep(session, 3, a);
5309 c = open_stream_with_dep(session, 5, a);
5310 d = open_stream_with_dep(session, 7, c);
5319 nghttp2_stream_dep_remove(a);
5327 CU_ASSERT(1 == a->num_substreams);
5328 CU_ASSERT(1 == b->num_substreams);
5329 CU_ASSERT(2 == c->num_substreams);
5330 CU_ASSERT(1 == d->num_substreams);
5332 CU_ASSERT(0 == a->sum_dep_weight);
5333 CU_ASSERT(0 == b->sum_dep_weight);
5334 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5335 CU_ASSERT(0 == d->sum_dep_weight);
5337 check_stream_dep_sib(a, NULL, NULL, NULL, NULL);
5338 check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
5339 check_stream_dep_sib(c, NULL, d, NULL, NULL);
5340 check_stream_dep_sib(d, c, NULL, NULL, NULL);
5342 CU_ASSERT(3 == session->roots.num_streams);
5343 CU_ASSERT(b == session->roots.head);
5344 CU_ASSERT(c == b->root_next);
5345 CU_ASSERT(NULL == c->root_next);
5347 nghttp2_session_del(session);
5349 /* Remove left most stream */
5350 nghttp2_session_server_new(&session, &callbacks, NULL);
5352 a = open_stream(session, 1);
5353 b = open_stream_with_dep(session, 3, a);
5354 c = open_stream_with_dep(session, 5, a);
5355 d = open_stream_with_dep(session, 7, c);
5364 nghttp2_stream_dep_remove(b);
5374 CU_ASSERT(3 == a->num_substreams);
5375 CU_ASSERT(1 == b->num_substreams);
5376 CU_ASSERT(2 == c->num_substreams);
5377 CU_ASSERT(1 == d->num_substreams);
5379 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
5380 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5381 CU_ASSERT(0 == d->sum_dep_weight);
5382 CU_ASSERT(0 == b->sum_dep_weight);
5384 check_stream_dep_sib(a, NULL, c, NULL, NULL);
5385 check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
5386 check_stream_dep_sib(c, a, d, NULL, NULL);
5387 check_stream_dep_sib(d, c, NULL, NULL, NULL);
5389 CU_ASSERT(3 == session->roots.num_streams);
5390 CU_ASSERT(a == session->roots.head);
5391 CU_ASSERT(NULL == a->root_next);
5393 nghttp2_session_del(session);
5395 /* Remove right most stream */
5396 nghttp2_session_server_new(&session, &callbacks, NULL);
5398 a = open_stream(session, 1);
5399 b = open_stream_with_dep(session, 3, a);
5400 c = open_stream_with_dep(session, 5, a);
5401 d = open_stream_with_dep(session, 7, c);
5410 nghttp2_stream_dep_remove(c);
5418 CU_ASSERT(3 == a->num_substreams);
5419 CU_ASSERT(1 == b->num_substreams);
5420 CU_ASSERT(1 == c->num_substreams);
5421 CU_ASSERT(1 == d->num_substreams);
5423 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
5424 CU_ASSERT(0 == b->sum_dep_weight);
5425 CU_ASSERT(0 == d->sum_dep_weight);
5426 CU_ASSERT(0 == c->sum_dep_weight);
5428 check_stream_dep_sib(a, NULL, d, NULL, NULL);
5429 check_stream_dep_sib(b, NULL, NULL, d, NULL);
5430 check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
5431 check_stream_dep_sib(d, a, NULL, NULL, b);
5433 nghttp2_session_del(session);
5435 /* Remove middle stream */
5436 nghttp2_session_server_new(&session, &callbacks, NULL);
5438 a = open_stream(session, 1);
5439 b = open_stream_with_dep(session, 3, a);
5440 c = open_stream_with_dep(session, 5, a);
5441 d = open_stream_with_dep(session, 7, a);
5442 e = open_stream_with_dep(session, 9, c);
5443 f = open_stream_with_dep(session, 11, c);
5452 CU_ASSERT(6 == a->num_substreams);
5453 CU_ASSERT(1 == b->num_substreams);
5454 CU_ASSERT(3 == c->num_substreams);
5455 CU_ASSERT(1 == d->num_substreams);
5456 CU_ASSERT(1 == e->num_substreams);
5457 CU_ASSERT(1 == f->num_substreams);
5459 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight);
5460 CU_ASSERT(0 == b->sum_dep_weight);
5461 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
5462 CU_ASSERT(0 == d->sum_dep_weight);
5463 CU_ASSERT(0 == e->sum_dep_weight);
5464 CU_ASSERT(0 == f->sum_dep_weight);
5466 nghttp2_stream_dep_remove(c);
5474 CU_ASSERT(5 == a->num_substreams);
5475 CU_ASSERT(1 == b->num_substreams);
5476 CU_ASSERT(1 == c->num_substreams);
5477 CU_ASSERT(1 == d->num_substreams);
5478 CU_ASSERT(1 == e->num_substreams);
5479 CU_ASSERT(1 == f->num_substreams);
5481 /* c's weight 16 is distributed evenly to e and f. Each weight of e
5483 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 + 8 * 2 == a->sum_dep_weight);
5484 CU_ASSERT(0 == b->sum_dep_weight);
5485 CU_ASSERT(0 == c->sum_dep_weight);
5486 CU_ASSERT(0 == d->sum_dep_weight);
5487 CU_ASSERT(0 == e->sum_dep_weight);
5488 CU_ASSERT(0 == f->sum_dep_weight);
5490 check_stream_dep_sib(a, NULL, d, NULL, NULL);
5491 check_stream_dep_sib(b, NULL, NULL, e, NULL);
5492 check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
5493 check_stream_dep_sib(e, NULL, NULL, f, b);
5494 check_stream_dep_sib(f, NULL, NULL, d, e);
5495 check_stream_dep_sib(d, a, NULL, NULL, f);
5497 nghttp2_session_del(session);
5500 void test_nghttp2_session_stream_dep_add_subtree(void) {
5501 nghttp2_session *session;
5502 nghttp2_session_callbacks callbacks;
5503 nghttp2_stream *a, *b, *c, *d, *e, *f;
5505 memset(&callbacks, 0, sizeof(callbacks));
5507 /* dep_stream has dep_next */
5508 nghttp2_session_server_new(&session, &callbacks, NULL);
5510 a = open_stream(session, 1);
5511 b = open_stream_with_dep(session, 3, a);
5512 c = open_stream_with_dep(session, 5, a);
5513 d = open_stream_with_dep(session, 7, c);
5515 e = open_stream(session, 9);
5516 f = open_stream_with_dep(session, 11, e);
5525 nghttp2_stream_dep_add_subtree(a, e, session);
5535 CU_ASSERT(6 == a->num_substreams);
5536 CU_ASSERT(1 == b->num_substreams);
5537 CU_ASSERT(2 == c->num_substreams);
5538 CU_ASSERT(1 == d->num_substreams);
5539 CU_ASSERT(2 == e->num_substreams);
5540 CU_ASSERT(1 == f->num_substreams);
5542 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight);
5543 CU_ASSERT(0 == b->sum_dep_weight);
5544 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5545 CU_ASSERT(0 == d->sum_dep_weight);
5546 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == e->sum_dep_weight);
5547 CU_ASSERT(0 == f->sum_dep_weight);
5549 check_stream_dep_sib(a, NULL, e, NULL, NULL);
5550 check_stream_dep_sib(b, NULL, NULL, c, NULL);
5551 check_stream_dep_sib(c, NULL, d, e, b);
5552 check_stream_dep_sib(d, c, NULL, NULL, NULL);
5553 check_stream_dep_sib(e, a, f, NULL, c);
5554 check_stream_dep_sib(f, e, NULL, NULL, NULL);
5556 nghttp2_session_del(session);
5558 /* dep_stream has dep_next and now we insert subtree */
5559 nghttp2_session_server_new(&session, &callbacks, NULL);
5561 a = open_stream(session, 1);
5562 b = open_stream_with_dep(session, 3, a);
5563 c = open_stream_with_dep(session, 5, a);
5564 d = open_stream_with_dep(session, 7, c);
5566 e = open_stream(session, 9);
5567 f = open_stream_with_dep(session, 11, e);
5576 nghttp2_stream_dep_insert_subtree(a, e, session);
5588 CU_ASSERT(6 == a->num_substreams);
5589 CU_ASSERT(1 == b->num_substreams);
5590 CU_ASSERT(2 == c->num_substreams);
5591 CU_ASSERT(1 == d->num_substreams);
5592 CU_ASSERT(5 == e->num_substreams);
5593 CU_ASSERT(1 == f->num_substreams);
5595 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
5596 CU_ASSERT(0 == b->sum_dep_weight);
5597 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5598 CU_ASSERT(0 == d->sum_dep_weight);
5599 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == e->sum_dep_weight);
5600 CU_ASSERT(0 == f->sum_dep_weight);
5602 check_stream_dep_sib(a, NULL, e, NULL, NULL);
5603 check_stream_dep_sib(e, a, f, NULL, NULL);
5604 check_stream_dep_sib(f, e, NULL, NULL, c);
5605 check_stream_dep_sib(b, NULL, NULL, c, NULL);
5606 check_stream_dep_sib(c, NULL, d, f, b);
5607 check_stream_dep_sib(d, c, NULL, NULL, NULL);
5609 nghttp2_session_del(session);
5612 void test_nghttp2_session_stream_dep_remove_subtree(void) {
5613 nghttp2_session *session;
5614 nghttp2_session_callbacks callbacks;
5615 nghttp2_stream *a, *b, *c, *d, *e;
5617 memset(&callbacks, 0, sizeof(callbacks));
5619 /* Remove left most stream */
5620 nghttp2_session_server_new(&session, &callbacks, NULL);
5622 a = open_stream(session, 1);
5623 b = open_stream_with_dep(session, 3, a);
5624 c = open_stream_with_dep(session, 5, a);
5625 d = open_stream_with_dep(session, 7, c);
5634 nghttp2_stream_dep_remove_subtree(c);
5642 CU_ASSERT(2 == a->num_substreams);
5643 CU_ASSERT(1 == b->num_substreams);
5644 CU_ASSERT(2 == c->num_substreams);
5645 CU_ASSERT(1 == d->num_substreams);
5647 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
5648 CU_ASSERT(0 == b->sum_dep_weight);
5649 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5650 CU_ASSERT(0 == d->sum_dep_weight);
5652 check_stream_dep_sib(a, NULL, b, NULL, NULL);
5653 check_stream_dep_sib(b, a, NULL, NULL, NULL);
5654 check_stream_dep_sib(c, NULL, d, NULL, NULL);
5655 check_stream_dep_sib(d, c, NULL, NULL, NULL);
5657 nghttp2_session_del(session);
5659 /* Remove right most stream */
5660 nghttp2_session_server_new(&session, &callbacks, NULL);
5662 a = open_stream(session, 1);
5663 b = open_stream_with_dep(session, 3, a);
5664 c = open_stream_with_dep(session, 5, a);
5665 d = open_stream_with_dep(session, 7, c);
5674 nghttp2_stream_dep_remove_subtree(b);
5684 CU_ASSERT(3 == a->num_substreams);
5685 CU_ASSERT(1 == b->num_substreams);
5686 CU_ASSERT(2 == c->num_substreams);
5687 CU_ASSERT(1 == d->num_substreams);
5689 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
5690 CU_ASSERT(0 == b->sum_dep_weight);
5691 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5692 CU_ASSERT(0 == d->sum_dep_weight);
5694 check_stream_dep_sib(a, NULL, c, NULL, NULL);
5695 check_stream_dep_sib(c, a, d, NULL, NULL);
5696 check_stream_dep_sib(d, c, NULL, NULL, NULL);
5697 check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
5699 nghttp2_session_del(session);
5701 /* Remove middle stream */
5702 nghttp2_session_server_new(&session, &callbacks, NULL);
5704 a = open_stream(session, 1);
5705 e = open_stream_with_dep(session, 9, a);
5706 c = open_stream_with_dep(session, 5, a);
5707 b = open_stream_with_dep(session, 3, a);
5708 d = open_stream_with_dep(session, 7, c);
5717 nghttp2_stream_dep_remove_subtree(c);
5725 CU_ASSERT(3 == a->num_substreams);
5726 CU_ASSERT(1 == b->num_substreams);
5727 CU_ASSERT(1 == e->num_substreams);
5728 CU_ASSERT(2 == c->num_substreams);
5729 CU_ASSERT(1 == d->num_substreams);
5731 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
5732 CU_ASSERT(0 == b->sum_dep_weight);
5733 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5734 CU_ASSERT(0 == d->sum_dep_weight);
5735 CU_ASSERT(0 == e->sum_dep_weight);
5737 check_stream_dep_sib(a, NULL, b, NULL, NULL);
5738 check_stream_dep_sib(b, a, NULL, NULL, e);
5739 check_stream_dep_sib(e, NULL, NULL, b, NULL);
5740 check_stream_dep_sib(c, NULL, d, NULL, NULL);
5741 check_stream_dep_sib(d, c, NULL, NULL, NULL);
5743 nghttp2_session_del(session);
5746 void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) {
5747 nghttp2_session *session;
5748 nghttp2_session_callbacks callbacks;
5749 nghttp2_stream *a, *b, *c, *d;
5751 memset(&callbacks, 0, sizeof(callbacks));
5753 nghttp2_session_server_new(&session, &callbacks, NULL);
5755 a = open_stream(session, 1);
5756 b = open_stream_with_dep(session, 3, a);
5758 c = open_stream(session, 5);
5765 nghttp2_stream_dep_remove_subtree(c);
5767 nghttp2_stream_dep_all_your_stream_are_belong_to_us(c, session));
5777 CU_ASSERT(3 == c->num_substreams);
5778 CU_ASSERT(2 == a->num_substreams);
5779 CU_ASSERT(1 == b->num_substreams);
5781 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5782 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
5783 CU_ASSERT(0 == b->sum_dep_weight);
5785 check_stream_dep_sib(c, NULL, a, NULL, NULL);
5786 check_stream_dep_sib(a, c, b, NULL, NULL);
5787 check_stream_dep_sib(b, a, NULL, NULL, NULL);
5789 nghttp2_session_del(session);
5791 nghttp2_session_server_new(&session, &callbacks, NULL);
5793 a = open_stream(session, 1);
5795 b = open_stream(session, 3);
5797 c = open_stream(session, 5);
5803 nghttp2_stream_dep_remove_subtree(c);
5805 nghttp2_stream_dep_all_your_stream_are_belong_to_us(c, session));
5813 CU_ASSERT(3 == c->num_substreams);
5814 CU_ASSERT(1 == a->num_substreams);
5815 CU_ASSERT(1 == b->num_substreams);
5817 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
5818 CU_ASSERT(0 == b->sum_dep_weight);
5819 CU_ASSERT(0 == a->sum_dep_weight);
5821 check_stream_dep_sib(c, NULL, b, NULL, NULL);
5822 check_stream_dep_sib(b, c, NULL, NULL, a);
5823 check_stream_dep_sib(a, NULL, NULL, b, NULL);
5825 nghttp2_session_del(session);
5827 nghttp2_session_server_new(&session, &callbacks, NULL);
5829 a = open_stream(session, 1);
5830 b = open_stream_with_dep(session, 3, a);
5832 c = open_stream(session, 5);
5833 d = open_stream_with_dep(session, 7, c);
5840 nghttp2_stream_dep_remove_subtree(c);
5842 nghttp2_stream_dep_all_your_stream_are_belong_to_us(c, session));
5852 CU_ASSERT(4 == c->num_substreams);
5853 CU_ASSERT(1 == d->num_substreams);
5854 CU_ASSERT(2 == a->num_substreams);
5855 CU_ASSERT(1 == b->num_substreams);
5857 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
5858 CU_ASSERT(0 == d->sum_dep_weight);
5859 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
5860 CU_ASSERT(0 == b->sum_dep_weight);
5862 check_stream_dep_sib(c, NULL, a, NULL, NULL);
5863 check_stream_dep_sib(d, NULL, NULL, a, NULL);
5864 check_stream_dep_sib(a, c, b, NULL, d);
5865 check_stream_dep_sib(b, a, NULL, NULL, NULL);
5867 nghttp2_session_del(session);
5870 void test_nghttp2_session_stream_attach_item(void) {
5871 nghttp2_session *session;
5872 nghttp2_session_callbacks callbacks;
5873 nghttp2_stream *a, *b, *c, *d;
5874 nghttp2_outbound_item *da, *db, *dc, *dd;
5876 memset(&callbacks, 0, sizeof(callbacks));
5878 nghttp2_session_server_new(&session, &callbacks, NULL);
5880 a = open_stream(session, 1);
5881 b = open_stream_with_dep(session, 3, a);
5882 c = open_stream_with_dep(session, 5, a);
5883 d = open_stream_with_dep(session, 7, c);
5892 db = create_data_ob_item();
5894 nghttp2_stream_attach_item(b, db, session);
5896 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
5897 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
5898 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
5899 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
5901 CU_ASSERT(16 == b->effective_weight);
5903 CU_ASSERT(16 == a->sum_norest_weight);
5905 CU_ASSERT(1 == db->queued);
5907 dc = create_data_ob_item();
5909 nghttp2_stream_attach_item(c, dc, session);
5911 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
5912 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
5913 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == c->dpri);
5914 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
5916 CU_ASSERT(16 * 16 / 32 == b->effective_weight);
5917 CU_ASSERT(16 * 16 / 32 == c->effective_weight);
5919 CU_ASSERT(32 == a->sum_norest_weight);
5921 CU_ASSERT(1 == dc->queued);
5923 da = create_data_ob_item();
5925 nghttp2_stream_attach_item(a, da, session);
5927 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == a->dpri);
5928 CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == b->dpri);
5929 CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == c->dpri);
5930 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
5932 CU_ASSERT(16 == a->effective_weight);
5934 CU_ASSERT(1 == da->queued);
5936 nghttp2_stream_detach_item(a, session);
5938 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
5939 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
5940 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == c->dpri);
5941 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
5943 CU_ASSERT(16 * 16 / 32 == b->effective_weight);
5944 CU_ASSERT(16 * 16 / 32 == c->effective_weight);
5946 dd = create_data_ob_item();
5948 nghttp2_stream_attach_item(d, dd, session);
5950 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
5951 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
5952 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == c->dpri);
5953 CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == d->dpri);
5955 CU_ASSERT(16 * 16 / 32 == b->effective_weight);
5956 CU_ASSERT(16 * 16 / 32 == c->effective_weight);
5958 CU_ASSERT(0 == dd->queued);
5960 nghttp2_stream_detach_item(c, session);
5962 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
5963 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
5964 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
5965 CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == d->dpri);
5967 CU_ASSERT(16 * 16 / 16 == b->effective_weight);
5969 CU_ASSERT(0 == dd->queued);
5971 nghttp2_stream_detach_item(b, session);
5973 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
5974 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == b->dpri);
5975 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
5976 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == d->dpri);
5978 CU_ASSERT(16 * 16 / 16 == d->effective_weight);
5980 CU_ASSERT(1 == dd->queued);
5982 nghttp2_session_del(session);
5985 void test_nghttp2_session_stream_attach_item_subtree(void) {
5986 nghttp2_session *session;
5987 nghttp2_session_callbacks callbacks;
5988 nghttp2_stream *a, *b, *c, *d, *e, *f;
5989 nghttp2_outbound_item *db, *dd, *de;
5991 memset(&callbacks, 0, sizeof(callbacks));
5993 nghttp2_session_server_new(&session, &callbacks, NULL);
5995 a = open_stream(session, 1);
5996 b = open_stream_with_dep(session, 3, a);
5997 c = open_stream_with_dep(session, 5, a);
5998 d = open_stream_with_dep(session, 7, c);
6000 e = open_stream(session, 9);
6001 f = open_stream_with_dep(session, 11, e);
6010 de = create_data_ob_item();
6012 nghttp2_stream_attach_item(e, de, session);
6014 db = create_data_ob_item();
6016 nghttp2_stream_attach_item(b, db, session);
6018 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6019 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6020 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6021 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
6022 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
6023 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
6025 CU_ASSERT(16 == b->effective_weight);
6026 CU_ASSERT(16 == e->effective_weight);
6028 /* Insert subtree e under a */
6030 nghttp2_stream_dep_remove_subtree(e);
6031 nghttp2_stream_dep_insert_subtree(a, e, session);
6043 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6044 CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == b->dpri);
6045 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6046 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
6047 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
6048 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
6050 CU_ASSERT(16 == e->effective_weight);
6052 /* Remove subtree b */
6054 nghttp2_stream_dep_remove_subtree(b);
6056 nghttp2_stream_dep_make_root(b, session);
6068 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6069 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6070 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6071 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
6072 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
6073 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
6075 CU_ASSERT(16 == b->effective_weight);
6076 CU_ASSERT(16 == e->effective_weight);
6078 /* Remove subtree a */
6080 nghttp2_stream_dep_remove_subtree(a);
6082 nghttp2_stream_dep_make_root(a, session);
6084 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6085 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6086 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6087 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
6088 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
6089 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
6091 /* Remove subtree c */
6093 nghttp2_stream_dep_remove_subtree(c);
6095 nghttp2_stream_dep_make_root(c, session);
6105 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6106 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6107 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6108 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
6109 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
6110 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
6112 dd = create_data_ob_item();
6114 nghttp2_stream_attach_item(d, dd, session);
6116 /* Add subtree c to a */
6118 nghttp2_stream_dep_remove_subtree(c);
6119 nghttp2_stream_dep_add_subtree(a, c, session);
6129 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6130 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6131 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6132 CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == d->dpri);
6133 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
6134 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
6136 CU_ASSERT(16 == b->effective_weight);
6137 CU_ASSERT(16 * 16 / 16 == e->effective_weight);
6139 CU_ASSERT(32 == a->sum_norest_weight);
6140 CU_ASSERT(16 == c->sum_norest_weight);
6142 /* Insert b under a */
6144 nghttp2_stream_dep_remove_subtree(b);
6145 nghttp2_stream_dep_insert_subtree(a, b, session);
6157 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6158 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6159 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6160 CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == d->dpri);
6161 CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == e->dpri);
6162 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
6164 CU_ASSERT(16 == b->effective_weight);
6166 CU_ASSERT(16 == a->sum_norest_weight);
6167 CU_ASSERT(0 == b->sum_norest_weight);
6169 /* Remove subtree b */
6171 nghttp2_stream_dep_remove_subtree(b);
6172 nghttp2_stream_dep_make_root(b, session);
6182 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6183 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6184 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6185 CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == d->dpri);
6186 CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == e->dpri);
6187 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
6189 CU_ASSERT(0 == a->sum_norest_weight);
6190 CU_ASSERT(0 == b->sum_norest_weight);
6192 nghttp2_session_del(session);
6195 void test_nghttp2_session_keep_closed_stream(void) {
6196 nghttp2_session *session;
6197 nghttp2_session_callbacks callbacks;
6198 const size_t max_concurrent_streams = 5;
6199 nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
6200 max_concurrent_streams};
6203 memset(&callbacks, 0, sizeof(callbacks));
6204 callbacks.send_callback = null_send_callback;
6206 nghttp2_session_server_new(&session, &callbacks, NULL);
6208 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
6210 for (i = 0; i < max_concurrent_streams; ++i) {
6211 open_stream(session, (int)i * 2 + 1);
6214 CU_ASSERT(0 == session->num_closed_streams);
6216 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
6218 CU_ASSERT(1 == session->num_closed_streams);
6219 CU_ASSERT(1 == session->closed_stream_tail->stream_id);
6220 CU_ASSERT(session->closed_stream_tail == session->closed_stream_head);
6222 nghttp2_session_close_stream(session, 5, NGHTTP2_NO_ERROR);
6224 CU_ASSERT(2 == session->num_closed_streams);
6225 CU_ASSERT(5 == session->closed_stream_tail->stream_id);
6226 CU_ASSERT(1 == session->closed_stream_head->stream_id);
6227 CU_ASSERT(session->closed_stream_head ==
6228 session->closed_stream_tail->closed_prev);
6229 CU_ASSERT(NULL == session->closed_stream_tail->closed_next);
6230 CU_ASSERT(session->closed_stream_tail ==
6231 session->closed_stream_head->closed_next);
6232 CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
6234 open_stream(session, 11);
6236 CU_ASSERT(1 == session->num_closed_streams);
6237 CU_ASSERT(5 == session->closed_stream_tail->stream_id);
6238 CU_ASSERT(session->closed_stream_tail == session->closed_stream_head);
6239 CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
6240 CU_ASSERT(NULL == session->closed_stream_head->closed_next);
6242 open_stream(session, 13);
6244 CU_ASSERT(0 == session->num_closed_streams);
6245 CU_ASSERT(NULL == session->closed_stream_tail);
6246 CU_ASSERT(NULL == session->closed_stream_head);
6248 nghttp2_session_del(session);
6251 void test_nghttp2_session_keep_idle_stream(void) {
6252 nghttp2_session *session;
6253 nghttp2_session_callbacks callbacks;
6254 const size_t max_concurrent_streams = 1;
6255 nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
6256 max_concurrent_streams};
6259 memset(&callbacks, 0, sizeof(callbacks));
6260 callbacks.send_callback = null_send_callback;
6262 nghttp2_session_server_new(&session, &callbacks, NULL);
6264 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
6266 /* We at least allow 2 idle streams even if max concurrent streams
6268 for (i = 0; i < 2; ++i) {
6269 nghttp2_session_open_stream(session, i * 2 + 1, NGHTTP2_STREAM_FLAG_NONE,
6270 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
6273 CU_ASSERT(2 == session->num_idle_streams);
6275 CU_ASSERT(1 == session->idle_stream_head->stream_id);
6276 CU_ASSERT(3 == session->idle_stream_tail->stream_id);
6278 nghttp2_session_open_stream(session, 5, NGHTTP2_FLAG_NONE, &pri_spec_default,
6279 NGHTTP2_STREAM_IDLE, NULL);
6281 CU_ASSERT(2 == session->num_idle_streams);
6283 CU_ASSERT(3 == session->idle_stream_head->stream_id);
6284 CU_ASSERT(5 == session->idle_stream_tail->stream_id);
6286 nghttp2_session_del(session);
6289 void test_nghttp2_session_detach_idle_stream(void) {
6290 nghttp2_session *session;
6291 nghttp2_session_callbacks callbacks;
6293 nghttp2_stream *stream;
6295 memset(&callbacks, 0, sizeof(callbacks));
6296 callbacks.send_callback = null_send_callback;
6298 nghttp2_session_server_new(&session, &callbacks, NULL);
6300 for (i = 1; i <= 3; ++i) {
6301 nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
6302 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
6305 CU_ASSERT(3 == session->num_idle_streams);
6307 /* Detach middle stream */
6308 stream = nghttp2_session_get_stream_raw(session, 2);
6310 CU_ASSERT(session->idle_stream_head == stream->closed_prev);
6311 CU_ASSERT(session->idle_stream_tail == stream->closed_next);
6312 CU_ASSERT(stream == session->idle_stream_head->closed_next);
6313 CU_ASSERT(stream == session->idle_stream_tail->closed_prev);
6315 nghttp2_session_detach_idle_stream(session, stream);
6317 CU_ASSERT(2 == session->num_idle_streams);
6319 CU_ASSERT(NULL == stream->closed_prev);
6320 CU_ASSERT(NULL == stream->closed_next);
6322 CU_ASSERT(session->idle_stream_head ==
6323 session->idle_stream_tail->closed_prev);
6324 CU_ASSERT(session->idle_stream_tail ==
6325 session->idle_stream_head->closed_next);
6327 /* Detach head stream */
6328 stream = session->idle_stream_head;
6330 nghttp2_session_detach_idle_stream(session, stream);
6332 CU_ASSERT(1 == session->num_idle_streams);
6334 CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
6335 CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
6336 CU_ASSERT(NULL == session->idle_stream_head->closed_next);
6338 /* Detach last stream */
6340 stream = session->idle_stream_head;
6342 nghttp2_session_detach_idle_stream(session, stream);
6344 CU_ASSERT(0 == session->num_idle_streams);
6346 CU_ASSERT(NULL == session->idle_stream_head);
6347 CU_ASSERT(NULL == session->idle_stream_tail);
6349 for (i = 4; i <= 5; ++i) {
6350 nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
6351 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
6354 CU_ASSERT(2 == session->num_idle_streams);
6356 /* Detach tail stream */
6358 stream = session->idle_stream_tail;
6360 nghttp2_session_detach_idle_stream(session, stream);
6362 CU_ASSERT(1 == session->num_idle_streams);
6364 CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
6365 CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
6366 CU_ASSERT(NULL == session->idle_stream_head->closed_next);
6368 nghttp2_session_del(session);
6371 void test_nghttp2_session_large_dep_tree(void) {
6372 nghttp2_session *session;
6373 nghttp2_session_callbacks callbacks;
6375 nghttp2_stream *dep_stream = NULL;
6376 nghttp2_stream *root_stream;
6379 memset(&callbacks, 0, sizeof(callbacks));
6380 callbacks.send_callback = null_send_callback;
6382 nghttp2_session_server_new(&session, &callbacks, NULL);
6385 for (i = 0; i < NGHTTP2_MAX_DEP_TREE_LENGTH; ++i) {
6386 dep_stream = open_stream_with_dep(session, stream_id, dep_stream);
6390 root_stream = nghttp2_session_get_stream(session, 1);
6392 /* Check that last dep_stream must be part of tree */
6393 CU_ASSERT(nghttp2_stream_dep_subtree_find(root_stream, dep_stream));
6395 dep_stream = open_stream_with_dep(session, stream_id, dep_stream);
6397 /* We exceeded NGHTTP2_MAX_DEP_TREE_LENGTH limit. dep_stream is now
6398 root node and has no descendants. */
6399 CU_ASSERT(!nghttp2_stream_dep_subtree_find(root_stream, dep_stream));
6400 CU_ASSERT(nghttp2_stream_in_dep_tree(dep_stream));
6402 nghttp2_session_del(session);
6405 void test_nghttp2_session_graceful_shutdown(void) {
6406 nghttp2_session *session;
6407 nghttp2_session_callbacks callbacks;
6410 memset(&callbacks, 0, sizeof(callbacks));
6411 callbacks.send_callback = null_send_callback;
6412 callbacks.on_frame_send_callback = on_frame_send_callback;
6413 callbacks.on_stream_close_callback = on_stream_close_callback;
6415 nghttp2_session_server_new(&session, &callbacks, &ud);
6417 open_stream(session, 301);
6418 open_stream(session, 302);
6419 open_stream(session, 309);
6420 open_stream(session, 311);
6421 open_stream(session, 319);
6423 CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
6425 ud.frame_send_cb_called = 0;
6427 CU_ASSERT(0 == nghttp2_session_send(session));
6429 CU_ASSERT(1 == ud.frame_send_cb_called);
6430 CU_ASSERT((1u << 31) - 1 == session->local_last_stream_id);
6432 CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 311,
6433 NGHTTP2_NO_ERROR, NULL, 0));
6435 ud.frame_send_cb_called = 0;
6436 ud.stream_close_cb_called = 0;
6438 CU_ASSERT(0 == nghttp2_session_send(session));
6440 CU_ASSERT(1 == ud.frame_send_cb_called);
6441 CU_ASSERT(311 == session->local_last_stream_id);
6442 CU_ASSERT(1 == ud.stream_close_cb_called);
6445 nghttp2_session_terminate_session2(session, 301, NGHTTP2_NO_ERROR));
6447 ud.frame_send_cb_called = 0;
6448 ud.stream_close_cb_called = 0;
6450 CU_ASSERT(0 == nghttp2_session_send(session));
6452 CU_ASSERT(1 == ud.frame_send_cb_called);
6453 CU_ASSERT(301 == session->local_last_stream_id);
6454 CU_ASSERT(2 == ud.stream_close_cb_called);
6456 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 301));
6457 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 302));
6458 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 309));
6459 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 311));
6460 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 319));
6462 nghttp2_session_del(session);
6465 void test_nghttp2_session_on_header_temporal_failure(void) {
6466 nghttp2_session *session;
6467 nghttp2_session_callbacks callbacks;
6471 nghttp2_hd_deflater deflater;
6472 nghttp2_nv nv[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
6476 nghttp2_frame frame;
6477 nghttp2_frame_hd hd;
6478 nghttp2_outbound_item *item;
6481 mem = nghttp2_mem_default();
6482 memset(&callbacks, 0, sizeof(callbacks));
6483 callbacks.on_header_callback = temporal_failure_on_header_callback;
6485 nghttp2_session_server_new(&session, &callbacks, &ud);
6487 frame_pack_bufs_init(&bufs);
6489 nghttp2_hd_deflate_init(&deflater, mem);
6491 nghttp2_nv_array_copy(&nva, nv, 1, mem);
6493 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_STREAM, 1,
6494 NGHTTP2_HCAT_REQUEST, NULL, nva, 1);
6495 nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
6496 nghttp2_frame_headers_free(&frame.headers, mem);
6498 /* We are going to create CONTINUATION. First serialize header
6499 block, and then frame header. */
6500 hdpos = nghttp2_bufs_len(&bufs);
6502 buf = &bufs.head->buf;
6503 buf->last += NGHTTP2_FRAME_HDLEN;
6505 nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv[1], 1);
6507 nghttp2_frame_hd_init(&hd,
6508 nghttp2_bufs_len(&bufs) - hdpos - NGHTTP2_FRAME_HDLEN,
6509 NGHTTP2_CONTINUATION, NGHTTP2_FLAG_END_HEADERS, 1);
6511 nghttp2_frame_pack_frame_hd(&buf->pos[hdpos], &hd);
6513 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_bufs_len(&bufs));
6515 CU_ASSERT(rv == nghttp2_bufs_len(&bufs));
6517 item = nghttp2_session_get_next_ob_item(session);
6519 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
6521 /* Make sure no header decompression error occurred */
6522 CU_ASSERT(NGHTTP2_GOAWAY_NONE == session->goaway_flags);
6524 nghttp2_bufs_free(&bufs);
6526 nghttp2_hd_deflate_free(&deflater);
6527 nghttp2_session_del(session);
6530 void test_nghttp2_session_recv_client_preface(void) {
6531 nghttp2_session *session;
6532 nghttp2_session_callbacks callbacks;
6533 nghttp2_option *option;
6535 nghttp2_frame ping_frame;
6538 memset(&callbacks, 0, sizeof(callbacks));
6540 nghttp2_option_new(&option);
6541 nghttp2_option_set_recv_client_preface(option, 1);
6543 /* Check success case */
6544 nghttp2_session_server_new2(&session, &callbacks, NULL, option);
6546 CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_RECV_CLIENT_PREFACE);
6548 rv = nghttp2_session_mem_recv(
6549 session, (const uint8_t *)NGHTTP2_CLIENT_CONNECTION_PREFACE,
6550 NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
6552 CU_ASSERT(rv == NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
6553 CU_ASSERT(NGHTTP2_IB_READ_FIRST_SETTINGS == session->iframe.state);
6555 /* Receiving PING is error */
6556 nghttp2_frame_ping_init(&ping_frame.ping, NGHTTP2_FLAG_NONE, NULL);
6558 nghttp2_frame_pack_frame_hd(buf, &ping_frame.ping.hd);
6560 rv = nghttp2_session_mem_recv(session, buf, NGHTTP2_FRAME_HDLEN);
6561 CU_ASSERT(NGHTTP2_FRAME_HDLEN == rv);
6562 CU_ASSERT(NGHTTP2_IB_IGN_PAYLOAD == session->iframe.state);
6563 CU_ASSERT(8 == session->iframe.payloadleft);
6565 nghttp2_frame_ping_free(&ping_frame.ping);
6567 nghttp2_session_del(session);
6569 /* Check bad case */
6570 nghttp2_session_server_new2(&session, &callbacks, NULL, option);
6572 /* Feed preface with one byte less */
6573 rv = nghttp2_session_mem_recv(
6574 session, (const uint8_t *)NGHTTP2_CLIENT_CONNECTION_PREFACE,
6575 NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN - 1);
6577 CU_ASSERT(rv == NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN - 1);
6578 CU_ASSERT(NGHTTP2_IB_READ_CLIENT_PREFACE == session->iframe.state);
6579 CU_ASSERT(1 == session->iframe.payloadleft);
6581 rv = nghttp2_session_mem_recv(session, (const uint8_t *)"\0", 1);
6583 CU_ASSERT(NGHTTP2_ERR_BAD_PREFACE == rv);
6585 nghttp2_session_del(session);
6587 nghttp2_option_del(option);
6590 void test_nghttp2_session_delete_data_item(void) {
6591 nghttp2_session *session;
6592 nghttp2_session_callbacks callbacks;
6594 nghttp2_data_provider prd;
6596 memset(&callbacks, 0, sizeof(callbacks));
6598 nghttp2_session_server_new(&session, &callbacks, NULL);
6600 a = open_stream(session, 1);
6601 open_stream_with_dep(session, 3, a);
6603 /* We don't care about these members, since we won't send data */
6604 prd.source.ptr = NULL;
6605 prd.read_callback = fail_data_source_read_callback;
6607 /* This data item will be marked as TOP */
6608 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &prd));
6609 /* This data item will be marked as REST */
6610 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 3, &prd));
6612 nghttp2_session_del(session);
6615 void test_nghttp2_session_open_idle_stream(void) {
6616 nghttp2_session *session;
6617 nghttp2_session_callbacks callbacks;
6618 nghttp2_stream *stream;
6619 nghttp2_stream *opened_stream;
6620 nghttp2_priority_spec pri_spec;
6621 nghttp2_frame frame;
6623 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6625 nghttp2_session_server_new(&session, &callbacks, NULL);
6627 nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
6629 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
6631 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
6633 stream = nghttp2_session_get_stream_raw(session, 1);
6635 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
6636 CU_ASSERT(NULL == stream->closed_prev);
6637 CU_ASSERT(NULL == stream->closed_next);
6638 CU_ASSERT(1 == session->num_idle_streams);
6639 CU_ASSERT(session->idle_stream_head == stream);
6640 CU_ASSERT(session->idle_stream_tail == stream);
6642 opened_stream = nghttp2_session_open_stream(
6643 session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
6644 NGHTTP2_STREAM_OPENING, NULL);
6646 CU_ASSERT(stream == opened_stream);
6647 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
6648 CU_ASSERT(0 == session->num_idle_streams);
6649 CU_ASSERT(NULL == session->idle_stream_head);
6650 CU_ASSERT(NULL == session->idle_stream_tail);
6652 nghttp2_frame_priority_free(&frame.priority);
6654 nghttp2_session_del(session);