author | Sebastian Harl <sh@tokkee.org> | |
Fri, 31 Jan 2014 06:27:24 +0000 (07:27 +0100) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Fri, 31 Jan 2014 06:27:24 +0000 (07:27 +0100) |
17 files changed:
configure.ac | patch | blob | history | |
src/Makefile.am | patch | blob | history | |
src/backend/puppet/store-configs.c | patch | blob | history | |
src/client/sock.c | patch | blob | history | |
src/core/data.c | [new file with mode: 0644] | patch | blob |
src/core/store.c | patch | blob | history | |
src/include/core/data.h | patch | blob | history | |
src/include/core/store.h | patch | blob | history | |
src/tools/sysdb/command.c | patch | blob | history | |
src/utils/dbi.c | patch | blob | history | |
src/utils/unixsock.c | patch | blob | history | |
t/Makefile.am | patch | blob | history | |
t/core/data_test.c | [new file with mode: 0644] | patch | blob |
t/core/store_test.c | patch | blob | history | |
t/libsysdb_test.c | patch | blob | history | |
t/libsysdb_test.h | patch | blob | history | |
t/utils/dbi_test.c | patch | blob | history |
diff --git a/configure.ac b/configure.ac
index ac281225e0a703cb0478aa4a809f358bcf3360ff..5cae366f0e47b6d16ee649b491ae17d34a8e7d2c 100644 (file)
--- a/configure.ac
+++ b/configure.ac
[AS_HELP_STRING([--with-libdbi], [libdbi support (default: auto)])],
[with_libdbi="$withval"],
[with_libdbi="yes"])
-if test "x$with_libdbi" = "xyes"; then
+if test "x$with_libdbi" = "xyes" || test "x$with_libdbi" = "xauto"; then
AC_CHECK_HEADERS([dbi/dbi.h],
[with_libdbi="yes"],
[with_libdbi="no (dbi/dbi.h not found)"])
-fi
+else if test "x$with_libdbi" = "xno"; then
+ with_libdbi="$with_libdbi (disabled on command-line)"
+else
+ AC_MSG_ERROR([Invalid value for option --with-libdbi=$with_libdbi (expected "yes", "no", or "auto")])
+fi; fi
if test "x$with_libdbi" = "xyes"; then
AC_CHECK_LIB([dbi], [dbi_initialize],
[with_libdbi="yes"],
if test "x$readline_support" = "xyes"; then
readline_support="auto"
-fi
+else if test "x$readline_support" != "xauto" \
+ && test "x$readline_support" != "xno" \
+ && test "x$readline_support" != "xlibedit" \
+ && test "x$readline_support" != "xlibreadline"; then
+ AC_MSG_ERROR([Invalid value for option --with-readline=$readline_support (expected "yes", "no", "auto", "libedit", or "libreadline")])
+fi; fi
have_libedit="no"
if test "x$readline_support" = "xauto" \
[backend accessing Nagios/Icinga/Shinken using MK Livestatus])
AC_SDB_PLUGIN([puppet-storeconfigs], [$puppet_storeconfigs_default],
[backend accessing the Puppet stored configuration database])
-AC_SDB_PLUGIN([syslog], [yes],
- [plugin logging to syslog])
+
+m4_divert_once([HELP_ENABLE], [
+Plugins:])
+
AC_SDB_PLUGIN([cname-dns], [yes],
[canonicalize hostnames by querying DNS])
+AC_SDB_PLUGIN([syslog], [yes],
+ [plugin logging to syslog])
AM_CONDITIONAL([BUILD_DOCUMENTATION], test "x$build_documentation" = "xyes")
AM_CONDITIONAL([BUILD_TESTING], test "x$build_testing" = "xyes")
AC_MSG_RESULT()
AC_MSG_RESULT([ Plugins:])
AC_MSG_RESULT([ cname::dns: . . . . . . . . $enable_cname_dns])
+AC_MSG_RESULT([ syslog: . . . . . . . . . . $enable_syslog])
AC_MSG_RESULT()
AC_MSG_RESULT([This package is maintained by $PACKAGE_MAINTAINER.])
AC_MSG_RESULT([Please report bugs to $PACKAGE_BUGREPORT.])
diff --git a/src/Makefile.am b/src/Makefile.am
index 9206e27c956fab434980d3658e5438880aa10651..873694874bc06645af68624bb93bbdb23204d875 100644 (file)
--- a/src/Makefile.am
+++ b/src/Makefile.am
core/object.c include/core/object.h \
core/plugin.c include/core/plugin.h \
core/store.c include/core/store.h \
- include/core/data.h \
+ core/data.c include/core/data.h \
frontend/connection.c include/frontend/connection.h \
frontend/connection-private.h \
frontend/parser.c include/frontend/parser.h \
pkgbackendpuppetlib_LTLIBRARIES =
pkgcnamelib_LTLIBRARIES =
+if BUILD_PLUGIN_CNAMEDNS
+pkgcnamelib_LTLIBRARIES += plugins/cname/dns.la
+plugins_cname_dns_la_SOURCE = plugins/cname/dns.c
+plugins_cname_dns_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version
+libsysdb_la_LIBADD += -dlopen plugins/cname/dns.la
+libsysdb_la_DEPENDENCIES += plugins/cname/dns.la
+endif
+
if BUILD_PLUGIN_COLLECTD
pkgbackendcollectdlib_LTLIBRARIES += backend/collectd/unixsock.la
backend_collectd_unixsock_la_SOURCES = backend/collectd/unixsock.c
libsysdb_la_DEPENDENCIES += plugins/syslog.la
endif
-if BUILD_PLUGIN_CNAMEDNS
-pkgcnamelib_LTLIBRARIES += plugins/cname/dns.la
-plugins_cname_dns_la_SOURCE = plugins/cname/dns.c
-plugins_cname_dns_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version
-libsysdb_la_LIBADD += -dlopen plugins/cname/dns.la
-libsysdb_la_DEPENDENCIES += plugins/cname/dns.la
-endif
-
include/client/sysdb.h: include/client/sysdb.h.in ../version
source ../version; sed \
-e "s/@SDB_VERSION_MAJOR@/$$VERSION_MAJOR/g" \
index a9a0ff777e9d6f35bd364885832b485d1f88beef..e109b305819cfcec5fb1d7f32403241ed519d69b 100644 (file)
const char *hostname;
const char *key;
- const char *value;
+ sdb_data_t value;
sdb_time_t last_update;
assert(n == 4);
hostname = data[0].data.string;
key = data[1].data.string;
- value = data[2].data.string;
+ value.type = SDB_TYPE_STRING;
+ value.data.string = data[2].data.string;
last_update = data[3].data.datetime;
- status = sdb_store_attribute(hostname, key, value, last_update);
+ status = sdb_store_attribute(hostname, key, &value, last_update);
if (status < 0) {
sdb_log(SDB_LOG_ERR, "puppet::store-configs backend: Failed to "
diff --git a/src/client/sock.c b/src/client/sock.c
index 49cefdf0935fb8315cda15c6b8921bbfa6d0a510..59c77873e08411b22a9c1e5a6a857a8e269210f5 100644 (file)
--- a/src/client/sock.c
+++ b/src/client/sock.c
size_t data_offset = sdb_strbuf_len(buf);
+ if (code)
+ *code = UINT32_MAX;
+
if ((! client) || (! client->fd) || (! buf)) {
errno = EBADF;
return -1;
}
- if (code)
- *code = UINT32_MAX;
-
while (42) {
ssize_t status;
diff --git a/src/core/data.c b/src/core/data.c
--- /dev/null
+++ b/src/core/data.c
@@ -0,0 +1,133 @@
+/*
+ * SysDB - src/core/data.c
+ * Copyright (C) 2014 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core/data.h"
+
+#include <inttypes.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * public API
+ */
+
+int
+sdb_data_copy(sdb_data_t *dst, const sdb_data_t *src)
+{
+ sdb_data_t tmp;
+
+ if ((! dst) || (! src))
+ return -1;
+
+ tmp = *src;
+ switch (src->type) {
+ case SDB_TYPE_STRING:
+ tmp.data.string = strdup(src->data.string);
+ if (! tmp.data.string)
+ return -1;
+ break;
+ case SDB_TYPE_BINARY:
+ tmp.data.binary.datum = malloc(src->data.binary.length);
+ if (! tmp.data.binary.datum)
+ return -1;
+ memcpy(tmp.data.binary.datum, src->data.binary.datum,
+ src->data.binary.length);
+ break;
+ }
+
+ *dst = tmp;
+ return 0;
+} /* sdb_data_copy */
+
+void
+sdb_data_free_datum(sdb_data_t *datum)
+{
+ if (! datum)
+ return;
+
+ switch (datum->type) {
+ case SDB_TYPE_STRING:
+ if (datum->data.string)
+ free(datum->data.string);
+ datum->data.string = NULL;
+ break;
+ case SDB_TYPE_BINARY:
+ if (datum->data.binary.datum)
+ free(datum->data.binary.datum);
+ datum->data.binary.datum = NULL;
+ datum->data.binary.length = 0;
+ break;
+ }
+} /* sdb_data_free_datum */
+
+int
+sdb_data_format(sdb_data_t *datum, sdb_strbuf_t *buf)
+{
+ if ((! datum) || (! buf))
+ return -1;
+
+ switch (datum->type) {
+ case SDB_TYPE_INTEGER:
+ sdb_strbuf_append(buf, "%"PRIi64, datum->data.integer);
+ break;
+ case SDB_TYPE_DECIMAL:
+ sdb_strbuf_append(buf, "%a", datum->data.decimal);
+ break;
+ case SDB_TYPE_STRING:
+ /* TODO: escape special characters */
+ sdb_strbuf_append(buf, "\"%s\"", datum->data.string);
+ break;
+ case SDB_TYPE_DATETIME:
+ {
+ char tmp[64];
+ if (! sdb_strftime(tmp, sizeof(tmp), "%F %T %z",
+ datum->data.datetime))
+ return -1;
+ tmp[sizeof(tmp) - 1] = '\0';
+ sdb_strbuf_append(buf, "%s", tmp);
+ }
+ break;
+ case SDB_TYPE_BINARY:
+ {
+ size_t i;
+ /* TODO: improve this! */
+ sdb_strbuf_append(buf, "%s", "\"");
+ for (i = 0; i < datum->data.binary.length; ++i)
+ sdb_strbuf_append(buf, "\\%x",
+ (int)datum->data.binary.datum[i]);
+ sdb_strbuf_append(buf, "%s", "\"");
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+} /* sdb_data_format */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+
diff --git a/src/core/store.c b/src/core/store.c
index e8d14a079679a12d5a76ef58735b44920065755d..2522233112a8d125024d9853710ff90565f768d4 100644 (file)
--- a/src/core/store.c
+++ b/src/core/store.c
typedef struct {
sdb_store_base_t super;
- char *value;
+ sdb_data_t value;
} sdb_attribute_t;
#define SDB_ATTR(obj) ((sdb_attribute_t *)(obj))
#define SDB_CONST_ATTR(obj) ((const sdb_attribute_t *)(obj))
static int
sdb_attr_init(sdb_object_t *obj, va_list ap)
{
- const char *value;
+ const sdb_data_t *value;
int ret;
- /* this will consume the first argument (type) of ap */
+ /* this will consume the first two arguments
+ * (type and last_update) of ap */
ret = store_base_init(obj, ap);
if (ret)
return ret;
- value = va_arg(ap, const char *);
+ value = va_arg(ap, const sdb_data_t *);
- if (value) {
- SDB_ATTR(obj)->value = strdup(value);
- if (! SDB_ATTR(obj)->value)
+ if (value)
+ if (sdb_data_copy(&SDB_ATTR(obj)->value, value))
return -1;
- }
return 0;
} /* sdb_attr_init */
assert(obj);
store_base_destroy(obj);
-
- if (SDB_ATTR(obj)->value)
- free(SDB_ATTR(obj)->value);
+ sdb_data_free_datum(&SDB_ATTR(obj)->value);
} /* sdb_attr_destroy */
static sdb_type_t sdb_store_obj_type = {
sdb_strbuf_append(buf, "{\"name\": \"%s\", ", SDB_OBJ(sobj)->name);
if (type == SDB_ATTRIBUTE)
+ /* XXX: this needs to be type-dependent */
sdb_strbuf_append(buf, "\"value\": \"%s\", ",
- SDB_ATTR(sobj)->value);
+ SDB_ATTR(sobj)->value.data.string);
sdb_strbuf_append(buf, "\"last_update\": \"%s\"}", time_str);
if (sdb_llist_iter_has_next(iter))
} /* sdb_store_get_host */
int
-sdb_store_attribute(const char *hostname, const char *key, const char *value,
+sdb_store_attribute(const char *hostname,
+ const char *key, const sdb_data_t *value,
sdb_time_t last_update)
{
int status;
if (status >= 0) {
assert(updated_attr);
- SDB_ATTR(updated_attr)->value = strdup(value);
- if (! SDB_ATTR(updated_attr)->value) {
+ if (sdb_data_copy(&SDB_ATTR(updated_attr)->value, value)) {
sdb_object_deref(SDB_OBJ(updated_attr));
status = -1;
}
index 4a4dd2d3385e5f2fbf9e17fbd39cf0e2161772b4..58e92cde59583dd7b114b163304223ecdb2f5d9c 100644 (file)
--- a/src/include/core/data.h
+++ b/src/include/core/data.h
#define SDB_CORE_DATA_H 1
#include "core/time.h"
+#include "utils/strbuf.h"
#include <inttypes.h>
#include <stddef.h>
/*
* sdb_data_t:
* A datum retrieved from an arbitrary data source.
- *
- * The string and binary objects are managed by whoever creates the data
- * object, thus, they must not be freed or modified. If you want to keep them,
- * make sure to make a copy.
*/
typedef struct {
int type;
union {
int64_t integer; /* SDB_TYPE_INTEGER */
double decimal; /* SDB_TYPE_DECIMAL */
- const char *string; /* SDB_TYPE_STRING */
+ char *string; /* SDB_TYPE_STRING */
sdb_time_t datetime; /* SDB_TYPE_DATETIME */
struct {
size_t length;
- const unsigned char *datum;
+ unsigned char *datum;
} binary; /* SDB_TYPE_BINARY */
} data;
} sdb_data_t;
+/*
+ * sdb_data_copy:
+ * Copy the datum stored in 'src' to the memory location pointed to by 'dst'.
+ * Any dynamic data (strings, binary data) is copied to newly allocated
+ * memory. Use, for example, sdb_data_free_datum() to free any dynamic memory
+ * stored in a datum.
+ *
+ * Returns:
+ * - 0 on success
+ * - a negative value else
+ */
+int
+sdb_data_copy(sdb_data_t *dst, const sdb_data_t *src);
+
+/*
+ * sdb_data_free_datum:
+ * Free any dynamic memory referenced by the specified datum. Does not free
+ * the memory allocated for the sdb_data_t object itself. This function must
+ * not be used if any static or stack memory is referenced from the data
+ * object.
+ */
+void
+sdb_data_free_datum(sdb_data_t *datum);
+
+/*
+ * sdb_data_format:
+ * Append the specified datum to the specified string buffer using a default
+ * format.
+ *
+ * Returns:
+ * - 0 on success
+ * - a negative value else
+ */
+int
+sdb_data_format(sdb_data_t *datum, sdb_strbuf_t *buf);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
index ab11a21776a193a460da5e3a8e100b4d1f25cff7..100aadf260700bdbb0c77f59c16cfedd0ca50048 100644 (file)
--- a/src/include/core/store.h
+++ b/src/include/core/store.h
#include "sysdb.h"
#include "core/object.h"
+#include "core/data.h"
#include "core/time.h"
#include "utils/llist.h"
#include "utils/strbuf.h"
* - a negative value on error
*/
int
-sdb_store_attribute(const char *hostname, const char *key, const char *value,
+sdb_store_attribute(const char *hostname,
+ const char *key, const sdb_data_t *value,
sdb_time_t last_update);
/*
index 30e6419e334d1b105749db8861826f2adf5f2883..f948d3aed65a5c18c78565819bdfac522b1cbe37 100644 (file)
#include "tools/sysdb/input.h"
#include "frontend/proto.h"
+#include "utils/error.h"
#include "utils/strbuf.h"
+#include <errno.h>
+
#include <assert.h>
#include <ctype.h>
#include <string.h>
if (query_len) {
sdb_strbuf_t *recv_buf;
+ const char *result;
uint32_t rcode = 0;
recv_buf = sdb_strbuf_create(1024);
if (rcode == UINT32_MAX)
printf("ERROR: ");
- printf("%s\n", sdb_strbuf_string(recv_buf));
+ result = sdb_strbuf_string(recv_buf);
+ if (result && *result)
+ printf("%s\n", result);
+ else if (rcode == UINT32_MAX) {
+ char errbuf[1024];
+ printf("%s\n", sdb_strerror(errno, errbuf, sizeof(errbuf)));
+ }
sdb_strbuf_destroy(recv_buf);
}
diff --git a/src/utils/dbi.c b/src/utils/dbi.c
index 1de2f1abe678b74dae092b4b51b40a888b68ceb0..a30f548db2c6661242970d5db6c639b93aa480c8 100644 (file)
--- a/src/utils/dbi.c
+++ b/src/utils/dbi.c
data->data.decimal = dbi_result_get_double_idx(res, i);
break;
case SDB_TYPE_STRING:
- data->data.string = dbi_result_get_string_idx(res, i);
+ data->data.string = dbi_result_get_string_copy_idx(res, i);
break;
case SDB_TYPE_DATETIME:
{
case SDB_TYPE_BINARY:
{
size_t length = dbi_result_get_field_length_idx(res, i);
- const unsigned char *datum = dbi_result_get_binary_idx(res, i);
+ unsigned char *datum = dbi_result_get_binary_copy_idx(res, i);
data->data.binary.length = length;
data->data.binary.datum = datum;
}
return -1;
for (n = 0; n < num_rows; ++n) {
+ int status;
+
if (! dbi_result_seek_row(res, n + 1)) {
sdb_log(SDB_LOG_ERR, "dbi: Failed to retrieve row %llu: %s",
n, sdb_dbi_strerror(client->conn));
types[i], &data[i]))
continue;
- if (callback(client, num_fields, data, user_data))
+ status = callback(client, num_fields, data, user_data);
+ for (i = 0; i < num_fields; ++i)
+ sdb_data_free_datum(&data[i]);
+
+ if (status)
continue;
++success;
diff --git a/src/utils/unixsock.c b/src/utils/unixsock.c
index 62b6f45aa404f360ed1f623c07362dcb2c2e26b0..9a5c3fab8c91de6c510a99d8740e4ae2301e0a01 100644 (file)
--- a/src/utils/unixsock.c
+++ b/src/utils/unixsock.c
case SDB_TYPE_BINARY:
/* we don't support any binary information containing 0-bytes */
data->data.binary.length = strlen(string);
- data->data.binary.datum = (const unsigned char *)string;
+ data->data.binary.datum = (unsigned char *)string;
break;
default:
sdb_log(SDB_LOG_ERR, "unixsock: Unexpected type %i while "
diff --git a/t/Makefile.am b/t/Makefile.am
index 6adf484bf9ab8acca0761c7a93c8a7ea5f35a095..3c13ad556b78c35b04b3907f223106dd0925e69e 100644 (file)
--- a/t/Makefile.am
+++ b/t/Makefile.am
libsysdb_test_SOURCES = \
libsysdb_test.c libsysdb_test.h \
+ core/data_test.c \
core/object_test.c \
core/store_test.c \
frontend/parser_test.c \
diff --git a/t/core/data_test.c b/t/core/data_test.c
--- /dev/null
+++ b/t/core/data_test.c
@@ -0,0 +1,200 @@
+/*
+ * SysDB - t/core/data_test.c
+ * Copyright (C) 2014 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core/data.h"
+#include "libsysdb_test.h"
+
+#include <check.h>
+
+START_TEST(test_data)
+{
+ sdb_data_t d1, d2;
+ int check;
+
+ d2.type = SDB_TYPE_INTEGER;
+ d2.data.integer = 4711;
+ check = sdb_data_copy(&d1, &d2);
+ fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
+ fail_unless(d1.type == d2.type,
+ "sdb_data_copy() didn't copy type; got: %i; expected: %i",
+ d1.type, d2.type);
+ fail_unless(d1.data.integer == d2.data.integer,
+ "sdb_data_copy() didn't copy integer data: got: %d; expected: %d",
+ d1.data.integer, d2.data.integer);
+
+ d2.type = SDB_TYPE_DECIMAL;
+ d2.data.decimal = 47.11;
+ check = sdb_data_copy(&d1, &d2);
+ fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
+ fail_unless(d1.type == d2.type,
+ "sdb_data_copy() didn't copy type; got: %i; expected: %i",
+ d1.type, d2.type);
+ fail_unless(d1.data.decimal == d2.data.decimal,
+ "sdb_data_copy() didn't copy decimal data: got: %f; expected: %f",
+ d1.data.decimal, d2.data.decimal);
+
+ d2.type = SDB_TYPE_STRING;
+ d2.data.string = "some string";
+ check = sdb_data_copy(&d1, &d2);
+ fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
+ fail_unless(d1.type == d2.type,
+ "sdb_data_copy() didn't copy type; got: %i; expected: %i",
+ d1.type, d2.type);
+ fail_unless(!strcmp(d1.data.string, d2.data.string),
+ "sdb_data_copy() didn't copy string data: got: %s; expected: %s",
+ d1.data.string, d2.data.string);
+
+ sdb_data_free_datum(&d1);
+ fail_unless(d1.data.string == NULL,
+ "sdb_data_free_datum() didn't free string data");
+
+ d2.type = SDB_TYPE_DATETIME;
+ d2.data.datetime = 4711;
+ check = sdb_data_copy(&d1, &d2);
+ fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
+ fail_unless(d1.type == d2.type,
+ "sdb_data_copy() didn't copy type; got: %i; expected: %i",
+ d1.type, d2.type);
+ fail_unless(d1.data.datetime == d2.data.datetime,
+ "sdb_data_copy() didn't copy datetime data: got: %d; expected: %d",
+ d1.data.datetime, d2.data.datetime);
+
+ d2.type = SDB_TYPE_BINARY;
+ d2.data.binary.datum = (unsigned char *)"some string";
+ d2.data.binary.length = strlen((const char *)d2.data.binary.datum);
+ check = sdb_data_copy(&d1, &d2);
+ fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
+ fail_unless(d1.type == d2.type,
+ "sdb_data_copy() didn't copy type; got: %i; expected: %i",
+ d1.type, d2.type);
+ fail_unless(d1.data.binary.length == d2.data.binary.length,
+ "sdb_data_copy() didn't copy length; got: %d; expected: 5d",
+ d1.data.binary.length, d2.data.binary.length);
+ fail_unless(!memcmp(d1.data.binary.datum, d2.data.binary.datum,
+ d2.data.binary.length),
+ "sdb_data_copy() didn't copy binary data: got: %s; expected: %s",
+ d1.data.string, d2.data.string);
+
+ sdb_data_free_datum(&d1);
+ fail_unless(d1.data.binary.length == 0,
+ "sdb_data_free_datum() didn't reset binary datum length");
+ fail_unless(d1.data.binary.datum == NULL,
+ "sdb_data_free_datum() didn't free binary datum");
+}
+END_TEST
+
+START_TEST(test_format)
+{
+ sdb_data_t datum;
+ sdb_strbuf_t *buf;
+ const char *string;
+ const char *expected;
+
+ int check;
+
+ buf = sdb_strbuf_create(1024);
+ fail_unless(buf != NULL,
+ "INTERNAL ERROR: Failed to allocate string buffer");
+
+ datum.type = SDB_TYPE_INTEGER;
+ datum.data.integer = 4711;
+ check = sdb_data_format(&datum, buf);
+ fail_unless(! check,
+ "sdb_data_format(INTEGER) = %d; expected: 0", check);
+ string = sdb_strbuf_string(buf);
+ expected = "4711";
+ fail_unless(! strcmp(string, expected),
+ "sdb_data_format() used wrong format: %s; expected: %s",
+ string, expected);
+
+ datum.type = SDB_TYPE_DECIMAL;
+ datum.data.decimal = 65536.0;
+ sdb_strbuf_clear(buf);
+ check = sdb_data_format(&datum, buf);
+ fail_unless(! check,
+ "sdb_data_format(DECIMAL) = %d; expected: 0", check);
+ string = sdb_strbuf_string(buf);
+ expected = "0x1p+16";
+ fail_unless(! strcmp(string, expected),
+ "sdb_data_format() used wrong format: %s; expected: %s",
+ string, expected);
+
+ datum.type = SDB_TYPE_STRING;
+ datum.data.string = "this is a test";
+ sdb_strbuf_clear(buf);
+ check = sdb_data_format(&datum, buf);
+ fail_unless(! check,
+ "sdb_data_format(STRING) = %d; expected: 0", check);
+ string = sdb_strbuf_string(buf);
+ expected = "\"this is a test\"";
+ fail_unless(! strcmp(string, expected),
+ "sdb_data_format() used wrong format: %s; expected: %s",
+ string, expected);
+
+ datum.type = SDB_TYPE_DATETIME;
+ datum.data.datetime = 471147114711471100;
+ sdb_strbuf_clear(buf);
+ check = sdb_data_format(&datum, buf);
+ fail_unless(! check,
+ "sdb_data_format(DATETIME) = %d; expected: 0", check);
+ string = sdb_strbuf_string(buf);
+ expected = "1984-12-06 02:11:54 +0000";
+ fail_unless(! strcmp(string, expected),
+ "sdb_data_format() used wrong format: %s; expected: %s",
+ string, expected);
+
+ datum.type = SDB_TYPE_BINARY;
+ datum.data.binary.datum = (unsigned char *)"binary\0crap\x42";
+ datum.data.binary.length = 12;
+ sdb_strbuf_clear(buf);
+ check = sdb_data_format(&datum, buf);
+ fail_unless(! check,
+ "sdb_data_format(BINARY) = %d; expected: 0", check);
+ string = sdb_strbuf_string(buf);
+ expected = "\"\\62\\69\\6e\\61\\72\\79\\0\\63\\72\\61\\70\\42\"";
+ fail_unless(! strcmp(string, expected),
+ "sdb_data_format() used wrong format: %s; expected: %s",
+ string, expected);
+}
+END_TEST
+
+Suite *
+core_data_suite(void)
+{
+ Suite *s = suite_create("core::data");
+ TCase *tc;
+
+ tc = tcase_create("core");
+ tcase_add_test(tc, test_data);
+ tcase_add_test(tc, test_format);
+ suite_add_tcase(s, tc);
+
+ return s;
+} /* core_data_suite */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+
diff --git a/t/core/store_test.c b/t/core/store_test.c
index effd05a7d5d8425f89b5f8db7d9f6d818b490940..855c8c09e857b4b821e022bda2ec5f23d525856f 100644 (file)
--- a/t/core/store_test.c
+++ b/t/core/store_test.c
struct {
const char *host;
const char *key;
- const char *value;
+ char *value;
sdb_time_t last_update;
int expected;
} golden_data[] = {
sdb_store_host("l", 1);
sdb_store_host("m", 1);
for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
+ sdb_data_t datum;
int status;
+ /* XXX: test other types as well */
+ datum.type = SDB_TYPE_STRING;
+ datum.data.string = golden_data[i].value;
+
status = sdb_store_attribute(golden_data[i].host,
- golden_data[i].key, golden_data[i].value,
+ golden_data[i].key, &datum,
golden_data[i].last_update);
fail_unless(status == golden_data[i].expected,
"sdb_store_attribute(%s, %s, %s, %d) = %d; expected: %d",
START_TEST(test_store_tojson)
{
sdb_strbuf_t *buf;
+ sdb_data_t datum;
size_t i;
struct {
sdb_store_host("h1", 1);
sdb_store_host("h2", 1);
- sdb_store_attribute("h1", "k1", "v1", 1);
- sdb_store_attribute("h1", "k2", "v2", 1);
- sdb_store_attribute("h1", "k3", "v3", 1);
+ datum.type = SDB_TYPE_STRING;
+ datum.data.string = "v1";
+ sdb_store_attribute("h1", "k1", &datum, 1);
+ datum.data.string = "v2";
+ sdb_store_attribute("h1", "k2", &datum, 1);
+ datum.data.string = "v3";
+ sdb_store_attribute("h1", "k3", &datum, 1);
sdb_store_service("h2", "s1", 1);
sdb_store_service("h2", "s2", 1);
diff --git a/t/libsysdb_test.c b/t/libsysdb_test.c
index 2fa83dc6af7f4dcbd758e19459cc8b37e37a7cde..c7787e4466bfc5fee7ec4e9869e7f42ddefe934e 100644 (file)
--- a/t/libsysdb_test.c
+++ b/t/libsysdb_test.c
size_t i;
suite_creator_t creators[] = {
+ { core_data_suite, NULL },
{ core_object_suite, NULL },
{ core_store_suite, NULL },
{ fe_parser_suite, NULL },
diff --git a/t/libsysdb_test.h b/t/libsysdb_test.h
index 64558cdadebfb2861f3c6f0fb459d7307c28eb65..5539d63290e54a258350c05a6846819820ae27d7 100644 (file)
--- a/t/libsysdb_test.h
+++ b/t/libsysdb_test.h
* test suites
*/
+/* t/core/data_test */
+Suite *
+core_data_suite(void);
+
/* t/core/object_test */
Suite *
core_object_suite(void);
diff --git a/t/utils/dbi_test.c b/t/utils/dbi_test.c
index 10447e9962980108c1aa430ad27253f0d2d381f2..c54ea3164dec8b965bb16a4d64368bbac6b3b694 100644 (file)
--- a/t/utils/dbi_test.c
+++ b/t/utils/dbi_test.c
return get_golden_data(res, i).string;
} /* dbi_result_get_string_idx */
+char *
+dbi_result_get_string_copy_idx(dbi_result res, unsigned int i)
+{
+ fail_unless(current_query->field_types[i - 1] == DBI_TYPE_STRING,
+ "dbi_result_get_string_copy_idx() called for non-string "
+ "column type %u", current_query->field_types[i - 1]);
+ if (! get_golden_data(res, i).string)
+ return NULL;
+ return strdup(get_golden_data(res, i).string);
+} /* dbi_result_get_string_copy_idx */
+
time_t
dbi_result_get_datetime_idx(dbi_result res, unsigned int i)
{
return get_golden_data(res, i).binary.datum;
} /* dbi_result_get_binary_idx */
+unsigned char *
+dbi_result_get_binary_copy_idx(dbi_result res, unsigned int i)
+{
+ const char *data;
+ fail_unless(current_query->field_types[i - 1] == DBI_TYPE_BINARY,
+ "dbi_result_get_binary_copy_idx() called for non-binary "
+ "column type %u", current_query->field_types[i - 1]);
+ data = (const char *)get_golden_data(res, i).binary.datum;
+ if (! data)
+ return NULL;
+ return (unsigned char *)strdup(data);
+} /* dbi_result_get_binary_copy_idx */
+
static unsigned long long dbi_result_free_called = 0;
int
dbi_result_free(dbi_result res)
data[i].data.decimal, i, expected_data.decimal);
break;
case SDB_TYPE_STRING:
- fail_unless(data[i].data.string == expected_data.string,
+ fail_unless(!strcmp(data[i].data.string, expected_data.string),
"query callback received unexpected data %s "
"for column %zu; expected: %s",
data[i].data.string, i, expected_data.string);
"binary data length %zu for column %zu; "
"expected: %lli", data[i].data.binary.length, i,
expected_data.binary.length);
- fail_unless(data[i].data.binary.datum ==
+ fail_unless(!memcmp(data[i].data.binary.datum,
expected_data.binary.datum,
+ expected_data.binary.length),
"query callback received unexpected binary data %p "
"for column %zu; expected: %p",
data[i].data.binary.datum, i,