This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
stellar-stellar/deps/utable/test/unit_test_ipfix_exporter.cpp
2024-11-25 19:23:01 +08:00

803 lines
32 KiB
C++

#include <stdio.h>
#include <sys/time.h>
#include <gtest/gtest.h>
#include <netinet/in.h>
#include "utable/utable.h"
#include "cjson/cJSON.h"
#include "uthash/utarray.h"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#define IPFIX_DEFUALT_VERSION 10
#define GEEDGE_NETWORKS_PEN_NUMBER 54450
#define IPFIX_DEFUALT_PEN_NUMBER GEEDGE_NETWORKS_PEN_NUMBER
#define IPFIX_NONE_PEN_NUMBER -1
#define IPFIX_TEMPLATE_SET_ID 2
#define IPFIX_BUFF_MAX_SIZE 2048
#define IPFIX_ELEMENT_MAX_LEN 32
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
enum ipfix_type
{
IPFIX_UNSIGNED8 = 0,
IPFIX_UNSIGNED16,
IPFIX_UNSIGNED32,
IPFIX_UNSIGNED64,
IPFIX_VARIABLE_STRING,
IPFIX_UNKNOWN
};
struct ipfix_element
{
enum ipfix_type type;
uint16_t element_id;
uint16_t value_length; // if type is variable_string, value_length is 0
int PEN_number;
char name[IPFIX_ELEMENT_MAX_LEN];
};
struct ipfix_template
{
uint16_t template_id;
char *name;
UT_array *elements_array; // utarray for current template elements
};
struct ipfix_worker_context
{
int source_id;
int sequence;
size_t template_blob_length;
char *template_blob;
};
struct ipfix_exporter_schema
{
uint16_t n_worker;
uint16_t version;
int domain_id;
int PEN_number;
UT_array *templates_array; // utarray for templates
struct ipfix_worker_context *worker_context_array; // utarray for worker_context
};
struct ipfix_message_head
{
uint16_t version;
uint16_t length;
int exporttime;
int ipfix_message_sequence;
int domain_id;
};
#define IPFIX_MESSAGE_HEAD_LEN sizeof(struct ipfix_message_head)
#define THREAD_MAX 4
#define TEMPLATE_MAX 13
struct gtest_ipfix_template_info
{
const char *template_name;
int template_id;
int n_elements;
};
struct gtest_ipfix_template_info gtest_ipfix_template_info[TEMPLATE_MAX] = {
{"BASE", 257, 87},
{"SSL", 258, 98},
{"HTTP", 259, 108},
{"MAIL", 260, 100},
{"DNS", 261, 106},
{"DTLS", 262, 97},
{"QUIC", 263, 90},
{"FTP", 264, 91},
{"SIP", 265, 102},
{"RTP", 266, 91},
{"SSH", 267, 98},
{"RDP", 268, 102},
{"Stratum", 269, 91}};
#define IPFIX_ELEMENT_HEAD_LEN sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t) // element_id + element_length + PEN_number
const char *ipfix_schema_json_path = "./conf/ipfix_schema.json";
int g_domain_id = 1;
TEST(utable_ipfix_exporter_test, ipfix_schema_new_error_path)
{
struct ipfix_exporter_schema *ipfix_schema = utable_ipfix_exporter_schema_new((const char *)"", g_domain_id, THREAD_MAX);
ASSERT_TRUE(ipfix_schema == NULL);
}
int test_template_blob_len_calculate(struct ipfix_exporter_schema *ipfix_schema)
{
int template_blob_length = 0;
template_blob_length += IPFIX_MESSAGE_HEAD_LEN; // message head
template_blob_length += sizeof(uint16_t) + sizeof(uint16_t); // flow set id + flow set length
for (unsigned int i = 0; i < TEMPLATE_MAX; i++)
{
struct ipfix_template *template_item = (struct ipfix_template *)utarray_eltptr(ipfix_schema->templates_array, i);
template_blob_length += sizeof(uint16_t) + sizeof(uint16_t) + utarray_len(template_item->elements_array) * (IPFIX_ELEMENT_HEAD_LEN); // sizeof(template_id) + sizeof(field_count) + n_elements * sizeof(element_id + element_length + PEN_number)
}
return template_blob_length;
}
TEST(utable_ipfix_exporter_test, ipfix_schema_new_check_schema)
{
struct ipfix_exporter_schema *ipfix_schema = utable_ipfix_exporter_schema_new(ipfix_schema_json_path, g_domain_id, THREAD_MAX);
ASSERT_TRUE(ipfix_schema != NULL);
EXPECT_EQ(ipfix_schema->domain_id, 1);
EXPECT_EQ(ipfix_schema->n_worker, THREAD_MAX);
EXPECT_EQ(utarray_len(ipfix_schema->templates_array), TEMPLATE_MAX);
EXPECT_EQ(ipfix_schema->PEN_number, GEEDGE_NETWORKS_PEN_NUMBER);
EXPECT_EQ(ipfix_schema->version, IPFIX_DEFUALT_VERSION);
for (unsigned int i = 0; i < TEMPLATE_MAX; i++)
{
struct ipfix_template *template_item = (struct ipfix_template *)utarray_eltptr(ipfix_schema->templates_array, i);
ASSERT_TRUE(template_item != NULL);
EXPECT_EQ(template_item->template_id, gtest_ipfix_template_info[i].template_id);
EXPECT_EQ(gtest_ipfix_template_info[i].n_elements, utarray_len(template_item->elements_array));
EXPECT_STREQ(template_item->name, gtest_ipfix_template_info[i].template_name);
}
ASSERT_TRUE(ipfix_schema->worker_context_array != NULL);
for (int i = 0; i < THREAD_MAX; i++)
{
EXPECT_EQ(ipfix_schema->worker_context_array[i].source_id, (g_domain_id << 16) + i);
EXPECT_EQ(ipfix_schema->worker_context_array[i].sequence, 0);
ASSERT_TRUE(ipfix_schema->worker_context_array[i].template_blob != NULL);
EXPECT_EQ(ipfix_schema->worker_context_array[i].template_blob_length, test_template_blob_len_calculate(ipfix_schema));
}
utable_ipfix_exporter_schema_free(ipfix_schema);
}
TEST(utable_ipfix_exporter_test, ipfix_template_flow_get0_all_elements_check_blob)
{
struct ipfix_exporter_schema *ipfix_schema = utable_ipfix_exporter_schema_new(ipfix_schema_json_path, g_domain_id, THREAD_MAX);
ASSERT_TRUE(ipfix_schema != NULL);
for (int i = 0; i < THREAD_MAX; i++)
{
size_t blob_len = 0;
const char *blob = utable_ipfix_template_flow_get0(ipfix_schema, i, &blob_len);
ASSERT_TRUE(blob != NULL);
EXPECT_EQ(blob_len, test_template_blob_len_calculate(ipfix_schema));
// check header
struct ipfix_message_head *header = (struct ipfix_message_head *)blob;
struct ipfix_message_head header_value = {};
header_value.version = htons(header->version);
header_value.length = htons(header->length);
header_value.domain_id = htonl(header->domain_id);
header_value.ipfix_message_sequence = htonl(header->ipfix_message_sequence);
EXPECT_EQ(header_value.version, IPFIX_DEFUALT_VERSION);
EXPECT_EQ(header_value.length, test_template_blob_len_calculate(ipfix_schema));
EXPECT_EQ(header_value.domain_id, (g_domain_id << 16) + i);
EXPECT_EQ(header_value.ipfix_message_sequence, 0);
size_t offset = 0;
offset += IPFIX_MESSAGE_HEAD_LEN;
uint16_t flow_set_id = ntohs(*(uint16_t *)(blob + offset));
EXPECT_EQ(flow_set_id, IPFIX_TEMPLATE_SET_ID); // template set id
offset += 2;
uint16_t flow_set_length = ntohs(*(uint16_t *)(blob + offset));
EXPECT_EQ(flow_set_length, blob_len - IPFIX_MESSAGE_HEAD_LEN); // template set length
offset += 2;
for (unsigned int j = 0; j < TEMPLATE_MAX; j++)
{
uint16_t cur_template_blob_len = sizeof(uint16_t) + sizeof(uint16_t) + gtest_ipfix_template_info[j].n_elements * IPFIX_ELEMENT_HEAD_LEN;
ASSERT_LE(offset + cur_template_blob_len, blob_len);
uint16_t template_id = ntohs(*(uint16_t *)(blob + offset));
EXPECT_EQ(template_id, gtest_ipfix_template_info[j].template_id); // template id
offset += 2;
uint16_t field_count = ntohs(*(uint16_t *)(blob + offset));
EXPECT_EQ(field_count, gtest_ipfix_template_info[j].n_elements); // field count
offset += 2;
struct ipfix_template *template_item = (struct ipfix_template *)utarray_eltptr(ipfix_schema->templates_array, j);
for (unsigned int p = 0; p < (unsigned int)gtest_ipfix_template_info[j].n_elements; p++)
{
struct ipfix_element *element = (struct ipfix_element *)utarray_eltptr(template_item->elements_array, p);
uint16_t PEN_number_flag = ntohs(*(uint16_t *)(blob + offset)) & 0x8000;
EXPECT_EQ(PEN_number_flag, 0x8000); // PEN number flag
uint16_t element_id = ntohs(*(uint16_t *)(blob + offset)) & 0x7fff;
EXPECT_EQ(element_id, element->element_id); // element id
offset += 2;
if (element->type == IPFIX_VARIABLE_STRING)
{
uint16_t element_length = ntohs(*(uint16_t *)(blob + offset));
EXPECT_EQ(element_length, 65535); // element length
}
else
{
uint16_t element_length = ntohs(*(uint16_t *)(blob + offset));
EXPECT_EQ(element_length, element->value_length); // element length
}
offset += 2;
uint32_t PEN_number = ntohl(*(uint32_t *)(blob + offset));
EXPECT_EQ(PEN_number, element->PEN_number); // PEN number
offset += 4;
}
}
}
utable_ipfix_exporter_schema_free(ipfix_schema);
}
TEST(utable_ipfix_exporter_test, ipfix_template_flow_get0_all_elements_check_sequence)
{
struct ipfix_exporter_schema *ipfix_schema = utable_ipfix_exporter_schema_new(ipfix_schema_json_path, g_domain_id, THREAD_MAX);
ASSERT_TRUE(ipfix_schema != NULL);
for (int i = 0; i < THREAD_MAX; i++)
{
size_t blob_len = 0;
const char *blob = utable_ipfix_template_flow_get0(ipfix_schema, i, &blob_len);
ASSERT_TRUE(blob != NULL);
// check header
struct ipfix_message_head *header = (struct ipfix_message_head *)blob;
struct ipfix_message_head header_value = {};
header_value.version = htons(header->version);
header_value.length = htons(header->length);
header_value.domain_id = htonl(header->domain_id);
header_value.ipfix_message_sequence = htonl(header->ipfix_message_sequence);
EXPECT_EQ(header_value.version, IPFIX_DEFUALT_VERSION);
EXPECT_EQ(header_value.length, test_template_blob_len_calculate(ipfix_schema));
EXPECT_EQ(header_value.domain_id, (g_domain_id << 16) + i);
EXPECT_EQ(header_value.ipfix_message_sequence, 0);
memset(&header_value, 0, sizeof(struct ipfix_message_head));
header = NULL;
blob = NULL;
// check sequence, utable_ipfix_template_flow_get0 will not increase sequence
blob = utable_ipfix_template_flow_get0(ipfix_schema, i, &blob_len);
ASSERT_TRUE(blob != NULL);
// check header
header = (struct ipfix_message_head *)blob;
header_value.ipfix_message_sequence = htonl(header->ipfix_message_sequence);
EXPECT_EQ(header_value.ipfix_message_sequence, 0);
}
utable_ipfix_exporter_schema_free(ipfix_schema);
}
TEST(utable_ipfix_exporter_test, ipfix_template_get_not_found)
{
struct ipfix_exporter_schema *ipfix_schema = utable_ipfix_exporter_schema_new(ipfix_schema_json_path, g_domain_id, THREAD_MAX);
ASSERT_TRUE(ipfix_schema != NULL);
int template_id = utable_ipfix_template_get(ipfix_schema, "test");
EXPECT_EQ(template_id, -1);
utable_ipfix_exporter_schema_free(ipfix_schema);
}
TEST(utable_ipfix_exporter_test, ipfix_template_get_check_template_id)
{
struct ipfix_exporter_schema *ipfix_schema = utable_ipfix_exporter_schema_new(ipfix_schema_json_path, g_domain_id, THREAD_MAX);
ASSERT_TRUE(ipfix_schema != NULL);
int template_id = 0;
for (unsigned int i = 0; i < TEMPLATE_MAX; i++)
{
template_id = utable_ipfix_template_get(ipfix_schema, gtest_ipfix_template_info[i].template_name);
EXPECT_EQ(template_id, i);
struct ipfix_template *template_item = (struct ipfix_template *)utarray_eltptr(ipfix_schema->templates_array, i);
ASSERT_TRUE(template_item != NULL);
}
utable_ipfix_exporter_schema_free(ipfix_schema);
}
cJSON *test_ipifx_data_blob_to_cjson(struct ipfix_template *template_item, char *blob, size_t sz_blob)
{
cJSON *root = cJSON_CreateObject();
size_t offset = IPFIX_MESSAGE_HEAD_LEN + sizeof(uint16_t) + sizeof(uint16_t); // skip message head and flow set id and flow set length
size_t n_elements = utarray_len(template_item->elements_array);
for (size_t i = 0; i < n_elements; i++)
{
struct ipfix_element *p_element = (struct ipfix_element *)utarray_eltptr(template_item->elements_array, i);
switch (p_element->type)
{
case IPFIX_UNSIGNED8:
{
cJSON_AddNumberToObject(root, p_element->name, *(uint8_t *)(blob + offset));
offset += sizeof(uint8_t);
break;
}
case IPFIX_UNSIGNED16:
{
cJSON_AddNumberToObject(root, p_element->name, ntohs(*(uint16_t *)(blob + offset)));
offset += sizeof(uint16_t);
break;
}
case IPFIX_UNSIGNED32:
{
cJSON_AddNumberToObject(root, p_element->name, ntohl(*(uint32_t *)(blob + offset)));
offset += sizeof(uint32_t);
break;
}
case IPFIX_UNSIGNED64:
{
cJSON_AddNumberToObject(root, p_element->name, be64toh(*(uint64_t *)(blob + offset)));
offset += sizeof(uint64_t);
break;
}
case IPFIX_VARIABLE_STRING:
{
uint8_t sz_value = *(uint8_t *)(blob + offset);
offset += sizeof(uint8_t);
char *string_value = NULL;
if (sz_value == 0)
{
break;
}
else if (sz_value < 255)
{
string_value = (char *)malloc(sizeof(char) * (sz_value + 1));
memcpy(string_value, blob + offset, sz_value);
string_value[sz_value] = '\0';
offset += sz_value;
}
else // >= 255
{
uint16_t sz_long_string_value = ntohs(*(uint16_t *)(blob + offset));
offset += sizeof(uint16_t);
string_value = (char *)malloc(sizeof(char) * (sz_long_string_value + 1));
memcpy(string_value, blob + offset, sz_long_string_value);
string_value[sz_long_string_value] = '\0';
offset += sz_long_string_value;
}
cJSON_AddStringToObject(root, p_element->name, string_value);
free(string_value);
break;
}
default:
break;
}
}
return root;
}
// after include before, and the extra part is cJSON_Number, but valueint = 0;
void test_ipfix_compare_cjson(cJSON *before, cJSON *after)
{
// find before's element in after
cJSON *item = before->child;
while (item != NULL)
{
if (item->type == cJSON_Number)
{
cJSON *item_after = cJSON_GetObjectItem(after, item->string);
ASSERT_TRUE(item_after != NULL);
EXPECT_EQ(item->valueint, item_after->valueint);
}
if (item->type == cJSON_String)
{
cJSON *item_after = cJSON_GetObjectItem(after, item->string);
ASSERT_TRUE(item_after != NULL);
EXPECT_STREQ(item->valuestring, item_after->valuestring);
}
item = item->next;
}
// find after's element in before
item = after->child;
while (item != NULL)
{
if (item->type == cJSON_Number) // if after's element is cJSON_Number, before's element may be empty or cJSON_Number
{
cJSON *item_before = cJSON_GetObjectItem(before, item->string);
if (item_before == NULL) // if before's element is empty, after's element valueint must be 0
{
EXPECT_EQ(item->valueint, 0);
}
else
{
EXPECT_EQ(item->valueint, item_before->valueint); // if before's element is cJSON_Number, after's element valueint must be equal to before's element valueint
}
}
if (item->type == cJSON_String)
{
cJSON *item_before = cJSON_GetObjectItem(before, item->string);
ASSERT_TRUE(item_before != NULL);
EXPECT_STREQ(item->valuestring, item_before->valuestring);
}
item = item->next;
}
}
int test_empty_data_blob_len_calculate(struct ipfix_exporter_schema *ipfix_schema, int template_id)
{
struct ipfix_template *template_item = (struct ipfix_template *)utarray_eltptr(ipfix_schema->templates_array, (unsigned int)template_id);
int data_blob_length = 0;
data_blob_length += IPFIX_MESSAGE_HEAD_LEN; // message head
data_blob_length += sizeof(uint16_t) + sizeof(uint16_t); // flow set id + flow set length
for (unsigned int i = 0; i < utarray_len(template_item->elements_array); i++)
{
struct ipfix_element *element = (struct ipfix_element *)utarray_eltptr(template_item->elements_array, i);
if (element->type == IPFIX_VARIABLE_STRING)
{
data_blob_length += 1;
}
else
{
data_blob_length += element->value_length; // element length
}
}
return data_blob_length;
}
TEST(utable_ipfix_exporter_test, ipfix_data_flow_empty_utable_check_blob)
{
struct ipfix_exporter_schema *ipfix_schema = utable_ipfix_exporter_schema_new(ipfix_schema_json_path, g_domain_id, THREAD_MAX);
ASSERT_TRUE(ipfix_schema != NULL);
for (unsigned int i = 0; i < TEMPLATE_MAX; i++)
{
cJSON *before = cJSON_CreateObject();
struct utable *table = utable_new();
int template_id = utable_ipfix_template_get(ipfix_schema, gtest_ipfix_template_info[i].template_name);
ASSERT_EQ(template_id, i);
for (unsigned int j = 0; j < THREAD_MAX; j++)
{
size_t blob_len = 0;
char *blob = NULL;
utable_ipfix_data_flow_exporter(table, ipfix_schema, template_id, j, &blob, &blob_len);
ASSERT_TRUE(blob != NULL);
struct ipfix_message_head *header = (struct ipfix_message_head *)blob;
struct ipfix_message_head header_value = {};
header_value.version = htons(header->version);
header_value.length = htons(header->length);
header_value.domain_id = htonl(header->domain_id);
header_value.ipfix_message_sequence = htonl(header->ipfix_message_sequence);
ASSERT_EQ(header_value.version, IPFIX_DEFUALT_VERSION);
ASSERT_EQ(header_value.length, blob_len);
ASSERT_EQ(header_value.length, test_empty_data_blob_len_calculate(ipfix_schema, i));
ASSERT_EQ(header_value.domain_id, (g_domain_id << 16) + j);
ASSERT_EQ(header_value.ipfix_message_sequence, i);
cJSON *after = test_ipifx_data_blob_to_cjson((struct ipfix_template *)utarray_eltptr(ipfix_schema->templates_array, i), blob, blob_len);
test_ipfix_compare_cjson(before, after);
cJSON_Delete(after);
free(blob);
blob = NULL;
}
cJSON_Delete(before);
utable_free(table);
}
utable_ipfix_exporter_schema_free(ipfix_schema);
}
TEST(utable_ipfix_exporter_test, ipfix_data_flow_utable_value_type_integer)
{
struct ipfix_exporter_schema *ipfix_schema = utable_ipfix_exporter_schema_new(ipfix_schema_json_path, g_domain_id, THREAD_MAX);
ASSERT_TRUE(ipfix_schema != NULL);
cJSON *before = cJSON_CreateObject();
struct utable *table = utable_new();
utable_add_integer(table, "session_id", 123456789);
cJSON_AddNumberToObject(before, "session_id", 123456789);
unsigned int template_id = utable_ipfix_template_get(ipfix_schema, "HTTP");
char *blob = NULL;
size_t sz_blob = 0;
utable_ipfix_data_flow_exporter(table, ipfix_schema, template_id, 0, &blob, &sz_blob);
ASSERT_EQ(sz_blob, test_empty_data_blob_len_calculate(ipfix_schema, template_id)); // integer value length has been calculated in test_empty_data_blob_len_calculate
cJSON *after = test_ipifx_data_blob_to_cjson((struct ipfix_template *)utarray_eltptr(ipfix_schema->templates_array, template_id), blob, sz_blob);
test_ipfix_compare_cjson(before, after);
cJSON_Delete(before);
cJSON_Delete(after);
utable_free(table);
free(blob);
utable_ipfix_exporter_schema_free(ipfix_schema);
}
TEST(utable_ipfix_exporter_test, ipfix_data_flow_utable_value_type_cstring)
{
struct ipfix_exporter_schema *ipfix_schema = utable_ipfix_exporter_schema_new(ipfix_schema_json_path, g_domain_id, THREAD_MAX);
ASSERT_TRUE(ipfix_schema != NULL);
cJSON *before = cJSON_CreateObject();
struct utable *table = utable_new();
utable_add_integer(table, "session_id", 123456789);
cJSON_AddNumberToObject(before, "session_id", 123456789);
utable_add_cstring(table, "http_url", "http://www.baidu.com", strlen("http://www.baidu.com"));
cJSON_AddStringToObject(before, "http_url", "http://www.baidu.com");
unsigned int template_id = utable_ipfix_template_get(ipfix_schema, "HTTP");
char *blob = NULL;
size_t sz_blob = 0;
utable_ipfix_data_flow_exporter(table, ipfix_schema, template_id, 0, &blob, &sz_blob);
ASSERT_EQ(sz_blob, test_empty_data_blob_len_calculate(ipfix_schema, template_id) + strlen("http://www.baidu.com")); // variable_string length need to be calculated
cJSON *after = test_ipifx_data_blob_to_cjson((struct ipfix_template *)utarray_eltptr(ipfix_schema->templates_array, template_id), blob, sz_blob);
test_ipfix_compare_cjson(before, after);
cJSON_Delete(before);
cJSON_Delete(after);
utable_free(table);
free(blob);
utable_ipfix_exporter_schema_free(ipfix_schema);
}
char http_url_test[] = "storeapi.app-vtion.com/storeApi/systemApp/checkAppStatus.json?store=com.tcl.appmarket2&mac=3C:59:1E:DC:F8:F4&accessKeyId=1472540256617";
TEST(utable_ipfix_exporter_test, ipfix_data_flow_variable_string_6000) // 6000 bytes > 2 * IPFIX_BUFF_MAX_SIZE, test variable_string length > 255 and realloc
{
struct ipfix_exporter_schema *ipfix_schema = utable_ipfix_exporter_schema_new(ipfix_schema_json_path, g_domain_id, THREAD_MAX);
ASSERT_TRUE(ipfix_schema != NULL);
char *http_url = NULL;
struct utable *table = utable_new();
cJSON *before = cJSON_CreateObject();
utable_add_cstring(table, "decoded_as", "HTTP", strlen("HTTP"));
cJSON_AddStringToObject(before, "decoded_as", "HTTP");
http_url = (char *)malloc(sizeof(char) * 7000);
int offset = 0;
while (offset < 6000)
{
memcpy(http_url + offset, http_url_test, sizeof(http_url_test));
offset += sizeof(http_url_test);
}
utable_add_cstring(table, "http_url", http_url, offset);
cJSON_AddStringToObject(before, "http_url", http_url);
unsigned int template_id = utable_ipfix_template_get(ipfix_schema, "HTTP");
char *blob = NULL;
size_t sz_blob = 0;
utable_ipfix_data_flow_exporter(table, ipfix_schema, template_id, 0, &blob, &sz_blob);
ASSERT_EQ(sz_blob, test_empty_data_blob_len_calculate(ipfix_schema, template_id) + offset + strlen("HTTP") + 2); // variable_string length need to be calculated, if length > 255, length + 2
cJSON *after = test_ipifx_data_blob_to_cjson((struct ipfix_template *)utarray_eltptr(ipfix_schema->templates_array, template_id), blob, sz_blob);
test_ipfix_compare_cjson(before, after);
cJSON_Delete(before);
cJSON_Delete(after);
utable_free(table);
free(blob);
free(http_url);
utable_ipfix_exporter_schema_free(ipfix_schema);
}
TEST(utable_ipfix_exporter_test, ipfix_data_flow_utable_value_type_integer_array)
{
struct ipfix_exporter_schema *ipfix_schema = utable_ipfix_exporter_schema_new(ipfix_schema_json_path, g_domain_id, THREAD_MAX);
ASSERT_TRUE(ipfix_schema != NULL);
cJSON *before = cJSON_CreateObject();
struct utable *table = utable_new();
utable_add_integer(table, "session_id", 123456789);
cJSON_AddNumberToObject(before, "session_id", 123456789);
int64_t monitor_rule_list[8] = {1, 2, 3, 4, 5, 6, 7, 8};
utable_add_integer_array(table, "monitor_rule_list", monitor_rule_list, 8);
cJSON_AddStringToObject(before, "monitor_rule_list", "[1,2,3,4,5,6,7,8]");
unsigned int template_id = utable_ipfix_template_get(ipfix_schema, "HTTP");
char *blob = NULL;
size_t sz_blob = 0;
utable_ipfix_data_flow_exporter(table, ipfix_schema, template_id, 0, &blob, &sz_blob);
ASSERT_EQ(sz_blob, test_empty_data_blob_len_calculate(ipfix_schema, template_id) + strlen("[1,2,3,4,5,6,7,8]")); // variable_string length need to be calculated
cJSON *after = test_ipifx_data_blob_to_cjson((struct ipfix_template *)utarray_eltptr(ipfix_schema->templates_array, template_id), blob, sz_blob);
test_ipfix_compare_cjson(before, after);
cJSON_Delete(before);
cJSON_Delete(after);
utable_free(table);
free(blob);
utable_ipfix_exporter_schema_free(ipfix_schema);
}
extern "C" int load_file_to_memory(const char *file_name, unsigned char **pp_out, size_t *out_sz);
cJSON *ipfix_init_utable_from_log_json(struct utable *table, const char *test_json_path, size_t *sz_blob)
{
size_t json_size = 0;
unsigned char *json_str = NULL;
load_file_to_memory(test_json_path, &json_str, &json_size);
if (json_str == NULL || json_size == 0)
{
return NULL;
}
cJSON *root = NULL;
root = cJSON_Parse((const char *)json_str);
cJSON *item = root->child;
while (item != NULL)
{
switch (item->type)
{
case cJSON_Number:
{
utable_add_integer(table, item->string, item->valueint);
break;
}
case cJSON_String:
{
int sz_value = strlen(item->valuestring);
utable_add_cstring(table, item->string, item->valuestring, sz_value);
if (sz_value < 255)
{
*sz_blob += strlen(item->valuestring);
}
else
{
*sz_blob += (strlen(item->valuestring) + 2);
}
break;
}
case cJSON_Array:
{
cJSON *array_item = cJSON_GetArrayItem(item, 0);
size_t array_sz = cJSON_GetArraySize(item);
if (array_sz > 0)
{
if (array_item->type == cJSON_Number)
{
int *array = (int *)malloc(sizeof(int) * array_sz);
int64_t *long_array = (int64_t *)malloc(sizeof(int64_t) * array_sz);
for (size_t i = 0; i < array_sz; i++)
{
array_item = cJSON_GetArrayItem(item, i);
if (array_item->type == cJSON_Number)
{
array[i] = array_item->valueint;
long_array[i] = array_item->valueint;
}
}
utable_add_integer_array(table, item->string, long_array, array_sz);
cJSON *json_array = cJSON_CreateIntArray((const int *)array, array_sz);
cJSON_Delete(item->child);
item->child = NULL;
item->type = cJSON_String;
item->valuestring = cJSON_PrintUnformatted(json_array);
cJSON_Delete(json_array);
free(array);
free(long_array);
}
else if (array_item->type == cJSON_String)
{
char **array = (char **)malloc(sizeof(char *) * array_sz);
size_t *sz_value = (size_t *)malloc(sizeof(size_t) * array_sz);
for (size_t i = 0; i < array_sz; i++)
{
array_item = cJSON_GetArrayItem(item, i);
if (array_item->type == cJSON_String)
{
sz_value[i] = strlen(array_item->valuestring);
array[i] = strdup(array_item->valuestring);
}
}
utable_add_cstring_array(table, item->string, (const char **)array, sz_value, array_sz);
free(sz_value);
cJSON *json_array = cJSON_CreateStringArray((const char **)array, array_sz);
item->valuestring = cJSON_PrintUnformatted(json_array);
item->type = cJSON_String;
cJSON_Delete(item->child);
item->child = NULL;
cJSON_Delete(json_array);
for (size_t i = 0; i < array_sz; i++)
{
free(array[i]);
}
free(array);
}
int sz_value = strlen(item->valuestring);
if (sz_value < 255)
{
*sz_blob += sz_value;
}
else
{
*sz_blob += (sz_value + 2);
}
}
break;
}
default:
break;
}
item = item->next;
}
free(json_str);
return root;
}
const char *ssl_test_json_path = "./conf/ipfix_ssl_test.json";
TEST(utable_ipfix_exporter_test, ipfix_data_flow_ssl_log_test)
{
struct ipfix_exporter_schema *ipfix_schema = utable_ipfix_exporter_schema_new(ipfix_schema_json_path, g_domain_id, THREAD_MAX);
ASSERT_TRUE(ipfix_schema != NULL);
struct utable *table = utable_new();
unsigned int template_id = utable_ipfix_template_get(ipfix_schema, "SSL");
size_t predict_sz_blob = test_empty_data_blob_len_calculate(ipfix_schema, template_id);
cJSON *before_json_root = ipfix_init_utable_from_log_json(table, ssl_test_json_path, &predict_sz_blob);
char *blob = NULL;
size_t sz_blob = 0;
utable_ipfix_data_flow_exporter(table, ipfix_schema, template_id, 0, &blob, &sz_blob);
ASSERT_EQ(sz_blob, predict_sz_blob);
cJSON *after_json_root = test_ipifx_data_blob_to_cjson((struct ipfix_template *)utarray_eltptr(ipfix_schema->templates_array, template_id), blob, sz_blob);
char *before_json_str = cJSON_Print(before_json_root);
char *after_json_str = cJSON_Print(after_json_root);
printf("before_json: %s\n", before_json_str);
printf("after_json: %s\n", after_json_str);
free(before_json_str);
free(after_json_str);
test_ipfix_compare_cjson(before_json_root, after_json_root);
cJSON_Delete(before_json_root);
cJSON_Delete(after_json_root);
free(blob);
utable_free(table);
utable_ipfix_exporter_schema_free(ipfix_schema);
}
const char *http_test_json_path = "./conf/ipfix_http_test.json";
TEST(utable_ipfix_exporter_test, ipfix_data_flow_http_log_test)
{
struct ipfix_exporter_schema *ipfix_schema = utable_ipfix_exporter_schema_new(ipfix_schema_json_path, g_domain_id, THREAD_MAX);
ASSERT_TRUE(ipfix_schema != NULL);
struct utable *table = utable_new();
unsigned int template_id = utable_ipfix_template_get(ipfix_schema, "HTTP");
size_t predict_sz_blob = test_empty_data_blob_len_calculate(ipfix_schema, template_id);
cJSON *before_json_root = ipfix_init_utable_from_log_json(table, http_test_json_path, &predict_sz_blob);
char *blob = NULL;
size_t sz_blob = 0;
utable_ipfix_data_flow_exporter(table, ipfix_schema, template_id, 0, &blob, &sz_blob);
ASSERT_EQ(sz_blob, predict_sz_blob);
cJSON *after_json_root = test_ipifx_data_blob_to_cjson((struct ipfix_template *)utarray_eltptr(ipfix_schema->templates_array, template_id), blob, sz_blob);
test_ipfix_compare_cjson(before_json_root, after_json_root);
cJSON_Delete(before_json_root);
cJSON_Delete(after_json_root);
free(blob);
utable_free(table);
utable_ipfix_exporter_schema_free(ipfix_schema);
}
int main(int argc, char *argv[])
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}