This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
stellar-stellar/test/decoders/http/http_gtest_llhttp.cpp

508 lines
21 KiB
C++
Raw Normal View History

2024-10-18 16:47:51 +08:00
#include <cstdint>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <gtest/gtest.h>
#include "stellar/utils.h"
#ifdef __cplusplus
extern "C"
{
#endif
#include <llhttp.h>
#ifdef __cplusplus
}
#endif
#ifndef UNUSED
#define UNUSED __attribute__((unused))
#endif
struct gtest_http_counter
{
uint8_t flag_on_message_begin;
uint8_t flag_on_url;
uint8_t flag_on_method;
uint8_t flag_on_status;
uint8_t flag_on_version;
uint8_t flag_on_header_field;
uint8_t flag_on_header_field_complete;
uint8_t flag_on_header_value;
uint8_t flag_on_header_value_complete;
uint8_t flag_on_headers_complete;
uint8_t flag_on_body;
uint8_t flag_on_message_complete;
};
struct gtest_http_parm
{
llhttp_t llhttp_parser;
llhttp_settings_t settings;
struct gtest_http_counter count;
};
static int on_message_begin(llhttp_t *parser)
{
printf("Message begin cb\n");
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_message_begin++;
return 0;
}
static int on_url(llhttp_t *parser, const char *at, size_t length)
{
printf("URI cb: %.*s\n", (int)length, at);
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_url++;
return 0;
}
static int on_method(llhttp_t *parser, const char *at, size_t length)
{
printf("method cb: %.*s\n", (int)length, at);
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_method++;
return 0;
}
static int on_status(llhttp_t *parser, const char *at, size_t length)
{
printf("status cb: %.*s\n", (int)length, at);
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_status++;
return 0;
}
static int on_version(llhttp_t *parser, const char *at, size_t length)
{
printf("version cb: %.*s\n", (int)length, at);
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_version++;
return 0;
}
static int on_header_field(llhttp_t *parser, const char *at, size_t length)
{
printf("Header field cb: %.*s\n", (int)length, at);
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_header_field++;
return 0;
}
static int on_header_field_complete(llhttp_t *parser)
{
printf("Header field complete cb\n");
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_header_field_complete++;
return 0;
}
static int on_header_value(llhttp_t *parser, const char *at, size_t length)
{
printf("Header value cb: %.*s\n", (int)length, at);
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_header_value++;
return 0;
}
static int on_header_value_complete(llhttp_t *parser)
{
printf("Header value complete cb\n");
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_header_value_complete++;
return 0;
}
static int on_headers_complete(llhttp_t *parser)
{
printf("All Headers complete cb\n");
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_headers_complete++;
return 0;
}
static int on_message_complete(llhttp_t *parser)
{
printf("Message complete cb\n");
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_message_complete++;
return 0;
}
static int on_body(llhttp_t *parser, const char *at, size_t length)
{
printf("on_body cb: %.*s\n", (int)length, at);
struct gtest_http_parm *para = container_of(parser, struct gtest_http_parm, llhttp_parser);
para->count.flag_on_body++;
return 0;
}
/******************************** request test case *********************************/
static int gtest_llhttp_init(llhttp_t *parser, llhttp_type_t type, llhttp_settings_t *settings)
{
llhttp_settings_init(settings);
settings->on_message_begin = on_message_begin;
settings->on_url = on_url;
settings->on_version = on_version;
settings->on_status = on_status;
settings->on_method = on_method;
settings->on_header_field = on_header_field;
settings->on_header_field_complete = on_header_field_complete;
settings->on_header_value = on_header_value;
settings->on_header_value_complete = on_header_value_complete;
settings->on_headers_complete = on_headers_complete;
settings->on_message_complete = on_message_complete;
settings->on_body = on_body;
llhttp_init(parser, type, settings);
return 0;
}
TEST(HTTP_llhttp, request_base)
{
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_REQUEST, &para.settings);
const char *request = "GET /path/index.html HTTP/1.1\r\nHost: example.com\r\nContent-Length: 0\r\n\r\n";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, request, strlen(request));
ASSERT_EQ(lerr, HPE_OK);
ASSERT_EQ(para.count.flag_on_message_begin, 1);
ASSERT_EQ(para.count.flag_on_url, 1);
ASSERT_EQ(para.count.flag_on_method, 1);
ASSERT_EQ(para.count.flag_on_version, 1);
ASSERT_EQ(para.count.flag_on_headers_complete, 1);
ASSERT_EQ(para.count.flag_on_message_complete, 1);
}
TEST(HTTP_llhttp, request_dir_error)
{
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_RESPONSE, &para.settings);
const char *request = "GET /path/index.html HTTP/1.1\r\nHost: example.com\r\nContent-Length: 0\r\n\r\n";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, request, strlen(request));
ASSERT_TRUE(lerr != HPE_OK);
}
TEST(HTTP_llhttp, request_uncompleted)
{
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_REQUEST, &para.settings);
const char *request = "GET /path/index.html HTTP/1.1\r\nHost: example.com\r\nContent-Length:";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, request, strlen(request));
ASSERT_EQ(lerr, HPE_OK);
ASSERT_EQ(para.count.flag_on_message_begin, 1);
ASSERT_EQ(para.count.flag_on_url, 1);
ASSERT_EQ(para.count.flag_on_method, 1);
ASSERT_EQ(para.count.flag_on_version, 1);
ASSERT_EQ(para.count.flag_on_message_complete, 0);
}
TEST(HTTP_llhttp, request_hdr_pipeline)
{
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_REQUEST, &para.settings);
const char *request = "GET /path/index.html HTTP/1.1\r\nHost: example1.com\r\nContent-Length: 0\r\n\r\nGET /path/index.html HTTP/1.1\r\nHost: example2.com\r\nContent-Length: 0\r\n\r\nGET /path/index.html HTTP/1.1\r\nHost: example3.com\r\nContent-Length: 0\r\n\r\n";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, request, strlen(request));
ASSERT_EQ(lerr, HPE_OK);
ASSERT_EQ(para.count.flag_on_message_begin, 3);
ASSERT_EQ(para.count.flag_on_url, 3);
ASSERT_EQ(para.count.flag_on_method, 3);
ASSERT_EQ(para.count.flag_on_version, 3);
ASSERT_EQ(para.count.flag_on_headers_complete, 3);
ASSERT_EQ(para.count.flag_on_message_complete, 3);
}
TEST(HTTP_llhttp, request_hdr_body_pipeline)
{
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_REQUEST, &para.settings);
const char *request = "GET /path/index.html HTTP/1.1\r\nHost: example1.com\r\nContent-Length: 1\r\n\r\nxGET /path/index.html HTTP/1.1\r\nHost: example2.com\r\nContent-Length: 2\r\n\r\nxxGET /path/index.html HTTP/1.1\r\nHost: example3.com\r\nContent-Length: 3\r\n\r\nxxx";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, request, strlen(request));
ASSERT_EQ(lerr, HPE_OK);
ASSERT_EQ(para.count.flag_on_message_begin, 3);
ASSERT_EQ(para.count.flag_on_url, 3);
ASSERT_EQ(para.count.flag_on_method, 3);
ASSERT_EQ(para.count.flag_on_version, 3);
ASSERT_EQ(para.count.flag_on_headers_complete, 3);
ASSERT_EQ(para.count.flag_on_body, 3);
ASSERT_EQ(para.count.flag_on_message_complete, 3);
}
TEST(HTTP_llhttp, request_body_chunked)
{
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_REQUEST, &para.settings);
const char *request = "GET /path/index.html HTTP/1.1\r\nHost: example.com\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nhello\r\n5\r\nworld\r\n0\r\n\r\n";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, request, strlen(request));
ASSERT_EQ(lerr, HPE_OK);
ASSERT_EQ(para.count.flag_on_message_begin, 1);
ASSERT_EQ(para.count.flag_on_url, 1);
ASSERT_EQ(para.count.flag_on_method, 1);
ASSERT_EQ(para.count.flag_on_version, 1);
ASSERT_EQ(para.count.flag_on_headers_complete, 1);
ASSERT_EQ(para.count.flag_on_body, 2); // 2 chunks
ASSERT_EQ(para.count.flag_on_message_complete, 1);
}
TEST(HTTP_llhttp, v11_GET_no_content_length_hdr_with_body)
{
/*
* v1.1
* if no obvious content-length header, the body will be parsed as new header,
* and the next transaction will call on_message_begin(), then raise a HPE_INVALID_METHOD error!
*/
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_REQUEST, &para.settings);
const char *request = "GET /path/index.html HTTP/1.1\r\nHost: example.com\r\n\r\n\r\n<html>some content<html/>";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, request, strlen(request));
ASSERT_EQ(lerr, HPE_INVALID_METHOD);
ASSERT_EQ(para.count.flag_on_message_begin, 2);
ASSERT_EQ(para.count.flag_on_url, 1);
ASSERT_EQ(para.count.flag_on_method, 1);
ASSERT_EQ(para.count.flag_on_version, 1);
ASSERT_EQ(para.count.flag_on_body, 0);
ASSERT_EQ(para.count.flag_on_headers_complete, 1);
ASSERT_EQ(para.count.flag_on_message_complete, 1);
}
TEST(HTTP_llhttp, v10_GET_no_content_length_hdr_with_body)
{
/* v1.0
* if no obvious content-length header, the body will be not parsed!
* then raise a HPE_CLOSED_CONNECTION error!
*/
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_REQUEST, &para.settings);
const char *request = "GET /path/index.html HTTP/1.0\r\nHost: example.com\r\n\r\n\r\n<html>some content<html/>";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, request, strlen(request));
ASSERT_EQ(lerr, HPE_CLOSED_CONNECTION);
ASSERT_EQ(para.count.flag_on_message_begin, 1);
ASSERT_EQ(para.count.flag_on_url, 1);
ASSERT_EQ(para.count.flag_on_method, 1);
ASSERT_EQ(para.count.flag_on_version, 1);
ASSERT_EQ(para.count.flag_on_body, 0);
ASSERT_EQ(para.count.flag_on_headers_complete, 1);
ASSERT_EQ(para.count.flag_on_message_complete, 1);
}
TEST(HTTP_llhttp, v11_POST_no_content_length_hdr_with_body)
{
/*
* v1.1
* if no obvious content-length header, the body will be parsed as new header,
* and the next transaction will call on_message_begin(), then raise a HPE_INVALID_METHOD error!
*/
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_REQUEST, &para.settings);
const char *request = "POST /path/index.html HTTP/1.1\r\nHost: example.com\r\n\r\n\r\n<html>some content<html/>";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, request, strlen(request));
ASSERT_EQ(lerr, HPE_INVALID_METHOD);
ASSERT_EQ(para.count.flag_on_message_begin, 2);
ASSERT_EQ(para.count.flag_on_url, 1);
ASSERT_EQ(para.count.flag_on_method, 1);
ASSERT_EQ(para.count.flag_on_version, 1);
ASSERT_EQ(para.count.flag_on_body, 0);
ASSERT_EQ(para.count.flag_on_headers_complete, 1);
ASSERT_EQ(para.count.flag_on_message_complete, 1);
}
TEST(HTTP_llhttp, v11_POST_no_len_has_type_with_body)
{
/*
* v1.1 POST
* if no obvious content-length header, the body will be parsed as new header,
* and the next transaction will call on_message_begin(), then raise a HPE_INVALID_METHOD error!
*/
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_REQUEST, &para.settings);
const char *request = "POST /path/index.html HTTP/1.1\r\nHost: example.com\r\nContent-type: text/html\r\n\r\n<html>some content<html/>";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, request, strlen(request));
ASSERT_EQ(lerr, HPE_INVALID_METHOD);
ASSERT_EQ(para.count.flag_on_message_begin, 2);
ASSERT_EQ(para.count.flag_on_url, 1);
ASSERT_EQ(para.count.flag_on_method, 1);
ASSERT_EQ(para.count.flag_on_version, 1);
ASSERT_EQ(para.count.flag_on_body, 0);
ASSERT_EQ(para.count.flag_on_headers_complete, 1);
ASSERT_EQ(para.count.flag_on_message_complete, 1);
}
TEST(HTTP_llhttp, v10_POST_no_len_has_type_with_body)
{
/*
* v1.0 POST
* if no obvious content-length header, the body will be parsed as new header,
* and the next transaction will call on_message_begin(), then raise a HPE_INVALID_METHOD error!
*/
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_REQUEST, &para.settings);
const char *request = "POST /path/index.html HTTP/1.0\r\nHost: example.com\r\nContent-type: text/html\r\n\r\n<html>some content<html/>";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, request, strlen(request));
ASSERT_EQ(lerr, HPE_CLOSED_CONNECTION);
ASSERT_EQ(para.count.flag_on_message_begin, 1);
ASSERT_EQ(para.count.flag_on_url, 1);
ASSERT_EQ(para.count.flag_on_method, 1);
ASSERT_EQ(para.count.flag_on_version, 1);
ASSERT_EQ(para.count.flag_on_body, 0);
ASSERT_EQ(para.count.flag_on_headers_complete, 1);
ASSERT_EQ(para.count.flag_on_message_complete, 1);
}
/******************************** response test case *********************************/
TEST(HTTP_llhttp, response_base)
{
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_RESPONSE, &para.settings);
const char *response = "HTTP/1.1 200 OK\r\nServer: nginx\r\nContent-Type: text/html\r\nContent-Length: 11\r\n\r\nhello,world";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, response, strlen(response));
ASSERT_EQ(lerr, HPE_OK);
ASSERT_EQ(para.count.flag_on_message_begin, 1);
ASSERT_EQ(para.count.flag_on_status, 1);
ASSERT_EQ(para.count.flag_on_version, 1);
ASSERT_EQ(para.count.flag_on_headers_complete, 1);
ASSERT_EQ(para.count.flag_on_message_complete, 1);
ASSERT_EQ(para.count.flag_on_body, 1);
}
TEST(HTTP_llhttp, response_dir_error)
{
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_REQUEST, &para.settings);
const char *response = "HTTP/1.1 200 OK\r\nServer: nginx\r\nContent-Type: text/html\r\nContent-Length: 11\r\n\r\nhello,world";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, response, strlen(response));
ASSERT_TRUE(lerr != HPE_OK);
}
TEST(HTTP_llhttp, response_uncompleted)
{
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_RESPONSE, &para.settings);
const char *response = "HTTP/1.1 200 OK\r\nServer: nginx\r\nContent-Type: text/html\r\nContent-Length: 11\r\n\r\nxx";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, response, strlen(response));
ASSERT_EQ(lerr, HPE_OK);
ASSERT_EQ(para.count.flag_on_message_begin, 1);
ASSERT_EQ(para.count.flag_on_status, 1);
ASSERT_EQ(para.count.flag_on_version, 1);
ASSERT_EQ(para.count.flag_on_headers_complete, 1);
ASSERT_EQ(para.count.flag_on_body, 1);
ASSERT_EQ(para.count.flag_on_message_complete, 0);
}
TEST(HTTP_llhttp, response_hdr_pipeline)
{
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_RESPONSE, &para.settings);
const char *response = "HTTP/1.1 200 OK\r\nServer: nginx\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\nHTTP/1.1 200 OK\r\nServer: nginx2\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\nHTTP/1.1 200 OK\r\nServer: nginx\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\n";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, response, strlen(response));
ASSERT_EQ(lerr, HPE_OK);
ASSERT_EQ(para.count.flag_on_message_begin, 3);
ASSERT_EQ(para.count.flag_on_status, 3);
ASSERT_EQ(para.count.flag_on_version, 3);
ASSERT_EQ(para.count.flag_on_headers_complete, 3);
ASSERT_EQ(para.count.flag_on_body, 0);
ASSERT_EQ(para.count.flag_on_message_complete, 3);
}
TEST(HTTP_llhttp, response_hdr_body_pipeline)
{
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_RESPONSE, &para.settings);
const char *response = "HTTP/1.1 200 OK\r\nServer: nginx\r\nContent-Type: text/html\r\nContent-Length: 1\r\n\r\nxHTTP/1.1 200 OK\r\nServer: nginx2\r\nContent-Type: text/html\r\nContent-Length: 2\r\n\r\nxxHTTP/1.1 200 OK\r\nServer: nginx\r\nContent-Type: text/html\r\nContent-Length: 3\r\n\r\nxxx";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, response, strlen(response));
ASSERT_EQ(lerr, HPE_OK);
ASSERT_EQ(para.count.flag_on_message_begin, 3);
ASSERT_EQ(para.count.flag_on_status, 3);
ASSERT_EQ(para.count.flag_on_version, 3);
ASSERT_EQ(para.count.flag_on_headers_complete, 3);
ASSERT_EQ(para.count.flag_on_body, 3);
ASSERT_EQ(para.count.flag_on_message_complete, 3);
}
TEST(HTTP_llhttp, response_no_len_no_type_body)
{
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_RESPONSE, &para.settings);
const char *response = "HTTP/1.1 200 OK\r\nServer: nginx\r\n\r\nxxx";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, response, strlen(response));
ASSERT_EQ(lerr, HPE_OK);
ASSERT_EQ(para.count.flag_on_message_begin, 1);
ASSERT_EQ(para.count.flag_on_status, 1);
ASSERT_EQ(para.count.flag_on_version, 1);
ASSERT_EQ(para.count.flag_on_headers_complete, 1);
ASSERT_EQ(para.count.flag_on_body, 1);
ASSERT_EQ(para.count.flag_on_message_complete, 0); // no completed
}
TEST(HTTP_llhttp, response_no_len_has_type_body)
{
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_RESPONSE, &para.settings);
const char *response = "HTTP/1.1 200 OK\r\nServer: nginx\r\nContent-Type: text/html\r\n\r\nxxx";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, response, strlen(response));
ASSERT_EQ(lerr, HPE_OK);
ASSERT_EQ(para.count.flag_on_message_begin, 1);
ASSERT_EQ(para.count.flag_on_status, 1);
ASSERT_EQ(para.count.flag_on_version, 1);
ASSERT_EQ(para.count.flag_on_headers_complete, 1);
ASSERT_EQ(para.count.flag_on_body, 1);
ASSERT_EQ(para.count.flag_on_message_complete, 0); // no completed
}
TEST(HTTP_llhttp, response_no_len_no_type_pipeline)
{
/*
* if no obvious content-length header, the body will be parsed until connection cloesd!
*
*/
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_RESPONSE, &para.settings);
const char *response = "HTTP/1.1 200 OK\r\nServer: nginx1\r\n\r\nHTTP/1.1 200 OK\r\nServer: nginx2\r\n\r\nHTTP/1.1 200 OK\r\nServer: nginx2\r\n\r\n";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, response, strlen(response));
ASSERT_EQ(lerr, HPE_OK);
ASSERT_EQ(para.count.flag_on_message_begin, 1);
ASSERT_EQ(para.count.flag_on_status, 1);
ASSERT_EQ(para.count.flag_on_version, 1);
ASSERT_EQ(para.count.flag_on_headers_complete, 1);
ASSERT_EQ(para.count.flag_on_body, 1);
ASSERT_EQ(para.count.flag_on_message_complete, 0);
}
TEST(HTTP_llhttp, response_no_len_no_type_and_reset)
{
/*
* if no obvious content-length header, the body will be parsed until connection cloesd!
*
*/
struct gtest_http_parm para = {};
gtest_llhttp_init(&para.llhttp_parser, HTTP_RESPONSE, &para.settings);
const char *response = "HTTP/1.1 200 OK\r\nServer: nginx1\r\n\r\n";
enum llhttp_errno lerr = llhttp_execute(&para.llhttp_parser, response, strlen(response));
ASSERT_EQ(lerr, HPE_OK);
lerr = llhttp_execute(&para.llhttp_parser, response, strlen(response));
ASSERT_EQ(lerr, HPE_OK);
lerr = llhttp_execute(&para.llhttp_parser, response, strlen(response));
ASSERT_EQ(lerr, HPE_OK);
llhttp_reset(&para.llhttp_parser);
memset(&para.count, 0, sizeof(para.count));
response = "HTTP/1.1 200 OK\r\nServer: nginx1\r\n\r\n";
lerr = llhttp_execute(&para.llhttp_parser, response, strlen(response));
ASSERT_EQ(lerr, HPE_OK);
ASSERT_EQ(para.count.flag_on_message_begin, 1);
ASSERT_EQ(para.count.flag_on_status, 1);
ASSERT_EQ(para.count.flag_on_version, 1);
ASSERT_EQ(para.count.flag_on_headers_complete, 1);
ASSERT_EQ(para.count.flag_on_body, 0);
ASSERT_EQ(para.count.flag_on_message_complete, 0); // no completed if no content-length filed
}
int main(int argc, char const *argv[])
{
::testing::InitGoogleTest(&argc, (char **)argv);
return RUN_ALL_TESTS();
}