rebase onto develop-2.0

This commit is contained in:
lijia
2024-10-18 16:47:51 +08:00
parent 99a68d5c9e
commit e734af76d8
66 changed files with 22616 additions and 6 deletions

View File

@@ -5,4 +5,5 @@ add_subdirectory(lpi_plus)
#add_subdirectory(decoders/http)
#add_subdirectory(decoders/socks)
#add_subdirectory(decoders/stratum)
#add_subdirectory(decoders/session_flags)
#add_subdirectory(decoders/session_flags)
add_subdirectory(monitor)

View File

@@ -0,0 +1,507 @@
#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();
}

View File

@@ -0,0 +1,78 @@
cmake_minimum_required (VERSION 2.8...3.10)
include_directories(${CMAKE_SOURCE_DIR}/include/)
include_directories(${CMAKE_SOURCE_DIR}/infra/)
include_directories(${CMAKE_SOURCE_DIR}/deps/)
set(MONITOR_SRC_DIR ${CMAKE_SOURCE_DIR}/infra/monitor)
# set(MONITOR_DEPEND_LIB gtest pcap sds linenoise pthread toml libevent-static cjson-static fieldstat4 stellar_lib monitor)
set(MONITOR_DEPEND_LIB gtest pcap pthread fieldstat4 )
set(WHOLE_ARCHIVE_STATIC_LIB sds linenoise toml libevent-static cjson-static stellar_lib monitor session_manager tuple)
add_executable(gtest_stm_sds gtest_sds.cpp)
add_executable(gtest_stm_util gtest_monitor_util.cpp )
# add_executable(gtest_stm_packet_dump_unit gtest_packet_dump_unit.cpp)
# add_executable(gtest_stm_packet_dump gtest_packet_dump.cpp)
add_executable(gtest_cmd_assistant gtest_cmd_assistant.cpp )
add_executable(gtest_stm_spinlock gtest_spinlock.cpp )
# add_executable(gtest_seek_layer gtest_seek_layer.cpp)
add_executable(gtest_stm_server gtest_monitor_server.cpp)
add_executable(gtest_stm_topk gtest_topk.cpp)
add_executable(stm_server monitor_main.cpp)
add_executable(gtest_stm_rpc gtest_rpc.cpp)
set(MONITOR_TEST_FILE gtest_stm_sds gtest_stm_util gtest_cmd_assistant gtest_stm_spinlock gtest_stm_server gtest_stm_topk stm_server gtest_stm_rpc)
foreach(tfile ${MONITOR_TEST_FILE})
target_link_libraries(${tfile} ${MONITOR_DEPEND_LIB} -Wl,--whole-archive ${WHOLE_ARCHIVE_STATIC_LIB} -Wl,--no-whole-archive)
endforeach()
set(MONITOR_TEST_RUN_DIR ${CMAKE_CURRENT_BINARY_DIR})
add_test(NAME MONITOR_ENV_SETUP COMMAND sh -c "mkdir -p ${MONITOR_TEST_RUN_DIR}/conf &&
mkdir -p ${MONITOR_TEST_RUN_DIR}/plugin &&
mkdir -p ${MONITOR_TEST_RUN_DIR}/log &&
mkdir -p ${MONITOR_TEST_RUN_DIR}/pcap &&
cp ${CMAKE_SOURCE_DIR}/conf/stellar.toml ${MONITOR_TEST_RUN_DIR}/conf/stellar.toml &&
tomlq -t -i '.packet_io.mode=\"pcapfile\"' ${MONITOR_TEST_RUN_DIR}/conf/stellar.toml &&
tomlq -t -i '.packet_io.pcap_path=\"pcap/test.pcap\"' ${MONITOR_TEST_RUN_DIR}/conf/stellar.toml &&
rm -f ${MONITOR_TEST_RUN_DIR}/conf/log.toml &&
echo '[log]' >> ${MONITOR_TEST_RUN_DIR}/conf/log.toml &&
echo 'output = \"file\"' >> ${MONITOR_TEST_RUN_DIR}/conf/log.toml &&
echo 'level = \"DEBUG\"' >> ${MONITOR_TEST_RUN_DIR}/conf/log.toml &&
rm -f ${MONITOR_TEST_RUN_DIR}/pcap/test.pcap &&
cp ${CMAKE_BINARY_DIR}/tools/monitor/stellar-cli ${MONITOR_TEST_RUN_DIR}/stellar-cli &&
cp ${CMAKE_BINARY_DIR}/tools/monitor/tcpdump/src/tcpdump-build/stellar-dump ${MONITOR_TEST_RUN_DIR}/stellar-dump")
add_test(NAME MONITOR_COPY_PCAP COMMAND sh -c "rm -f ${MONITOR_TEST_RUN_DIR}/pcap/test.pcap &&
cp ${CMAKE_SOURCE_DIR}/test/monitor/pcap/monitor_benchmark.pcap ${MONITOR_TEST_RUN_DIR}/pcap/test.pcap &&
md5sum ${MONITOR_TEST_RUN_DIR}/pcap/test.pcap |grep 79d4c8e526f638b59b12b7defb5021d9")
add_test(NAME MONITOR_TEST_SERVER COMMAND sh -c "./gtest_stm_server" WORKING_DIRECTORY ${GMONITOR_TEST_RUN_DIR})
set_tests_properties(MONITOR_ENV_SETUP
PROPERTIES FIXTURES_SETUP STM_ENV_SETUP)
set_tests_properties(MONITOR_TEST_SERVER
PROPERTIES FIXTURES_REQUIRED STM_ENV_SETUP)
# add_test(NAME MONITOR_PKT_DUMP_COPY_PCAP COMMAND sh -c "rm -f ${MONITOR_TEST_RUN_DIR}/pcap/test.pcap &&
# cp ${CMAKE_SOURCE_DIR}/test/monitor/pcap/monitor_packet_dump.pcap ${MONITOR_TEST_RUN_DIR}/pcap/test.pcap &&
# md5sum ${MONITOR_TEST_RUN_DIR}/pcap/test.pcap |grep eb7795612a389d71d0f82fef5737981d")
# set_tests_properties(MONITOR_ENV_SETUP MONITOR_PKT_DUMP_COPY_PCAP
# PROPERTIES FIXTURES_SETUP STM_GTEST_PKT_DUMP)
# add_test(NAME MONITOR_TEST_PKT_DUMP COMMAND sh -c "./gtest_stm_packet_dump" WORKING_DIRECTORY ${MONITOR_TEST_RUN_DIR})
# set_tests_properties(MONITOR_TEST_PKT_DUMP
# PROPERTIES FIXTURES_REQUIRED STM_GTEST_PKT_DUMP)
# add_test(NAME MONITOR_PKT_DUMP_TUNNEL_COPY_PCAP COMMAND sh -c "rm -f ${MONITOR_TEST_RUN_DIR}/pcap/test.pcap &&
# cp ${CMAKE_SOURCE_DIR}/test/monitor/pcap/monitor_tunnel.pcap ${MONITOR_TEST_RUN_DIR}/pcap/test.pcap &&
# md5sum ${MONITOR_TEST_RUN_DIR}/pcap/test.pcap |grep 525dab2a04d02b36d7d21be16f51e1cd")
# add_executable(gtest_stm_packet_dump_tunnel gtest_packet_dump_tunnel.cpp ${STM_DEP_SRC} )
# target_link_libraries(gtest_stm_packet_dump_tunnel ${MONITOR_DEPEND_LIB} ${WHOLE_ARCHIVE_STATIC_LIB} )
# set_tests_properties(MONITOR_ENV_SETUP MONITOR_PKT_DUMP_TUNNEL_COPY_PCAP
# PROPERTIES FIXTURES_SETUP STM_GTEST_PKT_DUMP_TUNNEL)
# add_test(NAME MONITOR_TEST_PKT_DUMP_TUNNEL COMMAND sh -c "./gtest_stm_packet_dump_tunnel" WORKING_DIRECTORY ${MONITOR_TEST_RUN_DIR})
# set_tests_properties(MONITOR_TEST_PKT_DUMP_TUNNEL
# PROPERTIES FIXTURES_REQUIRED STM_GTEST_PKT_DUMP_TUNNEL)
include(GoogleTest)
gtest_discover_tests(gtest_stm_util)
gtest_discover_tests(gtest_cmd_assistant)
# gtest_discover_tests(gtest_seek_layer)

View File

@@ -0,0 +1,252 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stddef.h>
#include <getopt.h>
#include <gtest/gtest.h>
#include "monitor/monitor_cmd_assistant.h"
#include "sds/sds.h"
#include "linenoise/linenoise.h"
static struct monitor_reply *test_cmd_cb(int argc, char *argv[], void *user_arg)
{
(void)argc;
(void)argv;
(void)user_arg;
return NULL;
}
TEST(MONITOR_CMD_ASSISTANT, sds_compare)
{
int cli_argc, register_cmd_argc;
const char *cli = "show";
const char *register_cmd = "show";
sds *cli_array = sdssplitargs(cli, &cli_argc);
sds *register_cmd_array = sdssplitargs(register_cmd, &register_cmd_argc);
EXPECT_EQ(0, stm_cmd_assistant_sds_compare(cli_array, cli_argc, register_cmd_array, register_cmd_argc));
sdsfreesplitres(cli_array, cli_argc);
sdsfreesplitres(register_cmd_array, register_cmd_argc);
cli = "s";
register_cmd = "show";
cli_array = sdssplitargs(cli, &cli_argc);
register_cmd_array = sdssplitargs(register_cmd, &register_cmd_argc);
EXPECT_EQ(-1, stm_cmd_assistant_sds_compare(cli_array, cli_argc, register_cmd_array, register_cmd_argc));
sdsfreesplitres(cli_array, cli_argc);
sdsfreesplitres(register_cmd_array, register_cmd_argc);
cli = "show";
register_cmd = "show session";
cli_array = sdssplitargs(cli, &cli_argc);
register_cmd_array = sdssplitargs(register_cmd, &register_cmd_argc);
EXPECT_EQ(-1, stm_cmd_assistant_sds_compare(cli_array, cli_argc, register_cmd_array, register_cmd_argc));
sdsfreesplitres(cli_array, cli_argc);
sdsfreesplitres(register_cmd_array, register_cmd_argc);
cli = "show s";
register_cmd = "show session";
cli_array = sdssplitargs(cli, &cli_argc);
register_cmd_array = sdssplitargs(register_cmd, &register_cmd_argc);
EXPECT_EQ(-1, stm_cmd_assistant_sds_compare(cli_array, cli_argc, register_cmd_array, register_cmd_argc));
sdsfreesplitres(cli_array, cli_argc);
sdsfreesplitres(register_cmd_array, register_cmd_argc);
cli = "show session xxx yyy zzz";
register_cmd = "show session";
cli_array = sdssplitargs(cli, &cli_argc);
register_cmd_array = sdssplitargs(register_cmd, &register_cmd_argc);
EXPECT_EQ(1, stm_cmd_assistant_sds_compare(cli_array, cli_argc, register_cmd_array, register_cmd_argc));
sdsfreesplitres(cli_array, cli_argc);
sdsfreesplitres(register_cmd_array, register_cmd_argc);
}
TEST(MONITOR_CMD_ASSISTANT, cmd_register)
{
struct stm_cmd_assistant *cmd_aide = stm_cmd_assistant_new();
stm_cmd_assistant_register_cmd(cmd_aide, "get", (void *)"test_cmd_cb", (void *)"get args", "readonly", "key", "get xxx");
EXPECT_EQ((void *)"test_cmd_cb", stm_cmd_assistant_get_cb(cmd_aide, "get"));
EXPECT_EQ((void *)"get args", stm_cmd_assistant_get_user_arg(cmd_aide, "get"));
stm_cmd_assistant_register_cmd(cmd_aide, "show session", (void *)"show_session_cb", (void *)"show session args", "readonly", "id", "show session xxx");
EXPECT_EQ((void *)"show_session_cb", stm_cmd_assistant_get_cb(cmd_aide, "show session id 1"));
EXPECT_EQ((void *)"show session args", stm_cmd_assistant_get_user_arg(cmd_aide, "show session id 3"));
stm_cmd_assistant_register_cmd(cmd_aide, "show http", (void *)"show_http_cb", (void *)"show http args", "readonly", "id", "show http xxx");
EXPECT_EQ((void *)"show_http_cb", stm_cmd_assistant_get_cb(cmd_aide, "show http url a.b.com"));
EXPECT_EQ((void *)"show http args", stm_cmd_assistant_get_user_arg(cmd_aide, "show http url a.b.com"));
stm_cmd_assistant_register_cmd(cmd_aide, "show http stat", (void *)"show_http_stat_cb", (void *)"show http stat args", "readonly", "id", "show http stat xxx");
EXPECT_EQ((void *)"show_http_stat_cb", stm_cmd_assistant_get_cb(cmd_aide, "show http stat brief"));
EXPECT_EQ((void *)"show http stat args", stm_cmd_assistant_get_user_arg(cmd_aide, "show http stat brief"));
stm_cmd_assistant_register_cmd(cmd_aide, "show http stat brief limit", (void *)"show_http_stat_limit_cb", (void *)"show http stat limit args", "readonly", "id", "show http stat limit xxx");
EXPECT_EQ((void *)"show_http_stat_limit_cb", stm_cmd_assistant_get_cb(cmd_aide, "show http stat brief limit 1"));
EXPECT_EQ((void *)"show http stat limit args", stm_cmd_assistant_get_user_arg(cmd_aide, "show http stat brief limit 1"));
stm_cmd_assistant_free(cmd_aide);
}
TEST(MONITOR_CMD_ASSISTANT, serialize_dserialize)
{
struct stm_cmd_assistant *cmd_aide = stm_cmd_assistant_new();
stm_cmd_assistant_register_cmd(cmd_aide, "get", (void *)test_cmd_cb, NULL, "readonly", "key", "get xxx");
stm_cmd_assistant_register_cmd(cmd_aide, "set", (void *)test_cmd_cb, NULL, "write", "key value [NX] [EX seconds | PX milliseconds]", "set xxx");
stm_cmd_assistant_register_cmd(cmd_aide, "show session id", (void *)test_cmd_cb, NULL, "readonly", "value", "show session id xxx");
char *free_after_used = stm_cmd_assistant_serialize(cmd_aide);
printf("serialize : \n%s\n", free_after_used);
struct stm_cmd_assistant *cmd_aide_new = stm_cmd_assistant_new();
stm_cmd_assistant_dserialize(cmd_aide_new, free_after_used);
char *free_after_used2 = stm_cmd_assistant_serialize(cmd_aide_new);
printf("serialize : \n%s\n", free_after_used2);
ASSERT_STREQ(free_after_used, free_after_used2);
free(free_after_used);
free(free_after_used2);
stm_cmd_assistant_free(cmd_aide);
stm_cmd_assistant_free(cmd_aide_new);
}
struct gtest_cmd_completion_stat
{
linenoiseCompletions *lc;
int expect_completion_num;
int match_num;
int not_match_num;
const char *expect_completion_str[128];
};
struct gtest_cmd_completion_stat g_expect_stat = {};
static void gtest_cmd_completion_cb(void *arg, const char *candidate_completion)
{
struct gtest_cmd_completion_stat *local_expect_stat = (struct gtest_cmd_completion_stat *)arg;
for (int i = 0; i < local_expect_stat->expect_completion_num; i++)
{
if (0 == strcasecmp(local_expect_stat->expect_completion_str[i], candidate_completion))
{
// printf("gtest completion cb match : %s\n", candidate_completion);
local_expect_stat->match_num++;
return;
}
}
local_expect_stat->not_match_num++;
}
void gtest_linenoise_completion_cb(const char *line, linenoiseCompletions *lc)
{
g_expect_stat.lc = lc;
stm_cmd_assistant_input_line(stm_cmd_assistant_get(), line, (void *)&g_expect_stat);
}
TEST(MONITOR_CMD_ASSISTANT, cmd_completion)
{
struct stm_cmd_assistant *cmd_aide = stm_cmd_assistant_new();
stm_cmd_assistant_register_cmd(cmd_aide, "get", (void *)test_cmd_cb, NULL, "readonly", "key", "get xxx");
stm_cmd_assistant_register_cmd(cmd_aide, "set", (void *)test_cmd_cb, NULL, "write", "key value [NX] [EX seconds | PX milliseconds]", "set xxx");
stm_cmd_assistant_register_cmd(cmd_aide, "show session", (void *)test_cmd_cb, NULL, "readonly", "value", "show session xxx");
stm_cmd_assistant_register_cmd(cmd_aide, "show session id", (void *)test_cmd_cb, NULL, "readonly", "value", "show session id xxx");
stm_cmd_assistant_register_cmd(cmd_aide, "show http", (void *)test_cmd_cb, NULL, "readonly", "status ", "show http xxx");
stm_cmd_assistant_register_cmd(cmd_aide, "show ssl", (void *)test_cmd_cb, NULL, "readonly", "status", "show ssl xxx");
g_expect_stat.expect_completion_num = 4;
g_expect_stat.expect_completion_str[0] = "show session";
g_expect_stat.expect_completion_str[1] = "show session id";
g_expect_stat.expect_completion_str[2] = "show http";
g_expect_stat.expect_completion_str[3] = "show ssl";
stm_cmd_assistant_set_completion_cb(cmd_aide, gtest_cmd_completion_cb);
#if 0 // linenoise not call completion callback if input is not stdin (freopn stdin to a local file)
linenoiseSetCompletionCallback(gtest_linenoise_completion_cb);
FILE *fake_stdin_file = fopen("./__fake_stdin_file", "w+");
fprintf(fake_stdin_file, "show");
fflush(fake_stdin_file);
fclose(fake_stdin_file);
FILE *raw_stdin_ptr = stdin;
ASSERT_TRUE(freopen("./__fake_stdin_file", "r", stdin) != NULL);
g_expect_stat.not_match_num = 0;
g_expect_stat.match_num = 0;
char *line = linenoise("cli> ");
printf("fake cli input line : %s\n", line);
free(line);
stdin = raw_stdin_ptr;
#else
(void)stm_cmd_assistant_input_line(cmd_aide, "show", &g_expect_stat);
#endif
EXPECT_EQ(0, g_expect_stat.not_match_num);
EXPECT_EQ(g_expect_stat.match_num, g_expect_stat.expect_completion_num);
g_expect_stat.not_match_num = 0;
g_expect_stat.match_num = 0;
stm_cmd_assistant_input_line(cmd_aide, "sh", &g_expect_stat);
EXPECT_EQ(0, g_expect_stat.not_match_num);
EXPECT_EQ(g_expect_stat.match_num, g_expect_stat.expect_completion_num);
g_expect_stat.not_match_num = 0;
g_expect_stat.match_num = 0;
stm_cmd_assistant_input_line(cmd_aide, "show h", &g_expect_stat);
EXPECT_EQ(0, g_expect_stat.not_match_num);
EXPECT_EQ(1, g_expect_stat.match_num);
g_expect_stat.not_match_num = 0;
g_expect_stat.match_num = 0;
stm_cmd_assistant_input_line(cmd_aide, "show s", &g_expect_stat);
EXPECT_EQ(0, g_expect_stat.not_match_num);
EXPECT_EQ(3, g_expect_stat.match_num);
g_expect_stat.not_match_num = 0;
g_expect_stat.match_num = 0;
stm_cmd_assistant_input_line(cmd_aide, "showxxx", &g_expect_stat);
EXPECT_EQ(0, g_expect_stat.match_num);
stm_cmd_assistant_free(cmd_aide);
}
char *line_noise_hints_callback(const char *line, int *color, int *bold)
{
char *hints = (char *)stm_cmd_assistant_input_line_for_hints(stm_cmd_assistant_get(), line);
// all commands hints result preappend a blank space before hints
if (NULL == hints)
{
return NULL;
}
sds tmp = sdsnew(" ");
tmp = sdscat(tmp, hints);
*color = 90;
*bold = 0;
return tmp;
}
void line_noise_free_hints_callback(void *arg)
{
sdsfree((sds)arg);
}
TEST(MONITOR_CMD_ASSISTANT, cmd_hints)
{
struct stm_cmd_assistant *cmd_aide = stm_cmd_assistant_new();
stm_cmd_assistant_register_cmd(cmd_aide, "get", (void *)test_cmd_cb, NULL, "readonly", "key", "get xxx");
stm_cmd_assistant_register_cmd(cmd_aide, "set", (void *)test_cmd_cb, NULL, "write", "key value [NX] [EX seconds | PX milliseconds]", "set xxx");
stm_cmd_assistant_register_cmd(cmd_aide, "show session", (void *)test_cmd_cb, NULL, "readonly", "value", "show session");
stm_cmd_assistant_register_cmd(cmd_aide, "show session id", (void *)test_cmd_cb, NULL, "readonly", "id", "show session id xxx");
stm_cmd_assistant_register_cmd(cmd_aide, "show http", (void *)test_cmd_cb, NULL, "readonly", "status", "show http xxx");
stm_cmd_assistant_register_cmd(cmd_aide, "show ssl", (void *)test_cmd_cb, NULL, "readonly", "status", "show ssl xxx");
EXPECT_STREQ("key", stm_cmd_assistant_input_line_for_hints(cmd_aide, "get"));
EXPECT_STREQ("key value [NX] [EX seconds | PX milliseconds]", stm_cmd_assistant_input_line_for_hints(cmd_aide, "set"));
EXPECT_STREQ(NULL, stm_cmd_assistant_input_line_for_hints(cmd_aide, "xxx"));
EXPECT_STREQ(NULL, stm_cmd_assistant_input_line_for_hints(cmd_aide, "show"));
EXPECT_STREQ("value", stm_cmd_assistant_input_line_for_hints(cmd_aide, "show session"));
EXPECT_STREQ("id", stm_cmd_assistant_input_line_for_hints(cmd_aide, "show session id"));
EXPECT_STREQ("status", stm_cmd_assistant_input_line_for_hints(cmd_aide, "show http"));
EXPECT_STREQ("status", stm_cmd_assistant_input_line_for_hints(cmd_aide, "show ssl"));
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
return ret;
}

View File

@@ -0,0 +1,172 @@
#include <stdint.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stddef.h>
#include <getopt.h>
#include <stdbool.h>
#include <gtest/gtest.h>
#ifdef __cplusplus
extern "C"
{
#endif
#include "stellar/monitor.h"
#include "stellar/stellar.h"
#include "monitor/monitor_private.h"
#ifdef __cplusplus
}
#endif
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;
}
#if 0 // for TEST_F
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");
assert(st != NULL);
stellar_run(st);
}
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;
#endif
TEST(monitor_server, curl_ping)
{
int cmd_array_size;
sds *cmd_result_array;
struct stellar *st = stellar_new("./conf/stellar.toml");
assert(st != NULL);
stellar_run(st);
cmd_result_array = stellar_cli_exec_cmd("curl --silent http://127.0.0.1:80/v1/stellar_monitor?raw_cmd=ping", &cmd_array_size);
ASSERT_TRUE(cmd_array_size >= 1);
ASSERT_TRUE(cmd_result_array != NULL);
EXPECT_STREQ("pong", cmd_result_array[0]);
sdsfreesplitres(cmd_result_array, cmd_array_size);
stellar_free(st);
}
TEST(monitor_server, curl_ping_messge)
{
int cmd_array_size;
sds *cmd_result_array;
struct stellar *st = stellar_new("./conf/stellar.toml");
assert(st != NULL);
stellar_run(st);
cmd_result_array = stellar_cli_exec_cmd("curl --silent http://127.0.0.1:80/v1/stellar_monitor?raw_cmd=ping%20hello,world", &cmd_array_size);
ASSERT_TRUE(cmd_array_size >= 1);
ASSERT_TRUE(cmd_result_array != NULL);
EXPECT_STREQ("hello,world", cmd_result_array[0]);
sdsfreesplitres(cmd_result_array, cmd_array_size);
stellar_free(st);
}
TEST(monitor_server, stellar_cli_ping)
{
int cmd_array_size;
sds *cmd_result_array;
struct stellar *st = stellar_new("./conf/stellar.toml");
assert(st != NULL);
stellar_run(st);
cmd_result_array = stellar_cli_exec_cmd("./stellar-cli -e ping", &cmd_array_size);
ASSERT_TRUE(cmd_array_size >= 1);
ASSERT_TRUE(cmd_result_array != NULL);
EXPECT_STREQ("pong", cmd_result_array[0]);
sdsfreesplitres(cmd_result_array, cmd_array_size);
stellar_free(st);
}
TEST(monitor_server, stellar_cli_ping_messge)
{
int cmd_array_size;
sds *cmd_result_array;
struct stellar *st = stellar_new("./conf/stellar.toml");
assert(st != NULL);
stellar_run(st);
cmd_result_array = stellar_cli_exec_cmd("./stellar-cli -e ping hello,world", &cmd_array_size);
ASSERT_TRUE(cmd_array_size >= 1);
ASSERT_TRUE(cmd_result_array != NULL);
EXPECT_STREQ("hello,world", cmd_result_array[0]);
sdsfreesplitres(cmd_result_array, cmd_array_size);
stellar_free(st);
}
TEST(monitor_server, not_found)
{
int cmd_array_size;
sds *cmd_result_array;
struct stellar *st = stellar_new("./conf/stellar.toml");
assert(st != NULL);
stellar_run(st);
cmd_result_array = stellar_cli_exec_cmd("./stellar-cli -e xxxxxxx", &cmd_array_size);
ASSERT_TRUE(cmd_array_size >= 1);
ASSERT_TRUE(cmd_result_array != NULL);
printf("cmd_result_array[0]: %s\n", cmd_result_array[0]);
EXPECT_TRUE(strstr(cmd_result_array[0], "ERR unknown command") != NULL);
sdsfreesplitres(cmd_result_array, cmd_array_size);
stellar_free(st);
}
TEST(monitor_server, invalid_args)
{
int cmd_array_size;
sds *cmd_result_array;
struct stellar *st = stellar_new("./conf/stellar.toml");
assert(st != NULL);
stellar_run(st);
cmd_result_array = stellar_cli_exec_cmd("./stellar-cli -e ping x y z ", &cmd_array_size);
ASSERT_TRUE(cmd_array_size >= 1);
ASSERT_TRUE(cmd_result_array != NULL);
printf("cmd_result_array[0]: %s\n", cmd_result_array[0]);
EXPECT_TRUE(strstr(cmd_result_array[0], "ERR wrong number of arguments") != NULL);
sdsfreesplitres(cmd_result_array, cmd_array_size);
stellar_free(st);
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
return ret;
}

