diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/zabbix_server/Makefile.am | 3 | ||||
-rw-r--r-- | tests/zabbix_server/preprocessor/Makefile.am | 2 | ||||
-rw-r--r-- | tests/zabbix_server/trapper/Makefile.am | 49 | ||||
-rw-r--r-- | tests/zabbix_server/trapper/zbx_trapper_preproc_test_run.c | 128 | ||||
-rw-r--r-- | tests/zabbix_server/trapper/zbx_trapper_preproc_test_run.yaml | 1250 | ||||
-rw-r--r-- | tests/zbxmockjson.c | 259 | ||||
-rw-r--r-- | tests/zbxmockjson.h | 29 |
7 files changed, 1718 insertions, 2 deletions
diff --git a/tests/zabbix_server/Makefile.am b/tests/zabbix_server/Makefile.am index 48defec4f66..013cdf6f410 100644 --- a/tests/zabbix_server/Makefile.am +++ b/tests/zabbix_server/Makefile.am @@ -1,2 +1,3 @@ SUBDIRS = \ - preprocessor + preprocessor \ + trapper diff --git a/tests/zabbix_server/preprocessor/Makefile.am b/tests/zabbix_server/preprocessor/Makefile.am index 6b7719e104c..032f2cbd215 100644 --- a/tests/zabbix_server/preprocessor/Makefile.am +++ b/tests/zabbix_server/preprocessor/Makefile.am @@ -13,6 +13,7 @@ COMMON_SRC_FILES = \ JSON_LIBS = \ $(top_srcdir)/tests/libzbxmocktest.a \ $(top_srcdir)/tests/libzbxmockdata.a \ + $(top_srcdir)/src/zabbix_server/preprocessor/libpreprocessor.a \ $(top_srcdir)/src/libs/zbxjson/libzbxjson.a \ $(top_srcdir)/src/libs/zbxalgo/libzbxalgo.a \ $(top_srcdir)/src/libs/zbxcommon/libzbxcommon.a \ @@ -32,7 +33,6 @@ JSON_LIBS = \ $(top_srcdir)/tests/libzbxmockdata.a zbx_item_preproc_SOURCES = \ - ../../../src/zabbix_server/preprocessor/item_preproc.c \ zbx_item_preproc.c zbx_item_preproc_LDADD = $(JSON_LIBS) diff --git a/tests/zabbix_server/trapper/Makefile.am b/tests/zabbix_server/trapper/Makefile.am new file mode 100644 index 00000000000..22650e761d4 --- /dev/null +++ b/tests/zabbix_server/trapper/Makefile.am @@ -0,0 +1,49 @@ +if SERVER +SERVER_tests = zbx_trapper_preproc_test_run + +noinst_PROGRAMS = $(SERVER_tests) + +COMMON_SRC_FILES = \ + ../../zbxmocktest.h + +TRAPPER_LIBS = \ + $(top_srcdir)/tests/libzbxmocktest.a \ + $(top_srcdir)/tests/libzbxmockdata.a \ + $(top_srcdir)/src/zabbix_server/preprocessor/libpreprocessor.a \ + $(top_srcdir)/src/libs/zbxipcservice/libzbxipcservice.a \ + $(top_srcdir)/src/libs/zbxjson/libzbxjson.a \ + $(top_srcdir)/src/libs/zbxalgo/libzbxalgo.a \ + $(top_srcdir)/src/libs/zbxjson/libzbxjson.a \ + $(top_srcdir)/src/libs/zbxcommon/libzbxcommon.a \ + $(top_srcdir)/src/libs/zbxcomms/libzbxcomms.a \ + $(top_srcdir)/src/libs/zbxcommshigh/libzbxcommshigh.a \ + $(top_srcdir)/src/libs/zbxcompress/libzbxcompress.a \ + $(top_srcdir)/src/libs/zbxcommon/libzbxcommon.a \ + $(top_srcdir)/src/libs/zbxregexp/libzbxregexp.a \ + $(top_srcdir)/src/libs/zbxnix/libzbxnix.a \ + $(top_srcdir)/src/libs/zbxcrypto/libzbxcrypto.a \ + $(top_srcdir)/src/libs/zbxsys/libzbxsys.a \ + $(top_srcdir)/src/libs/zbxlog/libzbxlog.a \ + $(top_srcdir)/src/libs/zbxsys/libzbxsys.a \ + $(top_srcdir)/src/libs/zbxconf/libzbxconf.a \ + $(top_srcdir)/src/libs/zbxembed/libzbxembed.a \ + $(top_srcdir)/src/libs/zbxprometheus/libzbxprometheus.a \ + $(top_srcdir)/src/libs/zbxalgo/libzbxalgo.a \ + $(top_srcdir)/tests/libzbxmockdata.a + +zbx_trapper_preproc_test_run_SOURCES = \ + zbx_trapper_preproc_test_run.c \ + ../../../src/zabbix_server/trapper/trapper_preproc.c \ + ../../zbxmockjson.c + +zbx_trapper_preproc_test_run_LDADD = $(TRAPPER_LIBS) +zbx_trapper_preproc_test_run_LDADD += @SERVER_LIBS@ +zbx_trapper_preproc_test_run_LDFLAGS = @SERVER_LDFLAGS@ + +zbx_trapper_preproc_test_run_CFLAGS = \ + -I@top_srcdir@/tests @LIBXML2_CFLAGS@ \ + -Wl,--wrap=zbx_preprocessor_test \ + -Wl,--wrap=DBget_user_by_active_session + +endif + diff --git a/tests/zabbix_server/trapper/zbx_trapper_preproc_test_run.c b/tests/zabbix_server/trapper/zbx_trapper_preproc_test_run.c new file mode 100644 index 00000000000..822f55b9cdf --- /dev/null +++ b/tests/zabbix_server/trapper/zbx_trapper_preproc_test_run.c @@ -0,0 +1,128 @@ +/* +** Zabbix +** Copyright (C) 2001-2019 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + +#include "zbxmocktest.h" +#include "zbxmockdata.h" +#include "zbxmockassert.h" +#include "zbxmockutil.h" +#include "zbxmockjson.h" + +#include "common.h" +#include "zbxjson.h" +#include "dbcache.h" +#include "zbxembed.h" +#include "log.h" +#include "preproc.h" +#include "../../../src/zabbix_server/preprocessor/item_preproc.h" +#include "../../../src/zabbix_server/preprocessor/preproc_history.h" + +zbx_es_t es_engine; + +int zbx_trapper_preproc_test_run(const struct zbx_json_parse *jp, struct zbx_json *json, char **error); + +int __wrap_zbx_preprocessor_test(unsigned char value_type, const char *value, const zbx_timespec_t *ts, + const zbx_vector_ptr_t *steps, zbx_vector_ptr_t *results, zbx_vector_ptr_t *history, + char **preproc_error, char **error) +{ + int i, results_num; + zbx_preproc_op_t *steps_array; + zbx_preproc_result_t *results_array, *result; + zbx_vector_ptr_t history_out; + zbx_variant_t value_var; + + ZBX_UNUSED(error); + + zbx_vector_ptr_create(&history_out); + zbx_variant_set_str(&value_var, zbx_strdup(NULL, value)); + + steps_array = (zbx_preproc_op_t *)zbx_malloc(NULL, steps->values_num * sizeof(zbx_preproc_op_t)); + for (i = 0; i < steps->values_num; i++) + steps_array[i] = *(zbx_preproc_op_t *)steps->values[i]; + + results_array = (zbx_preproc_result_t *)zbx_malloc(NULL, sizeof(zbx_preproc_result_t) * steps->values_num); + memset(results_array, 0, sizeof(zbx_preproc_result_t) * steps->values_num); + + zbx_item_preproc_test(value_type, &value_var, ts, steps_array, steps->values_num, history, &history_out, + results_array, &results_num, preproc_error); + + /* copy output history */ + zbx_vector_ptr_clear_ext(history, (zbx_clean_func_t)zbx_preproc_op_history_free); + + if (0 != history_out.values_num) + zbx_vector_ptr_append_array(history, history_out.values, history_out.values_num); + + /* copy results */ + for (i = 0; i < results_num; i++) + { + result = (zbx_preproc_result_t *)zbx_malloc(NULL, sizeof(zbx_preproc_result_t)); + *result = results_array[i]; + zbx_vector_ptr_append(results, result); + } + + zbx_variant_clear(&value_var); + zbx_free(steps_array); + zbx_free(results_array); + zbx_vector_ptr_destroy(&history_out); + + return SUCCEED; +} + +int __wrap_DBget_user_by_active_session(const char *sessionid, zbx_user_t *user) +{ + ZBX_UNUSED(sessionid); + + user->type = USER_TYPE_ZABBIX_ADMIN; + user->userid = 0; + + return SUCCEED; +} + +void zbx_mock_test_entry(void **state) +{ + const char *request; + char *error = NULL; + struct zbx_json_parse jp; + struct zbx_json out; + int returned_ret, expected_ret; + + ZBX_UNUSED(state); + + zbx_json_init(&out, 1024); + + request = zbx_mock_get_parameter_string("in.request"); + if (FAIL == zbx_json_open(request, &jp)) + fail_msg("Invalid request format: %s", zbx_json_strerror()); + + returned_ret = zbx_trapper_preproc_test_run(&jp, &out, &error); + if (FAIL == returned_ret) + printf("zbx_trapper_preproc_test_run error: %s\n", error); + else + printf("zbx_trapper_preproc_test_run output: %s\n", out.buffer); + + expected_ret = zbx_mock_str_to_return_code(zbx_mock_get_parameter_string("out.return")); + zbx_mock_assert_result_eq("Return value", expected_ret, returned_ret); + + if (FAIL == returned_ret) + zbx_mock_assert_ptr_ne("Error pointer", NULL, error); + else + zbx_mock_assert_json_eq("Output", zbx_mock_get_parameter_string("out.response"), out.buffer); + + zbx_free(error); + zbx_json_free(&out); +} diff --git a/tests/zabbix_server/trapper/zbx_trapper_preproc_test_run.yaml b/tests/zabbix_server/trapper/zbx_trapper_preproc_test_run.yaml new file mode 100644 index 00000000000..b8403833e92 --- /dev/null +++ b/tests/zabbix_server/trapper/zbx_trapper_preproc_test_run.yaml @@ -0,0 +1,1250 @@ +--- +test case: Empty request +in: + request: | + { + } +out: + return: FAIL +--- +test case: Missing sessionid field +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "2", + "error_handler": 0, + "type": 1 + } + ], + "value_type": 0, + "value": "1" + }, + "request": "preprocessing.test" + } +out: + return: FAIL +--- +test case: Missing data field +in: + request: | + { + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: FAIL +--- +test case: Missing data.steps field +in: + request: | + { + "data": { + "value_type": 0, + "value": "1" + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: FAIL +--- +test case: Missing data.value_type field +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "2", + "error_handler": 0, + "type": 1 + } + ], + "value": "1" + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: FAIL +--- +test case: Missing data.value field +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "2", + "error_handler": 0, + "type": 1 + } + ], + "value_type": 0 + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: FAIL +--- +test case: Missing data.steps[0].error_handler_params field +in: + request: | + { + "data": { + "steps": [ + { + "params": "2", + "error_handler": 0, + "type": 1 + } + ], + "value_type": 0, + "value": "1" + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: FAIL +--- +test case: Missing data.steps[0].params field +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "error_handler": 0, + "type": 1 + } + ], + "value_type": 0, + "value": "1" + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: FAIL +--- +test case: Missing data.steps[0].error_handler field +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "2", + "type": 1 + } + ], + "value_type": 0, + "value": "1" + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: FAIL +--- +test case: Missing data.steps[0].type field +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "2", + "error_handler": 0 + } + ], + "value_type": 0, + "value": "1" + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: FAIL +--- +test case: Missing data.history.timestamp field +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "2", + "error_handler": 0, + "type": 1 + } + ], + "value_type": 0, + "value": "1", + "history": { + "value": "0" + } + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: FAIL +--- +test case: Missing data.history.value field +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "2", + "error_handler": 0, + "type": 1 + } + ], + "value_type": 0, + "value": "1", + "history": { + "timestamp": "now-1m" + } + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: FAIL +--- +test case: 'Apply trim($) + regsub("data: *(.*)", \1) + mult(2) to data: 4$' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "$", + "error_handler": 0, + "type": 4 + }, + { + "error_handler_params": "", + "params": "data: *(.*)\n\\1", + "error_handler": 0, + "type": 5 + }, + { + "error_handler_params": "", + "params": "2", + "error_handler": 0, + "type": 1 + } + ], + "value_type": 0, + "value": "data: 4$" + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "steps": [ + { + "result": "data: 4" + }, + { + "result": "4" + }, + { + "result": "8" + } + ], + "result": "8" + } + } +--- +test case: 'Apply mult(2) + trim($) + regsub("data: *(.*)", \1) to data: 4$' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "2", + "error_handler": 0, + "type": 1 + }, + { + "error_handler_params": "", + "params": "$", + "error_handler": 0, + "type": 4 + }, + { + "error_handler_params": "", + "params": "data: *(.*)\n\\1", + "error_handler": 0, + "type": 5 + } + ], + "value_type": 0, + "value": "data: 4$" + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "steps": [ + { + "error": "/.*" + } + ], + "error": "/.*" + } + } +--- +test case: 'Apply trim($) + mult(2) + regsub("data: *(.*)", \1) to data: 4$' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "$", + "error_handler": 0, + "type": 4 + }, + { + "error_handler_params": "", + "params": "2", + "error_handler": 0, + "type": 1 + }, + { + "error_handler_params": "", + "params": "data: *(.*)\n\\1", + "error_handler": 0, + "type": 5 + } + ], + "value_type": 0, + "value": "data: 4$" + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "steps": [ + { + "result": "data: 4" + }, + { + "error": "/.*" + } + ], + "error": "/.*" + } + } +--- +test case: 'Apply trim($) + regsub("data: *(.*)", \1) + mult(2) to data: x$' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "$", + "error_handler": 0, + "type": 4 + }, + { + "error_handler_params": "", + "params": "data: *(.*)\n\\1", + "error_handler": 0, + "type": 5 + }, + { + "error_handler_params": "", + "params": "2", + "error_handler": 0, + "type": 1 + } + ], + "value_type": 0, + "value": "data: x$" + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "steps": [ + { + "result": "data: x" + }, + { + "result": "x" + }, + { + "error": "/.*" + } + ], + "error": "/.*" + } + } +--- +test case: 'Apply trim($) + regsub("data: *(.*)", \1) + mult(2) to 4$ with discard on fail' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "$", + "error_handler": 0, + "type": 4 + }, + { + "error_handler_params": "", + "params": "data: *(.*)\n\\1", + "error_handler": 1, + "type": 5 + }, + { + "error_handler_params": "", + "params": "2", + "error_handler": 0, + "type": 1 + } + ], + "value_type": 0, + "value": "4$" + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "steps": [ + { + "result": "4" + }, + { + "result": null, + "action": 1, + "error": "/.*" + } + ], + "result": null + } + } +--- +test case: 'Apply trim($) + regsub("data: *(.*)", \1) + mult(2) to 4$ with set value to 5 on fail' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "$", + "error_handler": 0, + "type": 4 + }, + { + "error_handler_params": "5", + "params": "data: *(.*)\n\\1", + "error_handler": 2, + "type": 5 + }, + { + "error_handler_params": "", + "params": "2", + "error_handler": 0, + "type": 1 + } + ], + "value_type": 0, + "value": "4$" + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "steps": [ + { + "result": "4" + }, + { + "result": "5", + "action": 2, + "error": "/.*" + }, + { + "result": "10" + } + ], + "result": "10" + } + } +--- +test case: 'Apply trim($) + regsub("data: *(.*)", \1) + mult(2) to 4$ with set error to Validation error on fail' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "$", + "error_handler": 0, + "type": 4 + }, + { + "error_handler_params": "Validation error", + "params": "data: *(.*)\n\\1", + "error_handler": 3, + "type": 5 + }, + { + "error_handler_params": "", + "params": "2", + "error_handler": 0, + "type": 1 + } + ], + "value_type": 0, + "value": "4$" + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "steps": [ + { + "result": "4" + }, + { + "failed": "Validation error", + "action": 3, + "error": "/[^V][^a][^l][^i][^d].*" + } + ], + "error": "Validation error" + } + } +--- +test case: 'Apply trim($) + regsub("data: *(.*)", \1) to data: x$ for uint value' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "$", + "error_handler": 0, + "type": 4 + }, + { + "error_handler_params": "", + "params": "data: *(.*)\n\\1", + "error_handler": 0, + "type": 5 + } + ], + "value_type": 3, + "value": "data: x$" + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "steps": [ + { + "result": "data: x" + }, + { + "result": "x" + } + ], + "error": "/.*" + } + } +--- +test case: 'Apply regsub("data: *(.*)", \1) to data: x for uint value testing single step' +in: + request: | + { + "data": { + "steps":[ + { + "error_handler_params": "", + "params": "data: *(.*)\n\\1", + "error_handler": 0, + "type": 5 + } + ], + "value_type": 3, + "value": "data: x", + "single": true + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "steps": [ + { + "result": "x" + } + ], + "result": "x" + } + } +--- +test case: 'Apply delta() to 100, 700' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "", + "error_handler": 0, + "type": 9 + } + ], + "value_type": 0, + "value": "700", + "history": { + "timestamp": "now-1m", + "value": "100" + } + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "steps": [ + { + "result": "600" + } + ], + "result": "600" + } + } +--- +test case: 'Apply delta_per_second() to 100, 700' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "", + "error_handler": 0, + "type": 10 + } + ], + "value_type": 0, + "value": "700", + "history": { + "timestamp": "now-1m", + "value": "100" + } + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "steps": [ + { + "result": "10" + } + ], + "result": "10" + } + } +--- +test case: 'Apply mult(2) + trim($) + regsub("data: *(.*)", \1) to history data: 4$' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "2", + "error_handler": 0, + "type": 1 + }, + { + "error_handler_params": "", + "params": "$", + "error_handler": 0, + "type": 4 + }, + { + "error_handler_params": "", + "params": "data: *(.*)\n\\1", + "error_handler": 0, + "type": 5 + } + ], + "value_type": 0, + "value": "data: 4", + "history": { + "timestamp": "now-1m", + "value": "data: 4$" + } + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "previous": true, + "steps": [ + { + "error": "/.*" + } + ], + "error": "/.*" + } + } +--- +test case: 'Apply trim($) + mult(2) + regsub("data: *(.*)", \1) to history data: 4$' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "$", + "error_handler": 0, + "type": 4 + }, + { + "error_handler_params": "", + "params": "2", + "error_handler": 0, + "type": 1 + }, + { + "error_handler_params": "", + "params": "data: *(.*)\n\\1", + "error_handler": 0, + "type": 5 + } + ], + "value_type": 0, + "value": "data: 4$", + "history": { + "timestamp": "now-1m", + "value": "data: 4$" + } + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "previous": true, + "steps": [ + { + "result": "data: 4" + }, + { + "error": "/.*" + } + ], + "error": "/.*" + } + } +--- +test case: 'Apply trim($) + regsub("data: *(.*)", \1) + mult(2) to history data: x$' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "$", + "error_handler": 0, + "type": 4 + }, + { + "error_handler_params": "", + "params": "data: *(.*)\n\\1", + "error_handler": 0, + "type": 5 + }, + { + "error_handler_params": "", + "params": "2", + "error_handler": 0, + "type": 1 + } + ], + "value_type": 0, + "value": "data: 4$", + "history": { + "timestamp": "now-1m", + "value": "data: x$" + } + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "previous": true, + "steps": [ + { + "result": "data: x" + }, + { + "result": "x" + }, + { + "error": "/.*" + } + ], + "error": "/.*" + } + } +--- +test case: 'Apply trim($) + regsub("data: *(.*)", \1) + mult(2) to history 4$ with discard on fail' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "$", + "error_handler": 0, + "type": 4 + }, + { + "error_handler_params": "", + "params": "data: *(.*)\n\\1", + "error_handler": 1, + "type": 5 + }, + { + "error_handler_params": "", + "params": "2", + "error_handler": 0, + "type": 1 + } + ], + "value_type": 0, + "value": "data: 3", + "history": { + "timestamp": "now-1m", + "value": "4$" + } + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "steps": [ + { + "result": "data: 3" + }, + { + "result": "3" + }, + { + "result": "6" + } + ], + "result": "6" + } + } +--- +test case: 'Apply trim($) + regsub("data: *(.*)", \1) + mult(2) to history 4$ with set value to 5 on fail' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "$", + "error_handler": 0, + "type": 4 + }, + { + "error_handler_params": "5", + "params": "data: *(.*)\n\\1", + "error_handler": 2, + "type": 5 + }, + { + "error_handler_params": "", + "params": "2", + "error_handler": 0, + "type": 1 + } + ], + "value_type": 0, + "value": "data: 3", + "history": { + "timestamp": "now-1m", + "value": "4$" + } + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "steps": [ + { + "result": "data: 3" + }, + { + "result": "3" + }, + { + "result": "6" + } + ], + "result": "6" + } + } +--- +test case: 'Apply trim($) + regsub("data: *(.*)", \1) + mult(2) to history 4$ with set error to Validation error on fail' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "$", + "error_handler": 0, + "type": 4 + }, + { + "error_handler_params": "Validation error", + "params": "data: *(.*)\n\\1", + "error_handler": 3, + "type": 5 + }, + { + "error_handler_params": "", + "params": "2", + "error_handler": 0, + "type": 1 + } + ], + "value_type": 0, + "value": "4$", + "history": { + "timestamp": "now-1m", + "value": "4$" + } + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "previous": true, + "steps": [ + { + "result": "4" + }, + { + "failed": "Validation error", + "action": 3, + "error": "/[^V][^a][^l][^i][^d].*" + } + ], + "error": "Validation error" + } + } +--- +test case: 'Apply trim($) + regsub("data: *(.*)", \1) to history data: x$ for uint value' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "", + "params": "$", + "error_handler": 0, + "type": 4 + }, + { + "error_handler_params": "", + "params": "data: *(.*)\n\\1", + "error_handler": 0, + "type": 5 + } + ], + "value_type": 3, + "value": "data: 1$", + "history": { + "timestamp": "now-1m", + "value": "data: x$" + } + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "previous": true, + "steps": [ + { + "result": "data: x" + }, + { + "result": "x" + } + ], + "error": "/.*" + } + } +--- +test case: 'Apply regsub("data: *(.*)", \1) to history data: x for uint value testing single step' +in: + request: | + { + "data": { + "steps":[ + { + "error_handler_params": "", + "params": "data: *(.*)\n\\1", + "error_handler": 0, + "type": 5 + } + ], + "value_type": 3, + "value": "data: x", + "single": true, + "history": { + "timestamp": "now-1m", + "value": "data: x$" + } + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "steps": [ + { + "result": "x" + } + ], + "result": "x" + } + } +--- +test case: 'Apply regsub("data: *(.*)", \1) + delta() to data: 9, data:10' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "0", + "params": "data: *(.*)\n\\1", + "error_handler": 2, + "type": 5 + }, + { + "error_handler_params": "", + "params": "", + "error_handler": 0, + "type": 9 + } + ], + "value_type": 0, + "value": "data: 10", + "history": { + "timestamp": "now-1m", + "value": "data: 9" + } + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "steps": [ + { + "result": "10" + }, + { + "result": "1" + } + ], + "result": "1" + } + } +--- +test case: 'Apply regsub("data: *(.*)", \1) + delta() to data: 9, data:10' +in: + request: | + { + "data": { + "steps": [ + { + "error_handler_params": "0", + "params": "data: *(.*)\n\\1", + "error_handler": 2, + "type": 5 + }, + { + "error_handler_params": "", + "params": "", + "error_handler": 0, + "type": 9 + } + ], + "value_type": 0, + "value": "data: 10", + "history": { + "timestamp": "now-1m", + "value": "x" + } + }, + "request": "preprocessing.test", + "sid": "6ed71f17963a881bd010e63b01c39484" + } +out: + return: SUCCEED + response: | + { + "response": "success", + "data": { + "steps": [ + { + "result": "10" + }, + { + "result": "10" + } + ], + "result": "10" + } + } +... diff --git a/tests/zbxmockjson.c b/tests/zbxmockjson.c new file mode 100644 index 00000000000..fda1e0f0ccf --- /dev/null +++ b/tests/zbxmockjson.c @@ -0,0 +1,259 @@ +/* +** Zabbix +** Copyright (C) 2001-2019 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + +#include "zbxalgo.h" +#include "zbxjson.h" +#include "zbxregexp.h" + +#include "zbxmocktest.h" +#include "zbxmockdata.h" +#include "zbxmockassert.h" + +#define _FAIL(file, line, prefix, message, ...) \ + \ +do \ +{ \ + cm_print_error("%s%s" message "\n", (NULL != prefix_msg ? prefix_msg : ""), \ + (NULL != prefix_msg && '\0' != *prefix_msg ? ": " : ""), \ + __VA_ARGS__); \ + _fail(file, line); \ +} \ +while(0) + +void cm_print_error(const char * const format, ...); + +static void json_flatten_contents(struct zbx_json_parse *jp, const char *prefix, zbx_vector_ptr_pair_t *props); + +static void json_append_prop(zbx_vector_ptr_pair_t *props, const char *key, const char *value) +{ + zbx_ptr_pair_t pair; + + pair.first = zbx_strdup(NULL, key); + pair.second = zbx_strdup(NULL, value); + zbx_vector_ptr_pair_append_ptr(props, &pair); +} + +static int json_compare_props(const void *d1, const void *d2) +{ + const zbx_ptr_pair_t *p1 = (const zbx_ptr_pair_t *)d1; + const zbx_ptr_pair_t *p2 = (const zbx_ptr_pair_t *)d2; + + return strcmp((const char *)p1->first, (const char *)p2->first); +} + +static void json_flatten_value(const char *ptr, const char *path, zbx_vector_ptr_pair_t *props) +{ + struct zbx_json_parse jp_value; + char *value = NULL; + size_t value_alloc = 0; + zbx_json_type_t type; + + if (FAIL == zbx_json_brackets_open(ptr, &jp_value)) + { + zbx_json_decodevalue_dyn(ptr, &value, &value_alloc, &type); + json_append_prop(props, path, (ZBX_JSON_TYPE_NULL != type ? value : "null")); + } + else + json_flatten_contents(&jp_value, path, props); + + zbx_free(value); +} + +static int json_quote_key(char *key, size_t size) +{ + char *ptr, *out; + int quotes = 0, dot = 1; + + for (ptr = key; '\0' != *ptr; ptr++) + { + if ('\'' == *ptr || '\\' == *ptr) + quotes++; + + if (0 == isalnum((unsigned char)*ptr) && '_' != *ptr && '-' != *ptr) + dot = 0; + } + + if (1 == dot) + return FAIL; + + if (0 == quotes) + return SUCCEED; + + if (ptr - key + quotes + 1 > (int)size) + fail_msg("The hardcoded 2k limit exceeded by JSON key: %s", key); + + for (out = ptr + quotes; ptr != key; ptr--) + { + *out-- = *ptr; + if ('\'' == *ptr || '\\' == *ptr) + *out-- = '\\'; + } + + return SUCCEED; +} + +static void json_flatten_object(struct zbx_json_parse *jp, const char *prefix, zbx_vector_ptr_pair_t *props) +{ + const char *pnext = NULL; + char *path = NULL, key[MAX_STRING_LEN]; + size_t path_alloc = 0, path_offset = 0; + + while (NULL != (pnext = zbx_json_pair_next(jp, pnext, key, sizeof(key)))) + { + path_offset = 0; + if (SUCCEED == json_quote_key(key, sizeof(key))) + zbx_snprintf_alloc(&path, &path_alloc, &path_offset, "%s['%s']", prefix, key); + else + zbx_snprintf_alloc(&path, &path_alloc, &path_offset, "%s.%s", prefix, key); + + json_flatten_value(pnext, path, props); + } + zbx_free(path); +} + +static void json_flatten_array(struct zbx_json_parse *jp, const char *parent, zbx_vector_ptr_pair_t *props) +{ + const char *pnext; + char *path, *value = NULL; + int index = 0; + + + for (pnext = NULL; NULL != (pnext = zbx_json_next(jp, pnext));) + { + path = zbx_dsprintf(NULL, "%s[%d]", parent, index++); + json_flatten_value(pnext, path, props); + zbx_free(path); + } + + zbx_free(value); +} + +static void json_flatten_contents(struct zbx_json_parse *jp, const char *prefix, zbx_vector_ptr_pair_t *props) +{ + if ('{' == *jp->start) + json_flatten_object(jp, prefix, props); + else if ('[' == *jp->start) + json_flatten_array(jp, prefix, props); +} + +/****************************************************************************** + * * + * Function: json_flatten * + * * + * Purpose: flattens json into vector of key (json path), value pairs, sorted * + * by keys * + * * + ******************************************************************************/ +static void json_flatten(struct zbx_json_parse *jp, zbx_vector_ptr_pair_t *props) +{ + json_flatten_contents(jp, "$", props); + zbx_vector_ptr_pair_sort(props, json_compare_props); +} + +/****************************************************************************** + * * + * Function: __zbx_mock_assert_json_eq * + * * + * Purpose: compares returned json with expected * + * * + * Comments: The comparison is done by first flattening both jsons into * + * key(jsonpath)-value pairs, sorting by keys and then comparing * + * the resulting lists. * + * If expected value starts with / then regular expression match is * + * performed. * + * * + ******************************************************************************/ +void __zbx_mock_assert_json_eq(const char *file, int line, const char *prefix_msg, const char *expected_value, + const char *returned_value) +{ + struct zbx_json_parse jp_expected, jp_returned; + zbx_vector_ptr_pair_t props_expected, props_returned; + int i, props_num; + + if (FAIL == zbx_json_open(expected_value, &jp_expected)) + _FAIL(file, line, prefix_msg, "Expected value is not a valid JSON object: %s", zbx_json_strerror()); + + if (FAIL == zbx_json_open(returned_value, &jp_returned)) + _FAIL(file, line, prefix_msg, "Returned value is not a valid JSON object: %s", zbx_json_strerror()); + + zbx_vector_ptr_pair_create(&props_expected); + zbx_vector_ptr_pair_create(&props_returned); + + json_flatten(&jp_expected, &props_expected); + json_flatten(&jp_returned, &props_returned); + + props_num = MIN(props_expected.values_num, props_returned.values_num); + + for (i = 0; i < props_num; i++) + { + zbx_ptr_pair_t *pair_expected = &props_expected.values[i]; + zbx_ptr_pair_t *pair_returned = &props_returned.values[i]; + + if (0 != strcmp(pair_expected->first, pair_returned->first)) + { + _FAIL(file, line, prefix_msg, "Expected key \"%s\" while got \"%s\"", pair_expected->first, + pair_returned->first); + } + + if ('/' == *(char *)pair_expected->second) + { + char *pattern = (char *)pair_expected->second + 1; + if (NULL == zbx_regexp_match(pair_returned->second, pattern, NULL)) + { + _FAIL(file, line, prefix_msg, "Key \"%s\" value \"%s\" does not match pattern \"%s\"", + pair_returned->first, pair_returned->second, pattern); + } + } + else + { + if (0 != strcmp(pair_expected->second, pair_returned->second)) + { + _FAIL(file, line, prefix_msg, "Expected key \"%s\" value \"%s\" while got \"%s\"", + pair_expected->first, pair_expected->second, pair_returned->second); + + } + } + } + + if (i < props_expected.values_num) + { + zbx_ptr_pair_t *pair_expected = &props_expected.values[i]; + _FAIL(file, line, prefix_msg, "Expected key \"%s\" while got nothing", pair_expected->first); + } + + if (i < props_returned.values_num) + { + zbx_ptr_pair_t *pair_returned = &props_returned.values[i]; + _FAIL(file, line, prefix_msg, "Did not expect key \"%s\"", pair_returned->first); + } + + for (i = 0; i < props_expected.values_num; i++) + { + zbx_free(props_expected.values[i].first); + zbx_free(props_expected.values[i].second); + } + zbx_vector_ptr_pair_destroy(&props_expected); + + for (i = 0; i < props_returned.values_num; i++) + { + zbx_free(props_returned.values[i].first); + zbx_free(props_returned.values[i].second); + } + zbx_vector_ptr_pair_destroy(&props_returned); +} diff --git a/tests/zbxmockjson.h b/tests/zbxmockjson.h new file mode 100644 index 00000000000..9e4d4045fb8 --- /dev/null +++ b/tests/zbxmockjson.h @@ -0,0 +1,29 @@ +/* +** Zabbix +** Copyright (C) 2001-2019 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + +#ifndef ZABBIX_MOCK_JSON_H +#define ZABBIX_MOCK_JSON_H + +void __zbx_mock_assert_json_eq(const char *file, int line, const char *prefix_msg, const char *expected_value, + const char *returned_value); + +#define zbx_mock_assert_json_eq(prefix_msg, expected_value, returned_value) \ + __zbx_mock_assert_json_eq(__FILE__, __LINE__, prefix_msg, expected_value, returned_value) + +#endif /* BUILD_TESTS_ZBXMOCKDB_H_ */ |