diff --git a/tests/main.c b/tests/main.c index 063c881e..0301c8cb 100644 --- a/tests/main.c +++ b/tests/main.c @@ -201,6 +201,8 @@ int main(int argc, char* argv[]) test_nghttp2_frame_pack_headers) || !CU_add_test(pSuite, "frame_pack_headers_frame_too_large", test_nghttp2_frame_pack_headers_frame_too_large) || + !CU_add_test(pSuite, "frame_pack_headers_with_padding", + test_nghttp2_frame_pack_headers_with_padding) || !CU_add_test(pSuite, "frame_pack_priority", test_nghttp2_frame_pack_priority) || !CU_add_test(pSuite, "frame_pack_rst_stream", diff --git a/tests/nghttp2_frame_test.c b/tests/nghttp2_frame_test.c index 2188d208..c8f127fb 100644 --- a/tests/nghttp2_frame_test.c +++ b/tests/nghttp2_frame_test.c @@ -184,6 +184,134 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void) nghttp2_hd_deflate_free(&deflater); } + +void test_nghttp2_frame_pack_headers_with_padding(void) +{ + nghttp2_hd_deflater deflater; + nghttp2_hd_inflater inflater; + nghttp2_headers frame, oframe; + uint8_t *buf = NULL; + size_t buflen = 0; + size_t bufoff; + ssize_t framelen; + nghttp2_nv *nva; + ssize_t nvlen; + nva_out out; + size_t trail_padlen; + size_t header_blocklen; + + nva_out_init(&out); + nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_REQUEST); + nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST); + + /* Payload length is 0, so no padding */ + nghttp2_frame_headers_init(&frame, + NGHTTP2_FLAG_END_STREAM|NGHTTP2_FLAG_END_HEADERS, + 1000000007, NGHTTP2_PRI_DEFAULT, NULL, 0); + framelen = nghttp2_frame_pack_headers(&buf, &buflen, &bufoff, &frame, + &deflater, 128); + + CU_ASSERT(2 == bufoff); + CU_ASSERT((ssize_t)bufoff + NGHTTP2_FRAME_HEAD_LENGTH == framelen); + + CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf + bufoff, + framelen - bufoff)); + check_frame_header(framelen - bufoff - NGHTTP2_FRAME_HEAD_LENGTH, + NGHTTP2_HEADERS, + NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS, + 1000000007, &oframe.hd); + + CU_ASSERT(NGHTTP2_PRI_DEFAULT == oframe.pri); + nghttp2_frame_headers_free(&oframe); + + /* Include priroty */ + frame.hd.flags |= NGHTTP2_FLAG_PRIORITY; + frame.pri = 1000000009; + bufoff = 0; + + framelen = nghttp2_frame_pack_headers(&buf, &buflen, &bufoff, &frame, + &deflater, 128); + + CU_ASSERT(1 == bufoff); + CU_ASSERT((ssize_t)bufoff + NGHTTP2_FRAME_HEAD_LENGTH + 128 == framelen); + + CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf + bufoff, + framelen - bufoff)); + check_frame_header(framelen - bufoff - NGHTTP2_FRAME_HEAD_LENGTH, + NGHTTP2_HEADERS, + NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS | + NGHTTP2_FLAG_PRIORITY | NGHTTP2_FLAG_PAD_LOW, + 1000000007, &oframe.hd); + + CU_ASSERT(1000000009 == oframe.pri); + nghttp2_frame_headers_free(&oframe); + + /* padding more than 256 */ + bufoff = 0; + + framelen = nghttp2_frame_pack_headers(&buf, &buflen, &bufoff, &frame, + &deflater, 512); + + CU_ASSERT(0 == bufoff); + CU_ASSERT(NGHTTP2_FRAME_HEAD_LENGTH + 512 == framelen); + + CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf + bufoff, + framelen - bufoff)); + check_frame_header(framelen - bufoff - NGHTTP2_FRAME_HEAD_LENGTH, + NGHTTP2_HEADERS, + NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS | + NGHTTP2_FLAG_PRIORITY | + NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW, + 1000000007, &oframe.hd); + + CU_ASSERT(1000000009 == oframe.pri); + nghttp2_frame_headers_free(&oframe); + + /* Include priority + headers */ + nva = headers(); + nvlen = HEADERS_LENGTH; + frame.nva = nva; + frame.nvlen = nvlen; + bufoff = 0; + + framelen = nghttp2_frame_pack_headers(&buf, &buflen, &bufoff, &frame, + &deflater, 512); + + CU_ASSERT(0 == bufoff); + CU_ASSERT(NGHTTP2_FRAME_HEAD_LENGTH + 512 == framelen); + + CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf + bufoff, + framelen - bufoff)); + check_frame_header(framelen - bufoff - NGHTTP2_FRAME_HEAD_LENGTH, + NGHTTP2_HEADERS, + NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS | + NGHTTP2_FLAG_PRIORITY | + NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW, + 1000000007, &oframe.hd); + + CU_ASSERT(1000000009 == oframe.pri); + trail_padlen = (buf[NGHTTP2_FRAME_HEAD_LENGTH] << 8) | + buf[NGHTTP2_FRAME_HEAD_LENGTH + 1]; + + header_blocklen = framelen - NGHTTP2_FRAME_HEAD_LENGTH - 2 - 4 + - trail_padlen; + CU_ASSERT((ssize_t)header_blocklen == + inflate_hd(&inflater, &out, + buf + NGHTTP2_FRAME_HEAD_LENGTH + 2 + 4, + header_blocklen)); + + CU_ASSERT(nvlen == (ssize_t)out.nvlen); + assert_nv_equal(nva, out.nva, nvlen); + + nghttp2_frame_headers_free(&oframe); + nva_out_reset(&out); + + free(buf); + nghttp2_frame_headers_free(&frame); + nghttp2_hd_inflate_free(&inflater); + nghttp2_hd_deflate_free(&deflater); +} + void test_nghttp2_frame_pack_priority(void) { nghttp2_priority frame, oframe; diff --git a/tests/nghttp2_frame_test.h b/tests/nghttp2_frame_test.h index 9a04c23d..a45732e8 100644 --- a/tests/nghttp2_frame_test.h +++ b/tests/nghttp2_frame_test.h @@ -27,6 +27,7 @@ void test_nghttp2_frame_pack_headers(void); void test_nghttp2_frame_pack_headers_frame_too_large(void); +void test_nghttp2_frame_pack_headers_with_padding(void); void test_nghttp2_frame_pack_priority(void); void test_nghttp2_frame_pack_rst_stream(void); void test_nghttp2_frame_pack_settings(void); diff --git a/tests/nghttp2_hd_test.c b/tests/nghttp2_hd_test.c index ad30c120..7d75eddd 100644 --- a/tests/nghttp2_hd_test.c +++ b/tests/nghttp2_hd_test.c @@ -35,15 +35,6 @@ #define GET_TABLE_ENT(context, index) nghttp2_hd_table_get(context, index) -static void assert_nv_equal(nghttp2_nv *a, nghttp2_nv *b, size_t len) -{ - size_t i; - nghttp2_nv_array_sort(b, len); - for(i = 0; i < len; ++i, ++a, ++b) { - CU_ASSERT(nghttp2_nv_equal(a, b)); - } -} - void test_nghttp2_hd_deflate(void) { nghttp2_hd_deflater deflater; diff --git a/tests/nghttp2_test_helper.c b/tests/nghttp2_test_helper.c index ef40e4ac..baff5835 100644 --- a/tests/nghttp2_test_helper.c +++ b/tests/nghttp2_test_helper.c @@ -33,11 +33,15 @@ int unpack_frame(nghttp2_frame *frame, const uint8_t *in, size_t len) ssize_t rv = 0; const uint8_t *payload = in + NGHTTP2_FRAME_HEAD_LENGTH; size_t payloadlen = len - NGHTTP2_FRAME_HEAD_LENGTH; + size_t payloadoff; + nghttp2_frame_unpack_frame_hd(&frame->hd, in); switch(frame->hd.type) { case NGHTTP2_HEADERS: + payloadoff = ((frame->hd.flags & NGHTTP2_FLAG_PAD_HIGH) > 0) + + ((frame->hd.flags & NGHTTP2_FLAG_PAD_LOW) > 0); rv = nghttp2_frame_unpack_headers_payload - (&frame->headers, payload, payloadlen); + (&frame->headers, payload + payloadoff, payloadlen - payloadoff); break; case NGHTTP2_PRIORITY: nghttp2_frame_unpack_priority_payload diff --git a/tests/nghttp2_test_helper.h b/tests/nghttp2_test_helper.h index e881bf1f..0f72a4b8 100644 --- a/tests/nghttp2_test_helper.h +++ b/tests/nghttp2_test_helper.h @@ -37,6 +37,24 @@ { (uint8_t*)NAME, (uint8_t*)VALUE, strlen(NAME), strlen(VALUE) } #define ARRLEN(ARR) (sizeof(ARR)/sizeof(ARR[0])) +#define assert_nv_equal(A, B, len) \ + do { \ + size_t alloclen = sizeof(nghttp2_nv) * len; \ + nghttp2_nv *sa = A, *sb = B; \ + nghttp2_nv *a = malloc(alloclen); \ + nghttp2_nv *b = malloc(alloclen); \ + ssize_t i_; \ + memcpy(a, sa, alloclen); \ + memcpy(b, sb, alloclen); \ + nghttp2_nv_array_sort(a, len); \ + nghttp2_nv_array_sort(b, len); \ + for(i_ = 0; i_ < (ssize_t)len; ++i_) { \ + CU_ASSERT(nghttp2_nv_equal(&a[i_], &b[i_])); \ + } \ + free(b); \ + free(a); \ + } while(0); + int unpack_frame(nghttp2_frame *frame, const uint8_t *in, size_t len); int strmemeq(const char *a, const uint8_t *b, size_t bn);