Skip to content

Commit

Permalink
Add: unit test
Browse files Browse the repository at this point in the history
Add: unit test for snmp_walk
Signed-off-by: k402xxxcenxxx <[email protected]>
  • Loading branch information
k402xxxcenxxx committed Dec 15, 2024
1 parent cf8b9ff commit 014716a
Show file tree
Hide file tree
Showing 2 changed files with 228 additions and 68 deletions.
131 changes: 74 additions & 57 deletions plugins/in_snmp/in_snmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,63 +30,82 @@ int mock_snmp_synch_response(netsnmp_session *ss, netsnmp_pdu *pdu, netsnmp_pdu
size_t mock_objid_len;

mock_status = getenv("TEST_SNMP_RESPONSE");
if ((mock_response = flb_calloc(1, sizeof(netsnmp_pdu))) == NULL) {
goto error;
}

if (strcmp(mock_status, "snmp_get") == 0) {
if ((mock_netsnmp_variable_list = flb_calloc(1, sizeof(netsnmp_variable_list))) == NULL) {
goto error;
}
// sysUpTime
mock_objid_len = MAX_OID_LEN;
if (snmp_parse_oid("1.3.6.1.2.1.1.3.0", mock_objid, &mock_objid_len) == NULL) {
goto error;
}

if (snmp_set_var_objid(mock_netsnmp_variable_list, mock_objid, mock_objid_len)) {
goto error;
}

if (snmp_set_var_typed_integer(mock_netsnmp_variable_list, ASN_TIMETICKS, 123)) {
goto error;
}

mock_response->variables = mock_netsnmp_variable_list;
mock_response->errstat = SNMP_ERR_NOERROR;
*response = mock_response;

return STAT_SUCCESS;
} else if (strcmp(mock_status, "snmp_walk") == 0) {
if ((mock_netsnmp_variable_list = flb_calloc(1, sizeof(netsnmp_variable_list))) == NULL) {
goto error;
}
// ifName.1
mock_objid_len = MAX_OID_LEN;
if (snmp_parse_oid("1.3.6.1.2.1.31.1.1.1.1.1", mock_objid, &mock_objid_len) == NULL) {
goto error;
}

if (snmp_set_var_objid(mock_netsnmp_variable_list, mock_objid, mock_objid_len)) {
goto error;
}

if (snmp_set_var_typed_value(mock_netsnmp_variable_list, ASN_OCTET_STR, "Fa0/0", strlen("Fa0/0"))) {
goto error;
}

if ((mock_netsnmp_variable_list->next_variable = flb_calloc(1, sizeof(netsnmp_variable_list))) == NULL) {
goto error;
}
// ifName.2
mock_objid_len = MAX_OID_LEN;
if (snmp_parse_oid("1.3.6.1.2.1.31.1.1.1.1.2", mock_objid, &mock_objid_len) == NULL) {
goto error;
}

if (snmp_set_var_objid(mock_netsnmp_variable_list->next_variable, mock_objid, mock_objid_len)) {
goto error;
}

if (snmp_set_var_typed_value(mock_netsnmp_variable_list->next_variable, ASN_OCTET_STR, "Fa0/1", strlen("Fa0/1"))) {
goto error;
}

if (strcmp(mock_status, "normal") == 0) {
// if ((mock_response = flb_calloc(1, sizeof(netsnmp_pdu))) == NULL) {
// flb_errno();
// flb_free(mock_status);
// return NULL;
// }

// if ((mock_netsnmp_variable_list = flb_calloc(1, sizeof(netsnmp_variable_list))) == NULL) {
// flb_errno();
// flb_free(mock_response);
// flb_free(mock_status);
// return NULL;
// }

// // sysUpTime
// mock_objid_len = MAX_OID_LEN;
// if (snmp_parse_oid("1.3.6.1.2.1.1.3.0", mock_objid, &mock_objid_len) == NULL) {
// flb_errno();
// flb_free(mock_netsnmp_variable_list);
// flb_free(mock_response);
// flb_free(mock_status);
// return NULL;
// }

// mock_netsnmp_variable_list->next_variable = NULL;
// mock_netsnmp_variable_list->name = NULL;
// mock_netsnmp_variable_list->val.string = NULL;
// mock_netsnmp_variable_list->val_len = 0;
// mock_netsnmp_variable_list->data = NULL;
// mock_netsnmp_variable_list->dataFreeHook = NULL;
// mock_netsnmp_variable_list->index = 0;

// if (snmp_set_var_objid(mock_netsnmp_variable_list, mock_objid, mock_objid_len)) {
// flb_errno();
// flb_free(mock_netsnmp_variable_list);
// flb_free(mock_response);
// flb_free(mock_status);
// return NULL;
// }

// if (snmp_set_var_typed_integer(mock_netsnmp_variable_list, ASN_TIMETICKS, 123)) {
// flb_errno();
// flb_free(mock_netsnmp_variable_list);
// flb_free(mock_response);
// flb_free(mock_status);
// return NULL;
// }

// mock_response->variables = mock_netsnmp_variable_list;
// mock_response->errstat == SNMP_ERR_NOERROR;
// *response = mock_response;

// flb_free(mock_status);
mock_response->variables = mock_netsnmp_variable_list;
mock_response->errstat = SNMP_ERR_NOERROR;
*response = mock_response;

return STAT_SUCCESS;
} else {
return STAT_ERROR;
}

error:
flb_errno();
if (mock_netsnmp_variable_list) flb_free(mock_netsnmp_variable_list);
if (mock_response) flb_free(mock_response);
return STAT_ERROR;
}

static int in_snmp_collect(struct flb_input_instance *ins, struct flb_config *config, void *in_context)
Expand Down Expand Up @@ -175,20 +194,18 @@ static int in_snmp_collect(struct flb_input_instance *ins, struct flb_config *co
pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
} else {
pdu = snmp_pdu_create(SNMP_MSG_GET);
running = 0;
}

snmp_add_null_var(pdu, name, name_len);

if (snmp_plugin_under_test() == FLB_TRUE) {
flb_plg_error(ctx->ins, "Ha Ha");

status = mock_snmp_synch_response(ss, pdu, &response);
} else {
status = snmp_synch_response(ss, pdu, &response);
}

if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {

for(vars = response->variables; vars; vars = vars->next_variable) {
if (is_walk && snmp_oid_compare(end_oid, end_len,
vars->name, vars->name_length) <= 0) {
Expand All @@ -206,7 +223,7 @@ static int in_snmp_collect(struct flb_input_instance *ins, struct flb_config *co
} else {
netsnmp_sprint_realloc_objid_tree(&oid_buf, &oid_buf_len, &oid_out_len,
1, &buf_overflow,
vars->name, vars->name_length);
vars->name, vars->name_length);
if (buf_overflow) {
flb_plg_error(ctx->ins, "[TRUNCATED]");
return -1;
Expand Down
165 changes: 154 additions & 11 deletions tests/runtime/in_snmp.c
Original file line number Diff line number Diff line change
@@ -1,37 +1,180 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

#include <fluent-bit.h>
#include <fluent-bit/flb_time.h>
#include "flb_tests_runtime.h"

void flb_test_snmp()
struct callback_record {
void *data;
size_t size;
};

struct callback_records {
int num_records;
struct callback_record *records;
};

int callback_add_record(void* data, size_t size, void* cb_data)
{
struct callback_records *ctx = (struct callback_records *)cb_data;

if (size > 0) {
flb_info("[test] flush record");
if (ctx->records == NULL) {
ctx->records = (struct callback_record *)
flb_calloc(1, sizeof(struct callback_record));
} else {
ctx->records = (struct callback_record *)
flb_realloc(ctx->records,
(ctx->num_records+1)*sizeof(struct callback_record));
}
if (ctx->records == NULL) {
return -1;
}
ctx->records[ctx->num_records].size = size;
ctx->records[ctx->num_records].data = data;
ctx->num_records++;
}
return 0;
}

void flb_test_snmp_records_message_get(struct callback_records *records)
{
int ret;
flb_ctx_t *ctx;
int i;
msgpack_unpacked result;
msgpack_object *obj;
size_t off = 0;
struct flb_time ftm;

TEST_CHECK(records->num_records > 0);
for (i = 0; i < records->num_records; i++) {
msgpack_unpacked_init(&result);

while (msgpack_unpack_next(&result, records->records[i].data,
records->records[i].size, &off) == MSGPACK_UNPACK_SUCCESS) {
flb_time_pop_from_msgpack(&ftm, &result, &obj);
TEST_CHECK(obj->type == MSGPACK_OBJECT_MAP);
TEST_CHECK(strncmp("iso.3.6.1.2.1.1.3.0",
obj->via.map.ptr[0].key.via.str.ptr,
obj->via.map.ptr[0].key.via.str.size) == 0);
TEST_CHECK(strncmp("123",
obj->via.map.ptr[0].val.via.str.ptr,
obj->via.map.ptr[0].val.via.str.size) == 0);
}
msgpack_unpacked_destroy(&result);
}
}

void flb_test_snmp_records_message_walk(struct callback_records *records)
{
int i, j;
msgpack_unpacked result;
msgpack_object *obj;
size_t off = 0;
struct flb_time ftm;
msgpack_object key;
msgpack_object val;

char expected_keys[2][26] = {
"iso.3.6.1.2.1.31.1.1.1.1.1",
"iso.3.6.1.2.1.31.1.1.1.1.2"
};

char expected_vals[2][7] = {
"\"Fa0/0\"",
"\"Fa0/1\""
};

TEST_CHECK(records->num_records > 0);
for (i = 0; i < records->num_records; i++) {
msgpack_unpacked_init(&result);
while (msgpack_unpack_next(&result, records->records[i].data,
records->records[i].size, &off) == MSGPACK_UNPACK_SUCCESS) {
flb_time_pop_from_msgpack(&ftm, &result, &obj);
TEST_CHECK(obj->type == MSGPACK_OBJECT_MAP);
for (j = 0; j < obj->via.map.size; j++) {
key = obj->via.map.ptr[j].key;
val = obj->via.map.ptr[j].val;

TEST_CHECK(strncmp(expected_keys[j],
key.via.str.ptr,
26) == 0);
TEST_CHECK(strncmp(expected_vals[j],
val.via.str.ptr,
7) == 0);
}
}
msgpack_unpacked_destroy(&result);
}
}


void do_test_records(char *response, void (*records_cb)(struct callback_records *), ...)
{
flb_ctx_t *ctx = NULL;
int in_ffd;
int out_ffd;

va_list va;
char *key;
char *value;
int i;
struct flb_lib_out_cb cb;
struct callback_records *records;

/* mocks calls- signals that we are in test mode */
setenv("FLB_SNMP_PLUGIN_UNDER_TEST", "true", 1);
setenv("TEST_SNMP_RESPONSE", "normal", 1);
setenv("TEST_SNMP_RESPONSE", response, 1);

records = flb_calloc(1, sizeof(struct callback_records));
records->num_records = 0;
records->records = NULL;
cb.cb = callback_add_record;
cb.data = (void *)records;

/* initialize */
ctx = flb_create();

in_ffd = flb_input(ctx, (char *) "snmp", NULL);
in_ffd = flb_input(ctx, "snmp", NULL);
TEST_CHECK(in_ffd >= 0);
TEST_CHECK(flb_input_set(ctx, in_ffd, "tag", "test", NULL) == 0);

va_start(va, records_cb);
while ((key = va_arg(va, char *))) {
value = va_arg(va, char *);
TEST_CHECK(value != NULL);
TEST_CHECK(flb_input_set(ctx, in_ffd, key, value, NULL) == 0);
}
va_end(va);

out_ffd = flb_output(ctx, (char *) "null", NULL);
out_ffd = flb_output(ctx, (char *) "lib", &cb);
TEST_CHECK(out_ffd >= 0);
flb_output_set(ctx, out_ffd, "match", "test", NULL);
TEST_CHECK(flb_output_set(ctx, out_ffd, "match", "test", NULL) == 0);

ret = flb_start(ctx);
TEST_CHECK(ret == 0);
/* Start test */
TEST_CHECK(flb_start(ctx) == 0);

sleep(8);
/* 4 sec passed. It must have flushed */
sleep(5);

records_cb(records);

flb_stop(ctx);

for (i = 0; i < records->num_records; i++) {
flb_lib_free(records->records[i].data);
}
flb_free(records->records);
flb_free(records);

flb_destroy(ctx);
}

void flb_test_snmp()
{
do_test_records("snmp_get", flb_test_snmp_records_message_get, NULL);
do_test_records("snmp_walk", flb_test_snmp_records_message_walk, NULL);
}

/* Test list */
TEST_LIST = {
{"snmp", flb_test_snmp},
Expand Down

0 comments on commit 014716a

Please sign in to comment.