diff --git a/lib/includes/nghttp2/nghttp2.h b/lib/includes/nghttp2/nghttp2.h index 6cae2f78..038030aa 100644 --- a/lib/includes/nghttp2/nghttp2.h +++ b/lib/includes/nghttp2/nghttp2.h @@ -2105,8 +2105,6 @@ void nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec); * @function * * Returns nonzero if the |pri_spec| is filled with default values. - * `pri_spec->exclusive` is ignored since it is irrelevant when - * `pri_spec->stream_id == 0`. */ int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec); diff --git a/lib/nghttp2_priority_spec.c b/lib/nghttp2_priority_spec.c index 6e6dcb24..778088fc 100644 --- a/lib/nghttp2_priority_spec.c +++ b/lib/nghttp2_priority_spec.c @@ -42,7 +42,7 @@ void nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec) int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec) { - /* Ignore exclusive flag */ return pri_spec->stream_id == 0 && - pri_spec->weight == NGHTTP2_DEFAULT_WEIGHT; + pri_spec->weight == NGHTTP2_DEFAULT_WEIGHT && + pri_spec->exclusive == 0; } diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index e2323b23..ea50843d 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -280,6 +280,8 @@ static int nghttp2_session_new(nghttp2_session **session_ptr, goto fail_map; } + nghttp2_stream_roots_init(&(*session_ptr)->roots); + (*session_ptr)->next_seq = 0; (*session_ptr)->remote_window_size = NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE; @@ -436,6 +438,8 @@ void nghttp2_session_del(nghttp2_session *session) } free(session->inflight_iv); + nghttp2_stream_roots_free(&session->roots); + /* Have to free streams first, so that we can check stream->data_item->queued */ nghttp2_map_each_free(&session->streams, nghttp2_free_streams, NULL); @@ -470,14 +474,21 @@ int nghttp2_session_reprioritize_stream /* We have to update weight after removing stream from tree */ stream->weight = pri_spec->weight; - rv = nghttp2_stream_dep_make_root(stream, &session->ob_pq); + if(pri_spec->exclusive && + session->roots.num_streams <= NGHTTP2_MAX_DEP_TREE_LENGTH) { + + rv = nghttp2_stream_dep_all_your_stream_are_belong_to_us + (stream, &session->ob_pq); + } else { + rv = nghttp2_stream_dep_make_root(stream, &session->ob_pq); + } return rv; } dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id); - if(dep_stream == NULL) { + if(!dep_stream || !nghttp2_stream_in_dep_tree(dep_stream)) { return 0; } @@ -711,7 +722,7 @@ nghttp2_stream* nghttp2_session_open_stream(nghttp2_session *session, } nghttp2_stream_init(stream, stream_id, flags, initial_state, - pri_spec->weight, + pri_spec->weight, &session->roots, session->remote_settings [NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE], session->local_settings @@ -747,9 +758,29 @@ nghttp2_stream* nghttp2_session_open_stream(nghttp2_session *session, return stream; } + if(pri_spec->stream_id == 0) { + + ++session->roots.num_streams; + + if(pri_spec->exclusive && + session->roots.num_streams <= NGHTTP2_MAX_DEP_TREE_LENGTH) { + rv = nghttp2_stream_dep_all_your_stream_are_belong_to_us + (stream, &session->ob_pq); + + /* Since no dpri is changed in dependency tree, the above + function call never fail. */ + assert(rv == 0); + } else { + nghttp2_stream_roots_add(&session->roots, stream); + } + + return stream; + } + dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id); - if(!dep_stream) { + /* If dep_stream is not part of dependency tree, we don't use it. */ + if(!dep_stream || !nghttp2_stream_in_dep_tree(dep_stream)) { return stream; } @@ -831,7 +862,9 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id, /* Closes both directions just in case they are not closed yet */ stream->flags |= NGHTTP2_STREAM_FLAG_CLOSED; - if(session->server && !nghttp2_session_is_my_stream_id(session, stream_id)) { + if(session->server && + nghttp2_stream_in_dep_tree(stream) && + !nghttp2_session_is_my_stream_id(session, stream_id)) { /* On server side, retain incoming stream object at most MAX_CONCURRENT_STREAMS combined with the current active streams to make dependency tree work better. */ diff --git a/lib/nghttp2_session.h b/lib/nghttp2_session.h index 21f728e5..bcdb0467 100644 --- a/lib/nghttp2_session.h +++ b/lib/nghttp2_session.h @@ -117,6 +117,7 @@ typedef enum { struct nghttp2_session { nghttp2_map /* */ streams; + nghttp2_stream_roots roots; /* Queue for outbound frames other than stream-creating HEADERS */ nghttp2_pq /* */ ob_pq; /* Queue for outbound stream-creating HEADERS frame */ diff --git a/lib/nghttp2_stream.c b/lib/nghttp2_stream.c index aafa35d4..fdda4e82 100644 --- a/lib/nghttp2_stream.c +++ b/lib/nghttp2_stream.c @@ -33,6 +33,7 @@ void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id, uint8_t flags, nghttp2_stream_state initial_state, int32_t weight, + nghttp2_stream_roots *roots, int32_t remote_initial_window_size, int32_t local_initial_window_size, void *stream_user_data) @@ -61,6 +62,10 @@ void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id, stream->weight = weight; stream->effective_weight = stream->weight; stream->sum_dep_weight = 0; + + stream->roots = roots; + stream->root_prev = NULL; + stream->root_next = NULL; } void nghttp2_stream_free(nghttp2_stream *stream) @@ -474,6 +479,8 @@ void nghttp2_stream_dep_insert(nghttp2_stream *dep_stream, stream_update_dep_length(dep_stream, 1); stream_update_dep_effective_weight(dep_stream); + + ++stream->roots->num_streams; } void nghttp2_stream_dep_add(nghttp2_stream *dep_stream, @@ -502,6 +509,8 @@ void nghttp2_stream_dep_add(nghttp2_stream *dep_stream, } stream_update_dep_effective_weight(dep_stream); + + ++stream->roots->num_streams; } void nghttp2_stream_dep_remove(nghttp2_stream *stream) @@ -568,6 +577,8 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream) dep_next = NULL; } } else { + nghttp2_stream_roots_remove(stream->roots, stream); + dep_next = NULL; /* stream is a root of tree. Removing stream makes its @@ -583,6 +594,8 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream) /* We already distributed weight of |stream| to this. */ si->effective_weight = si->weight; + nghttp2_stream_roots_add(si->roots, si); + si = next; } } @@ -606,6 +619,8 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream) stream->dep_next = NULL; stream->sib_prev = NULL; stream->sib_next = NULL; + + --stream->roots->num_streams; } int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream, @@ -748,6 +763,8 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream) } } else { + nghttp2_stream_roots_remove(stream->roots, stream); + dep_prev = NULL; } @@ -771,6 +788,8 @@ int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq) DEBUGF(fprintf(stderr, "stream: dep_make_root stream(%p)=%d\n", stream, stream->stream_id)); + nghttp2_stream_roots_add(stream->roots, stream); + stream_update_dep_set_rest(stream); stream->effective_weight = stream->weight; @@ -785,3 +804,141 @@ int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq) return 0; } + +int nghttp2_stream_dep_all_your_stream_are_belong_to_us +(nghttp2_stream *stream, nghttp2_pq *pq) +{ + nghttp2_stream *first, *si; + + DEBUGF(fprintf(stderr, "stream: ALL YOUR STREAM ARE BELONG TO US " + "stream(%p)=%d\n", + stream, stream->stream_id)); + + first = stream->roots->head; + + /* stream must not be include in stream->roots->head list */ + assert(first != stream); + + if(first) { + nghttp2_stream *prev; + + prev = first; + + DEBUGF(fprintf(stderr, "stream: root stream(%p)=%d\n", + first, first->stream_id)); + + stream->sum_dep_weight += first->weight; + stream->num_substreams += first->num_substreams; + + for(si = first->root_next; si; si = si->root_next) { + + assert(si != stream); + + DEBUGF(fprintf(stderr, "stream: root stream(%p)=%d\n", + si, si->stream_id)); + + fprintf(stderr, "w=%d, sum=%d\n", + si->weight, stream->sum_dep_weight); + stream->sum_dep_weight += si->weight; + stream->num_substreams += si->num_substreams; + + si->sib_prev = prev; + prev->sib_next = si; + + prev = si; + } + + if(stream->dep_next) { + nghttp2_stream *last_sib; + + last_sib = stream_last_sib(stream->dep_next); + + last_sib->sib_next = first; + first->sib_prev = last_sib; + } else { + stream->dep_next = first; + first->dep_prev = stream; + } + } + + nghttp2_stream_roots_remove_all(stream->roots); + + return nghttp2_stream_dep_make_root(stream, pq); +} + +int nghttp2_stream_in_dep_tree(nghttp2_stream *stream) +{ + return stream->dep_prev || stream->dep_next || + stream->sib_prev || stream->sib_next || + stream->root_next || stream->root_prev || + stream->roots->head == stream; +} + +void nghttp2_stream_roots_init(nghttp2_stream_roots *roots) +{ + roots->head = NULL; + roots->num_streams = 0; +} + +void nghttp2_stream_roots_free(nghttp2_stream_roots *roots) +{} + +void nghttp2_stream_roots_add(nghttp2_stream_roots *roots, + nghttp2_stream *stream) +{ + if(roots->head) { + nghttp2_stream *si; + for(si = roots->head; si; si = si->root_next) { + if(si == stream) { + assert(0); + } + } + + stream->root_next = roots->head; + roots->head->root_prev = stream; + } + + roots->head = stream; +} + +void nghttp2_stream_roots_remove(nghttp2_stream_roots *roots, + nghttp2_stream *stream) +{ + nghttp2_stream *root_prev, *root_next; + + root_prev = stream->root_prev; + root_next = stream->root_next; + + if(root_prev) { + root_prev->root_next = root_next; + + if(root_next) { + root_next->root_prev = root_prev; + } + } else { + if(root_next) { + root_next->root_prev = NULL; + } + + roots->head = root_next; + } + + stream->root_prev = NULL; + stream->root_next = NULL; +} + +void nghttp2_stream_roots_remove_all(nghttp2_stream_roots *roots) +{ + nghttp2_stream *si, *next; + + for(si = roots->head; si;) { + next = si->root_next; + + si->root_prev = NULL; + si->root_next = NULL; + + si = next; + } + + roots->head = NULL; +} diff --git a/lib/nghttp2_stream.h b/lib/nghttp2_stream.h index 05a4f52c..5c2fbced 100644 --- a/lib/nghttp2_stream.h +++ b/lib/nghttp2_stream.h @@ -102,6 +102,10 @@ typedef enum { NGHTTP2_STREAM_DPRI_REST = 0x04 } nghttp2_stream_dpri; +struct nghttp2_stream_roots; + +typedef struct nghttp2_stream_roots nghttp2_stream_roots; + struct nghttp2_stream; typedef struct nghttp2_stream nghttp2_stream; @@ -118,11 +122,17 @@ struct nghttp2_stream { dep_prev and sib_prev are NULL. */ nghttp2_stream *dep_prev, *dep_next; nghttp2_stream *sib_prev, *sib_next; + /* pointers to track dependency tree root streams. This is + doubly-linked list and first element is pointed by + roots->head. */ + nghttp2_stream *root_prev, *root_next; /* When stream is kept after closure, it may be kept in single linked list pointed by nghttp2_session closed_stream_head. closed_next points to the next stream object if it is the element of the list. */ nghttp2_stream *closed_next; + /* pointer to roots, which tracks dependency tree roots */ + nghttp2_stream_roots *roots; /* The arbitrary data provided by user for this stream. */ void *stream_user_data; /* DATA frame item */ @@ -165,6 +175,7 @@ void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id, uint8_t flags, nghttp2_stream_state initial_state, int32_t weight, + nghttp2_stream_roots *roots, int32_t remote_initial_window_size, int32_t local_initial_window_size, void *stream_user_data); @@ -380,4 +391,40 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream); */ int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq); +/* + * Makes the |stream| as root and all existing root streams become + * direct children of |stream|. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory + */ +int nghttp2_stream_dep_all_your_stream_are_belong_to_us +(nghttp2_stream *stream, nghttp2_pq *pq); + +/* + * Returns nonzero if |stream| is in any dependency tree. + */ +int nghttp2_stream_in_dep_tree(nghttp2_stream *stream); + +struct nghttp2_stream_roots { + nghttp2_stream *head; + + int32_t num_streams; +}; + +void nghttp2_stream_roots_init(nghttp2_stream_roots *roots); + +void nghttp2_stream_roots_free(nghttp2_stream_roots *roots); + +void nghttp2_stream_roots_add(nghttp2_stream_roots *roots, + nghttp2_stream *stream); + +void nghttp2_stream_roots_remove(nghttp2_stream_roots *roots, + nghttp2_stream *stream); + +void nghttp2_stream_roots_remove_all(nghttp2_stream_roots *roots); + #endif /* NGHTTP2_STREAM */ diff --git a/lib/nghttp2_submit.c b/lib/nghttp2_submit.c index fc6a0c31..23b8de1a 100644 --- a/lib/nghttp2_submit.c +++ b/lib/nghttp2_submit.c @@ -103,10 +103,6 @@ static int nghttp2_submit_headers_shared static void adjust_priority_spec_weight(nghttp2_priority_spec *pri_spec) { - if(pri_spec->stream_id == 0) { - pri_spec->exclusive = 0; - } - if(pri_spec->weight < NGHTTP2_MIN_WEIGHT) { pri_spec->weight = NGHTTP2_MIN_WEIGHT; } else if(pri_spec->weight > NGHTTP2_MAX_WEIGHT) { diff --git a/tests/main.c b/tests/main.c index 0335a713..3cca7ac6 100644 --- a/tests/main.c +++ b/tests/main.c @@ -222,6 +222,8 @@ int main(int argc, char* argv[]) test_nghttp2_session_stream_dep_add_subtree) || !CU_add_test(pSuite, "session_stream_dep_remove_subtree", test_nghttp2_session_stream_dep_remove_subtree) || + !CU_add_test(pSuite, "session_stream_dep_all_your_stream_are_belong_to_us", + test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us) || !CU_add_test(pSuite, "session_stream_attach_data", test_nghttp2_session_stream_attach_data) || !CU_add_test(pSuite, "session_stream_attach_data_subtree", diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c index 30f5e8f4..647864a2 100644 --- a/tests/nghttp2_session_test.c +++ b/tests/nghttp2_session_test.c @@ -4873,6 +4873,10 @@ void test_nghttp2_session_stream_dep_add(void) check_stream_dep_sib(c, NULL, d, b, NULL); check_stream_dep_sib(d, c, NULL, NULL, NULL); + CU_ASSERT(4 == session->roots.num_streams); + CU_ASSERT(a == session->roots.head); + CU_ASSERT(NULL == a->root_next); + e = open_stream_with_dep_excl(session, 9, a); /* a @@ -4902,6 +4906,10 @@ void test_nghttp2_session_stream_dep_add(void) check_stream_dep_sib(c, NULL, d, b, NULL); check_stream_dep_sib(d, c, NULL, NULL, NULL); + CU_ASSERT(5 == session->roots.num_streams); + CU_ASSERT(a == session->roots.head); + CU_ASSERT(NULL == a->root_next); + nghttp2_session_del(session); } @@ -4951,6 +4959,11 @@ void test_nghttp2_session_stream_dep_remove(void) check_stream_dep_sib(c, NULL, d, NULL, NULL); check_stream_dep_sib(d, c, NULL, NULL, NULL); + CU_ASSERT(3 == session->roots.num_streams); + CU_ASSERT(c == session->roots.head); + CU_ASSERT(b == c->root_next); + CU_ASSERT(NULL == b->root_next); + nghttp2_session_del(session); /* Remove left most stream */ @@ -4993,6 +5006,10 @@ void test_nghttp2_session_stream_dep_remove(void) check_stream_dep_sib(c, a, d, NULL, NULL); check_stream_dep_sib(d, c, NULL, NULL, NULL); + CU_ASSERT(3 == session->roots.num_streams); + CU_ASSERT(a == session->roots.head); + CU_ASSERT(NULL == a->root_next); + nghttp2_session_del(session); /* Remove right most stream */ @@ -5348,6 +5365,131 @@ void test_nghttp2_session_stream_dep_remove_subtree(void) nghttp2_session_del(session); } +void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) +{ + nghttp2_session *session; + nghttp2_session_callbacks callbacks; + nghttp2_stream *a, *b, *c, *d; + + memset(&callbacks, 0, sizeof(callbacks)); + + nghttp2_session_server_new(&session, &callbacks, NULL); + + a = open_stream(session, 1); + b = open_stream_with_dep(session, 3, a); + + c = open_stream(session, 5); + + /* a c + * | + * b + */ + + nghttp2_stream_dep_remove_subtree(c); + CU_ASSERT(0 == nghttp2_stream_dep_all_your_stream_are_belong_to_us + (c, &session->ob_pq)); + + /* + * c + * | + * a + * | + * b + */ + + CU_ASSERT(3 == c->num_substreams); + CU_ASSERT(2 == a->num_substreams); + CU_ASSERT(1 == b->num_substreams); + + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight); + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight); + CU_ASSERT(0 == b->sum_dep_weight); + + check_stream_dep_sib(c, NULL, a, NULL, NULL); + check_stream_dep_sib(a, c, b, NULL, NULL); + check_stream_dep_sib(b, a, NULL, NULL, NULL); + + nghttp2_session_del(session); + + nghttp2_session_server_new(&session, &callbacks, NULL); + + a = open_stream(session, 1); + + b = open_stream(session, 3); + + c = open_stream(session, 5); + + /* + * a b c + */ + + nghttp2_stream_dep_remove_subtree(c); + CU_ASSERT(0 == nghttp2_stream_dep_all_your_stream_are_belong_to_us + (c, &session->ob_pq)); + + /* + * c + * | + * b--a + */ + + CU_ASSERT(3 == c->num_substreams); + CU_ASSERT(1 == a->num_substreams); + CU_ASSERT(1 == b->num_substreams); + + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight); + CU_ASSERT(0 == b->sum_dep_weight); + CU_ASSERT(0 == a->sum_dep_weight); + + check_stream_dep_sib(c, NULL, b, NULL, NULL); + check_stream_dep_sib(b, c, NULL, NULL, a); + check_stream_dep_sib(a, NULL, NULL, b, NULL); + + nghttp2_session_del(session); + + nghttp2_session_server_new(&session, &callbacks, NULL); + + a = open_stream(session, 1); + b = open_stream_with_dep(session, 3, a); + + c = open_stream(session, 5); + d = open_stream_with_dep(session, 7, c); + + /* a c + * | | + * b d + */ + + nghttp2_stream_dep_remove_subtree(c); + CU_ASSERT(0 == nghttp2_stream_dep_all_your_stream_are_belong_to_us + (c, &session->ob_pq)); + + /* + * c + * | + * d--a + * | + * b + */ + + CU_ASSERT(4 == c->num_substreams); + CU_ASSERT(1 == d->num_substreams); + CU_ASSERT(2 == a->num_substreams); + CU_ASSERT(1 == b->num_substreams); + + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight); + CU_ASSERT(0 == d->sum_dep_weight); + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight); + CU_ASSERT(0 == b->sum_dep_weight); + + check_stream_dep_sib(c, NULL, d, NULL, NULL); + check_stream_dep_sib(d, c, NULL, NULL, a); + check_stream_dep_sib(a, NULL, b, d, NULL); + check_stream_dep_sib(b, a, NULL, NULL, NULL); + + nghttp2_session_del(session); +} + static nghttp2_outbound_item* create_data_ob_item(void) { nghttp2_outbound_item *item; @@ -5488,6 +5630,7 @@ void test_nghttp2_session_stream_attach_data_subtree(void) /* Insert subtree e under a */ + nghttp2_stream_dep_remove_subtree(e); nghttp2_stream_dep_insert_subtree(a, e, &session->ob_pq); /* @@ -5570,6 +5713,7 @@ void test_nghttp2_session_stream_attach_data_subtree(void) /* Add subtree c to a */ + nghttp2_stream_dep_remove_subtree(c); nghttp2_stream_dep_add_subtree(a, c, &session->ob_pq); /* @@ -5589,6 +5733,7 @@ void test_nghttp2_session_stream_attach_data_subtree(void) /* Insert b under a */ + nghttp2_stream_dep_remove_subtree(b); nghttp2_stream_dep_insert_subtree(a, b, &session->ob_pq); /* @@ -5608,21 +5753,10 @@ void test_nghttp2_session_stream_attach_data_subtree(void) CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == e->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == f->dpri); - nghttp2_stream_dep_make_root(a, &session->ob_pq); - - /* - * a - * | - * b - * | - * e--c - * | | - * f d - */ - /* Remove subtree b */ nghttp2_stream_dep_remove_subtree(b); + nghttp2_stream_dep_make_root(b, &session->ob_pq); /* * b a @@ -5870,6 +6004,58 @@ void test_nghttp2_session_stream_dep_effective_weight(void) CU_ASSERT(16 * 4 / 20 == d->effective_weight); nghttp2_session_del(session); + + nghttp2_session_server_new(&session, &callbacks, NULL); + + a = open_stream(session, 1); + b = open_stream_with_dep_weight(session, 3, 8, a); + c = open_stream_with_dep_weight(session, 5, 4, a); + d = open_stream_with_dep_weight(session, 7, 1, c); + + e = open_stream(session, 9); + f = open_stream_with_dep_weight(session, 11, 12, e); + + /* a e + * | | + * b--c f + * | + * d + */ + + CU_ASSERT(e->roots->head == e); + CU_ASSERT(a == e->root_next); + + /* Insert e under stream 0 */ + nghttp2_stream_dep_remove_subtree(e); + + CU_ASSERT(a == e->roots->head); + + CU_ASSERT(0 == nghttp2_stream_dep_all_your_stream_are_belong_to_us + (e, &session->ob_pq)); + + /* e + * | + * f--a + * | + * b--c + * | + * d + */ + + CU_ASSERT(6 == e->num_substreams); + CU_ASSERT(28 == e->sum_dep_weight); + + CU_ASSERT(16 == e->effective_weight); + + CU_ASSERT(16 * 16 / 28 == a->effective_weight); + CU_ASSERT(16 * 12 / 28 == f->effective_weight); + + CU_ASSERT((16 * 16 / 28) * 8 / 12 == b->effective_weight); + CU_ASSERT((16 * 16 / 28) * 4 / 12 == c->effective_weight); + + CU_ASSERT((16 * 16 / 28) * 4 / 12 == d->effective_weight); + + nghttp2_session_del(session); } void test_nghttp2_session_keep_closed_stream(void) diff --git a/tests/nghttp2_session_test.h b/tests/nghttp2_session_test.h index f65e6b36..e6bac7bf 100644 --- a/tests/nghttp2_session_test.h +++ b/tests/nghttp2_session_test.h @@ -103,6 +103,7 @@ void test_nghttp2_session_stream_dep_add(void); void test_nghttp2_session_stream_dep_remove(void); void test_nghttp2_session_stream_dep_add_subtree(void); void test_nghttp2_session_stream_dep_remove_subtree(void); +void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void); void test_nghttp2_session_stream_attach_data(void); void test_nghttp2_session_stream_attach_data_subtree(void); void test_nghttp2_session_stream_dep_effective_weight(void);