Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
288 changes: 285 additions & 3 deletions tests/nghttp3_conn_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ static const MunitTest tests[] = {
munit_void_test(test_nghttp3_conn_http_record_request_method),
munit_void_test(test_nghttp3_conn_http_error),
munit_void_test(test_nghttp3_conn_qpack_blocked_stream),
munit_void_test(test_nghttp3_conn_qpack_decoder_cancel_stream),
munit_void_test(test_nghttp3_conn_just_fin),
munit_void_test(test_nghttp3_conn_submit_response_read_blocked),
munit_void_test(test_nghttp3_conn_recv_uni),
Expand Down Expand Up @@ -155,6 +156,22 @@ static int end_headers(nghttp3_conn *conn, int64_t stream_id, int fin,
return 0;
}

static nghttp3_ssize empty_read_data(nghttp3_conn *conn, int64_t stream_id,
nghttp3_vec *vec, size_t veccnt,
uint32_t *pflags, void *user_data,
void *stream_user_data) {
(void)conn;
(void)stream_id;
(void)vec;
(void)veccnt;
(void)user_data;
(void)stream_user_data;

*pflags = NGHTTP3_DATA_FLAG_EOF | NGHTTP3_DATA_FLAG_NO_END_STREAM;

return 0;
}

static nghttp3_ssize step_read_data(nghttp3_conn *conn, int64_t stream_id,
nghttp3_vec *vec, size_t veccnt,
uint32_t *pflags, void *user_data,
Expand Down Expand Up @@ -491,6 +508,24 @@ static void conn_write_initial_streams(nghttp3_conn *conn) {
assert_ptrdiff(0, ==, sveccnt);
}

static void conn_read_control_stream(nghttp3_conn *conn, int64_t stream_id,
nghttp3_frame *fr) {
uint8_t rawbuf[1024];
nghttp3_buf buf;
nghttp3_ssize nconsumed;

nghttp3_buf_wrap_init(&buf, rawbuf, sizeof(rawbuf));

buf.last = nghttp3_put_varint(buf.last, NGHTTP3_STREAM_TYPE_CONTROL);

nghttp3_write_frame(&buf, fr);

nconsumed = nghttp3_conn_read_stream(conn, stream_id, buf.pos,
nghttp3_buf_len(&buf), /* fin = */ 0);

assert_ptrdiff((nghttp3_ssize)nghttp3_buf_len(&buf), ==, nconsumed);
}

void test_nghttp3_conn_read_control(void) {
nghttp3_conn *conn;
nghttp3_callbacks callbacks = {
Expand Down Expand Up @@ -833,6 +868,16 @@ void test_nghttp3_conn_write_control(void) {
nghttp3_ssize sveccnt;
int64_t stream_id;
int fin;
nghttp3_settings settings;
conn_options opts;
nghttp3_ssize nread;
union {
nghttp3_frame fr;
struct {
nghttp3_frame_settings settings;
nghttp3_settings pad[15];
};
} fr;

setup_default_server(&conn);

Expand All @@ -848,6 +893,53 @@ void test_nghttp3_conn_write_control(void) {
assert_uint8(NGHTTP3_STREAM_TYPE_CONTROL, ==, vec[0].base[0]);

nghttp3_conn_del(conn);

/* Enable H3 DATAGRAM and CONNECT protocol */
nghttp3_settings_default(&settings);
settings.h3_datagram = 1;
settings.enable_connect_protocol = 1;

conn_options_clear(&opts);
opts.settings = &settings;

setup_default_server_with_options(&conn, opts);

sveccnt = nghttp3_conn_writev_stream(conn, &stream_id, &fin, vec,
nghttp3_arraylen(vec));

assert_int64(3, ==, stream_id);
assert_ptrdiff(1, ==, sveccnt);
assert_true(vec[0].len > 1);
assert_uint8(NGHTTP3_STREAM_TYPE_CONTROL, ==, vec[0].base[0]);

++vec[0].base;
--vec[0].len;

nread = nghttp3_decode_settings_frame(&fr.fr.settings, vec, 1);

assert_ptrdiff((nghttp3_ssize)vec[0].len, ==, nread);
assert_size(5, ==, fr.fr.settings.niv);

assert_uint64(NGHTTP3_SETTINGS_ID_MAX_FIELD_SECTION_SIZE, ==,
fr.fr.settings.iv[0].id);
assert_uint64(NGHTTP3_VARINT_MAX, ==, fr.fr.settings.iv[0].value);

assert_uint64(NGHTTP3_SETTINGS_ID_QPACK_MAX_TABLE_CAPACITY, ==,
fr.fr.settings.iv[1].id);
assert_uint64(0, ==, fr.fr.settings.iv[1].value);

assert_uint64(NGHTTP3_SETTINGS_ID_QPACK_BLOCKED_STREAMS, ==,
fr.fr.settings.iv[2].id);
assert_uint64(0, ==, fr.fr.settings.iv[2].value);

assert_uint64(NGHTTP3_SETTINGS_ID_H3_DATAGRAM, ==, fr.fr.settings.iv[3].id);
assert_uint64(1, ==, fr.fr.settings.iv[3].value);

assert_uint64(NGHTTP3_SETTINGS_ID_ENABLE_CONNECT_PROTOCOL, ==,
fr.fr.settings.iv[4].id);
assert_uint64(1, ==, fr.fr.settings.iv[4].value);

nghttp3_conn_del(conn);
}

void test_nghttp3_conn_submit_request(void) {
Expand All @@ -865,13 +957,37 @@ void test_nghttp3_conn_submit_request(void) {
MAKE_NV(":scheme", "https"),
MAKE_NV(":method", "GET"),
};
const nghttp3_nv large_nva[] = {
MAKE_NV(":path", "/alpha/bravo/charlie/delta/echo/foxtrot/golf/hotel"),
MAKE_NV(":authority", "example.com"),
MAKE_NV(":scheme", "https"),
MAKE_NV(":method", "GET"),
MAKE_NV("priority", "u=0,i"),
MAKE_NV("user-agent",
"alpha=bravo; charlie=delta; echo=foxtrot; golf=hotel; "
"india=juliett; kilo=lima; mike=november; oscar=papa; "
"quebec=romeo; sierra=tango; uniform=vector; whiskey=xray; "
"yankee=zulu"),
};
const nghttp3_nv trailer_nva[] = {
MAKE_NV("digest", "foo"),
};
uint64_t len;
size_t i;
nghttp3_stream *stream;
userdata ud = {0};
nghttp3_data_reader dr;
union {
nghttp3_frame fr;
struct {
nghttp3_frame_settings settings;
nghttp3_settings_entry iv[15];
};
} fr;
nghttp3_settings_entry *iv;
nghttp3_typed_buf *tbuf;
int fin;
size_t outq_idx;
conn_options opts;

ud.data.left = 2000;
Expand Down Expand Up @@ -1014,6 +1130,112 @@ void test_nghttp3_conn_submit_request(void) {
assert_uint64(2000, ==, ud.ack.acc);

nghttp3_conn_del(conn);

/* QPACK request buffer exceeds NGHTTP3_STREAM_MAX_COPY_THRES */
setup_default_client(&conn);
conn_write_initial_streams(conn);

rv = nghttp3_conn_submit_request(conn, 0, large_nva,
nghttp3_arraylen(large_nva), NULL, NULL);

assert_int(0, ==, rv);

sveccnt = nghttp3_conn_writev_stream(conn, &stream_id, &fin, vec,
nghttp3_arraylen(vec));

assert_int64(0, ==, stream_id);
/* Extra vector */
assert_int64(2, ==, sveccnt);

rv = nghttp3_conn_add_write_offset(
conn, stream_id, (size_t)nghttp3_vec_len(vec, (size_t)sveccnt));

assert_int(0, ==, rv);

rv = nghttp3_conn_add_ack_offset(
conn, stream_id, (size_t)nghttp3_vec_len(vec, (size_t)sveccnt));

assert_int(0, ==, rv);

nghttp3_conn_del(conn);

/* QPACK encoder buffer exceeds NGHTTP3_STREAM_MAX_COPY_THRES */
setup_default_client(&conn);
conn_write_initial_streams(conn);

fr.settings.hd.type = NGHTTP3_FRAME_SETTINGS;
fr.settings.niv = 1;
iv = fr.settings.iv;
iv[0].id = NGHTTP3_SETTINGS_ID_QPACK_MAX_TABLE_CAPACITY;
iv[0].value = 4096;

conn_read_control_stream(conn, 3, &fr.fr);

rv = nghttp3_conn_submit_request(conn, 0, large_nva,
nghttp3_arraylen(large_nva), NULL, NULL);

assert_int(0, ==, rv);

sveccnt = nghttp3_conn_writev_stream(conn, &stream_id, &fin, vec,
nghttp3_arraylen(vec));

assert_int64(conn->tx.qenc->node.id, ==, stream_id);
assert_int64(1, ==, sveccnt);

tbuf = nghttp3_ringbuf_get(&conn->tx.qenc->outq,
nghttp3_ringbuf_len(&conn->tx.qenc->outq) - 1);

assert_enum(nghttp3_buf_type, NGHTTP3_BUF_TYPE_PRIVATE, ==, tbuf->type);

rv = nghttp3_conn_add_write_offset(
conn, stream_id, (size_t)nghttp3_vec_len(vec, (size_t)sveccnt));

assert_int(0, ==, rv);

rv = nghttp3_conn_add_ack_offset(
conn, stream_id, (size_t)nghttp3_vec_len(vec, (size_t)sveccnt));

assert_int(0, ==, rv);

nghttp3_conn_del(conn);

/* Extend the last shared buffer after it is written out */
setup_default_client(&conn);
conn_write_initial_streams(conn);

dr.read_data = empty_read_data;
rv =
nghttp3_conn_submit_request(conn, 0, nva, nghttp3_arraylen(nva), &dr, NULL);

assert_int(0, ==, rv);

sveccnt = nghttp3_conn_writev_stream(conn, &stream_id, &fin, vec,
nghttp3_arraylen(vec));

assert_int64(0, ==, stream_id);
assert_int64(1, ==, sveccnt);

rv = nghttp3_conn_add_write_offset(
conn, stream_id, (size_t)nghttp3_vec_len(vec, (size_t)sveccnt));

assert_int(0, ==, rv);

stream = nghttp3_conn_find_stream(conn, stream_id);
outq_idx = stream->outq_idx;

rv = nghttp3_conn_submit_trailers(conn, 0, trailer_nva,
nghttp3_arraylen(trailer_nva));

assert_int(0, ==, rv);

sveccnt = nghttp3_conn_writev_stream(conn, &stream_id, &fin, vec,
nghttp3_arraylen(vec));

assert_int64(0, ==, stream_id);
assert_int64(1, ==, sveccnt);
assert_size(outq_idx - 1, ==, stream->outq_idx);

nghttp3_conn_del(conn);
}

void test_nghttp3_conn_http_request(void) {
Expand Down Expand Up @@ -2580,6 +2802,7 @@ void test_nghttp3_conn_qpack_blocked_stream(void) {
};
nghttp3_frame fr;
nghttp3_ssize sconsumed;
size_t buffered_datalen;
nghttp3_stream *stream;
conn_options opts;

Expand Down Expand Up @@ -2616,17 +2839,31 @@ void test_nghttp3_conn_qpack_blocked_stream(void) {
nghttp3_write_frame_qpack_dyn(&buf, &ebuf, &qenc, 0, &fr);

sconsumed = nghttp3_conn_read_stream(conn, 0, buf.pos, nghttp3_buf_len(&buf),
/* fin = */ 1);
/* fin = */ 0);

assert_true(sconsumed > 0);
assert_ptrdiff((nghttp3_ssize)nghttp3_buf_len(&buf), !=, sconsumed);

rv = nghttp3_conn_close_stream(conn, 0, NGHTTP3_H3_NO_ERROR);
buffered_datalen = nghttp3_buf_len(&buf) - (size_t)sconsumed;

assert_int(0, ==, rv);
nghttp3_buf_reset(&buf);
nghttp3_write_frame_data(&buf, 1111);

sconsumed = nghttp3_conn_read_stream(conn, 0, buf.pos, nghttp3_buf_len(&buf),
/* fin = */ 1);

assert_ptrdiff(0, ==, sconsumed);

buffered_datalen += nghttp3_buf_len(&buf);
stream = nghttp3_conn_find_stream(conn, 0);

assert_size(buffered_datalen, ==,
nghttp3_stream_get_buffered_datalen(stream));

rv = nghttp3_conn_close_stream(conn, 0, NGHTTP3_H3_NO_ERROR);

assert_int(0, ==, rv);

assert_true(stream->flags & NGHTTP3_STREAM_FLAG_CLOSED);

nghttp3_buf_reset(&buf);
Expand Down Expand Up @@ -2718,6 +2955,51 @@ void test_nghttp3_conn_qpack_blocked_stream(void) {
nghttp3_buf_free(&ebuf, mem);
}

void test_nghttp3_conn_qpack_decoder_cancel_stream(void) {
nghttp3_conn *conn;
nghttp3_vec vec[256];
nghttp3_ssize sveccnt;
nghttp3_buf *buf;
int64_t stream_id;
int fin;
size_t i;
int rv;

/* Cancel streams and make QPACK decoder buffer grow, which makes
conn use custom sized shared buffer. */
setup_default_client(&conn);
conn_write_initial_streams(conn);

for (i = 0; i < NGHTTP3_STREAM_MIN_CHUNK_SIZE; ++i) {
rv = nghttp3_qpack_decoder_cancel_stream(&conn->qdec, (int64_t)i);

assert_int(0, ==, rv);
}

sveccnt = nghttp3_conn_writev_stream(conn, &stream_id, &fin, vec,
nghttp3_arraylen(vec));

assert_int64(conn->tx.qdec->node.id, ==, stream_id);
assert_ptrdiff(1, ==, sveccnt);

buf = nghttp3_ringbuf_get(&conn->tx.qdec->chunks,
nghttp3_ringbuf_len(&conn->tx.qdec->chunks) - 1);

assert_size(NGHTTP3_STREAM_MIN_CHUNK_SIZE, <, nghttp3_buf_cap(buf));

rv = nghttp3_conn_add_write_offset(
conn, stream_id, (size_t)nghttp3_vec_len(vec, (size_t)sveccnt));

assert_int(0, ==, rv);

rv = nghttp3_conn_add_ack_offset(
conn, stream_id, (size_t)nghttp3_vec_len(vec, (size_t)sveccnt));

assert_int(0, ==, rv);

nghttp3_conn_del(conn);
}

void test_nghttp3_conn_just_fin(void) {
nghttp3_conn *conn;
nghttp3_vec vec[256];
Expand Down
1 change: 1 addition & 0 deletions tests/nghttp3_conn_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ munit_void_test_decl(test_nghttp3_conn_http_ignore_content_length)
munit_void_test_decl(test_nghttp3_conn_http_record_request_method)
munit_void_test_decl(test_nghttp3_conn_http_error)
munit_void_test_decl(test_nghttp3_conn_qpack_blocked_stream)
munit_void_test_decl(test_nghttp3_conn_qpack_decoder_cancel_stream)
munit_void_test_decl(test_nghttp3_conn_just_fin)
munit_void_test_decl(test_nghttp3_conn_submit_response_read_blocked)
munit_void_test_decl(test_nghttp3_conn_recv_uni)
Expand Down
Loading
Loading