trafficserver-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bc...@apache.org
Subject trafficserver git commit: TS-4001: Separate Regression Tests for HPACK from HTTP2.cc
Date Tue, 10 Nov 2015 03:55:10 GMT
Repository: trafficserver
Updated Branches:
  refs/heads/master 02fe08ee9 -> df48fade2


TS-4001: Separate Regression Tests for HPACK from HTTP2.cc

This closes #328


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/df48fade
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/df48fade
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/df48fade

Branch: refs/heads/master
Commit: df48fade2526b71aa6def113cfc307e883544a73
Parents: 02fe08e
Author: Masaori Koshiba <mkoshiba@yahoo-corp.jp>
Authored: Mon Nov 9 19:51:52 2015 -0800
Committer: Bryan Call <bcall@apache.org>
Committed: Mon Nov 9 19:51:52 2015 -0800

----------------------------------------------------------------------
 proxy/http2/HTTP2.cc           | 387 +--------------------------------
 proxy/http2/Makefile.am        |   5 +
 proxy/http2/RegressionHPACK.cc | 416 ++++++++++++++++++++++++++++++++++++
 3 files changed, 426 insertions(+), 382 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/df48fade/proxy/http2/HTTP2.cc
----------------------------------------------------------------------
diff --git a/proxy/http2/HTTP2.cc b/proxy/http2/HTTP2.cc
index ef33e6b..ce10d62 100644
--- a/proxy/http2/HTTP2.cc
+++ b/proxy/http2/HTTP2.cc
@@ -727,390 +727,14 @@ Http2::init()
 
 #if TS_HAS_TESTS
 