View File

@@ -0,0 +1,453 @@
#include <unistd.h>
#include <stddef.h>
#include <getopt.h>
#include <arpa/inet.h>
#include <gtest/gtest.h>
#ifdef __cplusplus
extern "C"
{
#endif
#include "monitor/monitor_private.h"
#include "monitor/monitor_utils.h"
#include "sds/sds.h"
#ifdef __cplusplus
}
#endif
TEST(MONITOR_UTIL, key_value_test)
{
struct stm_key_value *kv = NULL;
char key_buf[16];
char value_buf[16];
for (int i = 0; i < 10; i++)
{
snprintf(key_buf, sizeof(key_buf), "key%d", i);
snprintf(value_buf, sizeof(value_buf), "value%d", i);
stm_cmd_key_value_append(&kv, key_buf, value_buf);
}
ASSERT_EQ(10, kv->tuple_num);
for (int i = 0; i < 10; i++)
{
snprintf(key_buf, sizeof(key_buf), "key%d", i);
snprintf(value_buf, sizeof(value_buf), "value%d", i);
ASSERT_STREQ(key_buf, kv->tuple[i].key);
ASSERT_STREQ(value_buf, kv->tuple[i].value);
}
stm_cmd_key_value_free(kv);
}
TEST(MONITOR_UTIL, stm_strncasecmp_exactly)
{
ASSERT_EQ(0, stm_strncasecmp_exactly("abc", "abc", 3));
ASSERT_EQ(0, stm_strncasecmp_exactly("abc", "ABC", 3));
ASSERT_EQ(-1, stm_strncasecmp_exactly("abc", "ABCD", 3));
ASSERT_EQ(-1, stm_strncasecmp_exactly("abc", "ABCD", 4));
ASSERT_EQ(-1, stm_strncasecmp_exactly(NULL, "ABCD", 4));
ASSERT_EQ(-1, stm_strncasecmp_exactly("abc", NULL, 4));
ASSERT_EQ(-1, stm_strncasecmp_exactly("", NULL, 4));
ASSERT_EQ(0, stm_strncasecmp_exactly("", "", 0));
}
TEST(MONITOR_UTIL, time_range)
{
time_t time_range[2];
ASSERT_EQ(-1, stm_time_range_pton(NULL, 0, NULL));
ASSERT_EQ(-1, stm_time_range_pton(NULL, 0, time_range));
ASSERT_EQ(-1, stm_time_range_pton("last-7-days", 0, NULL));
ASSERT_EQ(-1, stm_time_range_pton("last", 0, time_range));
ASSERT_EQ(-1, stm_time_range_pton("last-", 0, time_range));
ASSERT_EQ(-1, stm_time_range_pton("last-1", 0, time_range));
ASSERT_EQ(-1, stm_time_range_pton("last-1-", 0, time_range));
ASSERT_EQ(-1, stm_time_range_pton("last-1-d", 0, time_range));
ASSERT_EQ(-1, stm_time_range_pton("last-1-da", 0, time_range));
ASSERT_EQ(-1, stm_time_range_pton("last-1-day", 0, time_range));
ASSERT_EQ(0, stm_time_range_pton("last-1-days", 0, time_range));
time_t now = 10000000;
ASSERT_EQ(0, stm_time_range_pton("last-1-seconds", now, time_range));
ASSERT_EQ(now - 1, time_range[0]);
ASSERT_EQ(now, time_range[1]);
ASSERT_EQ(0, stm_time_range_pton("last-1-minutes", now, time_range));
ASSERT_EQ(now - 60, time_range[0]);
ASSERT_EQ(now, time_range[1]);
ASSERT_EQ(0, stm_time_range_pton("last-1-hours", now, time_range));
ASSERT_EQ(now - 60 * 60, time_range[0]);
ASSERT_EQ(now, time_range[1]);
ASSERT_EQ(0, stm_time_range_pton("last-1-days", now, time_range));
ASSERT_EQ(now - 24 * 60 * 60, time_range[0]);
ASSERT_EQ(now, time_range[1]);
now = 100;
ASSERT_EQ(0, stm_time_range_pton("last-999-days", now, time_range));
ASSERT_EQ(0, time_range[0]);
ASSERT_EQ(now, time_range[1]);
now = 10000;
ASSERT_EQ(0, stm_time_range_pton("last-1-seconds", now, time_range));
ASSERT_EQ(1, stm_time_in_range(now - 1, time_range));
ASSERT_EQ(0, stm_time_in_range(now - 10, time_range));
ASSERT_EQ(0, stm_time_in_range(now + 1, time_range));
ASSERT_EQ(0, stm_time_range_pton("last-1-minutes", now, time_range));
ASSERT_EQ(1, stm_time_in_range(now - 60, time_range));
ASSERT_EQ(0, stm_time_in_range(now - 61, time_range));
ASSERT_EQ(0, stm_time_in_range(now + 1, time_range));
ASSERT_EQ(0, stm_time_range_pton("last-1-hours", now, time_range));
ASSERT_EQ(1, stm_time_in_range(now - 60 * 60, time_range));
ASSERT_EQ(0, stm_time_in_range(now - 60 * 60 - 1, time_range));
ASSERT_EQ(0, stm_time_in_range(now + 1, time_range));
}
TEST(MONITOR_UTIL, inet_pton)
{
unsigned int ipv4;
struct in6_addr ipv6;
ASSERT_EQ(0, stm_inet_pton(NULL, NULL, NULL));
ASSERT_EQ(0, stm_inet_pton("", NULL, NULL));
ASSERT_EQ(0, stm_inet_pton("1.1.1.1", NULL, &ipv6));
ASSERT_EQ(0, stm_inet_pton("1234::1", &ipv4, NULL));
ASSERT_EQ(AF_INET, stm_inet_pton("1.2.3.4", &ipv4, &ipv6));
ASSERT_EQ(0x04030201, ipv4);
ASSERT_EQ(AF_INET, stm_inet_pton("1.2.3.0", &ipv4, &ipv6));
ASSERT_EQ(0x00030201, ipv4);
struct in6_addr ipv6_2;
inet_pton(AF_INET6, "1234::1", &ipv6_2);
ASSERT_EQ(AF_INET6, stm_inet_pton("1234::1", &ipv4, &ipv6));
ASSERT_EQ(0, memcmp(&ipv6_2, &ipv6, sizeof(struct in6_addr)));
inet_pton(AF_INET6, "1234::0", &ipv6_2);
ASSERT_EQ(AF_INET6, stm_inet_pton("1234::0", &ipv4, &ipv6));
ASSERT_EQ(0, memcmp(&ipv6_2, &ipv6, sizeof(struct in6_addr)));
}
TEST(MONITOR_UTIL, ip_cidr_pton)
{
unsigned int ipv4, maskv4;
struct in6_addr ipv6, maskv6;
struct in6_addr expect_maskv6;
ASSERT_EQ(0, stm_ip_cidr_pton(NULL, NULL, NULL, NULL, NULL));
ASSERT_EQ(0, stm_ip_cidr_pton("abcdefg", &ipv4, &maskv4, &ipv6, &maskv6));
ASSERT_EQ(0, stm_ip_cidr_pton("1.1.1.1", &ipv4, &maskv4, &ipv6, &maskv6));
ASSERT_EQ(0, stm_ip_cidr_pton("1.1.1.1/", &ipv4, &maskv4, &ipv6, &maskv6));
ASSERT_EQ(0, stm_ip_cidr_pton("1.1.1.1/xx", &ipv4, &maskv4, &ipv6, &maskv6));
ASSERT_EQ(AF_INET, stm_ip_cidr_pton("1.1.1.1/8", &ipv4, &maskv4, &ipv6, &maskv6));
ASSERT_EQ(0xFF000000, ntohl(maskv4));
ASSERT_EQ(AF_INET, stm_ip_cidr_pton("1.1.1.1/16", &ipv4, &maskv4, &ipv6, &maskv6));
ASSERT_EQ(0xFFFF0000, ntohl(maskv4));
ASSERT_EQ(AF_INET, stm_ip_cidr_pton("1.1.1.1/24", &ipv4, &maskv4, &ipv6, &maskv6));
ASSERT_EQ(0xFFFFFF00, ntohl(maskv4));
ASSERT_EQ(AF_INET, stm_ip_cidr_pton("1.1.1.1/32", &ipv4, &maskv4, &ipv6, &maskv6));
ASSERT_EQ(0xFFFFFFFF, maskv4);
ASSERT_EQ(0, stm_ip_cidr_pton("1.1.1.1/33", &ipv4, &maskv4, &ipv6, &maskv6));
/* IPV6 */
ASSERT_EQ(AF_INET6, stm_ip_cidr_pton("::1/8", &ipv4, &maskv4, &ipv6, &maskv6));
memset(&expect_maskv6, 0, sizeof(struct in6_addr));
expect_maskv6.s6_addr[0] = 0xFF;
ASSERT_EQ(0, memcmp(&expect_maskv6, &maskv6, sizeof(struct in6_addr)));
ASSERT_EQ(AF_INET6, stm_ip_cidr_pton("::1/32", &ipv4, &maskv4, &ipv6, &maskv6));
memset(&expect_maskv6, 0, sizeof(struct in6_addr));
expect_maskv6.s6_addr[0] = 0xFF;
expect_maskv6.s6_addr[1] = 0xFF;
expect_maskv6.s6_addr[2] = 0xFF;
expect_maskv6.s6_addr[3] = 0xFF;
ASSERT_EQ(0, memcmp(&expect_maskv6, &maskv6, sizeof(struct in6_addr)));
ASSERT_EQ(AF_INET6, stm_ip_cidr_pton("::1/128", &ipv4, &maskv4, &ipv6, &maskv6));
memset(&expect_maskv6, 0xFF, sizeof(struct in6_addr));
ASSERT_EQ(0, memcmp(&expect_maskv6, &maskv6, sizeof(struct in6_addr)));
ASSERT_EQ(0, stm_ip_cidr_pton("1.1.1.1/129", &ipv4, &maskv4, &ipv6, &maskv6));
}
TEST(MONITOR_UTIL, stm_ipv4_cidr_to_range)
{
uint32_t ipaddr, ipmask;
uint32_t iprange[2];
inet_pton(AF_INET, "192.168.1.1", &ipaddr);
inet_pton(AF_INET, "255.0.0.0", &ipmask);
stm_ipv4_cidr_to_range(ipaddr, ipmask, iprange);
ASSERT_EQ(iprange[0], ntohl(0xc0000000));
ASSERT_EQ(iprange[1], ntohl(0xc0FFFFFF));
inet_pton(AF_INET, "192.168.1.1", &ipaddr);
inet_pton(AF_INET, "255.255.0.0", &ipmask);
stm_ipv4_cidr_to_range(ipaddr, ipmask, iprange);
ASSERT_EQ(iprange[0], ntohl(0xc0A80000));
ASSERT_EQ(iprange[1], ntohl(0xc0A8FFFF));
inet_pton(AF_INET, "192.168.1.1", &ipaddr);
inet_pton(AF_INET, "255.128.0.0", &ipmask);
stm_ipv4_cidr_to_range(ipaddr, ipmask, iprange);
ASSERT_EQ(iprange[0], ntohl(0xc0800000));
ASSERT_EQ(iprange[1], ntohl(0xc0FFFFFF));
inet_pton(AF_INET, "192.168.1.1", &ipaddr);
inet_pton(AF_INET, "255.255.255.0", &ipmask);
stm_ipv4_cidr_to_range(ipaddr, ipmask, iprange);
ASSERT_EQ(iprange[0], ntohl(0xc0A80100));
ASSERT_EQ(iprange[1], ntohl(0xc0A801FF));
inet_pton(AF_INET, "192.168.1.1", &ipaddr);
inet_pton(AF_INET, "255.255.255.255", &ipmask);
stm_ipv4_cidr_to_range(ipaddr, ipmask, iprange);
ASSERT_EQ(iprange[0], ntohl(0xc0A80101));
ASSERT_EQ(iprange[1], ntohl(0xc0A80101));
}
TEST(MONITOR_UTIL, stm_ipv4_cidr_string_to_range)
{
uint32_t ipv4, maskv4;
struct in6_addr ipv6, maskv6;
uint32_t ipv4_range[2];
ASSERT_EQ(AF_INET, stm_ip_cidr_pton("1.1.1.0/8", &ipv4, &maskv4, &ipv6, &maskv6));
stm_ipv4_cidr_to_range(ipv4, maskv4, ipv4_range);
ASSERT_EQ(ipv4_range[0], ntohl(0x01000000));
ASSERT_EQ(ipv4_range[1], ntohl(0x01FFFFFF));
ASSERT_EQ(AF_INET, stm_ip_cidr_pton("1.1.1.0/24", &ipv4, &maskv4, &ipv6, &maskv6));
stm_ipv4_cidr_to_range(ipv4, maskv4, ipv4_range);
ASSERT_EQ(ipv4_range[0], ntohl(0x01010100));
ASSERT_EQ(ipv4_range[1], ntohl(0x010101FF));
ASSERT_EQ(AF_INET, stm_ip_cidr_pton("1.2.3.4/32", &ipv4, &maskv4, &ipv6, &maskv6));
stm_ipv4_cidr_to_range(ipv4, maskv4, ipv4_range);
ASSERT_EQ(ipv4_range[0], ntohl(0x01020304));
ASSERT_EQ(ipv4_range[1], ntohl(0x01020304));
}
TEST(MONITOR_UTIL, stm_ipv6_cidr_string_to_range)
{
uint32_t ipv4, maskv4;
struct in6_addr ipv6, maskv6;
struct in6_addr ipv6_range[2];
struct in6_addr expect_addr;
ASSERT_EQ(AF_INET6, stm_ip_cidr_pton("1234::abcd/8", &ipv4, &maskv4, &ipv6, &maskv6));
stm_ipv6_cidr_to_range(&ipv6, &maskv6, ipv6_range);
inet_pton(AF_INET6, "1200::0", &expect_addr);
ASSERT_EQ(0, memcmp(&ipv6_range[0], &expect_addr, sizeof(struct in6_addr)));
inet_pton(AF_INET6, "12ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", &expect_addr);
ASSERT_EQ(0, memcmp(&ipv6_range[1], &expect_addr, sizeof(struct in6_addr)));
ASSERT_EQ(AF_INET6, stm_ip_cidr_pton("1234::abcd/16", &ipv4, &maskv4, &ipv6, &maskv6));
stm_ipv6_cidr_to_range(&ipv6, &maskv6, ipv6_range);
inet_pton(AF_INET6, "1234::0", &expect_addr);
ASSERT_EQ(0, memcmp(&ipv6_range[0], &expect_addr, sizeof(struct in6_addr)));
inet_pton(AF_INET6, "1234:ffff:ffff:ffff:ffff:ffff:ffff:ffff", &expect_addr);
ASSERT_EQ(0, memcmp(&ipv6_range[1], &expect_addr, sizeof(struct in6_addr)));
ASSERT_EQ(AF_INET6, stm_ip_cidr_pton("1234::abcd/128", &ipv4, &maskv4, &ipv6, &maskv6));
stm_ipv6_cidr_to_range(&ipv6, &maskv6, ipv6_range);
inet_pton(AF_INET6, "1234::abcd", &expect_addr);
ASSERT_EQ(0, memcmp(&ipv6_range[0], &expect_addr, sizeof(struct in6_addr)));
ASSERT_EQ(0, memcmp(&ipv6_range[1], &expect_addr, sizeof(struct in6_addr)));
}
TEST(MONITOR_UTIL, stm_ipv6_cidr_to_range)
{
struct in6_addr ipaddr, ipmask;
struct in6_addr iprange[2];
struct in6_addr expect_range[2];
inet_pton(AF_INET6, "1234::abcd", &ipaddr);
inet_pton(AF_INET6, "ff00::", &ipmask); // 8bit mask
stm_ipv6_cidr_to_range(&ipaddr, &ipmask, iprange);
inet_pton(AF_INET6, "1200::", &expect_range[0]);
inet_pton(AF_INET6, "12ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", &expect_range[1]);
ASSERT_EQ(0, memcmp(&expect_range[0], &iprange[0], sizeof(struct in6_addr)));
ASSERT_EQ(0, memcmp(&expect_range[1], &iprange[1], sizeof(struct in6_addr)));
inet_pton(AF_INET6, "1234::abcd", &ipaddr);
inet_pton(AF_INET6, "ffff::", &ipmask); // 16bit mask
stm_ipv6_cidr_to_range(&ipaddr, &ipmask, iprange);
inet_pton(AF_INET6, "1234::", &expect_range[0]);
inet_pton(AF_INET6, "1234:ffff:ffff:ffff:ffff:ffff:ffff:ffff", &expect_range[1]);
ASSERT_EQ(0, memcmp(&expect_range[0], &iprange[0], sizeof(struct in6_addr)));
ASSERT_EQ(0, memcmp(&expect_range[1], &iprange[1], sizeof(struct in6_addr)));
inet_pton(AF_INET6, "1234::abcd", &ipaddr);
inet_pton(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", &ipmask); // 128bit mask
stm_ipv6_cidr_to_range(&ipaddr, &ipmask, iprange);
inet_pton(AF_INET6, "1234::abcd", &expect_range[0]);
inet_pton(AF_INET6, "1234::abcd", &expect_range[1]);
ASSERT_EQ(0, memcmp(&expect_range[0], &iprange[0], sizeof(struct in6_addr)));
ASSERT_EQ(0, memcmp(&expect_range[1], &iprange[1], sizeof(struct in6_addr)));
}
TEST(MONITOR_UTIL, mem_rand)
{
char buf[10000];
srand(time(NULL));
stm_mem_fill_rand(buf, sizeof(buf), 31, 61);
for (size_t i = 0; i < sizeof(buf); i++)
{
ASSERT_GE(buf[i], 31);
ASSERT_LE(buf[i], 61);
}
}
TEST(MONITOR_UTIL, timeout)
{
struct timeval start, end;
start.tv_sec = 10000;
start.tv_usec = 0;
end = start;
ASSERT_EQ(0, stm_timeout(start, end, 1));
end.tv_sec += 1;
ASSERT_EQ(1, stm_timeout(start, end, 1));
end = start;
end.tv_usec += 999999;
ASSERT_EQ(0, stm_timeout(start, end, 1));
start.tv_sec = 10000;
start.tv_usec = 900 * 1000;
end.tv_sec = 10001;
end.tv_usec = 1;
ASSERT_EQ(0, stm_timeout(start, end, 1));
end.tv_usec += 999999;
ASSERT_EQ(1, stm_timeout(start, end, 1));
}
TEST(MONITOR_UTIL, parse_cli_arg)
{
struct monitor_cli_args expect_args[] =
{
{"-i", "--ip", 1, 0, NULL},
{"-p", "--port", 1, 0, NULL},
{"-t", "--timeout", 1, 0, NULL},
{"-e", "--exec", 1, 1, NULL},
};
int argc = 0;
const char *cli_cmd = NULL;
sds *argv = NULL;
/* TEST: short options */
cli_cmd = "./monitor_cli -i 1.1.1.1 -p 8080 -t 30 -e a b c d e f g ";
argv = sdssplitargs((char *)cli_cmd, &argc);
EXPECT_EQ(0, monitor_util_parse_cmd_args(argc, (const char **)argv, expect_args, 4));
EXPECT_STREQ("1.1.1.1", expect_args[0].value);
EXPECT_STREQ("8080", expect_args[1].value);
EXPECT_STREQ("30", expect_args[2].value);
EXPECT_STREQ("a b c d e f g", expect_args[3].value);
sdsfree(expect_args[0].value);
expect_args[0].value = NULL;
sdsfree(expect_args[1].value);
expect_args[1].value = NULL;
sdsfree(expect_args[2].value);
expect_args[2].value = NULL;
sdsfree(expect_args[3].value);
expect_args[3].value = NULL;
sdsfreesplitres(argv, argc);
/* TEST: long options */
cli_cmd = "./monitor_cli --ip 111.111.111.111 --port 80808 --timeout 300 --exec a b c d e f g ";
argv = sdssplitargs((char *)cli_cmd, &argc);
EXPECT_EQ(0, monitor_util_parse_cmd_args(argc, (const char **)argv, expect_args, 4));
EXPECT_STREQ("111.111.111.111", expect_args[0].value);
EXPECT_STREQ("80808", expect_args[1].value);
EXPECT_STREQ("300", expect_args[2].value);
EXPECT_STREQ("a b c d e f g", expect_args[3].value);
sdsfree(expect_args[0].value);
expect_args[0].value = NULL;
sdsfree(expect_args[1].value);
expect_args[1].value = NULL;
sdsfree(expect_args[2].value);
expect_args[2].value = NULL;
sdsfree(expect_args[3].value);
expect_args[3].value = NULL;
sdsfreesplitres(argv, argc);
/* TEST: short options out of order */
cli_cmd = "./monitor_cli -e a b c d e f g -t 30 -i 1.1.1.1 -p 8080 ";
argv = sdssplitargs((char *)cli_cmd, &argc);
EXPECT_EQ(0, monitor_util_parse_cmd_args(argc, (const char **)argv, expect_args, 4));
EXPECT_STREQ("1.1.1.1", expect_args[0].value);
EXPECT_STREQ("8080", expect_args[1].value);
EXPECT_STREQ("30", expect_args[2].value);
EXPECT_STREQ("a b c d e f g", expect_args[3].value);
sdsfree(expect_args[0].value);
expect_args[0].value = NULL;
sdsfree(expect_args[1].value);
expect_args[1].value = NULL;
sdsfree(expect_args[2].value);
expect_args[2].value = NULL;
sdsfree(expect_args[3].value);
expect_args[3].value = NULL;
sdsfreesplitres(argv, argc);
/* TEST: short options with quotes */
cli_cmd = "./monitor_cli -i 1.1.1.1 -p 8080 -t 30 -e \"a b c d e f g\"";
argv = sdssplitargs((char *)cli_cmd, &argc);
EXPECT_EQ(0, monitor_util_parse_cmd_args(argc, (const char **)argv, expect_args, 4));
EXPECT_STREQ("1.1.1.1", expect_args[0].value);
EXPECT_STREQ("8080", expect_args[1].value);
EXPECT_STREQ("30", expect_args[2].value);
EXPECT_STREQ("a b c d e f g", expect_args[3].value);
sdsfree(expect_args[0].value);
expect_args[0].value = NULL;
sdsfree(expect_args[1].value);
expect_args[1].value = NULL;
sdsfree(expect_args[2].value);
expect_args[2].value = NULL;
sdsfree(expect_args[3].value);
expect_args[3].value = NULL;
sdsfreesplitres(argv, argc);
}
TEST(MONITOR_UTIL, reply)
{
struct monitor_reply *reply;
reply = monitor_reply_nil();
sds reply_str = monitor_reply_to_string(reply);
EXPECT_STREQ(reply_str, "(nil)\r\n");
sdsfree(reply_str);
monitor_reply_free(reply);
reply = monitor_reply_new_string("hello, %s", "world");
reply_str = monitor_reply_to_string(reply);
EXPECT_STREQ(reply_str, "hello, world\r\n");
sdsfree(reply_str);
monitor_reply_free(reply);
reply = monitor_reply_new_integer(12345);
reply_str = monitor_reply_to_string(reply);
EXPECT_STREQ(reply_str, "(integer) 12345\r\n");
sdsfree(reply_str);
monitor_reply_free(reply);
reply = monitor_reply_new_double(123.456);
reply_str = monitor_reply_to_string(reply);
EXPECT_STREQ(reply_str, "(double) 123.456000\r\n");
sdsfree(reply_str);
monitor_reply_free(reply);
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
return ret;
}

View File

@@ -0,0 +1,276 @@
#include <unistd.h>
#include <stddef.h>
#include <getopt.h>
#include <arpa/inet.h>
#include <gtest/gtest.h>
#include <pcap/pcap.h>
#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;
}

