803 lines
32 KiB
C++
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();
|
|
} |