#include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #include "stellar/stellar.h" #include "monitor/monitor_private.h" #include "sds/sds.h" #ifdef __cplusplus } #endif #define TEST_PKT_DUMP_FILE_NAME "__gtest_stm_pkt_dump.pcap" struct async_cmd_args { pthread_t tid; const char *cmd; int cmd_array_size; sds *cmd_result_array; int wait_thread_create_time_ms; }; static sds *stellar_cli_exec_cmd(const char *command_str, int *result_size) { int ret; sds *cmd_result_array = NULL; char result[4096] = {}; FILE *fp = popen(command_str, "r"); if (NULL == fp) { return NULL; } ret = fread(result, 1, sizeof(result), fp); if (ret > 0) { cmd_result_array = sdssplitlen(result, strlen(result), "\r\n", 1, result_size); } pclose(fp); return cmd_result_array; } static void *async_cmd_run_thread(void *arg) { struct async_cmd_args *async_arg = (struct async_cmd_args *)arg; async_arg->cmd_result_array = stellar_cli_exec_cmd(async_arg->cmd, &async_arg->cmd_array_size); return NULL; } static void async_cmd_run(struct async_cmd_args *arg) { pthread_create(&arg->tid, NULL, async_cmd_run_thread, arg); usleep(arg->wait_thread_create_time_ms * 1000); } static void async_cmd_wait(struct async_cmd_args *async_arg) { pthread_join(async_arg->tid, NULL); } // class MonitorServerMock : public testing::Test // { // public: // static struct stellar *st; // static pthread_t tid; // static int thread_count; // static int cmd_result_line_num; // static int cmd_array_size; // static sds *cmd_result_array; // protected: // static void SetUpTestCase() // { // printf("Gtest Stm Server: Setup Test Case Env...\n"); // st = stellar_new("./conf/stellar.toml", "./plugin/spec.toml", "./conf/log.toml"); // assert(st != NULL); // } // static void TearDownTestCase() // { // printf("Gtest Stm Server: Tear Down Test Case Env...\n"); // stellar_free(st); // } // }; // pthread_t MonitorServerMock::tid; // int MonitorServerMock::thread_count; // int MonitorServerMock::cmd_result_line_num; // struct stellar *MonitorServerMock::st; // int MonitorServerMock::cmd_array_size; // sds *MonitorServerMock::cmd_result_array; static int get_local_pcap_packet_number(const char *filename) { char cmd_buf[256] = {}; snprintf(cmd_buf, sizeof(cmd_buf), "tcpdump -r %s -n -nn -t -q | wc -l", filename); int cmd_res_size; sds *cmd_res = stellar_cli_exec_cmd(cmd_buf, &cmd_res_size); int pkt_num = 0; for (int i = 0; i < cmd_res_size; i++) { if (strstr(cmd_res[i], "reading from file") != NULL) { continue; } if (strstr(cmd_res[i], "tcpdump") != NULL) { continue; } if (isdigit(cmd_res[i][0])) { pkt_num = atoi(cmd_res[i]); } } sdsfreesplitres(cmd_res, cmd_res_size); return pkt_num; } static int get_netstat_num(const char *cmd) { int cmd_res_size; sds *cmd_res = stellar_cli_exec_cmd(cmd, &cmd_res_size); int pkt_num = 0; for (int i = 0; i < cmd_res_size; i++) { if (isdigit(cmd_res[i][0])) { pkt_num = atoi(cmd_res[i]); } } sdsfreesplitres(cmd_res, cmd_res_size); return pkt_num; } TEST(MONITOR_PKT_DUMP, base) { struct async_cmd_args async_arg = {}; async_arg.wait_thread_create_time_ms = 100; char cmd_buf[256] = {}; remove(TEST_PKT_DUMP_FILE_NAME); const int expect_cap_pkt_num = 11; struct stellar *st = stellar_new("./conf/stellar.toml"); ASSERT_TRUE(st != NULL); snprintf(cmd_buf, sizeof(cmd_buf), "./stellar-dump -n -nn -c %d -s0 -w %s", expect_cap_pkt_num, TEST_PKT_DUMP_FILE_NAME); async_arg.cmd = cmd_buf; async_cmd_run(&async_arg); stellar_run(st); async_cmd_wait(&async_arg); sdsfreesplitres(async_arg.cmd_result_array, async_arg.cmd_array_size); int actual_cap_num = get_local_pcap_packet_number(TEST_PKT_DUMP_FILE_NAME); EXPECT_EQ(expect_cap_pkt_num, actual_cap_num); stellar_free(st); } TEST(MONITOR_PKT_DUMP, arg_ip_port) { struct async_cmd_args async_arg = {}; async_arg.wait_thread_create_time_ms = 100; char cmd_buf[256] = {}; remove(TEST_PKT_DUMP_FILE_NAME); struct stellar *st = stellar_new("./conf/stellar.toml"); ASSERT_TRUE(st != NULL); const int expect_cap_pkt_num = 13; snprintf(cmd_buf, sizeof(cmd_buf), "./stellar-dump -n -nn -c %d -i 127.0.0.1 -P 80 -s0 -w %s", expect_cap_pkt_num, TEST_PKT_DUMP_FILE_NAME); async_arg.cmd = cmd_buf; async_cmd_run(&async_arg); stellar_run(st); async_cmd_wait(&async_arg); sdsfreesplitres(async_arg.cmd_result_array, async_arg.cmd_array_size); int actual_cap_num = get_local_pcap_packet_number(TEST_PKT_DUMP_FILE_NAME); EXPECT_EQ(expect_cap_pkt_num, actual_cap_num); stellar_free(st); } TEST(MONITOR_PKT_DUMP, arg_bpf) { struct async_cmd_args async_arg = {}; async_arg.wait_thread_create_time_ms = 100; char cmd_buf[256] = {}; remove(TEST_PKT_DUMP_FILE_NAME); struct stellar *st = stellar_new("./conf/stellar.toml"); ASSERT_TRUE(st != NULL); const int expect_cap_pkt_num = 33; snprintf(cmd_buf, sizeof(cmd_buf), "./stellar-dump -n -nn -c %d host 172.16.0.203 and host 172.100.15.25 and udp port 1935 and udp port 52043 -s0 -U -w %s", expect_cap_pkt_num, TEST_PKT_DUMP_FILE_NAME); async_arg.cmd = cmd_buf; async_cmd_run(&async_arg); stellar_run(st); async_cmd_wait(&async_arg); sdsfreesplitres(async_arg.cmd_result_array, async_arg.cmd_array_size); int actual_cap_num = get_local_pcap_packet_number(TEST_PKT_DUMP_FILE_NAME); EXPECT_EQ(expect_cap_pkt_num, actual_cap_num); stellar_free(st); } TEST(MONITOR_PKT_DUMP, all_args) { struct async_cmd_args async_arg = {}; async_arg.wait_thread_create_time_ms = 100; char cmd_buf[256] = {}; remove(TEST_PKT_DUMP_FILE_NAME); struct stellar *st = stellar_new("./conf/stellar.toml"); ASSERT_TRUE(st != NULL); const int expect_cap_pkt_num = 33; snprintf(cmd_buf, sizeof(cmd_buf), "./stellar-dump -n -nn -c %d -i 127.0.0.1 -P 80 -g host 172.16.0.203 and host 172.100.15.25 and udp port 1935 and udp port 52043 -s0 -U -w %s", expect_cap_pkt_num, TEST_PKT_DUMP_FILE_NAME); async_arg.cmd = cmd_buf; async_cmd_run(&async_arg); stellar_run(st); async_cmd_wait(&async_arg); sdsfreesplitres(async_arg.cmd_result_array, async_arg.cmd_array_size); int actual_cap_num = get_local_pcap_packet_number(TEST_PKT_DUMP_FILE_NAME); EXPECT_EQ(expect_cap_pkt_num, actual_cap_num); stellar_free(st); } TEST(MONITOR_PKT_DUMP, too_many_clients) { #define MAX_CLIENT_NUM 1000 struct async_cmd_args async_arg[MAX_CLIENT_NUM] = {}; char cmd_buf[256] = {}; const int expect_cap_pkt_num = 1; remove(TEST_PKT_DUMP_FILE_NAME); struct stellar *st = stellar_new("./conf/stellar.toml"); ASSERT_TRUE(st != NULL); snprintf(cmd_buf, sizeof(cmd_buf), "./stellar-dump -n -nn -q -t -c 1 udp port 5005 and udp port 39627 -w /dev/null"); // the last udp packet for (int i = 0; i < MAX_CLIENT_NUM; i++) { async_arg[i].wait_thread_create_time_ms = 0; async_arg[i].cmd = cmd_buf; async_cmd_run(&async_arg[i]); } struct async_cmd_args save_pcap_async_arg = {}; save_pcap_async_arg.wait_thread_create_time_ms = 100; char save_pcap_cmd_buf[256] = {}; snprintf(save_pcap_cmd_buf, sizeof(save_pcap_cmd_buf), "./stellar-dump -n -nn -q -t -c %d udp port 5005 and udp port 39627 -s0 -U -w %s", expect_cap_pkt_num, TEST_PKT_DUMP_FILE_NAME); save_pcap_async_arg.cmd = save_pcap_cmd_buf; async_cmd_run(&save_pcap_async_arg); /* todo: how do I make sure all stellar-dump are started? */ while (get_netstat_num("netstat -anup | grep stellar | wc -l") < MAX_CLIENT_NUM + 1) { printf("### wait for all stellar-dump starting...\n"); sleep(1); } stellar_run(st); for (int i = 0; i < MAX_CLIENT_NUM; i++) { async_cmd_wait(&async_arg[i]); sdsfreesplitres(async_arg[i].cmd_result_array, async_arg[i].cmd_array_size); } async_cmd_wait(&save_pcap_async_arg); sdsfreesplitres(save_pcap_async_arg.cmd_result_array, save_pcap_async_arg.cmd_array_size); int actual_cap_num = get_local_pcap_packet_number(TEST_PKT_DUMP_FILE_NAME); EXPECT_EQ(expect_cap_pkt_num, actual_cap_num); stellar_free(st); } int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); int ret = RUN_ALL_TESTS(); return ret; }