Add tests. Move around code a little.

This commit is contained in:
Lucas Pardue 2017-04-25 15:48:52 +01:00
parent fbc1e17f7b
commit 89d6d43c70
9 changed files with 371 additions and 92 deletions

View File

@ -196,26 +196,6 @@ void nghttp2_frame_extension_init(nghttp2_extension *frame, uint8_t type,
void nghttp2_frame_extension_free(nghttp2_extension *frame) { (void)frame; }
void nghttp2_frame_origin_init(nghttp2_extension *frame, uint8_t *origin,
size_t origin_len) {
nghttp2_ext_origin *origin_frame;
/* Always send ORIGIN frame on stream 0 */
nghttp2_frame_hd_init(&frame->hd, 2 + origin_len, NGHTTP2_ORIGIN,
NGHTTP2_FLAG_NONE, 0);
origin_frame = frame->payload;
origin_frame->origin = origin;
origin_frame->origin_len = origin_len;
}
void nghttp2_frame_origin_free(nghttp2_extension *frame, nghttp2_mem *mem) {
nghttp2_ext_origin *origin_frame;
origin_frame = frame->payload;
nghttp2_mem_free(mem, origin_frame->origin);
}
void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id,
uint8_t *origin, size_t origin_len,
uint8_t *field_value, size_t field_value_len) {
@ -248,6 +228,26 @@ size_t nghttp2_frame_priority_len(uint8_t flags) {
return 0;
}
void nghttp2_frame_origin_init(nghttp2_extension *frame, uint8_t *origin,
size_t origin_len) {
nghttp2_ext_origin *origin_frame;
/* Always send ORIGIN frame on stream 0 */
nghttp2_frame_hd_init(&frame->hd, 2 + origin_len, NGHTTP2_ORIGIN,
NGHTTP2_FLAG_NONE, 0);
origin_frame = frame->payload;
origin_frame->origin = origin;
origin_frame->origin_len = origin_len;
}
void nghttp2_frame_origin_free(nghttp2_extension *frame, nghttp2_mem *mem) {
nghttp2_ext_origin *origin_frame;
origin_frame = frame->payload;
nghttp2_mem_free(mem, origin_frame->origin);
}
size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame) {
return nghttp2_frame_priority_len(frame->hd.flags);
}

View File

