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/glimpse_detector/gtest_glimpse_detector_main.cpp

454 lines
13 KiB
C++
Raw Normal View History

/*
* author:yangwei
* create time:2021-8-21
*
*/
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <assert.h>
#include "app_l7_protocol.h"
#include "cjson/cJSON.h"
//#include "MESA_prof_load.h"
#include "stellar/stellar.h"
#include "stellar/session.h"
#include "stellar/stellar_exdata.h"
#include "stellar/stellar_mq.h"
struct app_test_para
{
cJSON *test_result_root;
cJSON *load_result_root;
int result_count;
};
struct app_test_para g_test_para={};
static int commit_test_result_json(struct app_test_para *para, cJSON *node, const char *name);
struct app_test_plugin_env
{
int test_exdata_idx;
int l7_exdata_idx;
int test_app_plugin_id;
struct stellar *st;
};
#define MAX_PROTO_ID_NUM 10000
static char *g_proto_id2name[MAX_PROTO_ID_NUM];
static int load_l7_protocol_mapper(const char *filename)
{
memset(g_proto_id2name, 0, sizeof(g_proto_id2name));
int ret=0, proto_id=0;;
FILE *fp=NULL;
char line[1024]={0};
char type_name[32]={0};
char proto_name[32]={0};
fp=fopen(filename, "r");
if(fp==NULL)
{
printf("Open %s failed ...", filename);
return -1;
}
memset(line, 0, sizeof(line));
while((fgets(line, sizeof(line), fp))!=NULL)
{
if(line[0]=='#' || line[0]=='\n' || line[0]=='\r' ||line[0]=='\0')
{
continue;
}
ret=sscanf(line, "%31s %31s %d", type_name, proto_name, &proto_id);
assert(ret==3 && proto_id < MAX_PROTO_ID_NUM);
g_proto_id2name[proto_id] = (char*)calloc(strlen(proto_name)+1, 1);
strcpy(g_proto_id2name[proto_id], proto_name);
memset(line, 0, sizeof(line));
}
fclose(fp);
fp=NULL;
return ret;
}
static void commit_test_result(struct app_test_plugin_env *env, cJSON *ctx, struct session *sess)
{
assert(env->l7_exdata_idx >= 0 && ctx != NULL);
struct l7_protocol_label *label = (struct l7_protocol_label *)session_exdata_get(sess, env->l7_exdata_idx);;
if(label != NULL)
{
int proto_ids[8];
const char* proto_names[8];
for(int i = 0; i < label->protocol_id_num; i++)
{
proto_ids[i] = (int)(label->protocol_id[i]);
proto_names[i] = g_proto_id2name[proto_ids[i]];
}
cJSON *label_ids = cJSON_CreateIntArray(proto_ids, label->protocol_id_num);
cJSON_AddItemToObject(ctx, "l7_label_id", label_ids);
cJSON *label_names = cJSON_CreateStringArray(proto_names, label->protocol_id_num);
cJSON_AddItemToObject(ctx, "l7_label_name", label_names);
}
else
{
cJSON_AddStringToObject(ctx, "l7_label_id", "UNKNOWN");
}
unsigned char dir_flag;
int is_symmetric=session_is_symmetric(sess, &dir_flag);
if(is_symmetric)
{
cJSON_AddStringToObject(ctx, "STREAM_DIR", "DOUBLE");
}
else if(dir_flag == SESSION_SEEN_C2S_FLOW)
{
cJSON_AddStringToObject(ctx, "STREAM_DIR", "C2S");
}
else if(dir_flag == SESSION_SEEN_S2C_FLOW)
{
cJSON_AddStringToObject(ctx, "STREAM_DIR", "S2C");
}
else
{
assert(0);
}
if (ctx)
{
char result_name[128] = "";
sprintf(result_name, "APP_PROTO_IDENTIFY_RESULT_%d", g_test_para.result_count);
commit_test_result_json(&g_test_para, ctx, result_name);
g_test_para.result_count += 1;
}
return;
}
void *APP_TEST_CTX_NEW(struct session *sess, void *plugin_env)
{
cJSON *ctx =cJSON_CreateObject();
cJSON_AddStringToObject(ctx, "Tuple4", session_get0_readable_addr(sess));
enum session_type type= session_get_type(sess);
if (type == SESSION_TYPE_TCP)
{
cJSON_AddStringToObject(ctx, "STREAM_TYPE", "TCP");
}
if (type == SESSION_TYPE_UDP)
{
cJSON_AddStringToObject(ctx, "STREAM_TYPE", "UDP");
}
return ctx;
}
void APP_TEST_CTX_FREE(struct session *sess, void *session_ctx, void *plugin_env)
{
cJSON *ctx = (cJSON *)session_ctx;
commit_test_result((struct app_test_plugin_env*)plugin_env, ctx, sess);
return;
}
static void APP_TEST_ON_SESSION_MSG(struct session *sess, int topic_id, const void *msg, void *per_session_ctx, void *plugin_env)
{
return;
}
extern "C" void *APP_TEST_PLUG_INIT(struct stellar *st)
{
struct app_test_plugin_env *env = (struct app_test_plugin_env *)calloc(1, sizeof(struct app_test_plugin_env));
env->st=st;
//const char *l7_label_name=(const char*)"L7_PROTOCOL_LABEL";
//const char *l7_bridge_name=(const char*)"APP_BRIDGE";
const char *l7_proto_name=(const char*)"./tsgconf/tsg_l7_protocol.conf";
//MESA_load_profile_string_def("./tsgconf/main.conf", "SYSTEM", "L7_LABEL_NAME", l7_label_name, sizeof(l7_label_name), "L7_PROTOCOL_LABEL");
//MESA_load_profile_string_def("./tsgconf/main.conf", "SYSTEM", "APP_BRIDGE_NAME", l7_bridge_name, sizeof(l7_bridge_name), "APP_BRIDGE");
//MESA_load_profile_string_def("./tsgconf/main.conf", "SYSTEM", "L7_PROTOCOL_FILE", l7_proto_name, sizeof(l7_proto_name), "./tsgconf/tsg_l7_protocol.conf");
env->l7_exdata_idx= stellar_exdata_new_index(st, "L7_PROTOCOL", stellar_exdata_free_default, NULL);
env->test_exdata_idx= stellar_exdata_new_index(st, "APP_PROTO_TEST", stellar_exdata_free_default, NULL);
if(env->l7_exdata_idx<0 || env->test_exdata_idx<0)
{
printf("APP_PROTO_IDENTIFY_TEST_PLUG_INIT:stellar_session_get_ex_new_index faild!!!\n");
exit(-1);
}
int ret = load_l7_protocol_mapper(l7_proto_name);
if(ret<0)
{
printf("APP_PROTO_IDENTIFY_TEST_PLUG_INIT:l7_protocol_mapper failed !!!\n");
exit(-1);
}
env->test_app_plugin_id=stellar_session_plugin_register(st, APP_TEST_CTX_NEW, APP_TEST_CTX_FREE, env);
if(env->test_app_plugin_id < 0)
{
printf("APP_PROTO_IDENTIFY_TEST_PLUG_INIT:stellar_plugin_register failed !!!\n");
exit(-1);
}
int tcp_topic_id=stellar_mq_get_topic_id(st, TOPIC_TCP);
int udp_topic_id=stellar_mq_get_topic_id(st, TOPIC_UDP);
if(tcp_topic_id < 0 || udp_topic_id < 0)
{
perror("get tcp or udp topic id failed\n");
exit(-1);
}
stellar_session_mq_subscribe(st, tcp_topic_id, APP_TEST_ON_SESSION_MSG, env->test_app_plugin_id);
stellar_session_mq_subscribe(st, udp_topic_id, APP_TEST_ON_SESSION_MSG, env->test_app_plugin_id);
printf("APP_PROTO_IDENTIFY_TEST_PLUG_INIT OK!\n");
return env;
}
extern "C" void APP_TEST_PLUG_DESTROY(void *ctx)
{
struct app_test_plugin_env *env = (struct app_test_plugin_env *)ctx;
free(env);
printf("APP_PROTO_IDENTIFY_TEST_PLUG_DESTROY OK!\n");
return ;
}
#include <gtest/gtest.h>
#include "stellar/stellar.h"
static int commit_test_result_json(struct app_test_para *para, cJSON *node, const char *name)
{
assert(node != NULL || name != NULL || para != NULL);
if(para->test_result_root)
{
//cJSON_AddItemToObject(g_test_result_root, name, node);
cJSON_AddStringToObject(node, "name", name);
cJSON_AddItemToArray(para->test_result_root, node);
return 0;
}
return -1;
}
static cJSON *load_result_from_jsonfile(const char *json_path)
{
if(json_path == NULL)return NULL;
long file_len = 0;
char *file_content = NULL;
FILE *fp = NULL;
fp = fopen(json_path, "r+");
if (NULL == fp)
{
return NULL;
}
fseek(fp, 0, SEEK_END);
file_len = ftell(fp);
fseek(fp, 0, SEEK_SET);
if (file_len == 0) {
fclose(fp);
return NULL;
}
file_content = (char *) malloc(file_len + 1);
fread(file_content, file_len, 1, fp);
file_content[file_len] = '\0';
cJSON *load = cJSON_Parse(file_content);
free(file_content);
fclose(fp);
return load;
}
static int app_test_para_start(struct app_test_para *para, const char *load_json_path)
{
para->test_result_root = cJSON_CreateArray();
para->load_result_root = load_result_from_jsonfile(load_json_path);
para->result_count=1;//count start from 1
return 0;
}
static int app_test_para_finish(struct app_test_para *para)
{
if(para==NULL)return -1;
if(para->test_result_root==NULL || para->load_result_root==NULL)return -1;
int ret=-1;
if(cJSON_GetArraySize(para->test_result_root)!=cJSON_GetArraySize(para->load_result_root))
{
char *load_json_str = cJSON_Print(para->load_result_root);
printf("LOAD Raw:\n%s\n", load_json_str);
free(load_json_str);
char *result_json_str = cJSON_Print(para->test_result_root);
printf("TEST Raw:\n%s\n", result_json_str);
free(result_json_str);
ret=-1;
goto error_out;
}
ret = cJSON_Compare(para->load_result_root, para->test_result_root, 0);
if (ret != 1)
{
char *load_json_str = cJSON_Print(para->load_result_root);
printf("LOAD Raw:\n%s\n", load_json_str);
free(load_json_str);
char *result_json_str = cJSON_Print(para->test_result_root);
printf("TEST Raw:\n%s\n", result_json_str);
free(result_json_str);
cJSON *t_load = para->load_result_root->child, *t_test = para->test_result_root->child;
while (t_load != NULL)
{
// print first diff item, then return;
if(1 != cJSON_Compare(t_load, t_test, 0))
{
load_json_str = cJSON_Print(t_load);
printf("LOAD Diff:\n%s\n", load_json_str);
free(load_json_str);
result_json_str = cJSON_Print(t_test);
printf("TEST Diff:\n%s\n", result_json_str);
free(result_json_str);
goto error_out;
}
t_load = t_load->next;
t_test = t_test->next;
}
}
error_out:
if(para->test_result_root)cJSON_Delete(para->test_result_root);
if(para->load_result_root)cJSON_Delete(para->load_result_root);
return ret;
}
/**********************************************
* GTEST MAIN *
**********************************************/
#define RESULT_JSON_DIR_NAME "test_result_json"
#define TEST_ENV_DIR_NAME "test_env"
const char *g_test_dir=NULL;
#include <limits.h>
char g_cwd[PATH_MAX];
#include <stdarg.h>
static inline void system_cmd(const char *cmd, ...)
{
char buf[4096] = {0};
va_list args;
va_start(args, cmd);
vsnprintf(buf, sizeof(buf), cmd, args);
va_end(args);
system(buf);
}
class gtest_glimpse_detector : public ::testing::Test {
protected:
char result_json_path[4096] = {0};
char pcap_path[4096] = {0};
// Constructor should be default; static members should be set externally
gtest_glimpse_detector() = default;
void SetUp() override {
chdir(g_cwd);
std::cout << "SetUpTestCase called for work_dir: " << g_test_dir<< std::endl;
system_cmd("mkdir -p ./conf/");
system_cmd("mkdir -p ./log/ ");
system_cmd("mkdir -p ./plugin");
system_cmd("mkdir -p ./tsgconf/");
system_cmd("cp %s/%s/tsg_l7_protocol.conf ./tsgconf/tsg_l7_protocol.conf", g_test_dir, TEST_ENV_DIR_NAME);
system_cmd("cp %s/%s/stellar.toml ./conf/stellar.toml", g_test_dir, TEST_ENV_DIR_NAME);
system_cmd("cp %s/%s/log.toml ./conf/log.toml", g_test_dir, TEST_ENV_DIR_NAME);
system_cmd("cp %s/%s/spec.toml ./plugin/spec.toml", g_test_dir, TEST_ENV_DIR_NAME);
// Retrieve current test info
const ::testing::TestInfo* test_info = ::testing::UnitTest::GetInstance()->current_test_info();
std::cout << "Setting up test environment for test case: "
<< test_info->test_case_name()
<< " in work_dir: " << g_test_dir << std::endl;
// Initialize paths based on test case name and arguments
memset(&g_test_para, 0, sizeof(struct app_test_para));
snprintf(result_json_path, sizeof(result_json_path),
"%s/%s/%s.json", g_test_dir, RESULT_JSON_DIR_NAME,
test_info->name());
snprintf(pcap_path, sizeof(pcap_path),
"%s/%s", g_test_dir, test_info->name());
std::cout << "result_json_path: " << result_json_path << std::endl;
std::cout << "pcap_path: " << pcap_path << std::endl;
system_cmd("tomlq -t -i '.packet_io.dumpfile_dir = \"%s\" ' ./conf/stellar.toml", pcap_path);
system_cmd("pwd");
system_cmd("cat ./conf/stellar.toml");
}
};
TEST_F(gtest_glimpse_detector, app_pcap) {
app_test_para_start(&g_test_para, result_json_path);
stellar_run(0, NULL);
EXPECT_EQ(app_test_para_finish(&g_test_para), 1);
}
TEST_F(gtest_glimpse_detector, dns_pcap) {
app_test_para_start(&g_test_para, result_json_path);
stellar_run(0, NULL);
EXPECT_EQ(app_test_para_finish(&g_test_para), 1);
}
TEST_F(gtest_glimpse_detector, mixed_pcap) {
app_test_para_start(&g_test_para, result_json_path);
stellar_run(0, NULL);
EXPECT_EQ(app_test_para_finish(&g_test_para), 1);
}
TEST_F(gtest_glimpse_detector, openvpn_pcap) {
app_test_para_start(&g_test_para, result_json_path);
stellar_run(0, NULL);
EXPECT_EQ(app_test_para_finish(&g_test_para), 1);
}
TEST_F(gtest_glimpse_detector, ppp_pcap) {
app_test_para_start(&g_test_para, result_json_path);
stellar_run(0, NULL);
EXPECT_EQ(app_test_para_finish(&g_test_para), 1);
}
TEST_F(gtest_glimpse_detector, socks_pcap) {
app_test_para_start(&g_test_para, result_json_path);
stellar_run(0, NULL);
EXPECT_EQ(app_test_para_finish(&g_test_para), 1);
}
int main(int argc, char ** argv)
{
if(argc != 2)
{
printf("Invalid Argument!!!\n Usage: ./[gtest_main] [/path/to/glimpse_detector_test_dir] \n");
return -1;
}
getcwd(g_cwd, sizeof(g_cwd));
::testing::InitGoogleTest(&argc, argv);
g_test_dir=argv[1];
return RUN_ALL_TESTS();
}