Files
oceanbase/deps/easy/test/packet/easy_http_handler_test.c
oceanbase-admin cea7de1475 init push
2021-05-31 22:56:52 +08:00

959 lines
27 KiB
C

/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#include "io/easy_io.h"
#include <easy_test.h>
#include "util/easy_time.h"
#include <http/easy_http_handler.h>
#include "packet/http/http_parser.h"
#include "io/easy_connection.h"
#include <sys/types.h>
#include <sys/wait.h>
static void* test_realloc(void* ptr, size_t size)
{
return NULL;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
TEST(easy_http_handler, create)
{
easy_http_packet_t* packet;
easy_pool_t* pool;
char *value, *key;
int i;
char data[16];
pool = easy_pool_create(1024);
packet = easy_http_packet_create(pool);
// add header
for (i = 0; i < 128; i++) {
lnprintf(data, 16, "key%d", i);
key = easy_pool_strdup(pool, data);
lnprintf(data, 16, "value%d", i);
value = easy_pool_strdup(pool, data);
easy_http_add_header(pool, packet->headers_out, key, value);
}
// get header
for (i = 0; i < 128; i++) {
lnprintf(data, 16, "key%d", i);
value = easy_http_get_header(packet->headers_out, data);
lnprintf(data, 16, "value%d", i);
EXPECT_TRUE(memcmp(value, data, strlen(data)) == 0);
}
// del header
for (i = 0; i < 128; i++) {
if (i % 2)
lnprintf(data, 16, "key%d", i);
else
lnprintf(data, 16, "Key%d", i);
value = easy_http_del_header(packet->headers_out, data);
lnprintf(data, 16, "value%d", i);
if (value) {
EXPECT_TRUE(memcmp(value, data, strlen(data)) == 0);
} else {
EXPECT_TRUE(0);
}
}
// header again
for (i = 0; i < 128; i++) {
lnprintf(data, 16, "key%d", i);
value = easy_http_del_header(packet->headers_out, data);
EXPECT_TRUE(value == NULL);
value = easy_http_get_header(packet->headers_out, data);
EXPECT_TRUE(value == NULL);
}
easy_pool_destroy(pool);
}
TEST(easy_http_handler, urldecode)
{
char buffer[32];
int len;
memcpy(buffer, "%41%41c", 8);
len = easy_url_decode(buffer, strlen(buffer));
EXPECT_EQ(len, 3);
EXPECT_TRUE(memcmp(buffer, "AAc", len) == 0);
}
TEST(easy_http_handler, string_end)
{
easy_pool_t* pool;
easy_http_request_t p;
easy_string_pair_t header;
char buffer[2];
// easy_http_request_t
memset(&p, 0, sizeof(easy_http_request_t));
memset(buffer, 'A', 2);
p.str_fragment.len = 1;
p.str_fragment.data--;
buffer[1] = '\0';
easy_buf_string_set(&header.name, buffer);
easy_buf_string_set(&header.value, buffer);
pool = easy_pool_create(1024);
p.headers_in = easy_header_create_table(pool);
easy_hash_string_add(p.headers_in, &header);
easy_pool_destroy(pool);
}
TEST(easy_http_hander, decode)
{
easy_pool_t* pool;
easy_message_t* m;
int size;
void* ptr;
// failure
easy_log_level = (easy_log_level_t)0;
pool = easy_pool_create(0);
m = (easy_message_t*)easy_pool_calloc(pool, sizeof(easy_message_t));
size = pool->end - pool->last - sizeof(easy_buf_t);
size = ((size < 0) ? EASY_POOL_ALIGNMENT : size);
m->input = easy_buf_create(pool, size);
m->pool = pool;
easy_pool_set_allocator(test_realloc);
ptr = easy_http_server_on_decode(m);
easy_pool_set_allocator(easy_test_realloc);
EXPECT_TRUE(ptr == NULL);
// null string
ptr = easy_http_server_on_decode(m);
EXPECT_TRUE(ptr == NULL);
// failure http
size = sprintf(m->input->pos, "XXX http://1.taobao.com/ HTTP/1.1");
m->input->last = m->input->pos + size;
ptr = easy_http_server_on_decode(m);
EXPECT_TRUE(ptr == NULL);
EXPECT_TRUE(m->status == EASY_ERROR);
// parse
m->user_data = NULL;
m->status = 0;
m->c = (easy_connection_t*)easy_pool_calloc(pool, sizeof(easy_connection_t));
size = sprintf(m->input->pos, "GET http://1.taobao.com/淘宝/a.html?a=y&b=c#test");
m->input->last = m->input->pos + size;
ptr = easy_http_server_on_decode(m);
EXPECT_TRUE(ptr == NULL);
EXPECT_TRUE(m->status != EASY_ERROR);
m->input->last += sprintf(m->input->last, " HTTP/1.1\r\nHost: x");
ptr = easy_http_server_on_decode(m);
EXPECT_TRUE(ptr == NULL);
EXPECT_TRUE(m->status != EASY_ERROR);
m->input->last += sprintf(m->input->last, "yz.taobao");
ptr = easy_http_server_on_decode(m);
EXPECT_TRUE(ptr == NULL);
EXPECT_TRUE(m->status != EASY_ERROR);
m->input->last += sprintf(m->input->last, ".com\r\nConnection: close\r\n\r\n");
ptr = easy_http_server_on_decode(m);
EXPECT_TRUE(ptr != NULL);
EXPECT_TRUE(m->status != EASY_ERROR);
EXPECT_TRUE(m->c->wait_close == 1);
if (ptr) {
easy_http_request_t* p = (easy_http_request_t*)ptr;
char* value = easy_http_get_header(p->headers_in, "Host");
EXPECT_TRUE(memcmp(value, "xyz.taobao.com", 14) == 0);
if (p->str_host.len > 0)
EXPECT_TRUE(strncmp((char*)p->str_host.data, "1.taobao.com", p->str_host.len) == 0);
}
easy_pool_destroy(pool);
}
TEST(easy_http_hander, server_on_encode)
{
easy_pool_t* pool;
easy_request_t* r;
easy_http_request_t* hr;
easy_buf_t *b, *b1;
easy_log_level = (easy_log_level_t)0;
// raw header
{
pool = easy_pool_create(0);
r = (easy_request_t*)easy_pool_calloc(pool, sizeof(easy_request_t));
hr = (easy_http_request_t*)easy_pool_calloc(pool, sizeof(easy_http_request_t));
r->ms = (easy_message_session_t*)easy_pool_calloc(pool, sizeof(easy_message_session_t));
r->ms->pool = pool;
r->ms->c = (easy_connection_t*)easy_pool_calloc(pool, sizeof(easy_connection_t));
easy_list_init(&r->ms->c->output);
easy_list_init(&hr->output);
b = easy_buf_create(pool, 1);
hr->is_raw_header = 1;
easy_list_add_tail(&b->node, &hr->output);
easy_http_server_on_encode(r, hr);
b1 = easy_list_get_first(&r->ms->c->output, easy_buf_t, node);
EXPECT_TRUE(b1 == b);
easy_pool_destroy(pool);
}
// status line
{
pool = easy_pool_create(0);
r = (easy_request_t*)easy_pool_calloc(pool, sizeof(easy_request_t));
hr = (easy_http_request_t*)easy_pool_calloc(pool, sizeof(easy_http_request_t));
r->ms = (easy_message_session_t*)easy_pool_calloc(pool, sizeof(easy_message_session_t));
r->ms->pool = pool;
r->ms->c = (easy_connection_t*)easy_pool_calloc(pool, sizeof(easy_connection_t));
easy_list_init(&r->ms->c->output);
easy_list_init(&hr->output);
easy_buf_string_set(&hr->status_line, EASY_HTTP_STATUS_400);
hr->headers_out = easy_header_create_table(pool);
easy_http_add_header(pool, hr->headers_out, "Host", "a.taobao.com");
hr->parser.http_major = hr->parser.http_minor = 1;
easy_http_server_on_encode(r, hr);
b = easy_list_get_first(&r->ms->c->output, easy_buf_t, node);
EXPECT_TRUE(memcmp(b->pos, "HTTP/1.1 400 Bad Request\r\nHost: a.taobao.com\r\n", 41) == 0);
easy_pool_destroy(pool);
}
}
TEST(easy_http_hander, client_on_encode)
{
easy_pool_t* pool;
easy_request_t* r;
easy_http_packet_t* hr;
easy_buf_t *b, *b1;
char* ptr;
easy_log_level = (easy_log_level_t)0;
// raw header
{
pool = easy_pool_create(0);
r = (easy_request_t*)easy_pool_calloc(pool, sizeof(easy_request_t));
hr = (easy_http_packet_t*)easy_pool_calloc(pool, sizeof(easy_http_packet_t));
r->ms = (easy_message_session_t*)easy_pool_calloc(pool, sizeof(easy_message_session_t));
r->ms->pool = pool;
r->ms->c = (easy_connection_t*)easy_pool_calloc(pool, sizeof(easy_connection_t));
easy_list_init(&r->ms->c->output);
easy_list_init(&hr->output);
b = easy_buf_create(pool, 1);
hr->is_raw_header = 1;
easy_list_add_tail(&b->node, &hr->output);
easy_http_client_on_encode(r, hr);
b1 = easy_list_get_first(&r->ms->c->output, easy_buf_t, node);
EXPECT_TRUE(b1 == b);
easy_pool_destroy(pool);
}
// post
{
pool = easy_pool_create(0);
r = (easy_request_t*)easy_pool_calloc(pool, sizeof(easy_request_t));
hr = (easy_http_packet_t*)easy_pool_calloc(pool, sizeof(easy_http_packet_t));
r->ms = (easy_message_session_t*)easy_pool_calloc(pool, sizeof(easy_message_session_t));
r->ms->pool = pool;
r->ms->c = (easy_connection_t*)easy_pool_calloc(pool, sizeof(easy_connection_t));
easy_list_init(&r->ms->c->output);
easy_list_init(&hr->output);
hr->method = HTTP_POST;
hr->keep_alive = 1;
hr->str_path.data = NULL;
easy_buf_string_set(&hr->str_query_string, "a=y&c=d");
hr->headers_out = easy_header_create_table(pool);
easy_http_add_header(pool, hr->headers_out, "Server", "apache");
easy_http_client_on_encode(r, hr);
b = easy_list_get_first(&r->ms->c->output, easy_buf_t, node);
ptr = "POST / HTTP/1.1\r\nServer: apache\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: "
"7\r\nConnection: keep-alive\r\n\r\na=y&c=d";
EXPECT_TRUE(memcmp(b->pos, ptr, strlen(ptr)) == 0);
easy_pool_destroy(pool);
}
// get
{
pool = easy_pool_create(0);
r = (easy_request_t*)easy_pool_calloc(pool, sizeof(easy_request_t));
hr = (easy_http_packet_t*)easy_pool_calloc(pool, sizeof(easy_http_packet_t));
r->ms = (easy_message_session_t*)easy_pool_calloc(pool, sizeof(easy_message_session_t));
r->ms->pool = pool;
r->ms->c = (easy_connection_t*)easy_pool_calloc(pool, sizeof(easy_connection_t));
easy_list_init(&r->ms->c->output);
easy_list_init(&hr->output);
hr->str_path.data = NULL;
easy_buf_string_set(&hr->str_query_string, "a=y&c=d");
hr->headers_out = easy_header_create_table(pool);
easy_http_add_header(pool, hr->headers_out, "Server", "apache");
easy_http_client_on_encode(r, hr);
b = easy_list_get_first(&r->ms->c->output, easy_buf_t, node);
EXPECT_TRUE(memcmp(b->pos, "GET /?a=y&c=d HTTP/1.1\r\nServer: apache\r\n", 40) == 0);
easy_pool_destroy(pool);
}
}
TEST(easy_http_hander, client_on_decode)
{
easy_pool_t* pool;
easy_message_t* m;
int size;
void* ptr;
easy_io_handler_pt handler;
easy_http_handler_init(&handler, NULL);
// failure
easy_log_level = (easy_log_level_t)0;
pool = easy_pool_create(0);
m = (easy_message_t*)easy_pool_calloc(pool, sizeof(easy_message_t));
size = pool->end - pool->last - sizeof(easy_buf_t);
size = ((size < 0) ? EASY_POOL_ALIGNMENT : size);
m->input = easy_buf_create(pool, size);
m->pool = pool;
easy_pool_set_allocator(test_realloc);
ptr = easy_http_client_on_decode(m);
easy_pool_set_allocator(easy_test_realloc);
EXPECT_TRUE(ptr == NULL);
// null string
ptr = easy_http_client_on_decode(m);
EXPECT_TRUE(ptr == NULL);
// failure http
size = sprintf(m->input->pos, "XXX http://1.taobao.com/ HTTP/1.1");
m->input->last = m->input->pos + size;
ptr = easy_http_client_on_decode(m);
EXPECT_TRUE(ptr == NULL);
EXPECT_TRUE(m->status == EASY_ERROR);
// parse
m->user_data = NULL;
m->status = 0;
m->c = (easy_connection_t*)easy_pool_calloc(pool, sizeof(easy_connection_t));
m->c->handler = &handler;
size = sprintf(m->input->pos, "HTTP/1.1 200");
m->input->last = m->input->pos + size;
ptr = easy_http_client_on_decode(m);
EXPECT_TRUE(ptr == NULL);
EXPECT_TRUE(m->status != EASY_ERROR);
m->input->last += sprintf(m->input->last, " OK\r\nHost: x");
ptr = easy_http_client_on_decode(m);
EXPECT_TRUE(ptr == NULL);
EXPECT_TRUE(m->status != EASY_ERROR);
m->input->last += sprintf(m->input->last, "yz.taobao");
ptr = easy_http_client_on_decode(m);
EXPECT_TRUE(ptr == NULL);
EXPECT_TRUE(m->status != EASY_ERROR);
m->input->last += sprintf(m->input->last, ".com\r\nConnection: close\r\nContent-Length: 2\r\n\r\nab");
ptr = easy_http_client_on_decode(m);
EXPECT_TRUE(ptr != NULL);
EXPECT_TRUE(m->status != EASY_ERROR);
EXPECT_TRUE(m->c->wait_close == 1);
if (ptr) {
easy_http_request_t* p = (easy_http_request_t*)ptr;
char* value = easy_http_get_header(p->headers_in, "Host");
EXPECT_TRUE(memcmp(value, "xyz.taobao.com", 14) == 0);
}
easy_pool_destroy(pool);
}
TEST(easy_http_hander, init)
{
easy_io_handler_pt handler;
easy_http_handler_init(&handler, NULL);
EXPECT_TRUE(handler.decode == easy_http_server_on_decode);
EXPECT_TRUE(handler.encode = easy_http_server_on_encode);
}
// int easy_url_decode(char *str, int len)
TEST(easy_http_hander, url_decode)
{
char data[128], data1[28];
strcpy(data, "HTTP://a.taobao.com/%26%RR%0");
strcpy(data1, "HTTP://a.taobao.com/&%RR%0");
int n = easy_url_decode(data, strlen(data));
EXPECT_TRUE(n > 0);
EXPECT_TRUE(strcmp(data, data1) == 0);
}
// int easy_http_merge_path(char *newpath, int len, const char *rootpath, const char *addpath)
TEST(easy_http_hander, merge_path)
{
/*
char newpath[128];
memset(newpath, 0, sizeof(newpath));
int n;
n = easy_http_merge_path(newpath, 128, "/root", "..");
fprintf(stderr, "%s\n", newpath);
EXPECT_NE(n, EASY_OK);
n = easy_http_merge_path(newpath, 128, "/root", "../");
fprintf(stderr, "%s\n", newpath);
EXPECT_NE(n, EASY_OK);
n = easy_http_merge_path(newpath, 128, "/root", "aa/..");
fprintf(stderr, "%s\n", newpath);
EXPECT_EQ(n, EASY_OK);
n = easy_http_merge_path(newpath, 128, "/root", "aa/../");
fprintf(stderr, "%s\n", newpath);
EXPECT_EQ(n, EASY_OK);
n = easy_http_merge_path(newpath, 128, "/root", "aa/../.");
fprintf(stderr, "%s\n", newpath);
EXPECT_EQ(n, EASY_OK);
n = easy_http_merge_path(newpath, 128, "/root", "aa/../..");
fprintf(stderr, "%s\n", newpath);
EXPECT_NE(n, EASY_OK);
*/
}
// int easy_http_request_printf(easy_http_request_t *r, const char *fmt, ...)
TEST(easy_http_hander, printf)
{
easy_pool_t* pool;
easy_http_request_t r;
easy_buf_t* b;
pool = easy_pool_create(0);
r.m = (easy_message_t*)easy_pool_calloc(pool, sizeof(easy_message_t));
r.m->pool = pool;
easy_list_init(&r.output);
easy_http_request_printf(&r, "a: %04d, s: %s", 123, "test");
b = easy_list_get_first(&r.output, easy_buf_t, node);
char* str = "a: 0123, s: test";
EXPECT_TRUE(strncmp(b->pos, str, strlen(str)) == 0);
easy_pool_destroy(pool);
}
TEST(easy_http_hander, args)
{
easy_pool_t* pool;
easy_http_request_t* p;
easy_header_set_case_sensitive(0);
pool = easy_pool_create(0);
p = (easy_http_request_t*)easy_pool_calloc(pool, sizeof(easy_http_request_t));
memset(p, 0, sizeof(easy_http_request_t));
p->m = (easy_message_t*)easy_pool_calloc(pool, sizeof(easy_message_t));
p->m->pool = pool;
easy_buf_string_set(&p->str_query_string, "a=b&c=d&x==&&=&Test=abc&a");
char* x = easy_http_get_args(p, "test");
EXPECT_TRUE(x != NULL);
if (x != NULL)
EXPECT_TRUE(strcmp(x, "abc") == 0);
easy_pool_destroy(pool);
}
static int http_fetch_set_data(easy_request_t* r, const char* data, int len)
{
easy_buf_t* b = r->args;
memcpy(b->last, data, len);
b->last += len;
return EASY_OK;
}
TEST(easy_http_hander, server_on_encode_chunked)
{
easy_pool_t* pool;
easy_request_t* r;
easy_http_request_t* hr;
easy_buf_t* b;
easy_message_t* m;
easy_session_t* s;
easy_io_handler_pt io_handler;
// init
easy_log_level = (easy_log_level_t)0;
memset(&io_handler, 0, sizeof(easy_io_handler_pt));
io_handler.set_data = (void*)http_fetch_set_data;
pool = easy_pool_create(0);
r = (easy_request_t*)easy_pool_calloc(pool, sizeof(easy_request_t));
hr = (easy_http_request_t*)easy_pool_calloc(pool, sizeof(easy_http_request_t));
r->ms = (easy_message_session_t*)easy_pool_calloc(pool, sizeof(easy_message_session_t));
r->ms->pool = pool;
r->ms->c = (easy_connection_t*)easy_pool_calloc(pool, sizeof(easy_connection_t));
easy_list_init(&r->ms->c->output);
easy_list_init(&hr->output);
r->ms->c->handler = &io_handler;
r->ms->c->send_queue = easy_hash_create(pool, 32, offsetof(easy_session_t, send_queue_hash));
// encode chunked
easy_buf_string_set(&hr->status_line, EASY_HTTP_STATUS_200);
hr->headers_out = easy_header_create_table(pool);
easy_http_add_header(pool, hr->headers_out, "hOst", "a.taobao.com");
easy_http_add_header(pool, hr->headers_out, "Transfer-Encoding", "chunked");
hr->parser.http_major = hr->parser.http_minor = 1;
hr->send_chunk = 1;
r->retcode = EASY_AGAIN;
b = easy_buf_create(pool, 32);
b->last = easy_strcpy(b->last, "test server on");
easy_list_add_tail(&b->node, &hr->output);
easy_http_server_on_encode(r, hr);
hr->is_raw_header = 1;
b = easy_buf_create(pool, 32);
b->last = easy_strcpy(b->last, " encode ");
easy_list_add_tail(&b->node, &hr->output);
easy_http_server_on_encode(r, hr);
b = easy_buf_create(pool, 32);
b->last = easy_strcpy(b->last, "chunked");
easy_list_add_tail(&b->node, &hr->output);
r->retcode = EASY_OK;
easy_http_server_on_encode(r, hr);
// output encode
m = (easy_message_t*)easy_pool_calloc(pool, sizeof(easy_message_t));
m->pool = pool;
m->c = r->ms->c;
m->input = easy_buf_create(pool, 1024);
easy_list_for_each_entry(b, &r->ms->c->output, node)
{
m->input->last += lnprintf(m->input->last, 1024, "%.*s", (int)(b->last - b->pos), b->pos);
}
// decode chunked
easy_header_set_case_sensitive(2);
s = easy_session_create(512);
s->r.args = easy_buf_create(pool, 1024);
s->packet_id = easy_connection_get_packet_id(m->c, NULL, 0);
easy_hash_dlist_add(m->c->send_queue, s->packet_id, &s->send_queue_hash, &s->send_queue_list);
hr = easy_http_client_on_decode(m);
if (hr) {
char* value = easy_http_get_header(hr->headers_in, "Host");
EXPECT_TRUE(value);
}
b = s->r.args;
EXPECT_TRUE(hr);
EXPECT_TRUE(m->status == EASY_OK);
EXPECT_TRUE(memcmp(b->pos, "test server on encode chunked", strlen("test server on encode chunked")) == 0);
easy_header_set_case_sensitive(0);
easy_session_destroy(s);
easy_pool_destroy(pool);
}
easy_http_request_t* easy_test_query_string_decode(easy_message_t* m, char* query_str)
{
easy_http_request_t* ptr;
int size;
// parse
m->input = easy_buf_create(m->pool, 4096);
m->user_data = NULL;
m->status = 0;
m->c = (easy_connection_t*)easy_pool_calloc(m->pool, sizeof(easy_connection_t));
size =
sprintf(m->input->pos, "GET http://1.taobao.com/淘宝/a.html%s HTTP/1.1\r\nHost: x.taobao.com\r\n\r\n", query_str);
m->input->last = m->input->pos + size;
ptr = easy_http_server_on_decode(m);
EXPECT_TRUE(ptr);
EXPECT_TRUE(m->status != EASY_ERROR);
EXPECT_TRUE(m->c->wait_close == 0);
return ptr;
}
#define easy_test_query_string_match(p, query_str) \
do { \
EXPECT_TRUE(p); \
if (p == NULL) \
break; \
EXPECT_EQ(strlen(query_str), p->str_query_string.len); \
if (p->str_query_string.len > 0) \
EXPECT_TRUE(strncmp((char*)p->str_query_string.data, query_str, p->str_query_string.len) == 0); \
} while (0)
TEST(easy_http_hander, decode1)
{
easy_pool_t* pool;
easy_message_t* m;
easy_http_request_t* ptr;
// failure
easy_log_level = (easy_log_level_t)0;
pool = easy_pool_create(0);
m = (easy_message_t*)easy_pool_calloc(pool, sizeof(easy_message_t));
m->pool = pool;
{
char* query_str = "a=y&b=c";
char* dst_query_str = "";
ptr = easy_test_query_string_decode(m, query_str);
easy_test_query_string_match(ptr, dst_query_str);
}
{
char* query_str = "?a=y&b=c";
char* dst_query_str = query_str + 1;
ptr = easy_test_query_string_decode(m, query_str);
easy_test_query_string_match(ptr, dst_query_str);
}
{
char* query_str = "?";
char* dst_query_str = "";
ptr = easy_test_query_string_decode(m, query_str);
easy_test_query_string_match(ptr, dst_query_str);
}
{
char* query_str = "??a=y&b=c";
char* dst_query_str = query_str + 1;
ptr = easy_test_query_string_decode(m, query_str);
easy_test_query_string_match(ptr, dst_query_str);
}
{
char* query_str = "??";
char* dst_query_str = "?";
ptr = easy_test_query_string_decode(m, query_str);
easy_test_query_string_match(ptr, dst_query_str);
}
{
char* query_str = "???";
char* dst_query_str = query_str + 1;
ptr = easy_test_query_string_decode(m, query_str);
easy_test_query_string_match(ptr, dst_query_str);
}
{
char* query_str = "?a=y&b=c?111";
char* dst_query_str = "a=y&b=c?111";
ptr = easy_test_query_string_decode(m, query_str);
easy_test_query_string_match(ptr, dst_query_str);
}
{
char* query_str = "?a=y&b=c?";
char* dst_query_str = "a=y&b=c?";
ptr = easy_test_query_string_decode(m, query_str);
easy_test_query_string_match(ptr, dst_query_str);
}
{
char* query_str = "?a=y&b=c#abc";
char* dst_query_str = "a=y&b=c";
ptr = easy_test_query_string_decode(m, query_str);
easy_test_query_string_match(ptr, dst_query_str);
}
{
char* query_str = "?a=y&b=c#abc??111";
char* dst_query_str = "a=y&b=c";
ptr = easy_test_query_string_decode(m, query_str);
easy_test_query_string_match(ptr, dst_query_str);
}
{
char* query_str = "?#abc??111";
char* dst_query_str = "";
ptr = easy_test_query_string_decode(m, query_str);
easy_test_query_string_match(ptr, dst_query_str);
}
{
char* query_str = "#?abc??111";
char* dst_query_str = "";
ptr = easy_test_query_string_decode(m, query_str);
easy_test_query_string_match(ptr, dst_query_str);
}
{
char* query_str = "#222?abc??111";
char* dst_query_str = "";
ptr = easy_test_query_string_decode(m, query_str);
easy_test_query_string_match(ptr, dst_query_str);
}
easy_pool_destroy(pool);
}
static http_parser_settings test_easy_http_settings = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
TEST(easy_http_handler, parser)
{
char buffer[1024];
int size, n, i;
int errnum = 0;
int oknum = 0;
int cnt = 10000 * 200;
strcpy(buffer,
"GET /index.php/0000000000/index.php/0000000000.html HTTP/1.0\r\nUser-Agent: ApacheBench/2.0.40-dev\r\nHost: "
"test.taobao.com\r\nAccept: */*\r\n");
size = strlen(buffer);
int64_t t1 = easy_time_now();
for (i = 0; i < cnt; i++) {
http_parser parser;
http_parser_init(&parser, HTTP_REQUEST);
n = http_parser_execute(&parser, &test_easy_http_settings, buffer, size);
if (http_parser_has_error(&parser) || n < 0) {
errnum++;
} else {
oknum++;
}
}
int64_t t2 = easy_time_now();
fprintf(stderr, "t: %" PRId64 ", speed: %.2f\n", (t2 - t1), cnt * 1000000.0 / (t2 - t1));
EXPECT_TRUE(errnum == 0);
EXPECT_TRUE(oknum == cnt);
}
///////////////////////////////////////////////////////////////////////////////////////////////
static easy_thread_pool_t* test_thread_101_server_tp;
static easy_list_t test_thread_101_list = EASY_LIST_HEAD_INIT(test_thread_101_list);
static int test_thread_101_server_process(easy_request_t* r)
{
easy_thread_pool_push(test_thread_101_server_tp, r, easy_hash_key((uint64_t)(long)r));
return EASY_AGAIN;
}
static int test_thread_101_request_process(easy_request_t* r, void* args)
{
easy_list_add_tail(&r->request_list_node, &test_thread_101_list);
easy_http_request_t* p;
p = (easy_http_request_t*)r->ipacket;
if (p->str_path.len != 5 || memcmp(p->str_path.data, "/done", 5) != 0) {
return EASY_ABORT;
}
// reply
easy_request_t *n1, *n2;
easy_list_for_each_entry_safe(n1, n2, &test_thread_101_list, request_list_node)
{
easy_list_del(&n1->request_list_node);
p = (easy_http_request_t*)n1->ipacket;
n1->opacket = p;
easy_http_request_printf(p, "%s", p->str_path.data);
easy_request_wakeup(n1);
}
easy_list_init(&test_thread_101_list);
return EASY_ABORT;
}
static void test_thread_101_server(int fd)
{
easy_listen_t* l;
easy_io_handler_pt io_handler;
int i, port;
easy_log_level = (easy_log_level_t)0;
easy_io_create(4);
memset(&io_handler, 0, sizeof(easy_io_handler_pt));
io_handler.decode = easy_http_server_on_decode;
io_handler.encode = easy_http_server_on_encode;
io_handler.process = test_thread_101_server_process;
test_thread_101_server_tp = easy_request_thread_create(1, test_thread_101_request_process, NULL);
port = 2011;
for (i = 0; i < 10; i++, port++) {
if ((l = easy_io_add_listen(NULL, port, &io_handler)) != NULL)
break;
}
easy_io_start();
i = write(fd, &port, 2);
easy_io_wait();
easy_io_destroy();
}
static int test_thread_101_disconnect(easy_connection_t* c)
{
easy_io_stop();
return EASY_OK;
}
static int test_thread_101_connect(easy_connection_t* c)
{
int retv = EASY_OK;
char buffer[65536];
char text[20000];
int i, ret, idx = 0;
memset(text, 'A', sizeof(text));
text[sizeof(text) - 1] = '\0';
text[2] = '=';
for (i = 0; i < 3; i++) {
idx += lnprintf(buffer + idx,
30000,
"POST /request_%d HTTP/1.1\r\nContent-Length: %d\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n"
"Host: test.com\r\nConnection: keep-alive\r\n\r\n%s",
i,
(int)strlen(text),
text);
}
idx += lnprintf(buffer + idx,
4000,
"GET /done HTTP/1.1\r\n"
"Host: test.com\r\n"
"Connection: keep-alive\r\n\r\n");
buffer[idx] = '\0';
char* p = buffer;
while (idx > 0) {
i = easy_min(idx, 1000);
ret = write(c->fd, p, i);
if (ret > 0) {
p += ret;
idx -= ret;
} else if (errno != EAGAIN && errno != EINTR) {
easy_error_log("write failure: %d:%s\n", errno, strerror(errno));
retv = EASY_ERROR;
break;
}
usleep(100);
}
return retv;
}
static int test_thread_101_client_process(easy_request_t* r)
{
return EASY_OK;
}
static void test_thread_101_client(int port)
{
easy_io_handler_pt io_handler;
easy_log_level = (easy_log_level_t)0;
easy_io_create(4);
easy_io_start();
memset(&io_handler, 0, sizeof(easy_io_handler_pt));
io_handler.decode = easy_http_server_on_decode;
io_handler.encode = easy_http_server_on_encode;
io_handler.process = test_thread_101_client_process;
io_handler.on_connect = test_thread_101_connect;
io_handler.on_disconnect = test_thread_101_disconnect;
// connect
easy_addr_t addr = easy_inet_str_to_addr("localhost", port);
int i = easy_io_connect(addr, &io_handler, 0, NULL);
EXPECT_TRUE(i == EASY_OK);
easy_io_wait();
easy_io_destroy();
}
TEST(easy_http_hander, thread_101)
{
int pfd[2];
pid_t pid1, pid2;
int ret = 0;
int port = 0;
if (pipe(pfd) == -1)
return;
// server
if ((pid1 = fork()) == 0) {
close(pfd[0]);
test_thread_101_server(pfd[1]);
close(pfd[1]);
exit(easy_test_retval);
} else {
close(pfd[1]);
ret = read(pfd[0], &port, 2);
close(pfd[0]);
}
// client
if ((pid2 = fork()) == 0) {
test_thread_101_client(port);
exit(easy_test_retval);
}
waitpid(pid2, &ret, 0);
EXPECT_EQ(WEXITSTATUS(ret), 0);
kill(pid1, SIGINT);
usleep(1000);
waitpid(pid1, &ret, 0);
EXPECT_EQ(WEXITSTATUS(ret), 0);
}