diff --git a/.gitignore b/.gitignore index 7c84a7e20d6..6d2f706e0e8 100644 --- a/.gitignore +++ b/.gitignore @@ -102,6 +102,7 @@ proxy/hdrs/test_mime proxy/hdrs/test_proxy_hdrs proxy/hdrs/test_hdr_heap proxy/hdrs/test_Huffmancode +proxy/hdrs/test_XPACK proxy/http/test_proxy_http proxy/http2/test_Http2DependencyTree proxy/http2/test_HPACK diff --git a/proxy/hdrs/Makefile.am b/proxy/hdrs/Makefile.am index 63abeab04f5..7067f5514a4 100644 --- a/proxy/hdrs/Makefile.am +++ b/proxy/hdrs/Makefile.am @@ -69,7 +69,8 @@ check_PROGRAMS = \ test_mime \ test_proxy_hdrs \ test_hdr_heap \ - test_Huffmancode + test_Huffmancode \ + test_XPACK TESTS = $(check_PROGRAMS) @@ -133,6 +134,18 @@ test_Huffmancode_SOURCES = \ HuffmanCodec.cc \ HuffmanCodec.h +test_XPACK_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -I$(abs_top_srcdir)/tests/include + +test_XPACK_LDADD = \ + $(top_builddir)/src/tscore/libtscore.la \ + $(top_builddir)/src/tscpp/util/libtscpputil.la + +test_XPACK_SOURCES = \ + unit_tests/test_XPACK.cc \ + HuffmanCodec.cc \ + XPACK.cc #test_UNUSED_SOURCES = \ # test_urlhash.cc diff --git a/proxy/hdrs/unit_tests/test_XPACK.cc b/proxy/hdrs/unit_tests/test_XPACK.cc new file mode 100644 index 00000000000..91bd8b31161 --- /dev/null +++ b/proxy/hdrs/unit_tests/test_XPACK.cc @@ -0,0 +1,123 @@ +/** @file + + Catch based unit tests for XPACK + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#define CATCH_CONFIG_MAIN + +#include "catch.hpp" + +#include "XPACK.h" +#include "HuffmanCodec.h" + +static constexpr int BUFSIZE_FOR_REGRESSION_TEST = 128; + +TEST_CASE("XPACK_Integer", "[xpack]") +{ + // [RFC 7541] C.1. Integer Representation Examples + static const struct { + uint32_t raw_integer; + uint8_t *encoded_field; + int encoded_field_len; + int prefix; + } integer_test_case[] = {{10, (uint8_t *)"\x0a", 1, 5}, {1337, (uint8_t *)"\x1F\x9A\x0A", 3, 5}, {42, (uint8_t *)R"(*)", 1, 8}}; + + SECTION("Encoding") + { + for (const auto &i : integer_test_case) { + uint8_t buf[BUFSIZE_FOR_REGRESSION_TEST] = {0}; + + int len = xpack_encode_integer(buf, buf + BUFSIZE_FOR_REGRESSION_TEST, i.raw_integer, i.prefix); + + REQUIRE(len > 0); + REQUIRE(len == i.encoded_field_len); + REQUIRE(memcmp(buf, i.encoded_field, len) == 0); + } + } + + SECTION("Decoding") + { + for (const auto &i : integer_test_case) { + uint64_t actual = 0; + int len = xpack_decode_integer(actual, i.encoded_field, i.encoded_field + i.encoded_field_len, i.prefix); + + REQUIRE(len == i.encoded_field_len); + REQUIRE(actual == i.raw_integer); + } + } +} + +TEST_CASE("XPACK_String", "[xpack]") +{ + // Example: custom-key: custom-header + const static struct { + char *raw_string; + uint32_t raw_string_len; + uint8_t *encoded_field; + int encoded_field_len; + } string_test_case[] = {{(char *)"", 0, + (uint8_t *)"\x0" + "", + 1}, + {(char *)"custom-key", 10, + (uint8_t *)"\xA" + "custom-key", + 11}, + {(char *)"", 0, + (uint8_t *)"\x80" + "", + 1}, + {(char *)"custom-key", 10, + (uint8_t *)"\x88" + "\x25\xa8\x49\xe9\x5b\xa9\x7d\x7f", + 9}}; + + SECTION("Encoding") + { + // FIXME Current encoder support only huffman conding. + for (unsigned int i = 2; i < sizeof(string_test_case) / sizeof(string_test_case[0]); i++) { + uint8_t buf[BUFSIZE_FOR_REGRESSION_TEST] = {0}; + int len = xpack_encode_string(buf, buf + BUFSIZE_FOR_REGRESSION_TEST, string_test_case[i].raw_string, + string_test_case[i].raw_string_len); + + REQUIRE(len > 0); + REQUIRE(len == string_test_case[i].encoded_field_len); + REQUIRE(memcmp(buf, string_test_case[i].encoded_field, len) == 0); + } + } + + SECTION("Decoding") + { + // Decoding string needs huffman tree + hpack_huffman_init(); + + for (const auto &i : string_test_case) { + Arena arena; + char *actual = nullptr; + uint64_t actual_len = 0; + int len = xpack_decode_string(arena, &actual, actual_len, i.encoded_field, i.encoded_field + i.encoded_field_len); + + REQUIRE(len == i.encoded_field_len); + REQUIRE(actual_len == i.raw_string_len); + REQUIRE(memcmp(actual, i.raw_string, actual_len) == 0); + } + } +} diff --git a/proxy/http2/RegressionHPACK.cc b/proxy/http2/RegressionHPACK.cc index d8c0beb3b4e..8beb73d508c 100644 --- a/proxy/http2/RegressionHPACK.cc +++ b/proxy/http2/RegressionHPACK.cc @@ -41,37 +41,6 @@ const static int MAX_TABLE_SIZE = 4096; * * ***********************************************************************************/ -// [RFC 7541] C.1. Integer Representation Examples -const static struct { - uint32_t raw_integer; - uint8_t *encoded_field; - int encoded_field_len; - int prefix; -} integer_test_case[] = {{10, (uint8_t *)"\x0A", 1, 5}, {1337, (uint8_t *)"\x1F\x9A\x0A", 3, 5}, {42, (uint8_t *)R"(*)", 1, 8}}; - -// Example: custom-key: custom-header -const static struct { - char *raw_string; - uint32_t raw_string_len; - uint8_t *encoded_field; - int encoded_field_len; -} string_test_case[] = {{(char *)"", 0, - (uint8_t *)"\x0" - "", - 1}, - {(char *)"custom-key", 10, - (uint8_t *)"\xA" - "custom-key", - 11}, - {(char *)"", 0, - (uint8_t *)"\x80" - "", - 1}, - {(char *)"custom-key", 10, - (uint8_t *)"\x88" - "\x25\xa8\x49\xe9\x5b\xa9\x7d\x7f", - 9}}; - // [RFC 7541] C.2.4. Indexed Header Field const static struct { int index; @@ -317,43 +286,6 @@ const static struct { * * ***********************************************************************************/ -REGRESSION_TEST(HPACK_EncodeInteger)(RegressionTest *t, int, int *pstatus) -{ - TestBox box(t, pstatus); - box = REGRESSION_TEST_PASSED; - uint8_t buf[BUFSIZE_FOR_REGRESSION_TEST]; - - for (const auto &i : integer_test_case) { - memset(buf, 0, BUFSIZE_FOR_REGRESSION_TEST); - - int len = xpack_encode_integer(buf, buf + BUFSIZE_FOR_REGRESSION_TEST, i.raw_integer, i.prefix); - - box.check(len == i.encoded_field_len, "encoded length was %d, expecting %d", len, i.encoded_field_len); - box.check(len > 0 && memcmp(buf, i.encoded_field, len) == 0, "encoded value was invalid"); - } -} - -REGRESSION_TEST(HPACK_EncodeString)(RegressionTest *t, int, int *pstatus) -{ - TestBox box(t, pstatus); - box = REGRESSION_TEST_PASSED; - - uint8_t buf[BUFSIZE_FOR_REGRESSION_TEST]; - int len; - - // FIXME Current encoder support only huffman conding. - for (unsigned int i = 2; i < sizeof(string_test_case) / sizeof(string_test_case[0]); i++) { - memset(buf, 0, BUFSIZE_FOR_REGRESSION_TEST); - - len = xpack_encode_string(buf, buf + BUFSIZE_FOR_REGRESSION_TEST, string_test_case[i].raw_string, - string_test_case[i].raw_string_len); - - box.check(len == string_test_case[i].encoded_field_len, "encoded length was %d, expecting %d", len, - string_test_case[i].encoded_field_len); - box.check(len > 0 && memcmp(buf, string_test_case[i].encoded_field, len) == 0, "encoded string was invalid"); - } -} - REGRESSION_TEST(HPACK_EncodeIndexedHeaderField)(RegressionTest *t, int, int *pstatus) { TestBox box(t, pstatus); @@ -467,42 +399,6 @@ REGRESSION_TEST(HPACK_Encode)(RegressionTest *t, int, int *pstatus) } } -REGRESSION_TEST(HPACK_DecodeInteger)(RegressionTest *t, int, int *pstatus) -{ - TestBox box(t, pstatus); - box = REGRESSION_TEST_PASSED; - - uint64_t actual; - - for (const auto &i : integer_test_case) { - int len = xpack_decode_integer(actual, i.encoded_field, i.encoded_field + i.encoded_field_len, i.prefix); - - box.check(len == i.encoded_field_len, "decoded length was %d, expecting %d", len, i.encoded_field_len); - box.check(actual == i.raw_integer, "decoded value was %" PRIu64 ", expected %d", actual, i.raw_integer); - } -} - -REGRESSION_TEST(HPACK_DecodeString)(RegressionTest *t, int, int *pstatus) -{ - TestBox box(t, pstatus); - box = REGRESSION_TEST_PASSED; - - Arena arena; - char *actual = nullptr; - uint64_t actual_len = 0; - - hpack_huffman_init(); - - for (const auto &i : string_test_case) { - int len = xpack_decode_string(arena, &actual, actual_len, i.encoded_field, i.encoded_field + i.encoded_field_len); - - box.check(len == i.encoded_field_len, "decoded length was %d, expecting %d", len, i.encoded_field_len); - box.check(actual_len == i.raw_string_len, "length of decoded string was %" PRIu64 ", expecting %d", actual_len, - i.raw_string_len); - box.check(memcmp(actual, i.raw_string, actual_len) == 0, "decoded string was invalid"); - } -} - REGRESSION_TEST(HPACK_DecodeIndexedHeaderField)(RegressionTest *t, int, int *pstatus) { TestBox box(t, pstatus);