You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

831 lines
29 KiB

/*
** Zabbix
** Copyright (C) 2001-2023 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 "zbxnum.h"
#include "zbxalgo.h"
#include "zbxcacheconfig/user_macro.h"
#include "um_cache_mock.h"
#include "zbxshmem.h"
char *um_mock_format_macro(const char *name, const char *context);
void *__wrap___zbx_shmem_malloc(const char *file, int line, zbx_shmem_info_t *info, const void *old, size_t size);
void *__wrap___zbx_shmem_realloc(const char *file, int line, zbx_shmem_info_t *info, void *old, size_t size);
void __wrap___zbx_shmem_free(const char *file, int line, zbx_shmem_info_t *info, void *ptr);
ZBX_PTR_VECTOR_IMPL(um_mock_macro, zbx_um_mock_macro_t *)
ZBX_PTR_VECTOR_DECL(um_mock_host, zbx_um_mock_host_t *)
ZBX_PTR_VECTOR_IMPL(um_mock_host, zbx_um_mock_host_t *)
ZBX_PTR_VECTOR_IMPL(um_mock_kv, zbx_um_mock_kv_t *)
ZBX_PTR_VECTOR_IMPL(um_mock_kvset, zbx_um_mock_kvset_t *)
static void um_mock_macro_free(zbx_um_mock_macro_t *macro)
{
zbx_free(macro->macro);
zbx_free(macro->value);
zbx_free(macro);
}
static void um_mock_macro_init(zbx_um_mock_macro_t *macro, zbx_uint64_t hostid, zbx_mock_handle_t hmacro)
{
zbx_mock_handle_t handle;
const char *str;
zbx_mock_error_t err;
macro->macroid = zbx_mock_get_object_member_uint64(hmacro, "macroid");
macro->hostid = hostid;
macro->macro = zbx_strdup(NULL, zbx_mock_get_object_member_string(hmacro, "macro"));
if (ZBX_MOCK_SUCCESS == zbx_mock_object_member(hmacro, "value", &handle))
{
if (ZBX_MOCK_SUCCESS != (err = zbx_mock_string(handle, &str)))
fail_msg("Cannot read macro value: %s", zbx_mock_error_string(err));
macro->value = zbx_strdup(NULL, str);
}
else
macro->value = NULL;
if (ZBX_MOCK_SUCCESS == zbx_mock_object_member(hmacro, "type", &handle))
{
if (ZBX_MOCK_SUCCESS != (err = zbx_mock_string(handle, &str)))
fail_msg("Cannot read macro type: %s", zbx_mock_error_string(err));
if (0 == strcmp(str, "ZBX_MACRO_VALUE_TEXT"))
macro->type = ZBX_MACRO_VALUE_TEXT;
else if (0 == strcmp(str, "ZBX_MACRO_VALUE_SECRET"))
macro->type = ZBX_MACRO_VALUE_SECRET;
else if (0 == strcmp(str, "ZBX_MACRO_VALUE_VAULT"))
macro->type = ZBX_MACRO_VALUE_VAULT;
else
fail_msg("unknown macro type '%s'", str);
}
else
macro->type = ZBX_MACRO_VALUE_TEXT;
}
/*********************************************************************************
* *
* Purpose: initialize mock user macro host from test data *
* *
*********************************************************************************/
static void um_mock_host_init(zbx_um_mock_host_t *host, zbx_mock_handle_t handle)
{
zbx_mock_handle_t hmacros, hmacro, htemplates, htemplate;
zbx_mock_error_t err;
host->hostid = zbx_mock_get_object_member_uint64(handle, "hostid");
zbx_vector_um_mock_macro_create(&host->macros);
zbx_vector_uint64_create(&host->templateids);
hmacros = zbx_mock_get_object_member_handle(handle, "macros");
while (ZBX_MOCK_END_OF_VECTOR != (err = (zbx_mock_vector_element(hmacros, &hmacro))))
{
zbx_um_mock_macro_t *macro;
macro = (zbx_um_mock_macro_t *)zbx_malloc(NULL, sizeof(zbx_um_mock_macro_t));
um_mock_macro_init(macro, host->hostid, hmacro);
zbx_vector_um_mock_macro_append(&host->macros, macro);
}
htemplates = zbx_mock_get_object_member_handle(handle, "templates");
while (ZBX_MOCK_END_OF_VECTOR != (err = (zbx_mock_vector_element(htemplates, &htemplate))))
{
const char *template;
zbx_uint64_t templateid;
if (ZBX_MOCK_SUCCESS != (err = zbx_mock_string(htemplate, &template)))
fail_msg("Cannot read templateid: %s", zbx_mock_error_string(err));
if (SUCCEED != zbx_is_uint64(template, &templateid))
fail_msg("Invalid templateid: %s", template);
zbx_vector_uint64_append(&host->templateids, templateid);
}
}
/*********************************************************************************
* *
* Purpose: initialize mock kv path *
* *
*********************************************************************************/
static void um_mock_kvset_init(zbx_um_mock_kvset_t *kvset, zbx_mock_handle_t handle)
{
zbx_mock_handle_t hvalues, hvalue;
zbx_mock_error_t err;
kvset->path = zbx_mock_get_object_member_string(handle, "path");
zbx_vector_um_mock_kv_create(&kvset->kvs);
hvalues = zbx_mock_get_object_member_handle(handle, "values");
while (ZBX_MOCK_END_OF_VECTOR != (err = (zbx_mock_vector_element(hvalues, &hvalue))))
{
zbx_um_mock_kv_t *kv;
kv = (zbx_um_mock_kv_t *)zbx_malloc(NULL, sizeof(zbx_um_mock_kv_t));
kv->key = zbx_mock_get_object_member_string(hvalue, "key");
kv->value = zbx_mock_get_object_member_string(hvalue, "value");
zbx_vector_um_mock_kv_append(&kvset->kvs, kv);
}
}
/*********************************************************************************
* *
* Purpose: free mock mock kv path *
* *
*********************************************************************************/
static void um_mock_kvset_free(zbx_um_mock_kvset_t *kvset)
{
zbx_vector_um_mock_kv_clear_ext(&kvset->kvs, (zbx_um_mock_kv_free_func_t)zbx_ptr_free);
zbx_vector_um_mock_kv_destroy(&kvset->kvs);
zbx_free(kvset);
}
/*********************************************************************************
* *
* Purpose: initialize mock user macro cache from test data *
* *
*********************************************************************************/
void um_mock_cache_init(zbx_um_mock_cache_t *cache, zbx_mock_handle_t handle)
{
zbx_mock_handle_t hhost, hhosts, hvault, hset;
zbx_mock_error_t err;
zbx_hashset_create(&cache->hosts, 10, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
zbx_vector_um_mock_kvset_create(&cache->kvsets);
if (-1 == handle)
return;
hhosts = zbx_mock_get_object_member_handle(handle, "hosts");
while (ZBX_MOCK_END_OF_VECTOR != (err = (zbx_mock_vector_element(hhosts, &hhost))))
{
zbx_um_mock_host_t host_local;
um_mock_host_init(&host_local, hhost);
zbx_hashset_insert(&cache->hosts, &host_local, sizeof(host_local));
}
hvault = zbx_mock_get_object_member_handle(handle, "vault");
while (ZBX_MOCK_END_OF_VECTOR != (err = (zbx_mock_vector_element(hvault, &hset))))
{
zbx_um_mock_kvset_t *kvset;
kvset = (zbx_um_mock_kvset_t *)zbx_malloc(NULL, sizeof(zbx_um_mock_kvset_t));
um_mock_kvset_init(kvset, hset);
zbx_vector_um_mock_kvset_append(&cache->kvsets, kvset);
}
}
/*********************************************************************************
* *
* Purpose: restore database macro format from cached macro name/context *
* *
* Comments: In database user macro has format '{$NAME:context}' (:context being *
* optional), but in cache macro name and context are stored separately*
* - '{$NAME}' and 'context' (context can be NULL). This function takes*
* the macro name and context from cache and assembles in original *
* format (note that spacing/quotes around the context might be lost). *
* *
* *
*********************************************************************************/
char *um_mock_format_macro(const char *name, const char *context)
{
char *context_esc, *macro = NULL;
size_t macro_alloc = 0, macro_offset = 0;
zbx_strcpy_alloc(&macro, &macro_alloc, &macro_offset, name);
if (NULL != context)
{
macro_offset--;
zbx_chrcpy_alloc(&macro, &macro_alloc, &macro_offset, ':');
if (zbx_get_escape_string_len(context, "\"") != strlen(context))
{
context_esc = zbx_dyn_escape_string(context, "\"");
zbx_snprintf_alloc(&macro, &macro_alloc, &macro_offset, "\"%s\"", context_esc);
zbx_free(context_esc);
}
else
zbx_strcpy_alloc(&macro, &macro_alloc, &macro_offset, context);
zbx_chrcpy_alloc(&macro, &macro_alloc, &macro_offset, '}');
}
return macro;
}
/*********************************************************************************
* *
* Purpose: initialize mock user macro cache from cache *
* *
*********************************************************************************/
void um_mock_cache_init_from_config(zbx_um_mock_cache_t *cache, zbx_um_cache_t *cfg)
{
zbx_hashset_iter_t iter;
zbx_um_host_t **phost;
zbx_hashset_create(&cache->hosts, (size_t)cfg->hosts.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
ZBX_DEFAULT_UINT64_COMPARE_FUNC);
zbx_vector_um_mock_kvset_create(&cache->kvsets);
zbx_hashset_iter_reset(&cfg->hosts, &iter);
while (NULL != (phost = (zbx_um_host_t **)zbx_hashset_iter_next(&iter)))
{
zbx_um_mock_host_t host_local;
int i;
host_local.hostid = (*phost)->hostid;
zbx_vector_um_mock_macro_create(&host_local.macros);
zbx_vector_uint64_create(&host_local.templateids);
zbx_vector_uint64_append_array(&host_local.templateids, (*phost)->templateids.values,
(*phost)->templateids.values_num);
for (i = 0; i < (*phost)->macros.values_num; i++)
{
zbx_um_mock_macro_t *macro;
macro = (zbx_um_mock_macro_t *)zbx_malloc(NULL, sizeof(zbx_um_mock_macro_t));
macro->hostid = (*phost)->hostid;
macro->macroid = (*phost)->macros.values[i]->macroid;
macro->macro = um_mock_format_macro((*phost)->macros.values[i]->name,
(*phost)->macros.values[i]->context);
macro->value = zbx_strdup(NULL, (*phost)->macros.values[i]->value);
macro->type = (*phost)->macros.values[i]->type;
zbx_vector_um_mock_macro_append(&host_local.macros, macro);
}
zbx_hashset_insert(&cache->hosts, &host_local, sizeof(host_local));
}
}
/*********************************************************************************
* *
* Purpose: frees resources used by mock macro cache *
* *
*********************************************************************************/
void um_mock_cache_clear(zbx_um_mock_cache_t *cache)
{
zbx_hashset_iter_t iter;
zbx_um_mock_host_t *host;
zbx_hashset_iter_reset(&cache->hosts, &iter);
while (NULL != (host = (zbx_um_mock_host_t *)zbx_hashset_iter_next(&iter)))
{
zbx_vector_um_mock_macro_clear_ext(&host->macros, um_mock_macro_free);
zbx_vector_um_mock_macro_destroy(&host->macros);
zbx_vector_uint64_destroy(&host->templateids);
}
zbx_hashset_destroy(&cache->hosts);
zbx_vector_um_mock_kvset_clear_ext(&cache->kvsets, um_mock_kvset_free);
zbx_vector_um_mock_kvset_destroy(&cache->kvsets);
}
static int um_mock_compare_macros_by_id(const void *d1, const void *d2)
{
const zbx_um_mock_macro_t *m1 = *(const zbx_um_mock_macro_t * const *)d1;
const zbx_um_mock_macro_t *m2 = *(const zbx_um_mock_macro_t * const *)d2;
ZBX_RETURN_IF_NOT_EQUAL(m1->macroid, m2->macroid);
return 0;
}
/*********************************************************************************
* *
* Purpose: compare macros by name, context and value *
* *
* Comments: Macros are parsed and the name/context are compared separately to *
* handle any spacing/quoting loss because of formatting. *
* *
*********************************************************************************/
static int um_mock_compare_macros_by_content(const zbx_um_mock_macro_t *m1, const zbx_um_mock_macro_t *m2)
{
int ret;
char *name1 = NULL, *name2 = NULL, *context1 = NULL, *context2 = NULL;
unsigned char context_op1, context_op2;
if (SUCCEED != zbx_user_macro_parse_dyn(m1->macro, &name1, &context1, NULL, &context_op1))
{
ret = -1;
goto out;
}
if (SUCCEED != zbx_user_macro_parse_dyn(m2->macro, &name2, &context2, NULL, &context_op2))
{
ret = 1;
goto out;
}
if (0 != (ret = strcmp(name1, name2)))
goto out;
if (0 != (ret = zbx_strcmp_null(context1, context2)))
goto out;
if (context_op1 > context_op2)
{
ret = 1;
goto out;
}
if (context_op1 < context_op2)
{
ret = -1;
goto out;
}
if (0 != (ret = (int)m1->type - (int)m2->type))
goto out;
ret = strcmp(m1->value, m2->value);
out:
zbx_free(name1);
zbx_free(name2);
zbx_free(context1);
zbx_free(context2);
return ret;
}
static void um_mock_dbsync_update_stats(zbx_dbsync_t *sync, unsigned char tag)
{
switch (tag)
{
case ZBX_DBSYNC_ROW_ADD:
sync->add_num++;
break;
case ZBX_DBSYNC_ROW_UPDATE:
sync->update_num++;
break;
case ZBX_DBSYNC_ROW_REMOVE:
sync->remove_num++;
break;
}
}
/*********************************************************************************
* *
* Purpose: add macro as dbsync row with the specified dbsync operation tag *
* *
* Comments: Global macros have 0 hostid and it will be omitted from dbsync row. *
* *
*********************************************************************************/
static void um_mock_dbsync_add_macro(zbx_dbsync_t *sync, unsigned char tag, const zbx_um_mock_macro_t *macro)
{
zbx_dbsync_row_t *row;
char **prow;
if (0 == sync->columns_num)
sync->columns_num = (0 == macro->hostid ? 4 : 5);
row = (zbx_dbsync_row_t *)zbx_malloc(NULL, sizeof(zbx_dbsync_row_t));
row->rowid = macro->macroid;
row->tag = tag;
prow = row->row = (char **)zbx_malloc(NULL, sizeof(char *) * (size_t)sync->columns_num);
*prow++ = zbx_dsprintf(NULL, ZBX_FS_UI64, macro->macroid);
if (0 != macro->hostid)
*prow++ = zbx_dsprintf(NULL, ZBX_FS_UI64, macro->hostid);
*prow++ = zbx_strdup(NULL, macro->macro);
*prow++ = zbx_strdup(NULL, macro->value);
*prow++ = zbx_dsprintf(NULL, "%u", macro->type);
zbx_vector_ptr_append(&sync->rows, row);
um_mock_dbsync_update_stats(sync, tag);
}
/*********************************************************************************
* *
* Purpose: add hosts_templates dbsync row *
* *
*********************************************************************************/
static void um_mock_dbsync_add_htmpl(zbx_dbsync_t *sync, unsigned char tag, zbx_uint64_t hostid,
zbx_uint64_t templateid)
{
zbx_dbsync_row_t *row;
if (0 == sync->columns_num)
sync->columns_num = 2;
row = (zbx_dbsync_row_t *)zbx_malloc(NULL, sizeof(zbx_dbsync_row_t));
row->rowid = 0;
row->tag = tag;
row->row = (char **)zbx_malloc(NULL, sizeof(char *) * (size_t)sync->columns_num);
row->row[0] = zbx_dsprintf(NULL, ZBX_FS_UI64, hostid);
row->row[1] = zbx_dsprintf(NULL, ZBX_FS_UI64, templateid);
zbx_vector_ptr_append(&sync->rows, row);
um_mock_dbsync_update_stats(sync, tag);
}
/*********************************************************************************
* *
* Purpose: compare macros on two hosts and: *
* 1) add new/updated macros to the sync object *
* 2) remove macros by adding them into the del_macros vector *
* *
*********************************************************************************/
static void um_mock_host_macro_diff(const zbx_um_mock_host_t *host1, const zbx_um_mock_host_t *host2,
zbx_dbsync_t *sync, zbx_vector_um_mock_macro_t *del_macros)
{
zbx_vector_um_mock_macro_t macros;
int i, j;
zbx_vector_um_mock_macro_create(&macros);
if (NULL != host2)
zbx_vector_um_mock_macro_append_array(&macros, host2->macros.values, host2->macros.values_num);
if (NULL != host1)
{
for (i = 0; i < host1->macros.values_num; i++)
{
if (FAIL != (j = zbx_vector_um_mock_macro_search(&macros, host1->macros.values[i],
um_mock_compare_macros_by_id)))
{
if (0 != um_mock_compare_macros_by_content(host1->macros.values[i], macros.values[j]))
um_mock_dbsync_add_macro(sync, ZBX_DBSYNC_ROW_UPDATE, macros.values[j]);
zbx_vector_um_mock_macro_remove_noorder(&macros, j);
}
else
zbx_vector_um_mock_macro_append(del_macros, host1->macros.values[i]);
}
}
for (i = 0; i < macros.values_num; i++)
um_mock_dbsync_add_macro(sync, ZBX_DBSYNC_ROW_ADD, macros.values[i]);
zbx_vector_um_mock_macro_destroy(&macros);
}
/*********************************************************************************
* *
* Purpose: compare template ids on two hosts and add new/updated ids to sync and*
* removed ids to del_templateids vector *
* *
*********************************************************************************/
static void um_mock_host_template_diff(const zbx_um_mock_host_t *host1, const zbx_um_mock_host_t *host2,
zbx_dbsync_t *sync, zbx_vector_uint64_pair_t *del_templateids)
{
zbx_vector_uint64_t templateids;
int i, j;
zbx_uint64_pair_t pair;
zbx_vector_uint64_create(&templateids);
if (NULL != host2)
zbx_vector_uint64_append_array(&templateids, host2->templateids.values, host2->templateids.values_num);
if (NULL != host1)
{
for (i = 0; i < host1->templateids.values_num; i++)
{
if (FAIL != (j = zbx_vector_uint64_search(&templateids, host1->templateids.values[i],
ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
{
zbx_vector_uint64_remove_noorder(&templateids, j);
}
else
{
pair.first = host1->hostid;
pair.second = host1->templateids.values[i];
zbx_vector_uint64_pair_append(del_templateids, pair);
}
}
}
for (i = 0; i < templateids.values_num; i++)
um_mock_dbsync_add_htmpl(sync, ZBX_DBSYNC_ROW_ADD, host2->hostid, templateids.values[i]);
zbx_vector_uint64_destroy(&templateids);
}
static int um_mock_compare_hosts_by_id(const void *d1, const void *d2)
{
const zbx_um_mock_host_t *h1 = *(const zbx_um_mock_host_t * const *)d1;
const zbx_um_mock_host_t *h2 = *(const zbx_um_mock_host_t * const *)d2;
ZBX_RETURN_IF_NOT_EQUAL(h1->hostid, h2->hostid);
return 0;
}
/*********************************************************************************
* *
* Purpose: compare two mock caches and output difference as database rows *
* stored into sync objects *
* *
*********************************************************************************/
void um_mock_cache_diff(zbx_um_mock_cache_t *cache1, zbx_um_mock_cache_t *cache2,
zbx_dbsync_t *gmacros, zbx_dbsync_t *hmacros, zbx_dbsync_t *htmpls)
{
zbx_hashset_iter_t iter;
zbx_vector_um_mock_host_t hosts;
zbx_vector_um_mock_macro_t del_macros;
zbx_vector_uint64_pair_t del_templateids;
zbx_um_mock_host_t *host1, *host2;
int i;
zbx_uint64_t hostid = 0;
zbx_vector_um_mock_host_create(&hosts);
zbx_vector_um_mock_macro_create(&del_macros);
zbx_vector_uint64_pair_create(&del_templateids);
/* compare global macros */
host1 = (zbx_um_mock_host_t *)zbx_hashset_search(&cache1->hosts, &hostid);
host2 = (zbx_um_mock_host_t *)zbx_hashset_search(&cache2->hosts, &hostid);
um_mock_host_macro_diff(host1, host2, gmacros, &del_macros);
for (i = 0; i < del_macros.values_num; i++)
um_mock_dbsync_add_macro(gmacros, ZBX_DBSYNC_ROW_REMOVE, del_macros.values[i]);
zbx_vector_um_mock_macro_clear(&del_macros);
/* compare host macros and templates */
zbx_hashset_iter_reset(&cache2->hosts, &iter);
while (NULL != (host2 = (zbx_um_mock_host_t *)zbx_hashset_iter_next(&iter)))
{
if (0 == host2->hostid)
continue;
zbx_vector_um_mock_host_append(&hosts, host2);
}
zbx_hashset_iter_reset(&cache1->hosts, &iter);
while (NULL != (host1 = (zbx_um_mock_host_t *)zbx_hashset_iter_next(&iter)))
{
if (0 == host1->hostid)
continue;
if (FAIL != (i = zbx_vector_um_mock_host_search(&hosts, host1, um_mock_compare_hosts_by_id)))
{
um_mock_host_macro_diff(host1, hosts.values[i], hmacros, &del_macros);
um_mock_host_template_diff(host1, hosts.values[i], htmpls, &del_templateids);
zbx_vector_um_mock_host_remove_noorder(&hosts, i);
}
else
{
um_mock_host_macro_diff(host1, NULL, hmacros, &del_macros);
um_mock_host_template_diff(host1, NULL, htmpls, &del_templateids);
}
}
for (i = 0; i < hosts.values_num; i++)
{
um_mock_host_macro_diff(NULL, hosts.values[i], hmacros, &del_macros);
um_mock_host_template_diff(NULL, hosts.values[i], htmpls, &del_templateids);
}
for (i = 0; i < del_macros.values_num; i++)
um_mock_dbsync_add_macro(hmacros, ZBX_DBSYNC_ROW_REMOVE, del_macros.values[i]);
for (i = 0; i < del_templateids.values_num; i++)
{
um_mock_dbsync_add_htmpl(htmpls, ZBX_DBSYNC_ROW_REMOVE, del_templateids.values[i].first,
del_templateids.values[i].second);
}
zbx_vector_uint64_pair_destroy(&del_templateids);
zbx_vector_um_mock_macro_destroy(&del_macros);
zbx_vector_um_mock_host_destroy(&hosts);
}
#define REFCOUNT_FIELD_SIZE sizeof(zbx_uint32_t)
static zbx_hash_t mock_strpool_hash(const void *data)
{
return ZBX_DEFAULT_STRING_HASH_FUNC((char *)data + REFCOUNT_FIELD_SIZE);
}
static int mock_strpool_compare(const void *d1, const void *d2)
{
return strcmp((char *)d1 + REFCOUNT_FIELD_SIZE, (char *)d2 + REFCOUNT_FIELD_SIZE);
}
/*********************************************************************************
* *
* Purpose: initialize configuration cache with mocked user macros and string *
* pool *
* *
*********************************************************************************/
void um_mock_config_init(void)
{
config = (ZBX_DC_CONFIG *)zbx_malloc(NULL, sizeof(ZBX_DC_CONFIG));
memset(config, 0, sizeof(ZBX_DC_CONFIG));
zbx_hashset_create(&config->gmacros, 100, um_macro_hash, um_macro_compare);
zbx_hashset_create(&config->hmacros, 100, um_macro_hash, um_macro_compare);
zbx_hashset_create(&config->strpool, 100, mock_strpool_hash, mock_strpool_compare);
zbx_vector_ptr_create(&config->kvs_paths);
zbx_hashset_create(&config->gmacro_kv, 100, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
zbx_hashset_create(&config->hmacro_kv, 100, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
}
static void um_mock_kv_path_free(zbx_dc_kvs_path_t *kvspath)
{
zbx_hashset_iter_t iter;
zbx_dc_kv_t *kv;
zbx_hashset_iter_reset(&kvspath->kvs, &iter);
while (NULL != (kv = (zbx_dc_kv_t *)zbx_hashset_iter_next(&iter)))
zbx_vector_uint64_pair_destroy(&kv->macros);
zbx_hashset_destroy(&kvspath->kvs);
zbx_free(kvspath);
}
/*********************************************************************************
* *
* Purpose: destroy configuration cache *
* *
*********************************************************************************/
void um_mock_config_destroy(void)
{
zbx_hashset_iter_t iter;
zbx_um_macro_t **pmacro;
zbx_hashset_iter_reset(&config->gmacros, &iter);
while (NULL != (pmacro = (zbx_um_macro_t **)zbx_hashset_iter_next(&iter)))
um_macro_release(*pmacro);
zbx_hashset_iter_reset(&config->hmacros, &iter);
while (NULL != (pmacro = (zbx_um_macro_t **)zbx_hashset_iter_next(&iter)))
um_macro_release(*pmacro);
zbx_vector_ptr_clear_ext(&config->kvs_paths, (zbx_ptr_free_func_t)um_mock_kv_path_free);
zbx_vector_ptr_destroy(&config->kvs_paths);
zbx_hashset_destroy(&config->gmacro_kv);
zbx_hashset_destroy(&config->hmacro_kv);
zbx_hashset_destroy(&config->gmacros);
zbx_hashset_destroy(&config->hmacros);
zbx_hashset_destroy(&config->strpool);
zbx_free(config);
}
/*********************************************************************************
* *
* Purpose: clear mocked sync data *
* *
*********************************************************************************/
void mock_dbsync_clear(zbx_dbsync_t *sync)
{
/* free the resources allocated by row pre-processing */
zbx_vector_ptr_clear_ext(&sync->columns, zbx_ptr_free);
zbx_vector_ptr_destroy(&sync->columns);
zbx_free(sync->row);
if (ZBX_DBSYNC_UPDATE == sync->mode)
{
int i, j;
zbx_dbsync_row_t *row;
for (i = 0; i < sync->rows.values_num; i++)
{
row = (zbx_dbsync_row_t *)sync->rows.values[i];
if (NULL != row->row)
{
for (j = 0; j < sync->columns_num; j++)
zbx_free(row->row[j]);
zbx_free(row->row);
}
zbx_free(row);
}
zbx_vector_ptr_destroy(&sync->rows);
}
else
{
zbx_db_free_result(sync->dbresult);
sync->dbresult = NULL;
}
}
/* mocked functions */
void *__wrap___zbx_shmem_malloc(const char *file, int line, zbx_shmem_info_t *info, const void *old, size_t size)
{
ZBX_UNUSED(file);
ZBX_UNUSED(line);
ZBX_UNUSED(info);
ZBX_UNUSED(old);
return zbx_malloc(NULL, size);
}
void *__wrap___zbx_shmem_realloc(const char *file, int line, zbx_shmem_info_t *info, void *old, size_t size)
{
ZBX_UNUSED(file);
ZBX_UNUSED(line);
ZBX_UNUSED(info);
return zbx_realloc(old, size);
}
void __wrap___zbx_shmem_free(const char *file, int line, zbx_shmem_info_t *info, void *ptr)
{
ZBX_UNUSED(file);
ZBX_UNUSED(line);
ZBX_UNUSED(info);
zbx_free(ptr);
}
/* debug */
static void um_mock_host_dump(const zbx_um_mock_host_t *host)
{
int i;
const char *separator;
printf("\thostid: " ZBX_FS_UI64 "\n\t\tmacros:\n", host->hostid);
for (i = 0; i < host->macros.values_num; i++)
{
printf("\t\t\t" ZBX_FS_UI64 " => %s:%s\n", host->macros.values[i]->macroid,
host->macros.values[i]->macro, host->macros.values[i]->value);
}
separator = "";
printf("\n\t\ttemplates: [");
for (i = 0; i < host->templateids.values_num; i++)
{
printf("%s" ZBX_FS_UI64 , separator, host->templateids.values[i]);
separator = ", ";
}
printf("]\n");
}
static void um_mock_kvset_dump(zbx_um_mock_kvset_t *kvset)
{
int i;
printf("\tpath:%s\n", kvset->path);
for (i = 0; i < kvset->kvs.values_num; i++)
printf("\t\t%s:%s\n", kvset->kvs.values[i]->key, kvset->kvs.values[i]->value);
}
void um_mock_cache_dump(zbx_um_mock_cache_t *cache)
{
zbx_hashset_iter_t iter;
zbx_um_mock_host_t *host;
int i;
printf("\nhosts:\n");
zbx_hashset_iter_reset(&cache->hosts, &iter);
while (NULL != (host = (zbx_um_mock_host_t *)zbx_hashset_iter_next(&iter)))
um_mock_host_dump(host);
printf("vault:\n");
for (i = 0; i < cache->kvsets.values_num; i++)
um_mock_kvset_dump(cache->kvsets.values[i]);
printf("---\n");
}