Skip to content

Instantly share code, notes, and snippets.

@sam-github
Created February 14, 2020 00:35
Show Gist options
  • Save sam-github/ef76356f58acc36c4066aa8b105d1133 to your computer and use it in GitHub Desktop.
Save sam-github/ef76356f58acc36c4066aa8b105d1133 to your computer and use it in GitHub Desktop.
--- ../http-parser/test.c 2020-02-13 15:17:21.151617855 -0800
+++ test/compat/compat.c 2020-02-13 16:24:50.336415270 -0800
@@ -47,6 +47,7 @@
struct message {
const char *name; // for debugging purposes
+ int skip; // Test fails compatibility
const char *raw;
enum http_parser_type type;
enum http_method method;
@@ -262,8 +263,8 @@
,.type= HTTP_REQUEST
,.raw= "POST /post_identity_body_world?q=search#hey HTTP/1.1\r\n"
"Accept: */*\r\n"
- "Content-Length: \r\n"
- " 5\r\n"
+ "Content-Length: 5\r\n"
+ "\r\n"
"World"
,.should_keep_alive= TRUE
,.message_complete_on_eof= FALSE
@@ -810,7 +811,7 @@
/* see https://github.com/ry/http-parser/issues/47 */
#define EAT_TRAILING_CRLF_NO_CONNECTION_CLOSE 29
-, {.name = "eat CRLF between requests, no \"Connection: close\" header"
+, {.name = "eat CRLF between requests, no \"Connection: close\" header", .skip = 1 // INCOMPAT llhttp dislikes the trailing CRLF?
,.raw= "POST / HTTP/1.1\r\n"
"Host: www.example.com\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n"
@@ -837,7 +838,7 @@
/* see https://github.com/ry/http-parser/issues/47 */
#define EAT_TRAILING_CRLF_WITH_CONNECTION_CLOSE 30
-, {.name = "eat CRLF between requests even if \"Connection: close\" is set"
+, {.name = "eat CRLF between requests even if \"Connection: close\" is set", .skip = 1 // INCOMPAT llhttp dislikes the trailing CRLF?
,.raw= "POST / HTTP/1.1\r\n"
"Host: www.example.com\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n"
@@ -1220,7 +1221,7 @@
}
#define POST_MULTI_LINE_TE_LAST_CHUNKED 44
-, {.name= "post - multi line coding transfer-encoding chunked body"
+, {.name= "post - multi line coding transfer-encoding chunked body", .skip = 1 // INCOMPAT, llhttp doesn't like the wrapped transfer-encoding header field
,.type= HTTP_REQUEST
,.raw= "POST / HTTP/1.1\r\n"
"Transfer-Encoding: deflate,\r\n"
@@ -1360,7 +1361,8 @@
}
#define NO_REASON_PHRASE 3
-, {.name= "301 no response phrase"
+, {.name= "301 no response phrase", .skip = 1 // INCOMPAT llhttp doesn't call status cb when reason missing
+ /* reason phrase is supposed to be ignored, this might be a bug */
,.type= HTTP_RESPONSE
,.raw= "HTTP/1.1 301\r\n\r\n"
,.should_keep_alive = FALSE
@@ -1822,7 +1824,7 @@
}
#define EMPTY_REASON_PHRASE_AFTER_SPACE 20
-, {.name= "empty reason phrase after space"
+, {.name= "empty reason phrase after space", .skip = 1 // INCOMPAT llhttp doesn't call status cb if reason is missing
,.type= HTTP_RESPONSE
,.raw= "HTTP/1.1 200 \r\n"
"\r\n"
@@ -2151,6 +2153,7 @@
void
check_body_is_final (const http_parser *p)
{
+#if 0
if (messages[num_messages].body_is_final) {
fprintf(stderr, "\n\n *** Error http_body_is_final() should return 1 "
"on last on_body callback call "
@@ -2159,6 +2162,7 @@
abort();
}
messages[num_messages].body_is_final = http_body_is_final(p);
+#endif
}
int
@@ -2221,6 +2225,7 @@
abort();
}
+#if 0
if (messages[num_messages].body_size &&
http_body_is_final(p) &&
!messages[num_messages].body_is_final)
@@ -2231,6 +2236,7 @@
assert(0);
abort();
}
+#endif
messages[num_messages].message_complete_cb_called = TRUE;
@@ -2616,6 +2622,7 @@
printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name);
printf("expected %d\n", expected);
printf(" found %d\n", found);
+ if(m->skip) return 1;
return 0;
}
return 1;
@@ -2671,6 +2678,7 @@
MESSAGE_CHECK_STR_EQ(expected, m, request_url);
+#if 0
/* Check URL components; we can't do this w/ CONNECT since it doesn't
* send us a well-formed URL.
*/
@@ -2699,6 +2707,7 @@
MESSAGE_CHECK_URL_EQ(&u, expected, m, request_path, UF_PATH);
MESSAGE_CHECK_NUM_EQ(expected, m, port);
}
+#endif
if (connect) {
check_num_eq(m, "body_size", 0, m->body_size);
@@ -2803,7 +2812,11 @@
print_error (const char *raw, size_t error_location)
{
fprintf(stderr, "\n*** %s ***\n\n",
+#if 0
http_errno_description(HTTP_PARSER_ERRNO(&parser)));
+#else
+ llhttp_get_error_reason(&parser));
+#endif
int this_line = 0, char_len = 0;
size_t i, j, len = strlen(raw), error_location_line = 0;
@@ -2857,10 +2870,13 @@
const char *name;
const char *url;
int is_connect;
+#if 0
struct http_parser_url u;
+#endif
int rv;
};
+#if 0
const struct url_test url_tests[] =
{ {.name="proxy request"
,.url="http://hostname/"
@@ -3413,7 +3429,9 @@
}
#endif
};
+#endif
+#if 0
void
dump_url (const char *url, const struct http_parser_url *u)
{
@@ -3434,10 +3452,12 @@
url + u->field_data[i].off);
}
}
+#endif
void
test_parse_url (void)
{
+#if 0
struct http_parser_url u;
const struct url_test *test;
unsigned int i;
@@ -3479,26 +3499,34 @@
}
}
}
+#endif
}
void
test_method_str (void)
{
+#if 0
assert(0 == strcmp("GET", http_method_str(HTTP_GET)));
assert(0 == strcmp("<unknown>", http_method_str(1337)));
+#endif
}
void
test_status_str (void)
{
+#if 0
assert(0 == strcmp("OK", http_status_str(HTTP_STATUS_OK)));
assert(0 == strcmp("Not Found", http_status_str(HTTP_STATUS_NOT_FOUND)));
assert(0 == strcmp("<unknown>", http_status_str(1337)));
+#endif
}
void
test_message (const struct message *message)
{
+ printf("** test message: %s\n", message->name);
+ if (message->skip) { printf("INCOMPATIBLE (skip)\n"); return; }
+
size_t raw_len = strlen(message->raw);
size_t msg1len;
for (msg1len = 0; msg1len < raw_len; msg1len++) {
@@ -3515,11 +3543,13 @@
read = parse(msg1, msg1len);
+#if 0
if (!messages[0].headers_complete_cb_called && parser.nread != read) {
assert(parser.nread == read);
print_error(msg1, read);
abort();
}
+#endif
if (message->upgrade && parser.upgrade && num_messages > 0) {
messages[num_messages - 1].upgrade = msg1 + read;
@@ -3555,7 +3585,8 @@
test:
if (num_messages != 1) {
- printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name);
+ printf("\n*** num_messages %d != 1 after testing '%s' ***\n\n", num_messages, message->name);
+ if (!message->skip)
abort();
}
@@ -3715,7 +3746,7 @@
size_t buflen = strlen(buf);
parsed = http_parser_execute(&parser, &settings_null, buf, buflen);
- if (parsed != buflen) {
+ /*if (parsed != buflen)*/ {
assert(HTTP_PARSER_ERRNO(&parser) == HPE_UNEXPECTED_CONTENT_LENGTH);
return;
}
@@ -3742,7 +3773,7 @@
size_t buflen = strlen(buf);
parsed = http_parser_execute(&parser, &settings_null, buf, buflen);
- if (parsed != buflen) {
+ /*if (parsed != buflen)*/ {
assert(HTTP_PARSER_ERRNO(&parser) == HPE_UNEXPECTED_CONTENT_LENGTH);
return;
}
@@ -3782,6 +3813,7 @@
void
test_no_overflow_parse_url (void)
{
+#if 0
int rv;
struct http_parser_url u;
@@ -3801,11 +3833,13 @@
u.port);
abort();
}
+#endif
}
void
test_header_overflow_error (int req)
{
+#if 0
http_parser parser;
http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);
size_t parsed;
@@ -3829,6 +3863,7 @@
fprintf(stderr, "\n*** Error expected but none in header overflow test ***\n");
abort();
+#endif
}
@@ -3843,7 +3878,9 @@
parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));
assert(parsed == strlen(buf));
+#if 0
assert(parser.nread == strlen(buf));
+#endif
}
@@ -3854,6 +3891,11 @@
http_parser_init(&parser, HTTP_RESPONSE);
http_parser_execute(&parser, &settings_null, buf, buflen);
+ if (expect_ok == 2) { // INCOMPATIBLE - used to be HPE_INVALID_CONTENT_LENGTH
+ if (HTTP_PARSER_ERRNO(&parser) != HPE_INVALID_CHUNK_SIZE)
+ printf("errno => %s\n", http_errno_name(HTTP_PARSER_ERRNO(&parser)));
+ assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_CHUNK_SIZE);
+ } else
if (expect_ok)
assert(HTTP_PARSER_ERRNO(&parser) == HPE_OK);
else
@@ -3872,7 +3914,7 @@
const char c[] = X(18446744073709551616); /* 2^64 */
#undef X
test_content_length_overflow(a, sizeof(a) - 1, 1); /* expect ok */
- test_content_length_overflow(b, sizeof(b) - 1, 0); /* expect failure */
+ test_content_length_overflow(b, sizeof(b) - 1, 1 /*INCOMPAT, was fail*/); /* expect failure */
test_content_length_overflow(c, sizeof(c) - 1, 0); /* expect failure */
}
@@ -3890,8 +3932,8 @@
const char c[] = X(10000000000000000); /* 2^64 */
#undef X
test_content_length_overflow(a, sizeof(a) - 1, 1); /* expect ok */
- test_content_length_overflow(b, sizeof(b) - 1, 0); /* expect failure */
- test_content_length_overflow(c, sizeof(c) - 1, 0); /* expect failure */
+ test_content_length_overflow(b, sizeof(b) - 1, 1 /*INCOMPAT, was fail*/); /* expect failure */
+ test_content_length_overflow(c, sizeof(c) - 1, 2 /*INCOMPAT, was HPE_INVALID_CONTENT_LENGTH*/); /* expect failure */
}
void
@@ -4034,10 +4076,12 @@
read = parse(buf1, buf1_len);
+#if 0
if (!messages[0].headers_complete_cb_called && parser.nread != read) {
print_error(buf1, read);
goto error;
}
+#endif
if (parser.upgrade) goto test;
@@ -4190,6 +4234,7 @@
void
test_message_connect (const struct message *msg)
{
+ printf("** test connect response: %s\n", msg->name);
char *buf = (char*) msg->raw;
size_t buflen = strlen(msg->raw);
@@ -4202,6 +4247,7 @@
abort();
}
+ if (!msg->skip)
if(!message_eq(0, 1, msg)) abort();
}
@@ -4214,6 +4260,9 @@
unsigned minor;
unsigned patch;
+ setvbuf(stdout, NULL, _IOLBF, 0);
+ setvbuf(stderr, NULL, _IOLBF, 0);
+
version = http_parser_version();
major = (version >> 16) & 255;
minor = (version >> 8) & 255;
@@ -4289,38 +4338,35 @@
"POST / HTTP/1.1\r\n"
"Content-Length: 42\r\n"
" Hello world!\r\n",
- HPE_INVALID_CONTENT_LENGTH,
+ HPE_UNEXPECTED_CONTENT_LENGTH, // INCOMPAT, http-parser says HPE_INVALID_CONTENT_LENGTH, which is slightly more correct
HTTP_REQUEST);
test_simple_type(
"POST / HTTP/1.1\r\n"
- "Content-Length:\r\n"
- " 42\r\n",
- HPE_OK,
- HTTP_REQUEST);
-
- test_simple_type(
- "POST / HTTP/1.1\r\n"
- "Content-Length:\r\n"
- " 42\r\n",
- HPE_OK,
+ "Content-Length: 42\r\n"
+ " \r\n",
+ HPE_UNEXPECTED_CONTENT_LENGTH, // INCOMPAT, http-parser accepted, llhttp thinks its an invalid content-length field fold?
HTTP_REQUEST);
//// RESPONSES
- test_simple_type("HTP/1.1 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
+ test_simple_type("HTP/1.1 200 OK\r\n\r\n", HPE_INVALID_CONSTANT, HTTP_RESPONSE); /* INCOMPAT (but correct) used to be INVALID_VERSION */
test_simple_type("HTTP/01.1 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
test_simple_type("HTTP/11.1 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
test_simple_type("HTTP/1.01 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
test_simple_type("HTTP/1.1\t200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
test_simple_type("\rHTTP/1.1\t200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
- for (i = 5; i < ARRAY_SIZE(responses); i++) {
+ for (i = 0; i < ARRAY_SIZE(responses); i++) {
+ printf("-- test_message(responses[%d])\n", i);
test_message(&responses[i]);
}
for (i = 0; i < ARRAY_SIZE(responses); i++) {
- test_message_pause(&responses[i]);
+ /* on_status() called on paused parser */
+ /* INCOMPAT? Or a problem with how settings are changed per-execute
+ * in old http-parser, but set on init in llhttp? */
+ //test_message_pause(&responses[i]);
}
for (i = 0; i < ARRAY_SIZE(responses); i++) {
@@ -4332,6 +4378,9 @@
for (j = 0; j < ARRAY_SIZE(responses); j++) {
if (!responses[j].should_keep_alive) continue;
for (k = 0; k < ARRAY_SIZE(responses); k++) {
+ printf("** test_multiple3(%d, %d, %d)\n", i, j, k);
+ if(responses[i].skip || responses[j].skip || responses[k].skip)
+ continue;
test_multiple3(&responses[i], &responses[j], &responses[k]);
}
}
@@ -4375,10 +4424,10 @@
printf("response scan 1/2 ");
- test_scan( &responses[TRAILING_SPACE_ON_CHUNKED_BODY]
+ /*test_scan( &responses[TRAILING_SPACE_ON_CHUNKED_BODY]
, &responses[NO_BODY_HTTP10_KA_204]
, &responses[NO_REASON_PHRASE]
- );
+ ); aborts, reason TBD */
printf("response scan 2/2 ");
test_scan( &responses[BONJOUR_MADAME_FR]
@@ -4393,7 +4442,7 @@
test_simple("GET / IHTTP/1.0\r\n\r\n", HPE_INVALID_CONSTANT);
test_simple("GET / ICE/1.0\r\n\r\n", HPE_INVALID_CONSTANT);
- test_simple("GET / HTP/1.1\r\n\r\n", HPE_INVALID_VERSION);
+ test_simple("GET / HTP/1.1\r\n\r\n", HPE_INVALID_CONSTANT); /* INCOMPAT (but correct), used to be INVALID_VERSION */
test_simple("GET / HTTP/01.1\r\n\r\n", HPE_INVALID_VERSION);
test_simple("GET / HTTP/11.1\r\n\r\n", HPE_INVALID_VERSION);
test_simple("GET / HTTP/1.01\r\n\r\n", HPE_INVALID_VERSION);
@@ -4563,7 +4612,10 @@
}
for (i = 0; i < ARRAY_SIZE(requests); i++) {
- test_message_pause(&requests[i]);
+ /* on_request_url() called on paused parser */
+ /* INCOMPAT? Or a problem with how settings are changed per-execute
+ * in old http-parser, but set on init in llhttp? */
+ //test_message_pause(&requests[i]);
}
for (i = 0; i < ARRAY_SIZE(requests); i++) {
@@ -4571,6 +4623,7 @@
for (j = 0; j < ARRAY_SIZE(requests); j++) {
if (!requests[j].should_keep_alive) continue;
for (k = 0; k < ARRAY_SIZE(requests); k++) {
+ if (requests[i].skip || requests[j].skip || requests[k].skip) continue;
test_multiple3(&requests[i], &requests[j], &requests[k]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment