2 * nghttp2 - HTTP/2 C Library
4 * Copyright (c) 2012, 2014 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 "failmalloc_test.h"
27 #include <CUnit/CUnit.h>
32 #include "nghttp2_session.h"
33 #include "nghttp2_stream.h"
34 #include "nghttp2_frame.h"
35 #include "nghttp2_helper.h"
36 #include "malloc_wrapper.h"
37 #include "nghttp2_test_helper.h"
41 uint8_t *datamark, *datalimit;
46 size_t data_source_length;
49 static void data_feed_init(data_feed *df, nghttp2_bufs *bufs) {
53 buf = &bufs->head->buf;
54 data_length = nghttp2_buf_len(buf);
56 assert(data_length <= sizeof(df->data));
57 memcpy(df->data, buf->pos, data_length);
58 df->datamark = df->data;
59 df->datalimit = df->data + data_length;
62 static ssize_t null_send_callback(nghttp2_session *session _U_,
63 const uint8_t *data _U_, size_t len,
64 int flags _U_, void *user_data _U_) {
68 static ssize_t data_feed_recv_callback(nghttp2_session *session _U_,
69 uint8_t *data, size_t len, int flags _U_,
71 data_feed *df = ((my_user_data *)user_data)->df;
72 size_t avail = df->datalimit - df->datamark;
73 size_t wlen = nghttp2_min(avail, len);
74 memcpy(data, df->datamark, wlen);
79 static ssize_t fixed_length_data_source_read_callback(
80 nghttp2_session *session _U_, int32_t stream_id _U_, uint8_t *buf _U_,
81 size_t len, uint32_t *data_flags, nghttp2_data_source *source _U_,
83 my_user_data *ud = (my_user_data *)user_data;
85 if (len < ud->data_source_length) {
88 wlen = ud->data_source_length;
90 ud->data_source_length -= wlen;
91 if (ud->data_source_length == 0) {
92 *data_flags = NGHTTP2_DATA_FLAG_EOF;
97 #define TEST_FAILMALLOC_RUN(FUN) \
101 nghttp2_failmalloc = 0; \
102 nghttp2_nmalloc = 0; \
104 nmalloc = nghttp2_nmalloc; \
106 nghttp2_failmalloc = 1; \
107 for (i = 0; i < nmalloc; ++i) { \
108 nghttp2_nmalloc = 0; \
109 nghttp2_failstart = i; \
110 /* printf("i=%zu\n", i); */ \
112 /* printf("nmalloc=%d\n", nghttp2_nmalloc); */ \
114 nghttp2_failmalloc = 0; \
117 static void run_nghttp2_session_send(void) {
118 nghttp2_session *session;
119 nghttp2_session_callbacks callbacks;
120 nghttp2_nv nv[] = {MAKE_NV(":host", "example.org"),
121 MAKE_NV(":scheme", "https")};
122 nghttp2_data_provider data_prd;
123 nghttp2_settings_entry iv[2];
126 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
127 callbacks.send_callback = null_send_callback;
129 data_prd.read_callback = fixed_length_data_source_read_callback;
130 ud.data_source_length = 64 * 1024;
132 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
134 iv[1].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
137 rv = nghttp2_session_client_new3(&session, &callbacks, &ud, NULL,
140 goto client_new_fail;
142 rv = nghttp2_submit_request(session, NULL, nv, ARRLEN(nv), &data_prd, NULL);
146 rv = nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL, nv,
151 rv = nghttp2_session_send(session);
155 /* The HEADERS submitted by the previous nghttp2_submit_headers will
156 have stream ID 3. Send HEADERS to that stream. */
157 rv = nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 3, NULL, nv,
162 rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 3, &data_prd);
166 rv = nghttp2_session_send(session);
170 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 3, NGHTTP2_CANCEL);
174 rv = nghttp2_session_send(session);
178 /* Sending against half-closed stream */
179 rv = nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 3, NULL, nv,
184 rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 3, &data_prd);
188 rv = nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
192 rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 2);
196 rv = nghttp2_session_send(session);
200 rv = nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 100, NGHTTP2_NO_ERROR,
205 rv = nghttp2_session_send(session);
211 nghttp2_session_del(session);
216 void test_nghttp2_session_send(void) {
217 TEST_FAILMALLOC_RUN(run_nghttp2_session_send);
220 static void run_nghttp2_session_recv(void) {
221 nghttp2_session *session;
222 nghttp2_session_callbacks callbacks;
223 nghttp2_hd_deflater deflater;
226 nghttp2_nv nv[] = {MAKE_NV(":authority", "example.org"),
227 MAKE_NV(":scheme", "https")};
228 nghttp2_settings_entry iv[2];
235 rv = frame_pack_bufs_init(&bufs);
241 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
242 callbacks.recv_callback = data_feed_recv_callback;
245 nghttp2_failmalloc_pause();
247 nghttp2_nv_array_copy(&nva, nv, nvlen, nghttp2_mem_fm());
248 nghttp2_hd_deflate_init(&deflater, nghttp2_mem_fm());
249 nghttp2_session_server_new3(&session, &callbacks, &ud, NULL,
251 nghttp2_failmalloc_unpause();
254 nghttp2_failmalloc_pause();
255 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_STREAM, 1,
256 NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
257 nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
258 nghttp2_frame_headers_free(&frame.headers, nghttp2_mem_fm());
259 data_feed_init(&df, &bufs);
260 nghttp2_bufs_reset(&bufs);
262 nghttp2_failmalloc_unpause();
264 rv = nghttp2_session_recv(session);
270 nghttp2_failmalloc_pause();
271 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
272 nghttp2_frame_pack_ping(&bufs, &frame.ping);
273 nghttp2_frame_ping_free(&frame.ping);
274 data_feed_init(&df, &bufs);
275 nghttp2_bufs_reset(&bufs);
277 nghttp2_failmalloc_unpause();
279 rv = nghttp2_session_recv(session);
285 nghttp2_failmalloc_pause();
286 nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_PROTOCOL_ERROR);
287 nghttp2_frame_pack_rst_stream(&bufs, &frame.rst_stream);
288 nghttp2_frame_rst_stream_free(&frame.rst_stream);
289 nghttp2_bufs_reset(&bufs);
291 nghttp2_failmalloc_unpause();
293 rv = nghttp2_session_recv(session);
299 nghttp2_failmalloc_pause();
300 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
302 iv[1].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
304 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE,
305 nghttp2_frame_iv_copy(iv, 2, nghttp2_mem_fm()),
307 nghttp2_frame_pack_settings(&bufs, &frame.settings);
308 nghttp2_frame_settings_free(&frame.settings, nghttp2_mem_fm());
309 nghttp2_bufs_reset(&bufs);
311 nghttp2_failmalloc_unpause();
313 rv = nghttp2_session_recv(session);
319 nghttp2_bufs_free(&bufs);
320 nghttp2_session_del(session);
321 nghttp2_hd_deflate_free(&deflater);
324 void test_nghttp2_session_recv(void) {
325 TEST_FAILMALLOC_RUN(run_nghttp2_session_recv);
328 static void run_nghttp2_frame_pack_headers(void) {
329 nghttp2_hd_deflater deflater;
330 nghttp2_hd_inflater inflater;
331 nghttp2_frame frame, oframe;
333 nghttp2_nv nv[] = {MAKE_NV(":host", "example.org"),
334 MAKE_NV(":scheme", "https")};
339 rv = frame_pack_bufs_init(&bufs);
345 rv = nghttp2_hd_deflate_init(&deflater, nghttp2_mem_fm());
347 goto deflate_init_fail;
349 rv = nghttp2_hd_inflate_init(&inflater, nghttp2_mem_fm());
351 goto inflate_init_fail;
354 rv = nghttp2_nv_array_copy(&nva, nv, nvlen, nghttp2_mem_fm());
358 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_STREAM, 1,
359 NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
360 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
364 rv = unpack_framebuf(&oframe, &bufs);
368 nghttp2_frame_headers_free(&oframe.headers, nghttp2_mem_fm());
371 nghttp2_frame_headers_free(&frame.headers, nghttp2_mem_fm());
373 nghttp2_hd_inflate_free(&inflater);
375 nghttp2_hd_deflate_free(&deflater);
377 nghttp2_bufs_free(&bufs);
380 static void run_nghttp2_frame_pack_settings(void) {
381 nghttp2_frame frame, oframe;
384 nghttp2_settings_entry iv[2], *iv_copy;
387 rv = frame_pack_bufs_init(&bufs);
393 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
395 iv[1].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
398 iv_copy = nghttp2_frame_iv_copy(iv, 2, nghttp2_mem_fm());
400 if (iv_copy == NULL) {
404 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, iv_copy, 2);
406 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
412 buf = &bufs.head->buf;
414 rv = nghttp2_frame_unpack_settings_payload2(
415 &oframe.settings.iv, &oframe.settings.niv, buf->pos + NGHTTP2_FRAME_HDLEN,
416 nghttp2_buf_len(buf) - NGHTTP2_FRAME_HDLEN, nghttp2_mem_fm());
421 nghttp2_frame_settings_free(&oframe.settings, nghttp2_mem_fm());
424 nghttp2_frame_settings_free(&frame.settings, nghttp2_mem_fm());
426 nghttp2_bufs_free(&bufs);
429 void test_nghttp2_frame(void) {
430 TEST_FAILMALLOC_RUN(run_nghttp2_frame_pack_headers);
431 TEST_FAILMALLOC_RUN(run_nghttp2_frame_pack_settings);
434 static int deflate_inflate(nghttp2_hd_deflater *deflater,
435 nghttp2_hd_inflater *inflater, nghttp2_bufs *bufs,
436 nghttp2_nv *nva, size_t nvlen) {
439 rv = nghttp2_hd_deflate_hd_bufs(deflater, bufs, nva, nvlen);
445 rv = (int)inflate_hd(inflater, NULL, bufs, 0);
451 nghttp2_bufs_reset(bufs);
456 static void run_nghttp2_hd(void) {
457 nghttp2_hd_deflater deflater;
458 nghttp2_hd_inflater inflater;
461 nghttp2_nv nva1[] = {MAKE_NV(":scheme", "https"),
462 MAKE_NV(":authority", "example.org"),
463 MAKE_NV(":path", "/slashdot"),
464 MAKE_NV("accept-encoding", "gzip, deflate")};
465 nghttp2_nv nva2[] = {
466 MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "example.org"),
467 MAKE_NV(":path", "/style.css"), MAKE_NV("cookie", "nghttp2=FTW")};
469 rv = frame_pack_bufs_init(&bufs);
475 rv = nghttp2_hd_deflate_init(&deflater, nghttp2_mem_fm());
478 goto deflate_init_fail;
481 rv = nghttp2_hd_inflate_init(&inflater, nghttp2_mem_fm());
484 goto inflate_init_fail;
487 rv = deflate_inflate(&deflater, &inflater, &bufs, nva1, ARRLEN(nva1));
490 goto deflate_hd_fail;
493 rv = deflate_inflate(&deflater, &inflater, &bufs, nva2, ARRLEN(nva2));
496 goto deflate_hd_fail;
500 nghttp2_hd_inflate_free(&inflater);
502 nghttp2_hd_deflate_free(&deflater);
504 nghttp2_bufs_free(&bufs);
507 void test_nghttp2_hd(void) { TEST_FAILMALLOC_RUN(run_nghttp2_hd); }