summaryrefslogtreecommitdiff
path: root/test/http_decoder_gtest.cpp
diff options
context:
space:
mode:
authorlijia <[email protected]>2024-04-08 09:48:13 +0800
committerlijia <[email protected]>2024-04-08 09:48:13 +0800
commit215e383be1f47cd18c235855d0cee0485f6cb423 (patch)
tree34668fd59622c37826c3a786ba0e196a7d65147b /test/http_decoder_gtest.cpp
parentea795e9c6940281bf8557bfd79f13f319f947c58 (diff)
Separate from stellar-on-sapp project.
Diffstat (limited to 'test/http_decoder_gtest.cpp')
-rw-r--r--test/http_decoder_gtest.cpp370
1 files changed, 370 insertions, 0 deletions
diff --git a/test/http_decoder_gtest.cpp b/test/http_decoder_gtest.cpp
new file mode 100644
index 0000000..aa81df2
--- /dev/null
+++ b/test/http_decoder_gtest.cpp
@@ -0,0 +1,370 @@
+/*
+**********************************************************************************************
+* File: http_decoder_gtest.cpp
+* Description:
+* Authors: Liu WenTan <[email protected]>
+* Date: 2023-12-15
+* Copyright: (c) Since 2023 Geedge Networks, Ltd. All rights reserved.
+***********************************************************************************************
+*/
+
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <assert.h>
+#include <string.h>
+
+#include "../include/http_decoder.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+
+#include "cJSON.h"
+#include "http_decoder_gtest.h"
+#include "stellar/utils.h"
+#include "stellar/stellar.h"
+#include "stellar/session_exdata.h"
+#include "stellar/session_mq.h"
+
+ int commit_test_result_json(cJSON *node, const char *name);
+}
+#endif
+
+#define MAX_KEY_STR_LEN 2048
+
+enum http_transaction_type
+{
+ HTTP_TRANSACTION_REQ = 0,
+ HTTP_TRANSACTION_RES,
+ HTTP_TRANSACTION_SESSION,
+ HTTP_TRANSACTION_MAX
+};
+
+struct gtest_plug_exdata_t
+{
+ cJSON *result_jnode[HTTP_TRANSACTION_MAX];
+};
+
+static int g_result_count = 0;
+static int g_header_count = 1;
+static int g_exdata_idx = 0;
+static int g_topic_id = 0;
+
+#if 1
+void output_http_req_line(struct http_request_line *req_line)
+{
+ char tmp_str[MAX_KEY_STR_LEN] = {0};
+ memcpy(tmp_str, req_line->method.str, req_line->method.str_len);
+ printf("req_method:%s\n", tmp_str);
+
+ memset(tmp_str, 0, sizeof(tmp_str));
+ memcpy(tmp_str, req_line->uri.str, req_line->uri.str_len);
+ printf("req_uri:%s\n", tmp_str);
+
+ memset(tmp_str, 0, sizeof(tmp_str));
+ memcpy(tmp_str, req_line->version.str, req_line->version.str_len);
+ printf("req_version:%s\n", tmp_str);
+}
+
+void output_http_res_line(struct http_response_line *res_line)
+{
+ char tmp_str[MAX_KEY_STR_LEN] = {0};
+ memcpy(tmp_str, res_line->version.str, res_line->version.str_len);
+ printf("res_version:%s\n", tmp_str);
+
+ memset(tmp_str, 0, sizeof(tmp_str));
+ memcpy(tmp_str, res_line->status.str, res_line->status.str_len);
+ printf("res_status:%s\n", tmp_str);
+}
+
+void output_http_header(struct http_header *header)
+{
+ char tmp_key[MAX_KEY_STR_LEN] = {0};
+ char tmp_val[MAX_KEY_STR_LEN] = {0};
+
+ memcpy(tmp_key, header->key.str, header->key.str_len);
+ memcpy(tmp_val, header->val.str, header->val.str_len);
+ printf("<%s:%s>\n", tmp_key, tmp_val);
+}
+#endif
+
+void output_http_body(struct hstring *body, int decompress_flag)
+{
+ int counter = 0;
+
+ if (1 == decompress_flag)
+ {
+ printf("\n\n----------------decompress body len:%zu---------------\n",
+ body->str_len);
+ }
+ else
+ {
+ printf("\n\n----------------raw body len:%zu---------------\n",
+ body->str_len);
+ }
+
+ for (size_t i = 0; i < body->str_len; i++)
+ {
+ if (counter % 16 == 0)
+ {
+ printf("\n");
+ }
+ printf("%02x ", (unsigned char)body->str[i]);
+ counter++;
+ }
+ printf("\n");
+}
+
+int http_field_to_json(cJSON *object, const char *key, char *val, size_t val_len)
+{
+ if (NULL == object || NULL == key || NULL == val || 0 == val_len)
+ {
+ return -1;
+ }
+
+ char *tmp = CALLOC(char, val_len + 1);
+ memcpy(tmp, val, val_len);
+ cJSON_AddStringToObject(object, key, tmp);
+ FREE(tmp);
+
+ return 0;
+}
+
+void req_line_to_json(cJSON *ctx, struct http_request_line *req_line)
+{
+ http_field_to_json(ctx, "method", req_line->method.str,
+ req_line->method.str_len);
+ http_field_to_json(ctx, "uri", req_line->uri.str, req_line->uri.str_len);
+ http_field_to_json(ctx, "req_version", req_line->version.str,
+ req_line->version.str_len);
+
+ cJSON_AddNumberToObject(ctx, "major_version", req_line->major_version);
+ cJSON_AddNumberToObject(ctx, "minor_version", req_line->minor_version);
+}
+
+void res_line_to_json(cJSON *ctx, struct http_response_line *res_line)
+{
+ http_field_to_json(ctx, "res_version", res_line->version.str,
+ res_line->version.str_len);
+ http_field_to_json(ctx, "res_status", res_line->status.str,
+ res_line->status.str_len);
+
+ cJSON_AddNumberToObject(ctx, "major_version", res_line->major_version);
+ cJSON_AddNumberToObject(ctx, "minor_version", res_line->minor_version);
+ cJSON_AddNumberToObject(ctx, "status_code", res_line->status_code);
+}
+
+void http_header_to_json(cJSON *ctx, struct http_header *header)
+{
+ char key[MAX_KEY_STR_LEN] = {0};
+
+ memcpy(key, header->key.str, header->key.str_len);
+
+ if (cJSON_HasObjectItem(ctx, key) == FALSE)
+ {
+ http_field_to_json(ctx, key, header->val.str, header->val.str_len);
+ }
+ else
+ {
+ // ctx already has the key, so rename key by key%d
+ char new_key[MAX_KEY_STR_LEN] = {0};
+ sprintf(new_key, "%s%d", key, g_header_count++);
+ http_field_to_json(ctx, new_key, header->val.str, header->val.str_len);
+ }
+}
+
+void http_url_add_to_json(cJSON *ctx, struct http_message *msg)
+{
+ struct hstring url_result = {};
+
+ if (cJSON_GetObjectItem(ctx, GTEST_HTTP_URL_NAME))
+ {
+ return;
+ }
+
+ if (http_message_get_url(msg, &url_result) < 0)
+ {
+ // printf("url:%s\n", url_result.str);
+ return;
+ }
+
+ struct http_header url_header_result = {};
+
+ url_header_result.key.str = (char *)GTEST_HTTP_URL_NAME;
+ url_header_result.key.str_len = strlen(GTEST_HTTP_URL_NAME);
+ url_header_result.val = url_result;
+
+ http_header_to_json(ctx, &url_header_result);
+}
+
+// Full duplex
+static void commit_last_half_flow_data(struct session *sess, struct gtest_plug_exdata_t *gtest_plug_exdata, enum http_transaction_type type)
+{
+ char result_name[MAX_KEY_STR_LEN] = {0};
+
+ cJSON *last_jnode = gtest_plug_exdata->result_jnode[type];
+ if (last_jnode)
+ {
+ sprintf(result_name, "%d", g_result_count);
+ commit_test_result_json(last_jnode, result_name);
+ gtest_plug_exdata->result_jnode[type] = NULL;
+ g_result_count++;
+ }
+
+ gtest_plug_exdata->result_jnode[type] = cJSON_CreateObject();
+ if (HTTP_TRANSACTION_REQ == type)
+ {
+ cJSON_AddStringToObject(gtest_plug_exdata->result_jnode[type], GTEST_HTTP_TRANS_NAME, "request");
+ }
+ else if (HTTP_TRANSACTION_RES == type)
+ {
+ cJSON_AddStringToObject(gtest_plug_exdata->result_jnode[type], GTEST_HTTP_TRANS_NAME, "response");
+ }
+}
+
+static void http_decoder_test_update_session_tuple4(struct session *sess, struct gtest_plug_exdata_t *gtest_plug_exdata)
+{
+ if (gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION] == NULL)
+ {
+ char result_name[MAX_KEY_STR_LEN] = {0};
+ gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION] = cJSON_CreateObject();
+ cJSON_AddStringToObject(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION], GTEST_HTTP_TUPLE4_NAME, session_get0_readable_addr(sess));
+ sprintf(result_name, "%d", g_result_count++);
+ commit_test_result_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION], result_name);
+ }
+}
+
+extern "C" int
+http_decoder_test_entry(struct session *sess, int topic_id, const void *data,
+ void *cb_arg)
+{
+ struct http_request_line req_line = {0};
+ struct http_response_line res_line = {0};
+ struct http_header header = {0};
+ struct hstring body = {0};
+ struct http_message *msg = (struct http_message *)data;
+ enum http_message_type msg_type = http_message_type(msg);
+
+ struct gtest_plug_exdata_t *gtest_plug_exdata = (struct gtest_plug_exdata_t *)session_get_ex_data(sess, g_exdata_idx);
+ if (NULL == gtest_plug_exdata)
+ {
+ gtest_plug_exdata = (struct gtest_plug_exdata_t *)calloc(1, sizeof(struct gtest_plug_exdata_t));
+ session_set_ex_data(sess, g_exdata_idx, gtest_plug_exdata);
+ }
+
+ if (msg_type == HTTP_MESSAGE_REQ_LINE || msg_type == HTTP_MESSAGE_REQ_HEADER || msg_type == HTTP_MESSAGE_REQ_BODY)
+ {
+ cJSON *json = gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ];
+ }
+ else
+ {
+ cJSON *json = gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES];
+ }
+
+ http_decoder_test_update_session_tuple4(sess, gtest_plug_exdata);
+
+ switch (msg_type)
+ {
+ case HTTP_MESSAGE_REQ_LINE:
+ commit_last_half_flow_data(sess, gtest_plug_exdata, HTTP_TRANSACTION_REQ);
+ http_message_get_request_line(msg, &req_line);
+ req_line_to_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ], &req_line);
+ break;
+ case HTTP_MESSAGE_REQ_HEADER:
+ while (http_message_request_header_next(msg, &header) > 0)
+ {
+ http_header_to_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ], &header);
+ }
+ g_header_count = 1;
+ http_url_add_to_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ], msg);
+ break;
+ case HTTP_MESSAGE_REQ_BODY:
+ http_message_get_request_raw_body(msg, &body);
+ // output_http_body(&body, 0);
+
+ http_message_get_request_decompress_body(msg, &body);
+ // output_http_body(&body, 1);
+ break;
+ case HTTP_MESSAGE_RES_LINE:
+ commit_last_half_flow_data(sess, gtest_plug_exdata, HTTP_TRANSACTION_RES);
+ http_message_get_response_line(msg, &res_line);
+ res_line_to_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES], &res_line);
+ break;
+ case HTTP_MESSAGE_RES_HEADER:
+ while (http_message_response_header_next(msg, &header) > 0)
+ {
+ http_header_to_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES], &header);
+ }
+ g_header_count = 1;
+ break;
+ case HTTP_MESSAGE_RES_BODY:
+ http_message_get_response_raw_body(msg, &body);
+ // output_http_body(&body, 0);
+
+ http_message_get_response_decompress_body(msg, &body);
+ // output_http_body(&body, 1);
+ break;
+
+ // to do: check payload
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+void http_decoder_test_exdata_free(struct session *sess, int idx, void *ex_ptr,
+ void *arg)
+{
+ if (ex_ptr != NULL)
+ {
+ struct gtest_plug_exdata_t *gtest_plug_exdata = (struct gtest_plug_exdata_t *)ex_ptr;
+ if (gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ])
+ {
+ commit_last_half_flow_data(sess, gtest_plug_exdata, HTTP_TRANSACTION_REQ);
+ }
+ if (gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES])
+ {
+ commit_last_half_flow_data(sess, gtest_plug_exdata, HTTP_TRANSACTION_RES);
+ }
+ free(ex_ptr);
+ }
+}
+
+extern "C" void *http_decoder_test_init(struct stellar *st)
+{
+ g_exdata_idx =
+ stellar_session_get_ex_new_index(st, "HTTP_DECODER_REQ_TEST",
+ http_decoder_test_exdata_free,
+ NULL);
+ if (g_exdata_idx < 0)
+ {
+ printf("[%s:%d]: can't get http_decoder exdata index !!!\n",
+ __FUNCTION__, __LINE__);
+ exit(-1);
+ }
+
+ g_topic_id = session_mq_get_topic_id(st, "HTTP_DECODER_MESSAGE");
+ if (g_topic_id < 0)
+ {
+ printf("[%s:%d]: can't get http_decoder topic id !!!\n",
+ __FUNCTION__, __LINE__);
+ exit(-1);
+ }
+
+ session_mq_subscribe_topic(st, g_topic_id, http_decoder_test_entry, NULL);
+ printf("http_decoder_test_init OK!\n");
+
+ return NULL;
+}
+
+extern "C" void http_decoder_test_exit(void *test_ctx)
+{
+ if (test_ctx != NULL)
+ {
+ FREE(test_ctx);
+ }
+
+ printf("http_decoder_test_exit OK!\n");
+} \ No newline at end of file