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.
307 lines
7.5 KiB
307 lines
7.5 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 "zbxmockdb.h"
|
|
|
|
/* make sure that __wrap_*() prototypes match unwrapped counterparts */
|
|
|
|
#define zbx_db_vselect __wrap_zbx_db_vselect
|
|
#define zbx_db_fetch_basic __wrap_zbx_db_fetch_basic
|
|
#define zbx_db_fetch __wrap_zbx_db_fetch_basic
|
|
#define zbx_db_free_result __wrap_zbx_db_free_result
|
|
#include "zbxdb.h"
|
|
#undef zbx_db_vselect
|
|
#undef zbx_db_fetch_basic
|
|
#undef zbx_db_fetch
|
|
#undef zbx_db_free_result
|
|
|
|
#define __zbx_db_execute __wrap___zbx_db_execute
|
|
#define zbx_db_execute_multiple_query __wrap_zbx_db_execute_multiple_query
|
|
#define zbx_db_begin __wrap_zbx_db_begin
|
|
#define zbx_db_commit __wrap_xbc_db_commit
|
|
#include "zbxdbhigh.h"
|
|
#undef __zbx_db_execute
|
|
#undef zbx_db_execute_multiple_query
|
|
#undef zbx_db_begin
|
|
#undef zbx_db_commit
|
|
|
|
#define ZBX_MOCK_DB_RESULT_COLUMNS_MAX 128
|
|
|
|
typedef struct
|
|
{
|
|
char *data_source;
|
|
int num;
|
|
}
|
|
zbx_mockdb_query_t;
|
|
|
|
typedef struct
|
|
{
|
|
zbx_hashset_t queries;
|
|
}
|
|
zbx_mockdb_t;
|
|
|
|
static zbx_mockdb_t mockdb;
|
|
|
|
struct zbx_db_result
|
|
{
|
|
zbx_db_row_t row;
|
|
char *data_source; /* for error messages */
|
|
zbx_mock_handle_t rows;
|
|
int row_to_fetch; /* for error messages */
|
|
int columns; /* to make sure that rows have identical number of columns */
|
|
};
|
|
|
|
zbx_db_result_t __fwd_zbx_db_select(const char *fmt, ...);
|
|
zbx_db_result_t __wrap_zbx_db_select_n_basic(const char *query, int n);
|
|
int __wrap___zbx_db_execute(const char *fmt, ...);
|
|
|
|
/* zbx_mockdb_t:queries hashset support */
|
|
static zbx_hash_t mockdb_query_hash(const void *data)
|
|
{
|
|
const zbx_mockdb_query_t *query = (const zbx_mockdb_query_t *)data;
|
|
return ZBX_DEFAULT_STRING_HASH_FUNC(query->data_source);
|
|
}
|
|
|
|
static int mockdb_query_compare(const void *d1, const void *d2)
|
|
{
|
|
const zbx_mockdb_query_t *q1 = (const zbx_mockdb_query_t *)d1;
|
|
const zbx_mockdb_query_t *q2 = (const zbx_mockdb_query_t *)d2;
|
|
|
|
return strcmp(q1->data_source, q2->data_source);
|
|
}
|
|
|
|
static void mockdb_query_clear(void *data)
|
|
{
|
|
zbx_mockdb_query_t *query = (zbx_mockdb_query_t *)data;
|
|
|
|
zbx_free(query->data_source);
|
|
}
|
|
|
|
/* <data_source> = <table name> , { "_" , <table name> } */
|
|
static char *generate_data_source(const char *sql)
|
|
{
|
|
int found = 0;
|
|
char *data_source = NULL, *ptr_ds;
|
|
const char *ptr_sql = sql, *ptr_tmp;
|
|
|
|
data_source = zbx_calloc(NULL, 64, sizeof(char *));
|
|
ptr_ds = data_source;
|
|
|
|
while ('\0' != *ptr_sql)
|
|
{
|
|
if (0 != found)
|
|
{
|
|
if (' ' == *ptr_sql || ';' == *ptr_sql)
|
|
{
|
|
found = 0;
|
|
*(ptr_ds++) = ' ';
|
|
}
|
|
else
|
|
*(ptr_ds++) = *ptr_sql;
|
|
|
|
ptr_sql++;
|
|
}
|
|
else if (NULL != (ptr_tmp = strstr(ptr_sql, "from ")))
|
|
{
|
|
found = 1;
|
|
ptr_sql = ptr_tmp + strlen("from ");
|
|
}
|
|
else if (NULL != (ptr_tmp = strstr(ptr_sql, "join ")))
|
|
{
|
|
found = 1;
|
|
ptr_sql = ptr_tmp + strlen("join ");
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
if (ptr_ds == data_source)
|
|
zbx_free(data_source); /* failed to generate data_source */
|
|
else
|
|
*(ptr_ds - 1) = '\0';
|
|
|
|
return data_source;
|
|
}
|
|
|
|
zbx_db_result_t __wrap_zbx_db_vselect(const char *fmt, va_list args)
|
|
{
|
|
char *sql = NULL, *data_source = NULL;
|
|
zbx_mock_error_t error;
|
|
zbx_mock_handle_t rows;
|
|
zbx_mockdb_query_t *query, query_local;
|
|
zbx_db_result_t result = NULL;
|
|
|
|
sql = zbx_dvsprintf(sql, fmt, args);
|
|
printf("\tSQL: %s\n", sql);
|
|
|
|
if (NULL == (query_local.data_source = generate_data_source(sql)))
|
|
fail_msg("Cannot generate data source string from SQL query: %s", sql);
|
|
|
|
zbx_free(sql);
|
|
|
|
if (NULL == (query = zbx_hashset_search(&mockdb.queries, &query_local)))
|
|
{
|
|
query_local.num = 1;
|
|
query = zbx_hashset_insert(&mockdb.queries, &query_local, sizeof(query_local));
|
|
data_source = zbx_strdup(NULL, query->data_source);
|
|
}
|
|
else
|
|
{
|
|
query->num++;
|
|
zbx_free(query_local.data_source);
|
|
data_source = zbx_dsprintf(NULL, "%s (%d)", query->data_source, query->num);
|
|
}
|
|
|
|
if (ZBX_MOCK_SUCCESS != (error = zbx_mock_db_rows(data_source, &rows)))
|
|
fail_msg("Cannot find data for data source \"%s\": %s", data_source, zbx_mock_error_string(error));
|
|
|
|
result = zbx_malloc(result, sizeof(struct zbx_db_result));
|
|
result->row = zbx_malloc(NULL, ZBX_MOCK_DB_RESULT_COLUMNS_MAX * sizeof(char *));
|
|
result->data_source = data_source;
|
|
result->rows = rows;
|
|
result->row_to_fetch = 1;
|
|
result->columns = -1;
|
|
|
|
return result;
|
|
}
|
|
|
|
zbx_db_result_t __fwd_zbx_db_select(const char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
zbx_db_result_t result;
|
|
|
|
va_start(args, fmt);
|
|
result = __wrap_zbx_db_vselect(fmt, args);
|
|
va_end(args);
|
|
|
|
return result;
|
|
}
|
|
|
|
zbx_db_result_t __wrap_zbx_db_select_n_basic(const char *query, int n)
|
|
{
|
|
return __fwd_zbx_db_select("%s limit %d", query, n);
|
|
}
|
|
|
|
zbx_db_row_t __wrap_zbx_db_fetch_basic(zbx_db_result_t result)
|
|
{
|
|
zbx_mock_error_t error;
|
|
zbx_mock_handle_t row, field;
|
|
int column = 0;
|
|
|
|
if (NULL == result || ZBX_MOCK_END_OF_VECTOR == (error = zbx_mock_vector_element(result->rows, &row)))
|
|
return NULL;
|
|
|
|
if (ZBX_MOCK_SUCCESS != error)
|
|
{
|
|
fail_msg("Cannot fetch row %d for data source \"%s\": %s", result->row_to_fetch, result->data_source,
|
|
zbx_mock_error_string(error));
|
|
}
|
|
|
|
while (ZBX_MOCK_SUCCESS == (error = zbx_mock_vector_element(row, &field)))
|
|
{
|
|
if (ZBX_MOCK_DB_RESULT_COLUMNS_MAX <= column)
|
|
fail_msg("Too many columns for data source \"%s\".", result->data_source);
|
|
|
|
if (ZBX_MOCK_SUCCESS != (error = zbx_mock_string(field, (const char **)&result->row[column])))
|
|
break;
|
|
|
|
column++;
|
|
}
|
|
|
|
if (ZBX_MOCK_END_OF_VECTOR != error)
|
|
{
|
|
fail_msg("Cannot get value of column %d, row %d for data source \"%s\": %s", column + 1,
|
|
result->row_to_fetch, result->data_source, zbx_mock_error_string(error));
|
|
}
|
|
|
|
if (0 <= result->columns)
|
|
{
|
|
if (column < result->columns)
|
|
{
|
|
fail_msg("Too few columns in row %d for data source \"%s\".", result->row_to_fetch,
|
|
result->data_source);
|
|
}
|
|
|
|
if (column > result->columns)
|
|
{
|
|
fail_msg("Too many columns in row %d for data source \"%s\".", result->row_to_fetch,
|
|
result->data_source);
|
|
}
|
|
}
|
|
else
|
|
result->columns = column;
|
|
|
|
while (column < ZBX_MOCK_DB_RESULT_COLUMNS_MAX)
|
|
result->row[column++] = NULL;
|
|
|
|
result->row_to_fetch++;
|
|
|
|
return result->row;
|
|
}
|
|
|
|
|
|
void __wrap_zbx_db_free_result(zbx_db_result_t result)
|
|
{
|
|
if (NULL != result)
|
|
{
|
|
zbx_free(result->row);
|
|
zbx_free(result->data_source);
|
|
}
|
|
|
|
zbx_free(result);
|
|
}
|
|
|
|
int __wrap___zbx_db_execute(const char *fmt, ...)
|
|
{
|
|
ZBX_UNUSED(fmt);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int __wrap_zbx_db_execute_multiple_query(const char *query, const char *field_name, zbx_vector_uint64_t *ids)
|
|
{
|
|
ZBX_UNUSED(query);
|
|
ZBX_UNUSED(field_name);
|
|
ZBX_UNUSED(ids);
|
|
|
|
return SUCCEED;
|
|
}
|
|
|
|
void __wrap_zbx_db_begin(void)
|
|
{
|
|
}
|
|
|
|
int __wrap_zbx_db_commit(void)
|
|
{
|
|
return ZBX_DB_OK;
|
|
}
|
|
|
|
void zbx_mockdb_init(void)
|
|
{
|
|
zbx_hashset_create_ext(&mockdb.queries, 0, mockdb_query_hash, mockdb_query_compare, mockdb_query_clear,
|
|
ZBX_DEFAULT_MEM_MALLOC_FUNC, ZBX_DEFAULT_MEM_REALLOC_FUNC, ZBX_DEFAULT_MEM_FREE_FUNC);
|
|
}
|
|
|
|
void zbx_mockdb_destroy(void)
|
|
{
|
|
zbx_hashset_destroy(&mockdb.queries);
|
|
}
|