View File

@@ -0,0 +1,140 @@
#include <unistd.h>
#include <stddef.h>
#include <getopt.h>
#include <arpa/inet.h>
#include <gtest/gtest.h>
#include <pcap/pcap.h>
#ifdef __cplusplus
extern "C"
{
#endif
#include "monitor/monitor_private.h"
#include "sds/sds.h"
#include "stellar/stellar.h"
#ifdef __cplusplus
}
#endif
#define TEST_PKT_DUMP_FILE_NAME "__gtest_stm_pkt_dump.pcap"
static pthread_t tid;
static int cmd_result_array_size;
static sds *cmd_result_array;
static sds *stellar_cli_exec_cmd(const char *command_str, int *result_size)
{
int ret;
sds *cmd_res_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_res_array = sdssplitlen(result, strlen(result), "\r\n", 1, result_size);
}
pclose(fp);
return cmd_res_array;
}
static void *async_cmd_run_thread(void *arg)
{
cmd_result_array = stellar_cli_exec_cmd((char *)arg, &cmd_result_array_size);
return NULL;
}
static void async_cmd_run(char *cmd)
{
pthread_create(&tid, NULL, async_cmd_run_thread, cmd);
usleep(100000);
}
static void async_cmd_wait(void)
{
pthread_join(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_result_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");
// 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_result_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;
}
TEST(MONITOR_PKT_DUMP_TUNNEL, arg_bpf)
{
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 = 5;
snprintf(cmd_buf, sizeof(cmd_buf), "./stellar-dump -n -nn -g -c %d udp port 53 or udp port 443 or udp port 8246 or udp port 6620 -s0 -U -w %s", expect_cap_pkt_num, TEST_PKT_DUMP_FILE_NAME);
async_cmd_run(cmd_buf);
stellar_run(st);
async_cmd_wait();
sdsfreesplitres(cmd_result_array, cmd_result_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;
}

View File

@@ -0,0 +1,229 @@
#include <unistd.h>
#include <stddef.h>
#include <getopt.h>
#include <arpa/inet.h>
#include <gtest/gtest.h>
#include <pcap/pcap.h>
#ifdef __cplusplus
extern "C"
{
#endif
#include "stellar/packet.h"
#include "monitor/monitor_private.h"
#include "sds/sds.h"
#include "monitor/monitor_packet_dump.h"
#ifdef __cplusplus
}
#endif
#define TEST_PKT_DUMP_FILE_NAME "__gtest_stm_pkt_dump.pcap"
/* mock */
int packet_manager_subscribe(UNUSED struct packet_manager *pkt_mgr, UNUSED enum packet_stage stage, UNUSED on_packet_stage_callback *cb, UNUSED void *args)
{
assert(0);
return 0;
}
TEST(MONITOR_PKT_DUMP_UNIT, parse_args)
{
int thread_enable_flag[STELLAR_MAX_THREAD_NUM] = {};
struct stm_pktdump_task tmp_conn_parm = {};
const char *argv[] = {"./stellar_dump", "greedy", "threads", "1,2,3", "datalinkip", "1.2.3.4", "datalinkport", "54321", "bpf", "tcp", "port", "80"};
int argc = sizeof(argv) / sizeof(char *);
sds cli_bpf_str;
struct monitor_reply *reply = stm_packet_dump_parse_args(argc, (char **)argv, &tmp_conn_parm, thread_enable_flag, STELLAR_MAX_THREAD_NUM, &cli_bpf_str);
ASSERT_EQ(NULL, reply);
EXPECT_EQ(1, tmp_conn_parm.greedy_mode);
EXPECT_EQ(0, thread_enable_flag[0]);
EXPECT_EQ(1, thread_enable_flag[1]);
EXPECT_EQ(1, thread_enable_flag[2]);
EXPECT_EQ(1, thread_enable_flag[3]);
EXPECT_EQ(0, thread_enable_flag[5]);
EXPECT_EQ(0, thread_enable_flag[7]);
EXPECT_EQ(0, thread_enable_flag[9]);
EXPECT_EQ(0x04030201, tmp_conn_parm.peer_data_ip_net_order);
EXPECT_EQ(htons(54321), tmp_conn_parm.peer_data_port_net_order);
EXPECT_STREQ(cli_bpf_str, "tcp port 80");
pcap_freecode(&tmp_conn_parm.bpf_filter);
sdsfree(cli_bpf_str);
}
TEST(MONITOR_PKT_DUMP_UNIT, parse_args_out_of_order)
{
int thread_enable_flag[STELLAR_MAX_THREAD_NUM] = {};
struct stm_pktdump_task tmp_conn_parm = {};
const char *argv[] = {"./stellar_dump", "datalinkip", "1.2.3.4", "datalinkport", "54321", "bpf", "tcp", "port", "80", "greedy", "threads", "1,3,5,7,9"};
int argc = sizeof(argv) / sizeof(char *);
sds cli_bpf_str;
struct monitor_reply *reply = stm_packet_dump_parse_args(argc, (char **)argv, &tmp_conn_parm, thread_enable_flag, STELLAR_MAX_THREAD_NUM, &cli_bpf_str);
ASSERT_EQ(NULL, reply);
EXPECT_EQ(1, tmp_conn_parm.greedy_mode);
EXPECT_EQ(0, thread_enable_flag[0]);
EXPECT_EQ(1, thread_enable_flag[1]);
EXPECT_EQ(0, thread_enable_flag[2]);
EXPECT_EQ(1, thread_enable_flag[3]);
EXPECT_EQ(1, thread_enable_flag[5]);
EXPECT_EQ(1, thread_enable_flag[7]);
EXPECT_EQ(1, thread_enable_flag[9]);
EXPECT_EQ(0, thread_enable_flag[10]);
EXPECT_EQ(0x04030201, tmp_conn_parm.peer_data_ip_net_order);
EXPECT_EQ(htons(54321), tmp_conn_parm.peer_data_port_net_order);
EXPECT_STREQ(cli_bpf_str, "tcp port 80 ");
pcap_freecode(&tmp_conn_parm.bpf_filter);
sdsfree(cli_bpf_str);
}
TEST(MONITOR_PKT_DUMP_UNIT, parse_args_error_ip)
{
int thread_enable_flag[STELLAR_MAX_THREAD_NUM] = {};
struct stm_pktdump_task tmp_conn_parm = {};
const char *argv[] = {"./stellar_dump", "datalinkip", "1.2.3.256", "datalinkport", "54321", "bpf", "tcp", "port", "80", "greedy", "threads", "1,3,5,7,9"};
int argc = sizeof(argv) / sizeof(char *);
sds cli_bpf_str = NULL;
struct monitor_reply *reply = stm_packet_dump_parse_args(argc, (char **)argv, &tmp_conn_parm, thread_enable_flag, STELLAR_MAX_THREAD_NUM, &cli_bpf_str);
ASSERT_TRUE(reply != NULL);
pcap_freecode(&tmp_conn_parm.bpf_filter);
sdsfree(cli_bpf_str);
monitor_reply_free(reply);
}
TEST(MONITOR_PKT_DUMP_UNIT, parse_args_error_port)
{
int thread_enable_flag[STELLAR_MAX_THREAD_NUM] = {};
struct stm_pktdump_task tmp_conn_parm = {};
const char *argv[] = {"./stellar_dump", "datalinkip", "1.2.3.4", "datalinkport", "654321", "bpf", "tcp", "port", "80", "greedy", "threads", "1,3,5,7,9"};
int argc = sizeof(argv) / sizeof(char *);
sds cli_bpf_str = NULL;
struct monitor_reply *reply = stm_packet_dump_parse_args(argc, (char **)argv, &tmp_conn_parm, thread_enable_flag, STELLAR_MAX_THREAD_NUM, &cli_bpf_str);
ASSERT_TRUE(reply != NULL);
pcap_freecode(&tmp_conn_parm.bpf_filter);
sdsfree(cli_bpf_str);
monitor_reply_free(reply);
}
TEST(MONITOR_PKT_DUMP_UNIT, parse_args_no_port)
{
int thread_enable_flag[STELLAR_MAX_THREAD_NUM] = {};
struct stm_pktdump_task tmp_conn_parm = {};
const char *argv[] = {"./stellar_dump", "datalinkip", "1.2.3.4", "bpf", "tcp", "port", "80", "greedy", "threads", "1,3,5,7,9"};
int argc = sizeof(argv) / sizeof(char *);
sds cli_bpf_str = NULL;
struct monitor_reply *reply = stm_packet_dump_parse_args(argc, (char **)argv, &tmp_conn_parm, thread_enable_flag, STELLAR_MAX_THREAD_NUM, &cli_bpf_str);
ASSERT_TRUE(reply != NULL);
pcap_freecode(&tmp_conn_parm.bpf_filter);
sdsfree(cli_bpf_str);
monitor_reply_free(reply);
}
TEST(MONITOR_PKT_DUMP_UNIT, parse_args_error_bpf)
{
int thread_enable_flag[STELLAR_MAX_THREAD_NUM] = {};
struct stm_pktdump_task tmp_conn_parm = {};
const char *argv[] = {"./stellar_dump", "datalinkip", "1.2.3.4", "datalinkport", "654321", "bpf", "tcp", "port", "xxx", "greedy", "threads", "1,3,5,7,9"};
int argc = sizeof(argv) / sizeof(char *);
sds cli_bpf_str = NULL;
struct monitor_reply *reply = stm_packet_dump_parse_args(argc, (char **)argv, &tmp_conn_parm, thread_enable_flag, STELLAR_MAX_THREAD_NUM, &cli_bpf_str);
ASSERT_TRUE(reply != NULL);
pcap_freecode(&tmp_conn_parm.bpf_filter);
sdsfree(cli_bpf_str);
monitor_reply_free(reply);
}
TEST(MONITOR_PKT_DUMP_UNIT, parse_args_error_threads)
{
int thread_enable_flag[STELLAR_MAX_THREAD_NUM] = {};
struct stm_pktdump_task tmp_conn_parm = {};
const char *argv[] = {"./stellar_dump", "datalinkip", "1.2.3.4", "datalinkport", "54321", "bpf", "tcp", "port", "xxx", "greedy", "threads", "1,3,5,7,999"};
int argc = sizeof(argv) / sizeof(char *);
sds cli_bpf_str = NULL;
struct monitor_reply *reply = stm_packet_dump_parse_args(argc, (char **)argv, &tmp_conn_parm, thread_enable_flag, STELLAR_MAX_THREAD_NUM, &cli_bpf_str);
ASSERT_TRUE(reply != NULL);
pcap_freecode(&tmp_conn_parm.bpf_filter);
sdsfree(cli_bpf_str);
monitor_reply_free(reply);
}
TEST(MONITOR_PKT_DUMP_UNIT, pcap_compile_and_filter_ipv4)
{
/* This is a IPv4 tcp SYN packet, 192.168.40.139:48662 -> 107.155.25.121:80 */
static const unsigned char packet_bytes[] = {
0x48, 0x73, 0x97, 0x96, 0x38, 0x10, 0x00, 0x22,
0x46, 0x2f, 0x35, 0xb4, 0x08, 0x00,
0x45, 0x00, 0x00, 0x38, 0x0c, 0x1d, 0x40, 0x00, 0x40, 0x06,
0xc0, 0x5b, 0xc0, 0xa8, 0x28, 0x8b, 0x6b, 0x9b,
0x19, 0x79, 0xbe, 0x16, 0x00, 0x50, 0x7b, 0xf9,
0x8b, 0x34, 0x00, 0x00, 0x00, 0x00, 0x90, 0x02,
0x72, 0x10, 0x6e, 0x72, 0x00, 0x00, 0x02, 0x04,
0x05, 0xb4, 0x04, 0x02, 0x08, 0x0a, 0x2d, 0xbb,
0x87, 0x29, 0x00, 0x00, 0x00, 0x00};
struct bpf_program bpf_bin;
pcap_compile_nopcap(STM_PACKET_DUMP_CAP_LEN, DLT_EN10MB, &bpf_bin, "tcp port 48662 and host 192.168.40.139 and host 107.155.25.121", 1, 0);
int match_from_eth = bpf_filter(bpf_bin.bf_insns, packet_bytes, sizeof(packet_bytes), sizeof(packet_bytes));
EXPECT_TRUE(match_from_eth != 0);
pcap_freecode(&bpf_bin);
pcap_compile_nopcap(STM_PACKET_DUMP_CAP_LEN, DLT_EN10MB, &bpf_bin, "tcp port 12345 and tcp port 54321", 1, 0);
int unmatch_from_eth = bpf_filter(bpf_bin.bf_insns, packet_bytes, sizeof(packet_bytes), sizeof(packet_bytes));
EXPECT_TRUE(unmatch_from_eth == 0);
pcap_freecode(&bpf_bin);
pcap_compile_nopcap(STM_PACKET_DUMP_CAP_LEN, DLT_RAW, &bpf_bin, "tcp port 48662 and host 192.168.40.139 and host 107.155.25.121", 1, 0);
int match_from_ip = bpf_filter(bpf_bin.bf_insns, packet_bytes + 14, sizeof(packet_bytes) - 14, sizeof(packet_bytes) - 14);
EXPECT_TRUE(match_from_ip != 0);
pcap_freecode(&bpf_bin);
pcap_compile_nopcap(STM_PACKET_DUMP_CAP_LEN, DLT_RAW, &bpf_bin, "host 1.2.3.4 and host 5.6.7.8", 1, 0);
int unmatch_from_ip = bpf_filter(bpf_bin.bf_insns, packet_bytes + 14, sizeof(packet_bytes) - 14, sizeof(packet_bytes) - 14);
EXPECT_TRUE(unmatch_from_ip == 0);
pcap_freecode(&bpf_bin);
}
TEST(MONITOR_PKT_DUMP_UNIT, pcap_compile_and_filter_ipv6)
{
/* This is a IPv6 tcp SYN packet, 2001::192.168.40.134:37948 -> 2001::192.168.40.133:22 */
static const unsigned char packet_bytes[] = {
0x00, 0x22, 0x46, 0x36, 0x51, 0x38, 0x00, 0x22,
0x46, 0x36, 0x51, 0x3c, 0x86, 0xdd, 0x60, 0x00,
0x00, 0x00, 0x00, 0x28, 0x06, 0x40, 0x20, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x92,
0x01, 0x68, 0x00, 0x40, 0x01, 0x34, 0x20, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x92,
0x01, 0x68, 0x00, 0x40, 0x01, 0x33, 0x94, 0x3c,
0x00, 0x16, 0x09, 0x68, 0x7d, 0x85, 0x00, 0x00,
0x00, 0x00, 0xa0, 0x02, 0x71, 0xac, 0xff, 0xec,
0x00, 0x00, 0x02, 0x04, 0x07, 0x94, 0x04, 0x02,
0x08, 0x0a, 0x16, 0xa8, 0x59, 0xc2, 0x00, 0x00,
0x00, 0x00, 0x01, 0x03, 0x03, 0x07};
struct bpf_program bpf_bin;
pcap_compile_nopcap(STM_PACKET_DUMP_CAP_LEN, DLT_EN10MB, &bpf_bin, "tcp port 37948 and host 2001::192.168:40:134 and host 2001::192:168:40:133", 1, 0);
int match_from_eth = bpf_filter(bpf_bin.bf_insns, packet_bytes, sizeof(packet_bytes), sizeof(packet_bytes));
EXPECT_TRUE(match_from_eth != 0);
pcap_freecode(&bpf_bin);
pcap_compile_nopcap(STM_PACKET_DUMP_CAP_LEN, DLT_EN10MB, &bpf_bin, "tcp port 12345 and tcp port 54321", 1, 0);
int unmatch_from_eth = bpf_filter(bpf_bin.bf_insns, packet_bytes, sizeof(packet_bytes), sizeof(packet_bytes));
EXPECT_TRUE(unmatch_from_eth == 0);
pcap_freecode(&bpf_bin);
pcap_compile_nopcap(STM_PACKET_DUMP_CAP_LEN, DLT_RAW, &bpf_bin, "tcp port 37948 and host 2001::192.168:40:134 and host 2001::192:168:40:133", 1, 0);
int match_from_ip = bpf_filter(bpf_bin.bf_insns, packet_bytes + 14, sizeof(packet_bytes) - 14, sizeof(packet_bytes) - 14);
EXPECT_TRUE(match_from_ip != 0);
pcap_freecode(&bpf_bin);
pcap_compile_nopcap(STM_PACKET_DUMP_CAP_LEN, DLT_RAW, &bpf_bin, "host 1.2.3.4 and host 5.6.7.8", 1, 0);
int unmatch_from_ip = bpf_filter(bpf_bin.bf_insns, packet_bytes + 14, sizeof(packet_bytes) - 14, sizeof(packet_bytes) - 14);
EXPECT_TRUE(unmatch_from_ip == 0);
pcap_freecode(&bpf_bin);
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
return ret;
}

View File

@@ -0,0 +1,194 @@
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#include <getopt.h>
#include <pthread.h>
#include <gtest/gtest.h>
#include "stellar/monitor.h"
#include "monitor_ringbuf.h"
#define TOTAL_TEST_NUM 100000
#define BATCH_NUM 10
#define MAX_PAYLOAD_LEN 2048
#define MAGIC_NUM 0x1234ABCD
static struct monitor_ringbuf_wrap *rbf_ctop;
static struct monitor_ringbuf_wrap *rbf_ptoc;
static const size_t ringbuf_size = MAX_PAYLOAD_LEN * 1024;
static unsigned long long ctop_producer_len = 0, ctop_consumer_len = 0;
static unsigned long long ptoc_producer_len = 0, ptoc_consumer_len = 0;
struct test_ringbuf_data
{
long long magic;
long long block_len; /* total length, include this header and paylaod */
char payload[MAX_PAYLOAD_LEN];
};
static int test_ringbuf_push_mode = 0; /* 0: easy push, 1: push by offset */
static int ringbuf_push(int tid, struct monitor_ringbuf_wrap *rbf, struct test_ringbuf_data *payload)
{
int ret = 0;
if (0 == test_ringbuf_push_mode)
{
ret = stm_ringbuf_easy_push(tid, rbf, payload, payload->block_len);
}
else
{
ssize_t offset = stm_ringbuf_stream_start(tid, rbf, payload->block_len);
if (offset < 0)
{
return -1;
}
stm_ringbuf_stream_append(tid, rbf, offset++, payload++, 1);
usleep(1);
stm_ringbuf_stream_append(tid, rbf, offset++, payload++, 1);
usleep(10);
stm_ringbuf_stream_append(tid, rbf, offset++, payload++, 1);
usleep(100);
stm_ringbuf_stream_append(tid, rbf, offset, payload, payload->block_len - 3);
stm_ringbuf_stream_finish(tid, rbf);
}
return ret;
}
static int ringbuf_producer(int tid, struct monitor_ringbuf_wrap *rbf, int batch)
{
struct test_ringbuf_data t;
for (int i = 0; i < batch; i++)
{
t.magic = MAGIC_NUM;
t.block_len = rand() % (MAX_PAYLOAD_LEN - sizeof(long long) * 2) + sizeof(long long) * 2; /* variable-length */
while (ringbuf_push(tid, rbf, &t) < 0)
{
usleep(1);
}
if (rbf == rbf_ctop)
{
ctop_producer_len += t.block_len;
}
else
{
ptoc_producer_len += t.block_len;
}
}
return batch;
}
static int ringbuf_customer(int tid, struct monitor_ringbuf_wrap *rbf, int batch)
{
(void)tid;
void *data;
size_t pop_len;
for (int i = 0; i < batch; i++)
{
while ((data = stm_ringbuf_pop(rbf, &pop_len)) == NULL)
{
;
}
struct test_ringbuf_data *td = (struct test_ringbuf_data *)data;
if (td->magic != MAGIC_NUM)
{
stm_ringbuf_release(rbf, pop_len); /* maybe lost many messages */
return 0;
}
td->magic = random();
size_t rel_len = td->block_len;
if (rbf == rbf_ctop)
{
ctop_consumer_len += td->block_len;
}
else
{
ptoc_consumer_len += td->block_len;
}
td->block_len = 0;
stm_ringbuf_release(rbf, rel_len);
}
return batch;
}
static void *producer_thread(void *arg)
{
(void)arg;
int ctop_num = 0;
int ptoc_num = 0;
for (int i = 0; i < TOTAL_TEST_NUM; i++)
{
/* only two threads, use fake fix thread id */
ctop_num += ringbuf_producer(0, rbf_ctop, BATCH_NUM);
ptoc_num += ringbuf_customer(0, rbf_ptoc, BATCH_NUM);
}
return NULL;
}
static void *consumer_thread(void *arg)
{
(void)arg;
int ctop_num = 0;
int ptoc_num = 0;
for (int i = 0; i < TOTAL_TEST_NUM; i++)
{
/* only two threads, use fake fix thread id */
ptoc_num += ringbuf_producer(1, rbf_ptoc, BATCH_NUM);
ctop_num += ringbuf_customer(1, rbf_ctop, BATCH_NUM);
}
return NULL;
}
static int gtest_ringbuf(int mode)
{
pthread_t pid[2];
test_ringbuf_push_mode = mode;
rbf_ctop = stm_ringbuf_wrap_new(2, ringbuf_size);
rbf_ptoc = stm_ringbuf_wrap_new(2, ringbuf_size);
pthread_create(&pid[0], NULL, producer_thread, NULL);
pthread_create(&pid[1], NULL, consumer_thread, NULL);
pthread_join(pid[0], NULL);
pthread_join(pid[1], NULL);
stm_ringbuf_get_statistics(rbf_ctop, NULL, &ctop_producer_len, NULL, &ctop_consumer_len);
stm_ringbuf_get_statistics(rbf_ptoc, NULL, &ptoc_producer_len, NULL, &ptoc_consumer_len);
printf("ctop push len:%llu, ctop pop len:%llu\n", ctop_producer_len, ctop_consumer_len);
printf("ptoc push len:%llu, ctop pop len:%llu\n", ptoc_producer_len, ptoc_consumer_len);
if (ctop_producer_len != ctop_consumer_len)
{
return -1;
}
if (ptoc_producer_len != ptoc_consumer_len)
{
return -1;
}
stm_ringbuf_wrap_free(rbf_ptoc);
stm_ringbuf_wrap_free(rbf_ctop);
pthread_cancel(pid[0]);
pthread_cancel(pid[1]);
return 0;
}
TEST(MONITOR_RINGBUF, easy)
{
ASSERT_EQ(0, gtest_ringbuf(0));
}
TEST(MONITOR_RINGBUF, stream)
{
ASSERT_EQ(0, gtest_ringbuf(0));
}
int main(int argc, char **argv)
{
srand(time(NULL));
testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
return ret;
}

View File

@@ -0,0 +1,68 @@
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#include <getopt.h>
#include <pthread.h>
#include <gtest/gtest.h>
#include "stellar/monitor.h"
#include "monitor/monitor_private.h"
#include "monitor/monitor_rpc.h"
#define TEST_NUM 2000000
static long g_worker_thread_run = 1;
static void *phony_worker_thread(void *arg)
{
struct monitor_rpc *rpc_ins = (struct monitor_rpc *)arg;
while (g_worker_thread_run)
{
stm_rpc_exec(0, rpc_ins);
}
return NULL;
}
static struct iovec on_worker_thread_cb(int worker_thread_idx, struct iovec req, void *user_args)
{
EXPECT_EQ(0, worker_thread_idx);
pthread_t *phony_worker_thread_id = (pthread_t *)user_args;
EXPECT_EQ(*phony_worker_thread_id, pthread_self());
struct iovec resp = req;
resp.iov_base = (void *)"world";
resp.iov_len = 12345 + req.iov_len;
return resp;
}
TEST(MONITOR_RPC, base)
{
srand(time(NULL));
pthread_t phony_worker_thread_id = 0;
struct monitor_rpc *rpc_ins = stm_rpc_new();
ASSERT_TRUE(rpc_ins != NULL);
pthread_create(&phony_worker_thread_id, NULL, phony_worker_thread, rpc_ins);
struct iovec req = {.iov_base = (void *)"hello", .iov_len = 5};
usleep(10000);
for (int i = 0; i < TEST_NUM; i++)
{
req.iov_len = rand() % TEST_NUM;
struct iovec resp = stm_rpc_call(rpc_ins, req, on_worker_thread_cb, &phony_worker_thread_id);
EXPECT_EQ(req.iov_len + 12345, resp.iov_len);
EXPECT_EQ(resp.iov_base, (void *)"world");
}
printf("rpc call num: %d\n", TEST_NUM);
g_worker_thread_run = 0;
pthread_cancel(phony_worker_thread_id);
pthread_join(phony_worker_thread_id, NULL);
stm_rpc_free(rpc_ins);
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
return ret;
}

152
test/monitor/gtest_sds.cpp Normal file
View File

@@ -0,0 +1,152 @@
#include <unistd.h>
#include <stddef.h>
#include <getopt.h>
#include <gtest/gtest.h>
#ifdef __cplusplus
extern "C"
{
#endif
#include "sds/sds.h"
#ifdef __cplusplus
}
#endif
TEST(MONITOR_SDS, sds_new)
{
sds s = sdsnew("hello, world!");
ASSERT_STREQ(s, "hello, world!");
ASSERT_EQ(sdslen(s), strlen("hello, world!"));
sdsfree(s);
}
TEST(MONITOR_SDS, sds_cat)
{
sds s = sdsempty();
ASSERT_EQ(sdslen(s), 0);
s = sdscat(s, "h");
ASSERT_EQ(sdslen(s), 1);
ASSERT_STREQ(s, "h");
s = sdscat(s, "ello");
ASSERT_EQ(sdslen(s), 5);
ASSERT_STREQ(s, "hello");
sdsfree(s);
}
TEST(MONITOR_SDS, sds_cat_printf)
{
sds s = sdsempty();
s = sdscatprintf(s, "%s", "hello");
ASSERT_STREQ(s, "hello");
s = sdscatprintf(s, "%s", ",world!");
ASSERT_STREQ(s, "hello,world!");
s = sdscatprintf(s, "%d", 200);
ASSERT_STREQ(s, "hello,world!200");
sdsfree(s);
}
TEST(MONITOR_SDS, sdstrim)
{
sds s = sdsnew("hello, world!\r\n");
ASSERT_STRNE(s, "hello, world!");
sds s1 = sdstrim(s, "\r\n");
ASSERT_STREQ(s1, "hello, world!");
sdsfree(s);
s = sdsnew("xxxhello, world!xxx\r\n");
s1 = sdstrim(s, "xxx\r\n");
ASSERT_STREQ(s1, "hello, world!");
sdsfree(s);
}
TEST(MONITOR_SDS, sdsrange)
{
sds s = sdsnew("1234567890");
ASSERT_STREQ(s, "1234567890");
ASSERT_EQ(10, sdslen(s));
sdsrange(s, 0, 1);
ASSERT_EQ(2, sdslen(s));
ASSERT_STREQ(s, "12");
sdsfree(s);
}
TEST(MONITOR_SDS, sdscpylen)
{
sds s = sdsnew("1234567890");
ASSERT_EQ(10, sdslen(s));
sds s1 = sdscpylen(s, "abc", 3);
ASSERT_STRNE(s1, "1234567890abc");
sdsfree(s1);
}
TEST(MONITOR_SDS, sdssplitargs)
{
int argc = 0;
sds *array = sdssplitargs("a b c d e f g", &argc);
ASSERT_EQ(argc, 7);
ASSERT_STREQ(array[0], "a");
ASSERT_STREQ(array[1], "b");
ASSERT_STREQ(array[2], "c");
ASSERT_STREQ(array[3], "d");
ASSERT_STREQ(array[4], "e");
ASSERT_STREQ(array[5], "f");
ASSERT_STREQ(array[6], "g");
sdsfreesplitres(array, argc);
array = sdssplitargs("show", &argc);
ASSERT_EQ(argc, 1);
ASSERT_STREQ(array[0], "show");
sdsfreesplitres(array, argc);
array = sdssplitargs("show ", &argc);
ASSERT_EQ(argc, 1);
ASSERT_STREQ(array[0], "show");
sdsfreesplitres(array, argc);
array = sdssplitargs("", &argc);
ASSERT_EQ(argc, 0);
sdsfreesplitres(array, argc);
}
TEST(MONITOR_SDS, sdssplitlen)
{
int count = 0;
const char *sep = "&";
const char *request_url = "key1=value1&key2=value2&key3=value3";
sds *array = sdssplitlen(request_url, strlen(request_url), sep, 1, &count);
ASSERT_EQ(count, 3);
ASSERT_STREQ(array[0], "key1=value1");
ASSERT_STREQ(array[1], "key2=value2");
ASSERT_STREQ(array[2], "key3=value3");
int key1_cnt;
sds *key1_array = sdssplitlen(array[0], sdslen(array[0]), "=", 1, &key1_cnt);
ASSERT_EQ(key1_cnt, 2);
ASSERT_STREQ(key1_array[0], "key1");
ASSERT_STREQ(key1_array[1], "value1");
sdsfreesplitres(key1_array, key1_cnt);
sdsfreesplitres(array, count);
}
TEST(MONITOR_SDS, sdsIncrLen)
{
sds s = sdsnew("hello, world!\r\n");
ASSERT_EQ(sdslen(s), 15);
sdsIncrLen(s, -2);
ASSERT_EQ(sdslen(s), 13);
EXPECT_STREQ(s, "hello, world!");
sdsfree(s);
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
return ret;
}

View File

@@ -0,0 +1,142 @@
#include <unistd.h>
#include <stddef.h>
#include <getopt.h>
#include <pcap/pcap.h>
#include <gtest/gtest.h>
#include "stellar/packet.h"
#include "monitor/monitor_private.h"
#include "stellar/packet.h"
#include "packet_manager/packet_parser.h"
#include "packet_manager/packet_internal.h"
/* mock */
int packet_manager_subscribe(UNUSED struct packet_manager *pkt_mgr, UNUSED enum packet_stage stage, UNUSED on_packet_stage_callback *cb, UNUSED void *args)
{
assert(0);
return 0;
}
static int check_layer(const struct packet *pkt, const enum layer_proto *layers, int expect_layer_cnt)
{
int actual_pkt_layer = packet_get_layer_count(pkt);
if (actual_pkt_layer != expect_layer_cnt)
{
return -1;
}
for (int i = 0; i < expect_layer_cnt; i++)
{
const struct layer *layer = packet_get_layer_by_idx(pkt, i);
if (layer == NULL)
{
return -1;
}
if (layer->proto != layers[i])
{
return -1;
}
}
return 0;
}
TEST(MONITOR_SEEK_LAYER, ethernet_ipv4_udp_dns)
{
struct packet pkt = {};
/* a DNS query packet */
const unsigned char packet_bytes[] =
{
0xe8, 0x1c, 0xba, 0xcc, 0x87, 0x21, 0x7c, 0x2a,
0x31, 0x9f, 0x98, 0x2c, 0x08, 0x00, 0x45, 0x00,
0x00, 0x3e, 0x4a, 0x41, 0x00, 0x00, 0x80, 0x11,
0x26, 0x7a, 0xc0, 0xa8, 0x24, 0x67, 0x72, 0x72,
0x72, 0x72, 0xd5, 0xbc, 0x00, 0x35, 0x00, 0x2a,
0xd7, 0x33, 0xdf, 0x96, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x66,
0x75, 0x77, 0x75, 0x04, 0x62, 0x64, 0x70, 0x66,
0x03, 0x6f, 0x72, 0x67, 0x02, 0x63, 0x6e, 0x00,
0x00, 0x01, 0x00, 0x01};
ASSERT_TRUE(packet_parse(&pkt, (char *)packet_bytes, sizeof(packet_bytes)) != NULL);
int pkt_layer = packet_get_layer_count(&pkt);
ASSERT_EQ(pkt_layer, 3);
enum layer_proto layers[3] = {LAYER_PROTO_ETHER, LAYER_PROTO_IPV4, LAYER_PROTO_UDP};
ASSERT_EQ(0, check_layer(&pkt, layers, 3));
}
TEST(MONITOR_SEEK_LAYER, ethernet_ipv4_gre_ipv4_gre_ipv4_udp_dns)
{
struct packet pkt = {};
/* a DNS query packet */
const unsigned char packet_bytes[] = {
0x02, 0x00, 0x00, 0x01, 0x02, 0x95, 0x00, 0x00,
0xc3, 0x51, 0x05, 0x0f, 0x08, 0x00, 0x45, 0x00,
0x00, 0x7c, 0x46, 0xdb, 0x00, 0x00, 0xfb, 0x2f,
0xcc, 0x35, 0x73, 0x99, 0x4b, 0xf6, 0x7a, 0x70,
0x72, 0x42, 0x20, 0x00, 0x08, 0x00, 0x00, 0x00,
0x03, 0x84, 0x45, 0x00, 0x00, 0x60, 0xc8, 0xd5,
0x00, 0x00, 0xff, 0x2f, 0xe9, 0x58, 0x0a, 0x96,
0xfa, 0x0a, 0x0a, 0x96, 0xfa, 0x09, 0x00, 0x00,
0x08, 0x00, 0x45, 0x00, 0x00, 0x48, 0xb2, 0xc6,
0x00, 0x00, 0x3f, 0x11, 0x6a, 0x4b, 0x7a, 0x70,
0x72, 0x49, 0x73, 0xee, 0xfd, 0xeb, 0x51, 0x13,
0x00, 0x35, 0x00, 0x34, 0x3a, 0xbf, 0xb1, 0xba,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x08, 0x75, 0x72, 0x77, 0x70, 0x75,
0x6c, 0x65, 0x70, 0x03, 0x77, 0x77, 0x77, 0x09,
0x64, 0x65, 0x73, 0x68, 0x65, 0x6e, 0x67, 0x32,
0x38, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01,
0x00, 0x01};
ASSERT_TRUE(packet_parse(&pkt, (char *)packet_bytes, sizeof(packet_bytes)) != NULL);
int pkt_layer = packet_get_layer_count(&pkt);
ASSERT_EQ(pkt_layer, 7);
enum layer_proto layers[7] = {LAYER_PROTO_ETHER, LAYER_PROTO_IPV4, LAYER_PROTO_GRE, LAYER_PROTO_IPV4, LAYER_PROTO_GRE, LAYER_PROTO_IPV4, LAYER_PROTO_UDP};
ASSERT_EQ(0, check_layer(&pkt, layers, 7));
}
extern "C" u_int stm_bpf_filter_greedy(const struct bpf_insn *bpf_dlt_raw, struct packet *pkt);
TEST(MONITOR_SEEK_LAYER, ethernet_ipv4_gre_ipv4_gre_ipv4_udp_dns_bpf_filter_greedy)
{
struct packet pkt = {};
/* a DNS query packet */
const unsigned char packet_bytes[] = {
0x02, 0x00, 0x00, 0x01, 0x02, 0x95, 0x00, 0x00,
0xc3, 0x51, 0x05, 0x0f, 0x08, 0x00, 0x45, 0x00,
0x00, 0x7c, 0x46, 0xdb, 0x00, 0x00, 0xfb, 0x2f,
0xcc, 0x35, 0x73, 0x99, 0x4b, 0xf6, 0x7a, 0x70,
0x72, 0x42, 0x20, 0x00, 0x08, 0x00, 0x00, 0x00,
0x03, 0x84, 0x45, 0x00, 0x00, 0x60, 0xc8, 0xd5,
0x00, 0x00, 0xff, 0x2f, 0xe9, 0x58, 0x0a, 0x96,
0xfa, 0x0a, 0x0a, 0x96, 0xfa, 0x09, 0x00, 0x00,
0x08, 0x00, 0x45, 0x00, 0x00, 0x48, 0xb2, 0xc6,
0x00, 0x00, 0x3f, 0x11, 0x6a, 0x4b, 0x7a, 0x70,
0x72, 0x49, 0x73, 0xee, 0xfd, 0xeb, 0x51, 0x13,
0x00, 0x35, 0x00, 0x34, 0x3a, 0xbf, 0xb1, 0xba,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x08, 0x75, 0x72, 0x77, 0x70, 0x75,
0x6c, 0x65, 0x70, 0x03, 0x77, 0x77, 0x77, 0x09,
0x64, 0x65, 0x73, 0x68, 0x65, 0x6e, 0x67, 0x32,
0x38, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01,
0x00, 0x01};
ASSERT_TRUE(packet_parse(&pkt, (char *)packet_bytes, sizeof(packet_bytes)) != NULL);
struct bpf_program bpf_bin;
pcap_compile_nopcap(65535, DLT_RAW, &bpf_bin, "host 115.153.75.246 and host 122.112.114.66", 1, 0); // firset ipv4 layer
ASSERT_TRUE(0 != stm_bpf_filter_greedy(bpf_bin.bf_insns, &pkt));
pcap_freecode(&bpf_bin);
pcap_compile_nopcap(65535, DLT_RAW, &bpf_bin, "host 10.150.250.10 and host 10.150.250.9", 1, 0); // second ipv4 layer
ASSERT_TRUE(0 != stm_bpf_filter_greedy(bpf_bin.bf_insns, &pkt));
pcap_freecode(&bpf_bin);
pcap_compile_nopcap(65535, DLT_RAW, &bpf_bin, "host 122.112.114.73 and host 115.238.253.235", 1, 0); // third ipv4 layer
ASSERT_TRUE(0 != stm_bpf_filter_greedy(bpf_bin.bf_insns, &pkt));
pcap_freecode(&bpf_bin);
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
return ret;
}

View File

@@ -0,0 +1,49 @@
#include <unistd.h>
#include <pthread.h>
#include <getopt.h>
#include <gtest/gtest.h>
#include "monitor/monitor_private.h"
static volatile long sum = 0;
static volatile long barrier = 1;
#define CALC_NUM 10000000
static void *calc_thread(void *arg)
{
stm_spinlock *lock = (stm_spinlock *)arg;
(void)lock;
while (barrier)
;
for (int i = 0; i < CALC_NUM; i++)
{
stm_spinlock_lock(lock);
sum++;
stm_spinlock_unlock(lock);
}
return NULL;
}
TEST(MONITOR_SPINLOCK, base)
{
pthread_t pid;
stm_spinlock *lock = stm_spinlock_new();
pthread_create(&pid, NULL, calc_thread, (void *)lock);
usleep(5000);
barrier = 0;
for (int i = 0; i < CALC_NUM; i++)
{
stm_spinlock_lock(lock);
sum++;
stm_spinlock_unlock(lock);
}
pthread_join(pid, NULL);
stm_spinlock_free(lock);
EXPECT_EQ(sum, CALC_NUM * 2);
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
return ret;
}

535
test/monitor/gtest_topk.cpp Normal file
View File

@@ -0,0 +1,535 @@
#include <assert.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stddef.h>
#include <getopt.h>
#include <sys/time.h>
#include <gtest/gtest.h>
#include <arpa/inet.h>
// #include <fieldstat.h>
#include <fieldstat/fieldstat_exporter.h>
#define MAX_TOPK_CELL_NUM 100
#define MAX_TOPK_METRIC_NUM 255
#define SHOW_TOPK_RESULT_NUM 10
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#define TOPK_DIMENSION_NUM 8
static const char *g_topk_dimension[TOPK_DIMENSION_NUM] = {
"top_client_ip",
"top_server_ip",
"top_internal_ip",
"top_external_ip",
"top_server_fqdn",
"top_server_domain",
"top_client_country",
"top_server_country",
};
#define TOPK_RANK_BY_NUM 3
static const char *g_topk_rank_by[TOPK_RANK_BY_NUM] = {
"sessions",
"packets",
"bytes",
};
#define TOPK_METRIC_NUM 3
/* index corresponding to g_topk_rank_by[] */
static const char *g_metric_name[TOPK_METRIC_NUM] = {
"sessions",
"pkts",
"bytes",
};
struct topk_t
{
char name[128];
long long value;
};
static int g_topk_cubeid[TOPK_DIMENSION_NUM][TOPK_RANK_BY_NUM] = {}; // [dimension][rank_by]
static int g_topk_counter_id[TOPK_DIMENSION_NUM][TOPK_RANK_BY_NUM][TOPK_METRIC_NUM] = {}; // [dimension][rank_by][metric]
static struct fieldstat *g_fs4_ins = NULL;
/* the biggest value index is 0 */
static int qsort_topk_value_cmp_cb(const void *a, const void *b)
{
struct topk_t *la = (struct topk_t *)a;
struct topk_t *lb = (struct topk_t *)b;
return (int)(lb->value - la->value);
}
// lijia temp add for test
static void show_topk_stat(const char *dimension, const char *rank_by, struct topk_t *topk_result, size_t n_result, size_t topk)
{
if (n_result)
{
printf("### top '%s' rank_by '%s' result %zu: \n", dimension, rank_by, topk);
qsort((void *)topk_result, n_result, sizeof(struct topk_t), qsort_topk_value_cmp_cb);
int show_num = MIN(topk, n_result);
for (int i = 0; i < show_num; i++)
{
printf("%2d) %16s\t%8lld\n", i + 1, topk_result[i].name, topk_result[i].value);
}
}
}
static int get_topk_cube_id(struct fieldstat *fs4_ins, const char *dimension, const char *rank_by)
{
struct field find_cube_tmp[2] = {};
find_cube_tmp[0].key = "name";
find_cube_tmp[0].type = FIELD_VALUE_CSTRING;
find_cube_tmp[0].value_str = dimension;
find_cube_tmp[1].key = "rank_by";
find_cube_tmp[1].type = FIELD_VALUE_CSTRING;
find_cube_tmp[1].value_str = rank_by;
return fieldstat_find_cube(fs4_ins, find_cube_tmp, 2);
}
/*
dimensions: client_ip, server_ip, internal_ip, external_ip, server_fqdn, server_domain, client_country, server_country
rank_by: sessions, bytes, packets
metric: sessions, bytes, packets
*/
static int get_topk_rank_by(struct fieldstat *fs4_ins, const char *dimension, const char *rank_by, const char *metric_name, struct topk_t *topk_array, size_t max_array_num)
{
int cube_id = get_topk_cube_id(fs4_ins, dimension, rank_by);
assert(cube_id >= 0);
int metric_id = fieldstat_cube_get_metric_id_by_name(fs4_ins, cube_id, metric_name);
assert(metric_id >= 0);
struct field_list *cell_dimensions_list = NULL;
size_t n_cell = 0;
fieldstat_cube_get_cells(fs4_ins, cube_id, &cell_dimensions_list, &n_cell);
if (NULL == cell_dimensions_list)
{
return 0;
}
size_t result_min = MIN(max_array_num, n_cell);
for (size_t ce = 0; ce < result_min; ce++)
{
strncpy(topk_array[ce].name, cell_dimensions_list[ce].field->value_str, sizeof(topk_array[ce].name));
fieldstat_counter_get(fs4_ins, cube_id, &cell_dimensions_list[ce], metric_id, &topk_array[ce].value);
}
fieldstat_field_list_arr_free(cell_dimensions_list, n_cell);
return result_min;
}
static void stm_topk_register_cube(struct fieldstat *fs4_ins, int cube_id[TOPK_DIMENSION_NUM][TOPK_RANK_BY_NUM])
{
struct field reg_cube_tmp[2] = {};
for (size_t i = 0; i < sizeof(g_topk_dimension) / sizeof(g_topk_dimension[0]); i++)
{
for (size_t j = 0; j < sizeof(g_topk_rank_by) / sizeof(g_topk_rank_by[0]); j++)
{
reg_cube_tmp[0].key = "name";
reg_cube_tmp[0].type = FIELD_VALUE_CSTRING;
reg_cube_tmp[0].value_str = g_topk_dimension[i];
reg_cube_tmp[1].key = "rank_by";
reg_cube_tmp[1].type = FIELD_VALUE_CSTRING;
reg_cube_tmp[1].value_str = g_topk_rank_by[j];
cube_id[i][j] = fieldstat_cube_create(fs4_ins, reg_cube_tmp, 2);
assert(cube_id[i][j] >= 0);
}
}
}
static void stm_topk_register_counter(struct fieldstat *fs4_ins, int cube_id[TOPK_DIMENSION_NUM][TOPK_RANK_BY_NUM],
int counter_id[TOPK_DIMENSION_NUM][TOPK_RANK_BY_NUM][TOPK_METRIC_NUM])
{
for (size_t i = 0; i < sizeof(g_topk_dimension) / sizeof(g_topk_dimension[0]); i++)
{
for (size_t j = 0; j < sizeof(g_topk_rank_by) / sizeof(g_topk_rank_by[0]); j++)
{
for (size_t k = 0; k < sizeof(g_metric_name) / sizeof(char *); k++)
{
counter_id[i][j][k] = fieldstat_register_counter(fs4_ins, cube_id[i][j], g_metric_name[k]);
assert(counter_id[i][j][k] >= 0);
}
}
}
}
static void stm_topk_set_cube_sampling(struct fieldstat *fs4_ins, enum sampling_mode mode, int cube_id[TOPK_DIMENSION_NUM][TOPK_RANK_BY_NUM],
int counter_id[TOPK_DIMENSION_NUM][TOPK_RANK_BY_NUM][TOPK_METRIC_NUM])
{
for (size_t i = 0; i < sizeof(g_topk_dimension) / sizeof(g_topk_dimension[0]); i++)
{
for (size_t j = 0; j < sizeof(g_topk_rank_by) / sizeof(g_topk_rank_by[0]); j++)
{
fieldstat_cube_set_sampling(fs4_ins, cube_id[i][j], mode, MAX_TOPK_CELL_NUM, counter_id[i][j][j]);
}
}
}
static int stm_topk_client_ip_rankby_sessions(void)
{
struct field ip_tag = {};
ip_tag.key = "top_client_ip";
ip_tag.type = FIELD_VALUE_CSTRING;
unsigned int begin_ip_addr = 0x04030201;
struct topk_t benchmark_result[MAX_TOPK_METRIC_NUM];
long long max_value = 0;
memset(benchmark_result, 0, sizeof(benchmark_result));
for (int i = 0; i < MAX_TOPK_METRIC_NUM; i++)
{
benchmark_result[i].value = rand() % 10000;
if (benchmark_result[i].value > max_value)
{
max_value = benchmark_result[i].value;
}
unsigned int ip_addr_net = htonl(begin_ip_addr + i);
inet_ntop(AF_INET, &ip_addr_net, benchmark_result[i].name, sizeof(benchmark_result[i].name));
ip_tag.value_str = benchmark_result[i].name;
fieldstat_counter_incrby(g_fs4_ins, g_topk_cubeid[0][0], g_topk_counter_id[0][0][0], &ip_tag, 1, benchmark_result[i].value);
}
/*** query and verify ***/
struct topk_t fs4_topk_result[MAX_TOPK_CELL_NUM] = {};
int num = get_topk_rank_by(g_fs4_ins, "top_client_ip", "sessions", "sessions", fs4_topk_result, sizeof(fs4_topk_result) / sizeof(struct topk_t));
assert(num > 0);
printf("topk top_client_ip rankby sessions, max value:%lld\n", max_value);
show_topk_stat("top_client_ip", "sessions", fs4_topk_result, num, SHOW_TOPK_RESULT_NUM);
qsort((void *)benchmark_result, MAX_TOPK_METRIC_NUM, sizeof(struct topk_t), qsort_topk_value_cmp_cb);
assert(max_value == fs4_topk_result[0].value);
return memcmp(fs4_topk_result, &benchmark_result[0], SHOW_TOPK_RESULT_NUM);
}
static int stm_topk_server_ip_rankby_packets(void)
{
struct field ip_tag = {};
ip_tag.key = "top_server_ip";
ip_tag.type = FIELD_VALUE_CSTRING;
unsigned int begin_ip_addr = 0x64640101;
long long max_value = 0;
struct topk_t benchmark_result[MAX_TOPK_METRIC_NUM];
memset(benchmark_result, 0, sizeof(benchmark_result));
for (int i = 0; i < MAX_TOPK_METRIC_NUM; i++)
{
benchmark_result[i].value = rand() % 10000;
if (benchmark_result[i].value > max_value)
{
max_value = benchmark_result[i].value;
}
unsigned int ip_addr_net = htonl(begin_ip_addr + i);
inet_ntop(AF_INET, &ip_addr_net, benchmark_result[i].name, sizeof(benchmark_result[i].name));
ip_tag.value_str = benchmark_result[i].name;
fieldstat_counter_incrby(g_fs4_ins, g_topk_cubeid[1][1], g_topk_counter_id[1][1][1], &ip_tag, 1, benchmark_result[i].value);
}
/*** query and verify ***/
struct topk_t fs4_topk_result[MAX_TOPK_CELL_NUM] = {};
int num = get_topk_rank_by(g_fs4_ins, "top_server_ip", "packets", "pkts", fs4_topk_result, sizeof(fs4_topk_result) / sizeof(struct topk_t));
assert(num > 0);
printf("topk top_server_ip rankby packets, max value:%lld\n", max_value);
show_topk_stat("top_server_ip", "packets", fs4_topk_result, num, SHOW_TOPK_RESULT_NUM);
qsort((void *)benchmark_result, MAX_TOPK_METRIC_NUM, sizeof(struct topk_t), qsort_topk_value_cmp_cb);
assert(max_value == fs4_topk_result[0].value);
return memcmp(fs4_topk_result, &benchmark_result[0], SHOW_TOPK_RESULT_NUM);
}
static int stm_topk_server_domain_rankby_bytes(void)
{
struct field domain_tag = {};
domain_tag.key = "top_server_domain";
domain_tag.type = FIELD_VALUE_CSTRING;
struct topk_t benchmark_result[MAX_TOPK_METRIC_NUM];
memset(benchmark_result, 0, sizeof(benchmark_result));
for (int i = 0; i < MAX_TOPK_METRIC_NUM; i++)
{
snprintf(benchmark_result[i].name, sizeof(benchmark_result[i].name), "www.abcd.com");
}
for (int i = 0; i < MAX_TOPK_METRIC_NUM; i++)
{
benchmark_result[i].value = rand() % 10000;
benchmark_result[i].name[4] = rand() % 26 + 'a';
benchmark_result[i].name[5] = rand() % 26 + 'a';
benchmark_result[i].name[6] = rand() % 26 + 'a';
benchmark_result[i].name[7] = rand() % 26 + 'a';
domain_tag.value_str = benchmark_result[i].name;
fieldstat_counter_incrby(g_fs4_ins, g_topk_cubeid[5][2], g_topk_counter_id[5][2][2], &domain_tag, 1, benchmark_result[i].value);
}
/*** query and verify ***/
struct topk_t fs4_topk_result[SHOW_TOPK_RESULT_NUM] = {};
int num = get_topk_rank_by(g_fs4_ins, "top_server_domain", "bytes", "bytes", fs4_topk_result, sizeof(fs4_topk_result) / sizeof(struct topk_t));
assert(num > 0);
show_topk_stat("top_server_domain", "bytes", fs4_topk_result, num, SHOW_TOPK_RESULT_NUM);
qsort((void *)benchmark_result, MAX_TOPK_METRIC_NUM, sizeof(struct topk_t), qsort_topk_value_cmp_cb);
return memcmp(fs4_topk_result, &benchmark_result[0], SHOW_TOPK_RESULT_NUM);
}
class MONITOR_TOPK : public testing::Test
{
protected:
static void SetUpTestCase()
{
srand(time(NULL));
g_fs4_ins = fieldstat_new();
assert(g_fs4_ins != NULL);
stm_topk_register_cube(g_fs4_ins, g_topk_cubeid);
stm_topk_register_counter(g_fs4_ins, g_topk_cubeid, g_topk_counter_id);
stm_topk_set_cube_sampling(g_fs4_ins, SAMPLING_MODE_TOPK, g_topk_cubeid, g_topk_counter_id);
}
static void TearDownTestCase()
{
fieldstat_reset(g_fs4_ins);
fieldstat_free(g_fs4_ins);
}
};
static void generate_random_counter(struct fieldstat *fs4_ins, int cube_id[TOPK_DIMENSION_NUM][TOPK_RANK_BY_NUM],
int counter_id[TOPK_DIMENSION_NUM][TOPK_RANK_BY_NUM][TOPK_METRIC_NUM])
{
struct field tag = {};
tag.type = FIELD_VALUE_CSTRING;
tag.value_str = "random";
for (size_t i = 0; i < sizeof(g_topk_dimension) / sizeof(g_topk_dimension[0]); i++)
{
for (size_t j = 0; j < sizeof(g_topk_rank_by) / sizeof(g_topk_rank_by[0]); j++)
{
for (size_t k = 0; k < sizeof(g_metric_name) / sizeof(char *); k++)
{
assert(g_topk_counter_id[i][j][k] >= 0);
tag.key = g_topk_dimension[i];
fieldstat_counter_incrby(fs4_ins, cube_id[i][j], counter_id[i][j][k], &tag, 1, random());
}
}
}
}
char **show_topk_get_metrics_name(struct fieldstat *show_fs4_ins, int *metric_array_num)
{
int *cube_id_array = NULL;
int n_cube = 0;
fieldstat_get_cubes(show_fs4_ins, &cube_id_array, &n_cube);
if (NULL == cube_id_array)
{
return NULL;
}
struct field_list *cell_dimensions_list = NULL;
size_t n_cell = 0;
fieldstat_cube_get_cells(show_fs4_ins, cube_id_array[0], &cell_dimensions_list, &n_cell);
if (cell_dimensions_list == NULL)
{
return NULL;
}
/* get metric name of any valid cube_id */
int *metric_id_out;
size_t n_metric;
char **metric_array = NULL;
fieldstat_cell_get_metrics(show_fs4_ins, cube_id_array[0], cell_dimensions_list, &metric_id_out, &n_metric);
if (n_metric == 0)
{
fieldstat_field_list_arr_free(cell_dimensions_list, n_cell);
return NULL;
}
metric_array = (char **)malloc(sizeof(char *) * n_metric);
for (size_t j = 0; j < n_metric; j++)
{
metric_array[j] = strdup(fieldstat_metric_get_name(show_fs4_ins, cube_id_array[0], metric_id_out[j]));
}
fieldstat_field_list_arr_free(cell_dimensions_list, n_cell);
*metric_array_num = n_metric;
return metric_array;
}
TEST(MONITOR, show_all_valid_metrics)
{
struct fieldstat *show_fs4_ins = fieldstat_new();
int show_topk_cubeid[TOPK_DIMENSION_NUM][TOPK_RANK_BY_NUM] = {}; // [dimension][rank_by]
int show_topk_counter_id[TOPK_DIMENSION_NUM][TOPK_RANK_BY_NUM][TOPK_METRIC_NUM] = {}; // [dimension][rank_by][metric]
stm_topk_register_cube(show_fs4_ins, show_topk_cubeid);
stm_topk_register_counter(show_fs4_ins, show_topk_cubeid, show_topk_counter_id);
stm_topk_set_cube_sampling(show_fs4_ins, SAMPLING_MODE_TOPK, show_topk_cubeid, show_topk_counter_id);
generate_random_counter(show_fs4_ins, show_topk_cubeid, show_topk_counter_id);
int metric_array_num = 0;
char **metric_array = show_topk_get_metrics_name(show_fs4_ins, &metric_array_num);
EXPECT_TRUE(metric_array_num > 0);
EXPECT_TRUE(metric_array != NULL);
for (int i = 0; i < metric_array_num; i++)
{
printf("metric name: %s\n", metric_array[i]);
free(metric_array[i]);
}
free(metric_array);
fieldstat_free(show_fs4_ins);
}
static int charchar_array_exist(char **dimension_array, int dimension_array_num, const char *expect_name)
{
for (int i = 0; i < dimension_array_num && dimension_array[i] != NULL; i++)
{
if (0 == strcmp(dimension_array[i], expect_name))
{
return 1;
}
}
return 0;
}
char **show_topk_get_dimensions_name(struct fieldstat *show_fs4_ins, int *dimension_array_result)
{
int *cube_id_array = NULL;
int n_cube = 0;
fieldstat_get_cubes(show_fs4_ins, &cube_id_array, &n_cube);
if (0 == n_cube)
{
return NULL;
}
char **dimension_array = NULL;
int dimension_array_num = 0;
struct field_list *cell_dimensions_list = NULL;
for (int i = 0; i < n_cube; i++)
{
size_t n_cell = 0;
fieldstat_cube_get_cells(show_fs4_ins, cube_id_array[i], &cell_dimensions_list, &n_cell);
if (NULL == cell_dimensions_list)
{
continue;
}
for (size_t j = 0; j < cell_dimensions_list->n_field; j++)
{
if (0 == charchar_array_exist(dimension_array, dimension_array_num, cell_dimensions_list->field[j].key))
{
dimension_array = (char **)realloc(dimension_array, sizeof(char *) * (dimension_array_num + 1));
dimension_array[dimension_array_num] = strdup(cell_dimensions_list->field[j].key);
dimension_array_num++;
}
}
fieldstat_field_list_arr_free(cell_dimensions_list, n_cell);
}
*dimension_array_result = dimension_array_num;
return dimension_array;
}
TEST(MONITOR, show_all_valid_dimensions)
{
struct fieldstat *show_fs4_ins = fieldstat_new();
int show_topk_cubeid[TOPK_DIMENSION_NUM][TOPK_RANK_BY_NUM] = {}; // [dimension][rank_by]
int show_topk_counter_id[TOPK_DIMENSION_NUM][TOPK_RANK_BY_NUM][TOPK_METRIC_NUM] = {}; // [dimension][rank_by][metric]
stm_topk_register_cube(show_fs4_ins, show_topk_cubeid);
stm_topk_register_counter(show_fs4_ins, show_topk_cubeid, show_topk_counter_id);
stm_topk_set_cube_sampling(show_fs4_ins, SAMPLING_MODE_TOPK, show_topk_cubeid, show_topk_counter_id);
generate_random_counter(show_fs4_ins, show_topk_cubeid, show_topk_counter_id);
int dimension_array_num = 0;
char **dimension_array = show_topk_get_dimensions_name(show_fs4_ins, &dimension_array_num);
EXPECT_TRUE(dimension_array_num > 0);
EXPECT_TRUE(dimension_array != NULL);
for (int i = 0; i < dimension_array_num; i++)
{
printf("dimension name: %s\n", dimension_array[i]);
free(dimension_array[i]);
}
free(dimension_array);
fieldstat_free(show_fs4_ins);
}
char **show_topk_get_rankby_name(struct fieldstat *show_fs4_ins, int *rankby_array_result)
{
int *cube_id_array = NULL;
int n_cube = 0;
fieldstat_get_cubes(show_fs4_ins, &cube_id_array, &n_cube);
if (NULL == cube_id_array)
{
return NULL;
}
char **rankby_array = NULL;
int rankby_array_num = 0;
for (int i = 0; i < n_cube; i++)
{
struct field_list *flist = fieldstat_cube_get_dimension(show_fs4_ins, cube_id_array[i]);
if (flist == NULL)
{
continue;
}
for (size_t j = 0; j < flist->n_field; j++)
{
if (0 == strcmp(flist->field[j].key, "rank_by"))
{
if (0 == charchar_array_exist(rankby_array, rankby_array_num, flist->field[j].value_str))
{
rankby_array = (char **)realloc(rankby_array, sizeof(char *) * (rankby_array_num + 1));
rankby_array[rankby_array_num] = strdup(flist->field[j].value_str);
rankby_array_num++;
}
}
}
fieldstat_field_list_arr_free(flist, 1);
}
*rankby_array_result = rankby_array_num;
return rankby_array;
}
TEST(MONITOR, show_all_valid_rankby)
{
struct fieldstat *show_fs4_ins = fieldstat_new();
int show_topk_cubeid[TOPK_DIMENSION_NUM][TOPK_RANK_BY_NUM] = {}; // [dimension][rank_by]
int show_topk_counter_id[TOPK_DIMENSION_NUM][TOPK_RANK_BY_NUM][TOPK_METRIC_NUM] = {}; // [dimension][rank_by][metric]
stm_topk_register_cube(show_fs4_ins, show_topk_cubeid);
stm_topk_register_counter(show_fs4_ins, show_topk_cubeid, show_topk_counter_id);
stm_topk_set_cube_sampling(show_fs4_ins, SAMPLING_MODE_TOPK, show_topk_cubeid, show_topk_counter_id);
generate_random_counter(show_fs4_ins, show_topk_cubeid, show_topk_counter_id);
int rankby_array_num = 0;
char **rankby_array = show_topk_get_rankby_name(show_fs4_ins, &rankby_array_num);
EXPECT_TRUE(rankby_array_num > 0);
EXPECT_TRUE(rankby_array != NULL);
for (int i = 0; i < rankby_array_num; i++)
{
printf("rankby name: %s\n", rankby_array[i]);
free(rankby_array[i]);
}
free(rankby_array);
fieldstat_free(show_fs4_ins);
}
TEST_F(MONITOR_TOPK, show_client_ip_by_sessions)
{
EXPECT_EQ(0, stm_topk_client_ip_rankby_sessions());
}
TEST_F(MONITOR_TOPK, show_server_ip_by_packets)
{
EXPECT_EQ(0, stm_topk_server_ip_rankby_packets());
}
TEST_F(MONITOR_TOPK, show_server_domain_by_bytes)
{
EXPECT_EQ(0, stm_topk_server_domain_rankby_bytes());
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
return ret;
}

View File

@@ -0,0 +1,74 @@
#include <netinet/in.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stddef.h>
#include <getopt.h>
#include <gtest/gtest.h>
#include "monitor/monitor_private.h"
#include "stellar/packet.h"
#include "stellar/stellar.h"
/* main function to drives the stellar library to run,
using a delay plugin to increase the running time
*/
static int sleep_per_packet_ms = 0;
static int sleep_before_run_ms = 0;
static void delay_packet_cb(struct packet *pkt, enum packet_stage stage, void *plugin_env)
{
(void)stage;
(void)pkt;
(void)plugin_env;
if (sleep_per_packet_ms)
{
fprintf(stderr, "packet dump, sleep %d ms....\n", sleep_per_packet_ms);
usleep(1000 * sleep_per_packet_ms);
}
}
int main(int argc, char const *argv[])
{
if (argc > 1)
{
if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)
{
fprintf(stderr, "Usage: %s [sleep_before_run_ms] [sleep_per_packet_ms]\n", argv[0]);
exit(0);
}
sleep_before_run_ms = atoi(argv[1]);
if (argc >= 3)
{
sleep_per_packet_ms = atoi(argv[2]);
}
}
struct stellar *st = stellar_new("./conf/stellar.toml");
assert(st);
if (NULL == st)
{
fprintf(stderr, "stellar_new error!\n");
exit(1);
}
struct stellar_monitor *stm = stellar_monitor_get();
struct module *packet_mgr_mod = module_manager_get_module(stm->mod_mgr_ref, PACKET_MANAGER_MODULE_NAME);
struct packet_manager *pkt_mgr = module_to_packet_manager(packet_mgr_mod);
int ret = packet_manager_subscribe(pkt_mgr, PACKET_STAGE_INPUT, delay_packet_cb, stm);
if (ret < 0)
{
fprintf(stderr, "packet_manager_subscribe error!\n");
exit(1);
}
if (sleep_before_run_ms)
{
fprintf(stderr, "%s, sleep %d ms before run....\n", argv[0], sleep_before_run_ms);
usleep(1000 * sleep_before_run_ms);
}
fprintf(stderr, "%s starting...\r\n", argv[0]);
stellar_run(st);
stellar_free(st);
return 0;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.