You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2020/09/03 19:08:58 UTC
[trafficserver] 01/05: Convert Mime and URL unit tests in
proxy/hdrs to Catch.
This is an automated email from the ASF dual-hosted git repository.
zwoop pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 40e9d411229ddab4860c9287cc48abee500dc414
Author: Walter Karas <wk...@verizonmedia.com>
AuthorDate: Wed Mar 18 13:01:13 2020 -0500
Convert Mime and URL unit tests in proxy/hdrs to Catch.
(cherry picked from commit 051661e1e9ff3a3d74250f31f0a72da414484b0e)
Conflicts:
proxy/hdrs/test_mime.cc
---
proxy/hdrs/Makefile.am | 17 +--
proxy/hdrs/URL.cc | 85 ++-----------
proxy/hdrs/test_mime.cc | 104 ----------------
proxy/hdrs/unit_tests/test_URL.cc | 95 ++++++++++++++
proxy/hdrs/unit_tests/test_mime.cc | 249 +++++++++++++++++++++++++++++++++++++
5 files changed, 356 insertions(+), 194 deletions(-)
diff --git a/proxy/hdrs/Makefile.am b/proxy/hdrs/Makefile.am
index 950dd2b..7fcd248 100644
--- a/proxy/hdrs/Makefile.am
+++ b/proxy/hdrs/Makefile.am
@@ -60,7 +60,6 @@ load_http_hdr_LDADD = -L. -lhdrs \
$(top_builddir)/src/tscpp/util/libtscpputil.la
check_PROGRAMS = \
- test_mime \
test_proxy_hdrs \
test_hdr_heap \
test_Huffmancode \
@@ -68,25 +67,15 @@ check_PROGRAMS = \
TESTS = $(check_PROGRAMS)
-test_mime_LDADD = -L. -lhdrs \
- $(top_builddir)/src/tscore/libtscore.la \
- $(top_builddir)/src/tscpp/util/libtscpputil.la \
- $(top_builddir)/iocore/eventsystem/libinkevent.a \
- $(top_builddir)/lib/records/librecords_p.a \
- $(top_builddir)/mgmt/libmgmt_p.la \
- $(top_builddir)/proxy/shared/libUglyLogStubs.a \
- @HWLOC_LIBS@ \
- @LIBCAP@
-
-test_mime_SOURCES = test_mime.cc
-
test_proxy_hdrs_CPPFLAGS = $(AM_CPPFLAGS) \
-I$(abs_top_srcdir)/tests/include
test_proxy_hdrs_SOURCES = \
unit_tests/unit_test_main.cc \
unit_tests/test_Hdrs.cc \
- unit_tests/test_HdrUtils.cc
+ unit_tests/test_HdrUtils.cc \
+ unit_tests/test_URL.cc \
+ unit_tests/test_mime.cc
test_proxy_hdrs_LDADD = \
$(top_builddir)/src/tscore/libtscore.la \
diff --git a/proxy/hdrs/URL.cc b/proxy/hdrs/URL.cc
index ad100a5..c528ee8 100644
--- a/proxy/hdrs/URL.cc
+++ b/proxy/hdrs/URL.cc
@@ -1160,11 +1160,16 @@ url_parse_scheme(HdrHeap *heap, URLImpl *url, const char **start, const char *en
return PARSE_RESULT_ERROR; // no non-whitespace found
}
+// This implementation namespace is necessary because this function is tested by a Catch unit test
+// in another source file.
+//
+namespace UrlImpl
+{
/**
* This method will return TRUE if the uri is strictly compliant with
* RFC 3986 and it will return FALSE if not.
*/
-static bool
+bool
url_is_strictly_compliant(const char *start, const char *end)
{
for (const char *i = start; i < end; ++i) {
@@ -1176,6 +1181,9 @@ url_is_strictly_compliant(const char *start, const char *end)
return true;
}
+} // namespace UrlImpl
+using namespace UrlImpl;
+
ParseResult
url_parse(HdrHeap *heap, URLImpl *url, const char **start, const char *end, bool copy_strings_p, bool strict_uri_parsing)
{
@@ -1801,78 +1809,3 @@ url_host_CryptoHash_get(URLImpl *url, CryptoHash *hash)
ctx.update(&port, sizeof(port));
ctx.finalize(*hash);
}
-
-/*-------------------------------------------------------------------------
- * Regression tests
- -------------------------------------------------------------------------*/
-#if TS_HAS_TESTS
-#include "tscore/TestBox.h"
-
-const static struct {
- const char *const text;
- bool valid;
-} http_validate_hdr_field_test_case[] = {{"yahoo", true},
- {"yahoo.com", true},
- {"yahoo.wow.com", true},
- {"yahoo.wow.much.amaze.com", true},
- {"209.131.52.50", true},
- {"192.168.0.1", true},
- {"localhost", true},
- {"3ffe:1900:4545:3:200:f8ff:fe21:67cf", true},
- {"fe80:0:0:0:200:f8ff:fe21:67cf", true},
- {"fe80::200:f8ff:fe21:67cf", true},
- {"<svg onload=alert(1)>", false}, // Sample host header XSS attack
- {"jlads;f8-9349*(D&F*D(234jD*(FSD*(VKLJ#(*$@()#$)))))", false},
- {"\"\t\n", false},
- {"!@#$%^ &*(*&^%$#@#$%^&*(*&^%$#))", false},
- {":):(:O!!!!!!", false}};
-
-REGRESSION_TEST(VALIDATE_HDR_FIELD)(RegressionTest *t, int /* level ATS_UNUSED */, int *pstatus)
-{
- TestBox box(t, pstatus);
- box = REGRESSION_TEST_PASSED;
-
- for (auto i : http_validate_hdr_field_test_case) {
- const char *const txt = i.text;
- box.check(validate_host_name({txt}) == i.valid, "Validation of FQDN (host) header: \"%s\", expected %s, but not", txt,
- (i.valid ? "true" : "false"));
- }
-}
-
-REGRESSION_TEST(ParseRules_strict_URI)(RegressionTest *t, int /* level ATS_UNUSED */, int *pstatus)
-{
- const struct {
- const char *const uri;
- bool valid;
- } http_strict_uri_parsing_test_case[] = {{"/home", true},
- {"/path/data?key=value#id", true},
- {"/ABCDEFGHIJKLMNOPQRSTUVWXYZ", true},
- {"/abcdefghijklmnopqrstuvwxyz", true},
- {"/0123456789", true},
- {":/?#[]@", true},
- {"!$&'()*+,;=", true},
- {"-._~", true},
- {"%", true},
- {"\n", false},
- {"\"", false},
- {"<", false},
- {">", false},
- {"\\", false},
- {"^", false},
- {"`", false},
- {"{", false},
- {"|", false},
- {"}", false},
- {"é", false}};
-
- TestBox box(t, pstatus);
- box = REGRESSION_TEST_PASSED;
-
- for (auto i : http_strict_uri_parsing_test_case) {
- const char *const uri = i.uri;
- box.check(url_is_strictly_compliant(uri, uri + strlen(uri)) == i.valid, "Strictly parse URI: \"%s\", expected %s, but not", uri,
- (i.valid ? "true" : "false"));
- }
-}
-
-#endif // TS_HAS_TESTS
diff --git a/proxy/hdrs/test_mime.cc b/proxy/hdrs/test_mime.cc
deleted file mode 100644
index eba287d..0000000
--- a/proxy/hdrs/test_mime.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-/** @file
-
- A brief file description
-
- @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 "tscore/TestBox.h"
-#include "I_EventSystem.h"
-#include "MIME.h"
-
-REGRESSION_TEST(MIME)(RegressionTest *t, int /* atype ATS_UNUSED */, int *pstatus)
-{
- TestBox box(t, pstatus);
- box = REGRESSION_TEST_PASSED;
-
- MIMEField *field;
- MIMEHdr hdr;
- hdr.create(NULL);
-
- hdr.field_create("Test1", 5);
- hdr.field_create("Test2", 5);
- hdr.field_create("Test3", 5);
- hdr.field_create("Test4", 5);
- field = hdr.field_create("Test5", 5);
-
- box.check(hdr.m_mime->m_first_fblock.contains(field), "The field block doesn't contain the field but it should");
- box.check(!hdr.m_mime->m_first_fblock.contains(field + (1L << 32)), "The field block contains the field but it shouldn't");
-
- int slot_num = mime_hdr_field_slotnum(hdr.m_mime, field);
- box.check(slot_num == 4, "Slot number is %d but should be 4", slot_num);
-
- slot_num = mime_hdr_field_slotnum(hdr.m_mime, field + (1L << 32));
- box.check(slot_num == -1, "Slot number is %d but should be -1", slot_num);
-
- hdr.destroy();
-}
-
-REGRESSION_TEST(MIME_PARSERS)(RegressionTest *t, int /* atype ATS_UNUSED */, int *pstatus)
-{
- const char *end;
- int value;
- TestBox box(t, pstatus);
- box = REGRESSION_TEST_PASSED;
-
- std::vector<std::pair<const char *, int>> tests = {{"0", 0},
- {"1234", 1234},
- {"-1234", -1234},
- {"2147483647", 2147483647},
- {"-2147483648", 2147483648},
- {"2147483648", INT_MAX},
- {"-2147483649", INT_MIN},
- {"2147483647", INT_MAX},
- {"-2147483648", INT_MIN},
- {"999999999999", INT_MAX},
- {"-999999999999", INT_MIN}};
-
- for (const auto &it : tests) {
- auto [buf, val] = it;
-
- end = buf + strlen(buf);
- box.check(mime_parse_int(buf, end) == val, "Failed mime_parse_int");
- box.check(mime_parse_integer(buf, end, &value), "Failed mime_parse_integer call");
- box.check(value == val, "Failed mime_parse_integer value");
- }
-
- // Also check the date parser, which relies heavily on the mime_parse_integer() function
- const char *date1 = "Sun, 05 Dec 1999 08:49:37 GMT";
- const char *date2 = "Sunday, 05-Dec-1999 08:49:37 GMT";
-
- int d1 = mime_parse_date(date1, date1 + strlen(date1));
- int d2 = mime_parse_date(date2, date2 + strlen(date2));
-
- box.check(d1 == d2, "Failed mime_parse_date");
-
- printf("Date1: %d\n", d1);
- printf("Date2: %d\n", d2);
-}
-
-int
-main(int argc, const char **argv)
-{
- Thread *main_thread = new EThread();
- main_thread->set_specific();
- mime_init();
-
- return RegressionTest::main(argc, argv, REGRESSION_TEST_QUICK);
-}
diff --git a/proxy/hdrs/unit_tests/test_URL.cc b/proxy/hdrs/unit_tests/test_URL.cc
new file mode 100644
index 0000000..9ebcd9d
--- /dev/null
+++ b/proxy/hdrs/unit_tests/test_URL.cc
@@ -0,0 +1,95 @@
+/** @file
+
+ Catch-based unit tests for URL
+
+ @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 <cstdio>
+
+#include "catch.hpp"
+
+#include "URL.h"
+
+TEST_CASE("ValidateURL", "[proxy][validurl]")
+{
+ static const struct {
+ const char *const text;
+ bool valid;
+ } http_validate_hdr_field_test_case[] = {{"yahoo", true},
+ {"yahoo.com", true},
+ {"yahoo.wow.com", true},
+ {"yahoo.wow.much.amaze.com", true},
+ {"209.131.52.50", true},
+ {"192.168.0.1", true},
+ {"localhost", true},
+ {"3ffe:1900:4545:3:200:f8ff:fe21:67cf", true},
+ {"fe80:0:0:0:200:f8ff:fe21:67cf", true},
+ {"fe80::200:f8ff:fe21:67cf", true},
+ {"<svg onload=alert(1)>", false}, // Sample host header XSS attack
+ {"jlads;f8-9349*(D&F*D(234jD*(FSD*(VKLJ#(*$@()#$)))))", false},
+ {"\"\t\n", false},
+ {"!@#$%^ &*(*&^%$#@#$%^&*(*&^%$#))", false},
+ {":):(:O!!!!!!", false}};
+ for (auto i : http_validate_hdr_field_test_case) {
+ const char *const txt = i.text;
+ if (validate_host_name({txt}) != i.valid) {
+ std::printf("Validation of FQDN (host) header: \"%s\", expected %s, but not\n", txt, (i.valid ? "true" : "false"));
+ CHECK(false);
+ }
+ }
+}
+
+namespace UrlImpl
+{
+bool url_is_strictly_compliant(const char *start, const char *end);
+}
+using namespace UrlImpl;
+
+TEST_CASE("ParseRulesStrictURI", "[proxy][parseuri]")
+{
+ const struct {
+ const char *const uri;
+ bool valid;
+ } http_strict_uri_parsing_test_case[] = {{"/home", true},
+ {"/path/data?key=value#id", true},
+ {"/ABCDEFGHIJKLMNOPQRSTUVWXYZ", true},
+ {"/abcdefghijklmnopqrstuvwxyz", true},
+ {"/0123456789", true},
+ {":/?#[]@", true},
+ {"!$&'()*+,;=", true},
+ {"-._~", true},
+ {"%", true},
+ {"\n", false},
+ {"\"", false},
+ {"<", false},
+ {">", false},
+ {"\\", false},
+ {"^", false},
+ {"`", false},
+ {"{", false},
+ {"|", false},
+ {"}", false},
+ {"é", false}};
+
+ for (auto i : http_strict_uri_parsing_test_case) {
+ const char *const uri = i.uri;
+ if (url_is_strictly_compliant(uri, uri + strlen(uri)) != i.valid) {
+ std::printf("Strictly parse URI: \"%s\", expected %s, but not\n", uri, (i.valid ? "true" : "false"));
+ CHECK(false);
+ }
+ }
+}
diff --git a/proxy/hdrs/unit_tests/test_mime.cc b/proxy/hdrs/unit_tests/test_mime.cc
new file mode 100644
index 0000000..0ad7038
--- /dev/null
+++ b/proxy/hdrs/unit_tests/test_mime.cc
@@ -0,0 +1,249 @@
+/** @file
+
+ A brief file description
+
+ @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 <cstdio>
+
+#include "catch.hpp"
+
+#include "I_EventSystem.h"
+#include "MIME.h"
+
+TEST_CASE("Mime", "[proxy][mime]")
+{
+ MIMEField *field;
+ MIMEHdr hdr;
+ hdr.create(NULL);
+
+ hdr.field_create("Test1", 5);
+ hdr.field_create("Test2", 5);
+ hdr.field_create("Test3", 5);
+ hdr.field_create("Test4", 5);
+ field = hdr.field_create("Test5", 5);
+
+ if (!hdr.m_mime->m_first_fblock.contains(field)) {
+ std::printf("The field block doesn't contain the field but it should\n");
+ CHECK(false);
+ }
+ if (hdr.m_mime->m_first_fblock.contains(field + (1L << 32))) {
+ std::printf("The field block contains the field but it shouldn't\n");
+ CHECK(false);
+ }
+
+ int slot_num = mime_hdr_field_slotnum(hdr.m_mime, field);
+ if (slot_num != 4) {
+ std::printf("Slot number is %d but should be 4\n", slot_num);
+ CHECK(false);
+ }
+
+ slot_num = mime_hdr_field_slotnum(hdr.m_mime, field + (1L << 32));
+ if (slot_num != -1) {
+ std::printf("Slot number is %d but should be -1\n", slot_num);
+ CHECK(false);
+ }
+
+ hdr.destroy();
+}
+
+TEST_CASE("MimeGetHostPortValues", "[proxy][mimeport]")
+{
+ MIMEHdr hdr;
+ hdr.create(NULL);
+
+ const char *header_value;
+ const char *host;
+ int host_len;
+ const char *port;
+ int port_len;
+
+ header_value = "host";
+ hdr.value_set("Host", 4, header_value, strlen(header_value));
+ hdr.get_host_port_values(&host, &host_len, &port, &port_len);
+ if (host_len != 4) {
+ std::printf("host length doesn't match\n");
+ CHECK(false);
+ }
+ if (strncmp(host, "host", host_len) != 0) {
+ std::printf("host string doesn't match\n");
+ CHECK(false);
+ }
+ if (port_len != 0) {
+ std::printf("port length doesn't match\n");
+ CHECK(false);
+ }
+ if (port != nullptr) {
+ std::printf("port string doesn't match\n");
+ CHECK(false);
+ }
+
+ header_value = "host:";
+ hdr.value_set("Host", 4, header_value, strlen(header_value));
+ hdr.get_host_port_values(&host, &host_len, &port, &port_len);
+ if (host_len != 4) {
+ std::printf("host length doesn't match\n");
+ CHECK(false);
+ }
+ if (strncmp(host, "host", host_len) != 0) {
+ std::printf("host string doesn't match\n");
+ CHECK(false);
+ }
+ if (port_len != 0) {
+ std::printf("port length doesn't match\n");
+ CHECK(false);
+ }
+ if (port != nullptr) {
+ std::printf("port string doesn't match\n");
+ CHECK(false);
+ }
+
+ header_value = "[host]";
+ hdr.value_set("Host", 4, header_value, strlen(header_value));
+ hdr.get_host_port_values(&host, &host_len, &port, &port_len);
+ if (host_len != 6) {
+ std::printf("host length doesn't match\n");
+ CHECK(false);
+ }
+ if (strncmp(host, "[host]", host_len) != 0) {
+ std::printf("host string doesn't match\n");
+ CHECK(false);
+ }
+ if (port_len != 0) {
+ std::printf("port length doesn't match\n");
+ CHECK(false);
+ }
+ if (port != nullptr) {
+ std::printf("port string doesn't match\n");
+ CHECK(false);
+ }
+
+ header_value = "host:port";
+ hdr.value_set("Host", 4, header_value, strlen(header_value));
+ hdr.get_host_port_values(&host, &host_len, &port, &port_len);
+ if (host_len != 4) {
+ std::printf("host length doesn't match\n");
+ CHECK(false);
+ }
+ if (strncmp(host, "host", host_len) != 0) {
+ std::printf("host string doesn't match\n");
+ CHECK(false);
+ }
+ if (port_len != 4) {
+ std::printf("port length doesn't match\n");
+ CHECK(false);
+ }
+ if (strncmp(port, "port", port_len) != 0) {
+ std::printf("port string doesn't match\n");
+ CHECK(false);
+ }
+
+ header_value = "[host]:port";
+ hdr.value_set("Host", 4, header_value, strlen(header_value));
+ hdr.get_host_port_values(&host, &host_len, &port, &port_len);
+ if (host_len != 6) {
+ std::printf("host length doesn't match\n");
+ CHECK(false);
+ }
+ if (strncmp(host, "[host]", host_len) != 0) {
+ std::printf("host string doesn't match\n");
+ CHECK(false);
+ }
+ if (port_len != 4) {
+ std::printf("port length doesn't match\n");
+ CHECK(false);
+ }
+ if (strncmp(port, "port", port_len) != 0) {
+ std::printf("port string doesn't match\n");
+ CHECK(false);
+ }
+
+ header_value = "[host]:";
+ hdr.value_set("Host", 4, header_value, strlen(header_value));
+ hdr.get_host_port_values(&host, &host_len, &port, &port_len);
+ if (host_len != 6) {
+ std::printf("host length doesn't match\n");
+ CHECK(false);
+ }
+ if (strncmp(host, "[host]", host_len) != 0) {
+ std::printf("host string doesn't match\n");
+ CHECK(false);
+ }
+ if (port_len != 0) {
+ std::printf("port length doesn't match\n");
+ CHECK(false);
+ }
+ if (port != nullptr) {
+ std::printf("port string doesn't match\n");
+ CHECK(false);
+ }
+
+ hdr.destroy();
+}
+
+TEST_CASE("MimeParsers", "[proxy][mimeparsers]")
+{
+ const char *end;
+ int value;
+
+ static const std::vector<std::pair<const char *, int>> tests = {{"0", 0},
+ {"1234", 1234},
+ {"-1234", -1234},
+ {"2147483647", 2147483647},
+ {"-2147483648", 2147483648},
+ {"2147483648", INT_MAX},
+ {"-2147483649", INT_MIN},
+ {"2147483647", INT_MAX},
+ {"-2147483648", INT_MIN},
+ {"999999999999", INT_MAX},
+ {"-999999999999", INT_MIN}};
+
+ for (const auto &it : tests) {
+ auto [buf, val] = it;
+
+ end = buf + strlen(buf);
+ if (mime_parse_int(buf, end) != val) {
+ std::printf("Failed mime_parse_int\n");
+ CHECK(false);
+ }
+ if (!mime_parse_integer(buf, end, &value)) {
+ std::printf("Failed mime_parse_integer call\n");
+ CHECK(false);
+ } else if (value != val) {
+ std::printf("Failed mime_parse_integer value\n");
+ CHECK(false);
+ }
+ }
+
+ // Also check the date parser, which relies heavily on the mime_parse_integer() function
+ const char *date1 = "Sun, 05 Dec 1999 08:49:37 GMT";
+ const char *date2 = "Sunday, 05-Dec-1999 08:49:37 GMT";
+
+ int d1 = mime_parse_date(date1, date1 + strlen(date1));
+ int d2 = mime_parse_date(date2, date2 + strlen(date2));
+
+ if (d1 != d2) {
+ std::printf("Failed mime_parse_date\n");
+ CHECK(false);
+ }
+
+ std::printf("Date1: %d\n", d1);
+ std::printf("Date2: %d\n", d2);
+}