-#include "ts/TestBox.h"
-
-// Constants for regression test
-const static int BUFSIZE_FOR_REGRESSION_TEST = 128;
-const static int MAX_TEST_FIELD_NUM = 8;
-
-/***********************************************************************************
- *                                                                                 *
- *                       Regression test for HPACK                                 *
- *                                                                                 *
- *  Some test cases are based on examples of specification.                        *
- *  - https://tools.ietf.org/html/rfc7541#appendix-C                               *
- *                                                                                 *
- ***********************************************************************************/
-
-// [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 *) "\x2A", 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 *)"custom-key", 10, (uint8_t *) "\xA"
-                                                               "custom-key",
-                         11},
-                        {(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;
-  char *raw_name;
-  char *raw_value;
-  uint8_t *encoded_field;
-  int encoded_field_len;
-} indexed_test_case[] = {{2, (char *) ":method", (char *) "GET", (uint8_t *) "\x82", 1}};
-
-// [RFC 7541] C.2. Header Field Representation Examples
-const static struct {
-  char *raw_name;
-  char *raw_value;
-  int index;
-  HpackFieldType type;
-  uint8_t *encoded_field;
-  int encoded_field_len;
-} literal_test_case[] = {
-  {(char *)"custom-key", (char *) "custom-header", 0, HPACK_FIELD_INDEXED_LITERAL, (uint8_t
*) "\x40\x0a"
-                                                                                        
      "custom-key\x0d"
-                                                                                        
      "custom-header",
-   26},
-  {(char *)"custom-key", (char *) "custom-header", 0, HPACK_FIELD_NOINDEX_LITERAL, (uint8_t
*) "\x00\x0a"
-                                                                                        
      "custom-key\x0d"
-                                                                                        
      "custom-header",
-   26},
-  {(char *)"custom-key", (char *) "custom-header", 0, HPACK_FIELD_NEVERINDEX_LITERAL, (uint8_t
*) "\x10\x0a"
-                                                                                        
         "custom-key\x0d"
-                                                                                        
         "custom-header",
-   26},
-  {(char *)":path", (char *) "/sample/path", 4, HPACK_FIELD_INDEXED_LITERAL, (uint8_t *)
"\x44\x0c"
-                                                                                        
"/sample/path",
-   14},
-  {(char *)":path", (char *) "/sample/path", 4, HPACK_FIELD_NOINDEX_LITERAL, (uint8_t *)
"\x04\x0c"
-                                                                                        
"/sample/path",
-   14},
-  {(char *)":path", (char *) "/sample/path", 4, HPACK_FIELD_NEVERINDEX_LITERAL, (uint8_t
*) "\x14\x0c"
-                                                                                        
   "/sample/path",
-   14},
-  {(char *)"password", (char *) "secret", 0, HPACK_FIELD_INDEXED_LITERAL, (uint8_t *) "\x40\x08"
-                                                                                      "password\x06"
-                                                                                      "secret",
-   17},
-  {(char *)"password", (char *) "secret", 0, HPACK_FIELD_NOINDEX_LITERAL, (uint8_t *) "\x00\x08"
-                                                                                      "password\x06"
-                                                                                      "secret",
-   17},
-  {(char *)"password", (char *) "secret", 0, HPACK_FIELD_NEVERINDEX_LITERAL, (uint8_t *)
"\x10\x08"
-                                                                                        
"password\x06"
-                                                                                        
"secret",
-   17}};
-
-// [RFC 7541] C.3. Request Examples without Huffman Coding - C.3.1. First Request
-const static struct {
-  char *raw_name;
-  char *raw_value;
-} raw_field_test_case[][MAX_TEST_FIELD_NUM] = {{
-  {(char *)":method", (char *) "GET"},
-  {(char *)":scheme", (char *) "http"},
-  {(char *)":path", (char *) "/"},
-  {(char *)":authority", (char *) "www.example.com"},
-  {(char *)"", (char *) ""} // End of this test case
-}};
-const static struct {
-  uint8_t *encoded_field;
-  int encoded_field_len;
-} encoded_field_test_case[] = {{(uint8_t *)"\x40"
-                                           "\x7:method"
-                                           "\x3GET"
-                                           "\x40"
-                                           "\x7:scheme"
-                                           "\x4http"
-                                           "\x40"
-                                           "\x5:path"
-                                           "\x1/"
-                                           "\x40"
-                                           "\xa:authority"
-                                           "\xfwww.example.com",
-                                64}};
-
-/***********************************************************************************
- *                                                                                 *
- *                                Regression test codes                            *
- *                                                                                 *
- ***********************************************************************************/
-
-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 (unsigned int i = 0; i < sizeof(integer_test_case) / sizeof(integer_test_case[0]);
i++) {
-    memset(buf, 0, BUFSIZE_FOR_REGRESSION_TEST);
-
-    int len = encode_integer(buf, buf + BUFSIZE_FOR_REGRESSION_TEST, integer_test_case[i].raw_integer,
integer_test_case[i].prefix);
-
-    box.check(len == integer_test_case[i].encoded_field_len, "encoded length was %d, expecting
%d", len,
-              integer_test_case[i].encoded_field_len);
-    box.check(len > 0 && memcmp(buf, integer_test_case[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 don't support huffman conding.
-  for (unsigned int i = 0; i < 1; i++) {
-    memset(buf, 0, BUFSIZE_FOR_REGRESSION_TEST);
-
-    len = 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,
-              integer_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);
-  box = REGRESSION_TEST_PASSED;
-
-  uint8_t buf[BUFSIZE_FOR_REGRESSION_TEST];
-
-  for (unsigned int i = 0; i < sizeof(indexed_test_case) / sizeof(indexed_test_case[0]);
i++) {
-    memset(buf, 0, BUFSIZE_FOR_REGRESSION_TEST);
-
-    int len = encode_indexed_header_field(buf, buf + BUFSIZE_FOR_REGRESSION_TEST, indexed_test_case[i].index);
-
-    box.check(len == indexed_test_case[i].encoded_field_len, "encoded length was %d, expecting
%d", len,
-              indexed_test_case[i].encoded_field_len);
-    box.check(len > 0 && memcmp(buf, indexed_test_case[i].encoded_field, len)
== 0, "encoded value was invalid");
-  }
-}
-
-REGRESSION_TEST(HPACK_EncodeLiteralHeaderField)(RegressionTest *t, int, int *pstatus)
-{
-  TestBox box(t, pstatus);
-  box = REGRESSION_TEST_PASSED;
-
-  uint8_t buf[BUFSIZE_FOR_REGRESSION_TEST];
-  int len;
-
-  for (unsigned int i = 0; i < sizeof(literal_test_case) / sizeof(literal_test_case[0]);
i++) {
-    memset(buf, 0, BUFSIZE_FOR_REGRESSION_TEST);
-
-    ats_scoped_obj<HTTPHdr> headers(new HTTPHdr);
-    headers->create(HTTP_TYPE_RESPONSE);
-    MIMEField *field = mime_field_create(headers->m_heap, headers->m_http->m_fields_impl);
-    MIMEFieldWrapper header(field, headers->m_heap, headers->m_http->m_fields_impl);
-
-    header.value_set(literal_test_case[i].raw_value, strlen(literal_test_case[i].raw_value));
-    if (literal_test_case[i].index > 0) {
-      len = encode_literal_header_field(buf, buf + BUFSIZE_FOR_REGRESSION_TEST, header, literal_test_case[i].index,
-                                        literal_test_case[i].type);
-    } else {
-      header.name_set(literal_test_case[i].raw_name, strlen(literal_test_case[i].raw_name));
-      len = encode_literal_header_field(buf, buf + BUFSIZE_FOR_REGRESSION_TEST, header, literal_test_case[i].type);
-    }
-
-    box.check(len == literal_test_case[i].encoded_field_len, "encoded length was %d, expecting
%d", len,
-              literal_test_case[i].encoded_field_len);
-    box.check(len > 0 && memcmp(buf, literal_test_case[i].encoded_field, len)
== 0, "encoded value was invalid");
-  }
-}
-
-REGRESSION_TEST(HPACK_Encode)(RegressionTest *t, int, int *pstatus)
-{
-  TestBox box(t, pstatus);
-  box = REGRESSION_TEST_PASSED;
-
-  uint8_t buf[BUFSIZE_FOR_REGRESSION_TEST];
-  Http2DynamicTable dynamic_table;
-
-  // FIXME Current encoder don't support indexing.
-  for (unsigned int i = 0; i < sizeof(encoded_field_test_case) / sizeof(encoded_field_test_case[0]);
i++) {
-    ats_scoped_obj<HTTPHdr> headers(new HTTPHdr);
-    headers->create(HTTP_TYPE_REQUEST);
-
-    for (unsigned int j = 0; j < sizeof(raw_field_test_case[i]) / sizeof(raw_field_test_case[i][0]);
j++) {
-      const char *expected_name = raw_field_test_case[i][j].raw_name;
-      const char *expected_value = raw_field_test_case[i][j].raw_value;
-      if (strlen(expected_name) == 0)
-        break;
-
-      MIMEField *field = mime_field_create(headers->m_heap, headers->m_http->m_fields_impl);
-      mime_field_name_value_set(headers->m_heap, headers->m_http->m_fields_impl,
field, -1, expected_name, strlen(expected_name),
-                                expected_value, strlen(expected_value), 1, strlen(expected_name)
+ strlen(expected_value), true);
-      mime_hdr_field_attach(headers->m_http->m_fields_impl, field, 1, NULL);
-    }
-
-    memset(buf, 0, BUFSIZE_FOR_REGRESSION_TEST);
-    uint64_t buf_len = BUFSIZE_FOR_REGRESSION_TEST;
-    int64_t len = http2_write_psuedo_headers(headers, buf, buf_len, dynamic_table);
-    buf_len -= len;
-
-    MIMEFieldIter field_iter;
-    bool cont = false;
-    len += http2_write_header_fragment(headers, field_iter, buf, buf_len, dynamic_table,
cont);
-
-    box.check(len == encoded_field_test_case[i].encoded_field_len, "encoded length was %"
PRId64 ", expecting %d", len,
-              encoded_field_test_case[i].encoded_field_len);
-    box.check(len > 0 && memcmp(buf, encoded_field_test_case[i].encoded_field,
len) == 0, "encoded value was invalid");
-  }
-}
-
-REGRESSION_TEST(HPACK_DecodeInteger)(RegressionTest *t, int, int *pstatus)
-{
-  TestBox box(t, pstatus);
-  box = REGRESSION_TEST_PASSED;
-
-  uint32_t actual;
-
-  for (unsigned int i = 0; i < sizeof(integer_test_case) / sizeof(integer_test_case[0]);
i++) {
-    int len =
-      decode_integer(actual, integer_test_case[i].encoded_field,
-                     integer_test_case[i].encoded_field + integer_test_case[i].encoded_field_len,
integer_test_case[i].prefix);
-
-    box.check(len == integer_test_case[i].encoded_field_len, "decoded length was %d, expecting
%d", len,
-              integer_test_case[i].encoded_field_len);
-    box.check(actual == integer_test_case[i].raw_integer, "decoded value was %d, expected
%d", actual,
-              integer_test_case[i].raw_integer);
-  }
-}
-
-REGRESSION_TEST(HPACK_DecodeString)(RegressionTest *t, int, int *pstatus)
-{
-  TestBox box(t, pstatus);
-  box = REGRESSION_TEST_PASSED;
-
-  Arena arena;
-  char *actual = NULL;
-  uint32_t actual_len = 0;
-
-  hpack_huffman_init();
-
-  for (unsigned int i = 0; i < sizeof(string_test_case) / sizeof(string_test_case[0]);
i++) {
-    int len = decode_string(arena, &actual, actual_len, string_test_case[i].encoded_field,
-                            string_test_case[i].encoded_field + string_test_case[i].encoded_field_len);
-
-    box.check(len == string_test_case[i].encoded_field_len, "decoded length was %d, expecting
%d", len,
-              string_test_case[i].encoded_field_len);
-    box.check(actual_len == string_test_case[i].raw_string_len, "length of decoded string
was %d, expecting %d", actual_len,
-              string_test_case[i].raw_string_len);
-    box.check(memcmp(actual, string_test_case[i].raw_string, actual_len) == 0, "decoded string
was invalid");
-  }
-}
-
-REGRESSION_TEST(HPACK_DecodeIndexedHeaderField)(RegressionTest *t, int, int *pstatus)
-{
-  TestBox box(t, pstatus);
-  box = REGRESSION_TEST_PASSED;
-
-  Http2DynamicTable dynamic_table;
-
-  for (unsigned int i = 0; i < sizeof(indexed_test_case) / sizeof(indexed_test_case[0]);
i++) {
-    ats_scoped_obj<HTTPHdr> headers(new HTTPHdr);
-    headers->create(HTTP_TYPE_REQUEST);
-    MIMEField *field = mime_field_create(headers->m_heap, headers->m_http->m_fields_impl);
-    MIMEFieldWrapper header(field, headers->m_heap, headers->m_http->m_fields_impl);
-
-    int len =
-      decode_indexed_header_field(header, indexed_test_case[i].encoded_field,
-                                  indexed_test_case[i].encoded_field + indexed_test_case[i].encoded_field_len,
dynamic_table);
-
-    box.check(len == indexed_test_case[i].encoded_field_len, "decoded length was %d, expecting
%d", len,
-              indexed_test_case[i].encoded_field_len);
-
-    int name_len;
-    const char *name = header.name_get(&name_len);
-    box.check(len > 0 && memcmp(name, indexed_test_case[i].raw_name, name_len)
== 0, "decoded header name was invalid");
-
-    int actual_value_len;
-    const char *actual_value = header.value_get(&actual_value_len);
-    box.check(memcmp(actual_value, indexed_test_case[i].raw_value, actual_value_len) == 0,
"decoded header value was invalid");
-  }
-}
-
-REGRESSION_TEST(HPACK_DecodeLiteralHeaderField)(RegressionTest *t, int, int *pstatus)
+void forceLinkRegressionHPACK();
+void
+forceLinkRegressionHPACKCaller()
 {
-  TestBox box(t, pstatus);
-  box = REGRESSION_TEST_PASSED;
-
-  Http2DynamicTable dynamic_table;
-
-  for (unsigned int i = 0; i < sizeof(literal_test_case) / sizeof(literal_test_case[0]);
i++) {
-    ats_scoped_obj<HTTPHdr> headers(new HTTPHdr);
-    headers->create(HTTP_TYPE_REQUEST);
-    MIMEField *field = mime_field_create(headers->m_heap, headers->m_http->m_fields_impl);
-    MIMEFieldWrapper header(field, headers->m_heap, headers->m_http->m_fields_impl);
-
-    int len =
-      decode_literal_header_field(header, literal_test_case[i].encoded_field,
-                                  literal_test_case[i].encoded_field + literal_test_case[i].encoded_field_len,
dynamic_table);
-
-    box.check(len == literal_test_case[i].encoded_field_len, "decoded length was %d, expecting
%d", len,
-              literal_test_case[i].encoded_field_len);
-
-    int name_len;
-    const char *name = header.name_get(&name_len);
-    box.check(name_len > 0 && memcmp(name, literal_test_case[i].raw_name, name_len)
== 0, "decoded header name was invalid");
-
-    int actual_value_len;
-    const char *actual_value = header.value_get(&actual_value_len);
-    box.check(actual_value_len > 0 && memcmp(actual_value, literal_test_case[i].raw_value,
actual_value_len) == 0,
-              "decoded header value was invalid");
-  }
+  forceLinkRegressionHPACK();
 }
 
-REGRESSION_TEST(HPACK_Decode)(RegressionTest *t, int, int *pstatus)
-{
-  TestBox box(t, pstatus);
-  box = REGRESSION_TEST_PASSED;
-
-  Http2DynamicTable dynamic_table;
-
-  for (unsigned int i = 0; i < sizeof(encoded_field_test_case) / sizeof(encoded_field_test_case[0]);
i++) {
-    ats_scoped_obj<HTTPHdr> headers(new HTTPHdr);
-    headers->create(HTTP_TYPE_REQUEST);
-
-    http2_decode_header_blocks(headers, encoded_field_test_case[i].encoded_field,
-                               encoded_field_test_case[i].encoded_field + encoded_field_test_case[i].encoded_field_len,
-                               dynamic_table);
-
-    for (unsigned int j = 0; j < sizeof(raw_field_test_case[i]) / sizeof(raw_field_test_case[i][0]);
j++) {
-      const char *expected_name = raw_field_test_case[i][j].raw_name;
-      const char *expected_value = raw_field_test_case[i][j].raw_value;
-      if (strlen(expected_name) == 0)
-        break;
-
-      MIMEField *field = headers->field_find(expected_name, strlen(expected_name));
-      box.check(field != NULL, "A MIMEField that has \"%s\" as name doesn't exist", expected_name);
-
-      if (field) {
-        int actual_value_len;
-        const char *actual_value = field->value_get(&actual_value_len);
-        box.check(strncmp(expected_value, actual_value, actual_value_len) == 0,
-                  "A MIMEField that has \"%s\" as value doesn't exist", expected_value);
-      }
-    }
-  }
-}
+#include "ts/TestBox.h"
 
 /***********************************************************************************
  *                                                                                 *
@@ -1118,7 +742,6 @@ REGRESSION_TEST(HPACK_Decode)(RegressionTest *t, int, int *pstatus)
  *                                                                                 *
  ***********************************************************************************/
 
-
 const static struct {
   uint8_t ftype;
   uint8_t fflags;

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/df48fade/proxy/http2/Makefile.am
----------------------------------------------------------------------
diff --git a/proxy/http2/Makefile.am b/proxy/http2/Makefile.am
index 5d526da..0db813c 100644
--- a/proxy/http2/Makefile.am
+++ b/proxy/http2/Makefile.am
@@ -47,6 +47,11 @@ libhttp2_a_SOURCES = \
   HuffmanCodec.cc \
   HuffmanCodec.h
 
+if BUILD_TESTS
+  libhttp2_a_SOURCES += \
+	  RegressionHPACK.cc
+endif
+
 noinst_PROGRAMS = \
   test_Huffmancode
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/df48fade/proxy/http2/RegressionHPACK.cc
----------------------------------------------------------------------
diff --git a/proxy/http2/RegressionHPACK.cc b/proxy/http2/RegressionHPACK.cc
new file mode 100644
index 0000000..f4e8da8
--- /dev/null
+++ b/proxy/http2/RegressionHPACK.cc
@@ -0,0 +1,416 @@
+/** @file
+ *
+ *  Regression Tests for HPACK
+ *
+ *  @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.
+ */
+
+#include "HTTP2.h"
+#include "HPACK.h"
+#include "HuffmanCodec.h"
+#include "ts/TestBox.h"
+
+// Constants for regression test
+const static int BUFSIZE_FOR_REGRESSION_TEST = 128;
+const static int MAX_TEST_FIELD_NUM = 8;
+
+/***********************************************************************************
+ *                                                                                 *
+ *                       Regression test for HPACK                                 *
+ *                                                                                 *
+ *  Some test cases are based on examples of specification.                        *
+ *  - https://tools.ietf.org/html/rfc7541#appendix-C                               *
+ *                                                                                 *
+ ***********************************************************************************/
+
+// [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 *) "\x2A", 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 *)"custom-key", 10, (uint8_t *) "\xA"
+                                                               "custom-key",
+                         11},
+                        {(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;
+  char *raw_name;
+  char *raw_value;
+  uint8_t *encoded_field;
+  int encoded_field_len;
+} indexed_test_case[] = {{2, (char *) ":method", (char *) "GET", (uint8_t *) "\x82", 1}};
+
+// [RFC 7541] C.2. Header Field Representation Examples
+const static struct {
+  char *raw_name;
+  char *raw_value;
+  int index;
+  HpackFieldType type;
+  uint8_t *encoded_field;
+  int encoded_field_len;
+} literal_test_case[] = {
+  {(char *)"custom-key", (char *) "custom-header", 0, HPACK_FIELD_INDEXED_LITERAL, (uint8_t
*) "\x40\x0a"
+                                                                                        
      "custom-key\x0d"
+                                                                                        
      "custom-header",
+   26},
+  {(char *)"custom-key", (char *) "custom-header", 0, HPACK_FIELD_NOINDEX_LITERAL, (uint8_t
*) "\x00\x0a"
+                                                                                        
      "custom-key\x0d"
+                                                                                        
      "custom-header",
+   26},
+  {(char *)"custom-key", (char *) "custom-header", 0, HPACK_FIELD_NEVERINDEX_LITERAL, (uint8_t
*) "\x10\x0a"
+                                                                                        
         "custom-key\x0d"
+                                                                                        
         "custom-header",
+   26},
+  {(char *)":path", (char *) "/sample/path", 4, HPACK_FIELD_INDEXED_LITERAL, (uint8_t *)
"\x44\x0c"
+                                                                                        
"/sample/path",
+   14},
+  {(char *)":path", (char *) "/sample/path", 4, HPACK_FIELD_NOINDEX_LITERAL, (uint8_t *)
"\x04\x0c"
+                                                                                        
"/sample/path",
+   14},
+  {(char *)":path", (char *) "/sample/path", 4, HPACK_FIELD_NEVERINDEX_LITERAL, (uint8_t
*) "\x14\x0c"
+                                                                                        
   "/sample/path",
+   14},
+  {(char *)"password", (char *) "secret", 0, HPACK_FIELD_INDEXED_LITERAL, (uint8_t *) "\x40\x08"
+                                                                                      "password\x06"
+                                                                                      "secret",
+   17},
+  {(char *)"password", (char *) "secret", 0, HPACK_FIELD_NOINDEX_LITERAL, (uint8_t *) "\x00\x08"
+                                                                                      "password\x06"
+                                                                                      "secret",
+   17},
+  {(char *)"password", (char *) "secret", 0, HPACK_FIELD_NEVERINDEX_LITERAL, (uint8_t *)
"\x10\x08"
+                                                                                        
"password\x06"
+                                                                                        
"secret",
+   17}};
+
+// [RFC 7541] C.3. Request Examples without Huffman Coding - C.3.1. First Request
+const static struct {
+  char *raw_name;
+  char *raw_value;
+} raw_field_test_case[][MAX_TEST_FIELD_NUM] = {{
+  {(char *)":method", (char *) "GET"},
+  {(char *)":scheme", (char *) "http"},
+  {(char *)":path", (char *) "/"},
+  {(char *)":authority", (char *) "www.example.com"},
+  {(char *)"", (char *) ""} // End of this test case
+}};
+const static struct {
+  uint8_t *encoded_field;
+  int encoded_field_len;
+} encoded_field_test_case[] = {{(uint8_t *)"\x40"
+                                           "\x7:method"
+                                           "\x3GET"
+                                           "\x40"
+                                           "\x7:scheme"
+                                           "\x4http"
+                                           "\x40"
+                                           "\x5:path"
+                                           "\x1/"
+                                           "\x40"
+                                           "\xa:authority"
+                                           "\xfwww.example.com",
+                                64}};
+
+/***********************************************************************************
+ *                                                                                 *
+ *                                Regression test codes                            *
+ *                                                                                 *
+ ***********************************************************************************/
+
+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 (unsigned int i = 0; i < sizeof(integer_test_case) / sizeof(integer_test_case[0]);
i++) {
+    memset(buf, 0, BUFSIZE_FOR_REGRESSION_TEST);
+
+    int len = encode_integer(buf, buf + BUFSIZE_FOR_REGRESSION_TEST, integer_test_case[i].raw_integer,
integer_test_case[i].prefix);
+
+    box.check(len == integer_test_case[i].encoded_field_len, "encoded length was %d, expecting
%d", len,
+              integer_test_case[i].encoded_field_len);
+    box.check(len > 0 && memcmp(buf, integer_test_case[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 don't support huffman conding.
+  for (unsigned int i = 0; i < 1; i++) {
+    memset(buf, 0, BUFSIZE_FOR_REGRESSION_TEST);
+
+    len = 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,
+              integer_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);
+  box = REGRESSION_TEST_PASSED;
+
+  uint8_t buf[BUFSIZE_FOR_REGRESSION_TEST];
+
+  for (unsigned int i = 0; i < sizeof(indexed_test_case) / sizeof(indexed_test_case[0]);
i++) {
+    memset(buf, 0, BUFSIZE_FOR_REGRESSION_TEST);
+
+    int len = encode_indexed_header_field(buf, buf + BUFSIZE_FOR_REGRESSION_TEST, indexed_test_case[i].index);
+
+    box.check(len == indexed_test_case[i].encoded_field_len, "encoded length was %d, expecting
%d", len,
+              indexed_test_case[i].encoded_field_len);
+    box.check(len > 0 && memcmp(buf, indexed_test_case[i].encoded_field, len)
== 0, "encoded value was invalid");
+  }
+}
+
+REGRESSION_TEST(HPACK_EncodeLiteralHeaderField)(RegressionTest *t, int, int *pstatus)
+{
+  TestBox box(t, pstatus);
+  box = REGRESSION_TEST_PASSED;
+
+  uint8_t buf[BUFSIZE_FOR_REGRESSION_TEST];
+  int len;
+
+  for (unsigned int i = 0; i < sizeof(literal_test_case) / sizeof(literal_test_case[0]);
i++) {
+    memset(buf, 0, BUFSIZE_FOR_REGRESSION_TEST);
+
+    ats_scoped_obj<HTTPHdr> headers(new HTTPHdr);
+    headers->create(HTTP_TYPE_RESPONSE);
+    MIMEField *field = mime_field_create(headers->m_heap, headers->m_http->m_fields_impl);
+    MIMEFieldWrapper header(field, headers->m_heap, headers->m_http->m_fields_impl);
+
+    header.value_set(literal_test_case[i].raw_value, strlen(literal_test_case[i].raw_value));
+    if (literal_test_case[i].index > 0) {
+      len = encode_literal_header_field(buf, buf + BUFSIZE_FOR_REGRESSION_TEST, header, literal_test_case[i].index,
+                                        literal_test_case[i].type);
+    } else {
+      header.name_set(literal_test_case[i].raw_name, strlen(literal_test_case[i].raw_name));
+      len = encode_literal_header_field(buf, buf + BUFSIZE_FOR_REGRESSION_TEST, header, literal_test_case[i].type);
+    }
+
+    box.check(len == literal_test_case[i].encoded_field_len, "encoded length was %d, expecting
%d", len,
+              literal_test_case[i].encoded_field_len);
+    box.check(len > 0 && memcmp(buf, literal_test_case[i].encoded_field, len)
== 0, "encoded value was invalid");
+  }
+}
+
+REGRESSION_TEST(HPACK_Encode)(RegressionTest *t, int, int *pstatus)
+{
+  TestBox box(t, pstatus);
+  box = REGRESSION_TEST_PASSED;
+
+  uint8_t buf[BUFSIZE_FOR_REGRESSION_TEST];
+  Http2DynamicTable dynamic_table;
+
+  // FIXME Current encoder don't support indexing.
+  for (unsigned int i = 0; i < sizeof(encoded_field_test_case) / sizeof(encoded_field_test_case[0]);
i++) {
+    ats_scoped_obj<HTTPHdr> headers(new HTTPHdr);
+    headers->create(HTTP_TYPE_REQUEST);
+
+    for (unsigned int j = 0; j < sizeof(raw_field_test_case[i]) / sizeof(raw_field_test_case[i][0]);
j++) {
+      const char *expected_name = raw_field_test_case[i][j].raw_name;
+      const char *expected_value = raw_field_test_case[i][j].raw_value;
+      if (strlen(expected_name) == 0)
+        break;
+
+      MIMEField *field = mime_field_create(headers->m_heap, headers->m_http->m_fields_impl);
+      mime_field_name_value_set(headers->m_heap, headers->m_http->m_fields_impl,
field, -1, expected_name, strlen(expected_name),
+                                expected_value, strlen(expected_value), 1, strlen(expected_name)
+ strlen(expected_value), true);
+      mime_hdr_field_attach(headers->m_http->m_fields_impl, field, 1, NULL);
+    }
+
+    memset(buf, 0, BUFSIZE_FOR_REGRESSION_TEST);
+    uint64_t buf_len = BUFSIZE_FOR_REGRESSION_TEST;
+    int64_t len = http2_write_psuedo_headers(headers, buf, buf_len, dynamic_table);
+    buf_len -= len;
+
+    MIMEFieldIter field_iter;
+    bool cont = false;
+    len += http2_write_header_fragment(headers, field_iter, buf, buf_len, dynamic_table,
cont);
+
+    box.check(len == encoded_field_test_case[i].encoded_field_len, "encoded length was %"
PRId64 ", expecting %d", len,
+              encoded_field_test_case[i].encoded_field_len);
+    box.check(len > 0 && memcmp(buf, encoded_field_test_case[i].encoded_field,
len) == 0, "encoded value was invalid");
+  }
+}
+
+REGRESSION_TEST(HPACK_DecodeInteger)(RegressionTest *t, int, int *pstatus)
+{
+  TestBox box(t, pstatus);
+  box = REGRESSION_TEST_PASSED;
+
+  uint32_t actual;
+
+  for (unsigned int i = 0; i < sizeof(integer_test_case) / sizeof(integer_test_case[0]);
i++) {
+    int len =
+      decode_integer(actual, integer_test_case[i].encoded_field,
+                     integer_test_case[i].encoded_field + integer_test_case[i].encoded_field_len,
integer_test_case[i].prefix);
+
+    box.check(len == integer_test_case[i].encoded_field_len, "decoded length was %d, expecting
%d", len,
+              integer_test_case[i].encoded_field_len);
+    box.check(actual == integer_test_case[i].raw_integer, "decoded value was %d, expected
%d", actual,
+              integer_test_case[i].raw_integer);
+  }
+}
+
+REGRESSION_TEST(HPACK_DecodeString)(RegressionTest *t, int, int *pstatus)
+{
+  TestBox box(t, pstatus);
+  box = REGRESSION_TEST_PASSED;
+
+  Arena arena;
+  char *actual = NULL;
+  uint32_t actual_len = 0;
+
+  hpack_huffman_init();
+
+  for (unsigned int i = 0; i < sizeof(string_test_case) / sizeof(string_test_case[0]);
i++) {
+    int len = decode_string(arena, &actual, actual_len, string_test_case[i].encoded_field,
+                            string_test_case[i].encoded_field + string_test_case[i].encoded_field_len);
+
+    box.check(len == string_test_case[i].encoded_field_len, "decoded length was %d, expecting
%d", len,
+              string_test_case[i].encoded_field_len);
+    box.check(actual_len == string_test_case[i].raw_string_len, "length of decoded string
was %d, expecting %d", actual_len,
+              string_test_case[i].raw_string_len);
+    box.check(memcmp(actual, string_test_case[i].raw_string, actual_len) == 0, "decoded string
was invalid");
+  }
+}
+
+REGRESSION_TEST(HPACK_DecodeIndexedHeaderField)(RegressionTest *t, int, int *pstatus)
+{
+  TestBox box(t, pstatus);
+  box = REGRESSION_TEST_PASSED;
+
+  Http2DynamicTable dynamic_table;
+
+  for (unsigned int i = 0; i < sizeof(indexed_test_case) / sizeof(indexed_test_case[0]);
i++) {
+    ats_scoped_obj<HTTPHdr> headers(new HTTPHdr);
+    headers->create(HTTP_TYPE_REQUEST);
+    MIMEField *field = mime_field_create(headers->m_heap, headers->m_http->m_fields_impl);
+    MIMEFieldWrapper header(field, headers->m_heap, headers->m_http->m_fields_impl);
+
+    int len =
+      decode_indexed_header_field(header, indexed_test_case[i].encoded_field,
+                                  indexed_test_case[i].encoded_field + indexed_test_case[i].encoded_field_len,
dynamic_table);
+
+    box.check(len == indexed_test_case[i].encoded_field_len, "decoded length was %d, expecting
%d", len,
+              indexed_test_case[i].encoded_field_len);
+
+    int name_len;
+    const char *name = header.name_get(&name_len);
+    box.check(len > 0 && memcmp(name, indexed_test_case[i].raw_name, name_len)
== 0, "decoded header name was invalid");
+
+    int actual_value_len;
+    const char *actual_value = header.value_get(&actual_value_len);
+    box.check(memcmp(actual_value, indexed_test_case[i].raw_value, actual_value_len) == 0,
"decoded header value was invalid");
+  }
+}
+
+REGRESSION_TEST(HPACK_DecodeLiteralHeaderField)(RegressionTest *t, int, int *pstatus)
+{
+  TestBox box(t, pstatus);
+  box = REGRESSION_TEST_PASSED;
+
+  Http2DynamicTable dynamic_table;
+
+  for (unsigned int i = 0; i < sizeof(literal_test_case) / sizeof(literal_test_case[0]);
i++) {
+    ats_scoped_obj<HTTPHdr> headers(new HTTPHdr);
+    headers->create(HTTP_TYPE_REQUEST);
+    MIMEField *field = mime_field_create(headers->m_heap, headers->m_http->m_fields_impl);
+    MIMEFieldWrapper header(field, headers->m_heap, headers->m_http->m_fields_impl);
+
+    int len =
+      decode_literal_header_field(header, literal_test_case[i].encoded_field,
+                                  literal_test_case[i].encoded_field + literal_test_case[i].encoded_field_len,
dynamic_table);
+
+    box.check(len == literal_test_case[i].encoded_field_len, "decoded length was %d, expecting
%d", len,
+              literal_test_case[i].encoded_field_len);
+
+    int name_len;
+    const char *name = header.name_get(&name_len);
+    box.check(name_len > 0 && memcmp(name, literal_test_case[i].raw_name, name_len)
== 0, "decoded header name was invalid");
+
+    int actual_value_len;
+    const char *actual_value = header.value_get(&actual_value_len);
+    box.check(actual_value_len > 0 && memcmp(actual_value, literal_test_case[i].raw_value,
actual_value_len) == 0,
+              "decoded header value was invalid");
+  }
+}
+
+REGRESSION_TEST(HPACK_Decode)(RegressionTest *t, int, int *pstatus)
+{
+  TestBox box(t, pstatus);
+  box = REGRESSION_TEST_PASSED;
+
+  Http2DynamicTable dynamic_table;
+
+  for (unsigned int i = 0; i < sizeof(encoded_field_test_case) / sizeof(encoded_field_test_case[0]);
i++) {
+    ats_scoped_obj<HTTPHdr> headers(new HTTPHdr);
+    headers->create(HTTP_TYPE_REQUEST);
+
+    http2_decode_header_blocks(headers, encoded_field_test_case[i].encoded_field,
+                               encoded_field_test_case[i].encoded_field + encoded_field_test_case[i].encoded_field_len,
+                               dynamic_table);
+
+    for (unsigned int j = 0; j < sizeof(raw_field_test_case[i]) / sizeof(raw_field_test_case[i][0]);
j++) {
+      const char *expected_name = raw_field_test_case[i][j].raw_name;
+      const char *expected_value = raw_field_test_case[i][j].raw_value;
+      if (strlen(expected_name) == 0)
+        break;
+
+      MIMEField *field = headers->field_find(expected_name, strlen(expected_name));
+      box.check(field != NULL, "A MIMEField that has \"%s\" as name doesn't exist", expected_name);
+
+      if (field) {
+        int actual_value_len;
+        const char *actual_value = field->value_get(&actual_value_len);
+        box.check(strncmp(expected_value, actual_value, actual_value_len) == 0,
+                  "A MIMEField that has \"%s\" as value doesn't exist", expected_value);
+      }
+    }
+  }
+}
+
+void
+forceLinkRegressionHPACK()
+{
+  // NOTE: Do Nothing
+}


Mime
View raw message