@ -86,6 +86,9 @@ void nghttp2_outbound_item_free(nghttp2_outbound_item *item, nghttp2_mem *mem) {
case NGHTTP2_ALTSVC:
nghttp2_frame_altsvc_free(&frame->ext, mem);
break;
case NGHTTP2_ORIGIN:
nghttp2_frame_origin_free(&frame->ext, mem);
break;
default:
assert(0);
break;

View File

@ -4898,7 +4898,7 @@ static int session_process_origin_frame(nghttp2_session *session) {
&frame->ext, nghttp2_get_uint16(iframe->sbuf.pos), iframe->lbuf.pos,
nghttp2_buf_len(&iframe->lbuf));
/* nghttp2_frame_unpack_altsvc_payload steals buffer from
/* nghttp2_frame_unpack_origin_payload steals buffer from
iframe->lbuf */
nghttp2_buf_wrap_init(&iframe->lbuf, NULL, 0);

View File

@ -486,76 +486,6 @@ int nghttp2_session_set_local_window_size(nghttp2_session *session,
return 0;
}
int nghttp2_submit_origin(nghttp2_session *session, uint8_t flags,
const uint8_t *origin, size_t origin_len) {
nghttp2_mem *mem;
uint8_t *buf, *p;
uint8_t *origin_copy;
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_ext_origin *origin_frame;
int rv;
(void)flags;
mem = &session->mem;
if (!session->server) {
return NGHTTP2_ERR_INVALID_STATE;
}
if (2 + origin_len > NGHTTP2_MAX_PAYLOADLEN) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
buf = nghttp2_mem_malloc(mem, origin_len + 2);
if (buf == NULL) {
return NGHTTP2_ERR_NOMEM;
}
p = buf;
origin_copy = p;
if (origin_len) {
p = nghttp2_cpymem(p, origin, origin_len);
}
*p++ = '\0';
item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
if (item == NULL) {
rv = NGHTTP2_ERR_NOMEM;
goto fail_item_malloc;
}
nghttp2_outbound_item_init(item);
item->aux_data.ext.builtin = 1;
origin_frame = &item->ext_frame_payload.origin;
frame = &item->frame;
frame->ext.payload = origin_frame;
//
// nghttp2_frame_altsvc_init(&frame->ext, stream_id, origin_copy, origin_len,
// field_value_copy, field_value_len);
nghttp2_frame_origin_init(&frame->ext, origin_copy, origin_len);
rv = nghttp2_session_add_item(session, item);
if (rv != 0) {
nghttp2_frame_altsvc_free(&frame->ext, mem);
nghttp2_mem_free(mem, item);
return rv;
}
return 0;
fail_item_malloc:
free(buf);
return rv;
}
int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags,
int32_t stream_id, const uint8_t *origin,
size_t origin_len, const uint8_t *field_value,
@ -641,6 +571,73 @@ fail_item_malloc:
return rv;
}
int nghttp2_submit_origin(nghttp2_session *session, uint8_t flags,
const uint8_t *origin, size_t origin_len) {
nghttp2_mem *mem;
uint8_t *buf, *p;
uint8_t *origin_copy;
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_ext_origin *origin_frame;
int rv;
(void)flags;
mem = &session->mem;
if (!session->server) {
return NGHTTP2_ERR_INVALID_STATE;
}
if (2 + origin_len > NGHTTP2_MAX_PAYLOADLEN) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
buf = nghttp2_mem_malloc(mem, origin_len + 2);
if (buf == NULL) {
return NGHTTP2_ERR_NOMEM;
}
p = buf;
origin_copy = p;
if (origin_len) {
p = nghttp2_cpymem(p, origin, origin_len);
}
*p++ = '\0';
item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
if (item == NULL) {
rv = NGHTTP2_ERR_NOMEM;
goto fail_item_malloc;
}
nghttp2_outbound_item_init(item);
item->aux_data.ext.builtin = 1;
origin_frame = &item->ext_frame_payload.origin;
frame = &item->frame;
frame->ext.payload = origin_frame;
nghttp2_frame_origin_init(&frame->ext, origin_copy, origin_len);
rv = nghttp2_session_add_item(session, item);
if (rv != 0) {
nghttp2_frame_altsvc_free(&frame->ext, mem);
nghttp2_mem_free(mem, item);
return rv;
}
return 0;
fail_item_malloc:
free(buf);
return rv;
}
static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
const nghttp2_data_provider *data_prd) {
uint8_t flags = NGHTTP2_FLAG_NONE;

View File

@ -106,6 +106,8 @@ std::string strframetype(uint8_t type) {
return "WINDOW_UPDATE";
case NGHTTP2_ALTSVC:
return "ALTSVC";
case NGHTTP2_ORIGIN:
return "ORIGIN";
}
std::string s = "extension(0x";
@ -350,10 +352,16 @@ void print_frame(print_type ptype, const nghttp2_frame *frame) {
static_cast<int>(altsvc->field_value_len), altsvc->field_value);
break;
}
case NGHTTP2_ORIGIN: {
auto origin_frame = static_cast<nghttp2_ext_origin *>(frame->ext.payload);
print_frame_attr_indent();
fprintf(outfile, "(origin=[%.*s])\n",
static_cast<int>(origin_frame->origin_len), origin_frame->origin);
break;
}
default:
break;
}
}
} // namespace
int verbose_on_header_callback(nghttp2_session *session,

View File

@ -105,6 +105,8 @@ int main() {
test_nghttp2_session_recv_extension) ||
!CU_add_test(pSuite, "session_recv_altsvc",
test_nghttp2_session_recv_altsvc) ||
!CU_add_test(pSuite, "session_recv_origin",
test_nghttp2_session_recv_origin) ||
!CU_add_test(pSuite, "session_continue", test_nghttp2_session_continue) ||
!CU_add_test(pSuite, "session_add_frame",
test_nghttp2_session_add_frame) ||
@ -136,6 +138,8 @@ int main() {
test_nghttp2_session_on_data_received_fail_fast) ||
!CU_add_test(pSuite, "session_on_altsvc_received",
test_nghttp2_session_on_altsvc_received) ||
!CU_add_test(pSuite, "session_on_origin_received",
test_nghttp2_session_on_origin_received) ||
!CU_add_test(pSuite, "session_send_headers_start_stream",
test_nghttp2_session_send_headers_start_stream) ||
!CU_add_test(pSuite, "session_send_headers_reply",
@ -204,6 +208,7 @@ int main() {
test_nghttp2_submit_invalid_nv) ||
!CU_add_test(pSuite, "submit_extension", test_nghttp2_submit_extension) ||
!CU_add_test(pSuite, "submit_altsvc", test_nghttp2_submit_altsvc) ||
!CU_add_test(pSuite, "submit_origin", test_nghttp2_submit_origin) ||
!CU_add_test(pSuite, "session_open_stream",
test_nghttp2_session_open_stream) ||
!CU_add_test(pSuite, "session_open_stream_with_idle_stream_dep",
@ -353,6 +358,8 @@ int main() {
test_nghttp2_frame_pack_window_update) ||
!CU_add_test(pSuite, "frame_pack_altsvc",
test_nghttp2_frame_pack_altsvc) ||
!CU_add_test(pSuite, "frame_pack_origin",
test_nghttp2_frame_pack_origin) ||
!CU_add_test(pSuite, "nv_array_copy", test_nghttp2_nv_array_copy) ||
!CU_add_test(pSuite, "iv_check", test_nghttp2_iv_check) ||
!CU_add_test(pSuite, "hd_deflate", test_nghttp2_hd_deflate) ||

View File

@ -508,6 +508,53 @@ void test_nghttp2_frame_pack_altsvc(void) {
nghttp2_bufs_free(&bufs);
}
void test_nghttp2_frame_pack_origin(void) {
nghttp2_extension frame, oframe;
nghttp2_ext_origin origin_frame, oorigin_frame;
nghttp2_bufs bufs;
int rv;
size_t payloadlen;
static const uint8_t origin[] = "www.nghttp2.org";
nghttp2_buf buf;
uint8_t *rawbuf;
nghttp2_mem *mem;
mem = nghttp2_mem_default();
frame_pack_bufs_init(&bufs);
frame.payload = &origin_frame;
oframe.payload = &oorigin_frame;
rawbuf = nghttp2_mem_malloc(mem, 32);
nghttp2_buf_wrap_init(&buf, rawbuf, 32);
buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
nghttp2_frame_origin_init(&frame, buf.pos, sizeof(origin) - 1);
payloadlen = 2 + sizeof(origin) - 1;
rv = nghttp2_frame_pack_origin(&bufs, &frame);
CU_ASSERT(0 == rv);
CU_ASSERT(NGHTTP2_FRAME_HDLEN + payloadlen == nghttp2_bufs_len(&bufs));
rv = unpack_framebuf((nghttp2_frame *)&oframe, &bufs);
CU_ASSERT(0 == rv);
check_frame_header(payloadlen, NGHTTP2_ORIGIN, NGHTTP2_FLAG_NONE, 0,
&oframe.hd);
CU_ASSERT(sizeof(origin) - 1 == oorigin_frame.origin_len);
CU_ASSERT(0 == memcmp(origin, oorigin_frame.origin, sizeof(origin) - 1));
nghttp2_frame_origin_free(&oframe, mem);
nghttp2_frame_origin_free(&frame, mem);
nghttp2_bufs_free(&bufs);
}
void test_nghttp2_nv_array_copy(void) {
nghttp2_nv *nva;
ssize_t rv;

View File

@ -2321,6 +2321,121 @@ void test_nghttp2_session_recv_altsvc(void) {
nghttp2_option_del(option);
}
void test_nghttp2_session_recv_origin(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
my_user_data ud;
nghttp2_buf buf;
nghttp2_frame_hd hd;
nghttp2_mem *mem;
ssize_t rv;
nghttp2_option *option;
static const uint8_t origin[] = "www.nghttp2.org";
mem = nghttp2_mem_default();
nghttp2_buf_init2(&buf, NGHTTP2_FRAME_HDLEN + NGHTTP2_MAX_FRAME_SIZE_MIN,
mem);
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.on_frame_recv_callback = on_frame_recv_callback;
nghttp2_option_new(&option);
nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ORIGIN);
nghttp2_session_client_new2(&session, &callbacks, &ud, option);
nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1, NGHTTP2_ORIGIN,
NGHTTP2_FLAG_NONE, 0);
nghttp2_frame_pack_frame_hd(buf.last, &hd);
buf.last += NGHTTP2_FRAME_HDLEN;
nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
buf.last += 2;
buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
CU_ASSERT(1 == ud.frame_recv_cb_called);
CU_ASSERT(NGHTTP2_ORIGIN == ud.recv_frame_hd.type);
CU_ASSERT(NGHTTP2_FLAG_NONE == ud.recv_frame_hd.flags);
CU_ASSERT(0 == ud.recv_frame_hd.stream_id);
nghttp2_session_del(session);
/* size of origin is larger than frame length */
nghttp2_buf_reset(&buf);
nghttp2_session_client_new2(&session, &callbacks, &ud, option);
nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 - 1, NGHTTP2_ORIGIN,
NGHTTP2_FLAG_NONE, 0);
nghttp2_frame_pack_frame_hd(buf.last, &hd);
buf.last += NGHTTP2_FRAME_HDLEN;
nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
buf.last += 2;
buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1 - 1);
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
CU_ASSERT(0 == ud.frame_recv_cb_called);
nghttp2_session_del(session);
/* send large frame (16KiB) */
nghttp2_buf_reset(&buf);
nghttp2_session_client_new2(&session, &callbacks, &ud, option);
nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN, NGHTTP2_ORIGIN,
NGHTTP2_FLAG_NONE, 0);
nghttp2_frame_pack_frame_hd(buf.last, &hd);
buf.last += NGHTTP2_FRAME_HDLEN;
nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
buf.last += 2;
buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
memset(buf.last, 0, nghttp2_buf_avail(&buf));
buf.last += nghttp2_buf_avail(&buf);
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
CU_ASSERT(1 == ud.frame_recv_cb_called);
CU_ASSERT(NGHTTP2_ORIGIN == ud.recv_frame_hd.type);
CU_ASSERT(NGHTTP2_MAX_FRAME_SIZE_MIN == ud.recv_frame_hd.length);
nghttp2_session_del(session);
/* received by server */
nghttp2_buf_reset(&buf);
nghttp2_session_server_new2(&session, &callbacks, &ud, option);
nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1, NGHTTP2_ORIGIN,
NGHTTP2_FLAG_NONE, 0);
nghttp2_frame_pack_frame_hd(buf.last, &hd);
buf.last += NGHTTP2_FRAME_HDLEN;
nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
buf.last += 2;
buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
CU_ASSERT(0 == ud.frame_recv_cb_called);
nghttp2_session_del(session);
nghttp2_buf_free(&buf, mem);
nghttp2_option_del(option);
}
void test_nghttp2_session_continue(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
@ -3834,6 +3949,55 @@ void test_nghttp2_session_on_altsvc_received(void) {
nghttp2_option_del(option);
}
void test_nghttp2_session_on_origin_received(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
my_user_data ud;
nghttp2_frame frame;
nghttp2_option *option;
uint8_t origin[] = "www.nghttp2.org";
int rv;
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.on_frame_recv_callback = on_frame_recv_callback;
nghttp2_option_new(&option);
nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ORIGIN);
nghttp2_session_client_new2(&session, &callbacks, &ud, option);
frame.ext.payload = &session->iframe.ext_frame_payload;
/* We just pass the strings without making a copy. This is OK,
since we never call nghttp2_frame_origin_free(). */
nghttp2_frame_origin_init(&frame.ext, origin, sizeof(origin) - 1);
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_on_origin_received(session, &frame);
CU_ASSERT(0 == rv);
CU_ASSERT(1 == ud.frame_recv_cb_called);
nghttp2_session_del(session);
/* Receiving empty origin; this is OK */
nghttp2_session_client_new2(&session, &callbacks, &ud, option);
frame.ext.payload = &session->iframe.ext_frame_payload;
nghttp2_frame_origin_init(&frame.ext, origin, 0);
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_on_origin_received(session, &frame);
CU_ASSERT(0 == rv);
CU_ASSERT(1 == ud.frame_recv_cb_called);
nghttp2_session_del(session);
nghttp2_option_del(option);
}
void test_nghttp2_session_send_headers_start_stream(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
@ -5922,6 +6086,55 @@ void test_nghttp2_submit_altsvc(void) {
nghttp2_session_del(session);
}
void test_nghttp2_submit_origin(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
my_user_data ud;
int rv;
ssize_t len;
const uint8_t *data;
nghttp2_frame_hd hd;
size_t origin_len;
const uint8_t origin[] = "www.nghttp2.org";
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
nghttp2_session_server_new(&session, &callbacks, &ud);
rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, origin,
sizeof(origin) - 1);
CU_ASSERT(0 == rv);
ud.frame_send_cb_called = 0;
len = nghttp2_session_mem_send(session, &data);
CU_ASSERT(len == NGHTTP2_FRAME_HDLEN + 2 + sizeof(origin) - 1);
nghttp2_frame_unpack_frame_hd(&hd, data);
CU_ASSERT(2 + sizeof(origin) - 1 == hd.length);
CU_ASSERT(NGHTTP2_ORIGIN == hd.type);
CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
origin_len = nghttp2_get_uint16(data + NGHTTP2_FRAME_HDLEN);
CU_ASSERT(sizeof(origin) - 1 == origin_len);
CU_ASSERT(0 ==
memcmp(origin, data + NGHTTP2_FRAME_HDLEN + 2, sizeof(origin) - 1));
/* submitting from client side session is error */
nghttp2_session_client_new(&session, &callbacks, NULL);
rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, origin,
sizeof(origin) - 1);
CU_ASSERT(NGHTTP2_ERR_INVALID_STATE == rv);
nghttp2_session_del(session);
}
void test_nghttp2_session_open_stream(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;

View File

@ -84,6 +84,10 @@ int unpack_frame(nghttp2_frame *frame, const uint8_t *in, size_t len) {
assert(payloadlen > 2);
nghttp2_frame_unpack_altsvc_payload2(&frame->ext, payload, payloadlen, mem);
break;
case NGHTTP2_ORIGIN:
assert(payloadlen > 2);
nghttp2_frame_unpack_origin_payload2(&frame->ext, payload, payloadlen, mem);
break;
default:
/* Must not be reachable */
assert(0);