summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGergely Nagy <algernon@balabit.hu>2012-04-13 14:13:35 +0200
committerGergely Nagy <algernon@balabit.hu>2012-04-13 14:13:35 +0200
commit61ddecc3147ac6f2438995f215211fa84f7962a9 (patch)
tree7bf74c471917499252bae54abe128222fae3981f
parent63fcf21f9a9f616880dfb9c7174b8694423a7f75 (diff)
parent0b6974a24a5b199903d67aab08ae5e2cf4037a97 (diff)
downloadlibumberlog-61ddecc3147ac6f2438995f215211fa84f7962a9.tar.gz
libumberlog-61ddecc3147ac6f2438995f215211fa84f7962a9.tar.xz
libumberlog-61ddecc3147ac6f2438995f215211fa84f7962a9.zip
Merge branch 'feature/libc-only'
-rw-r--r--NEWS16
-rw-r--r--README.rst6
-rw-r--r--TODO.org9
-rw-r--r--configure.ac11
-rw-r--r--lib/Makefile.am4
-rw-r--r--lib/buffer.c220
-rw-r--r--lib/buffer.h48
-rw-r--r--lib/umberlog.c130
-rw-r--r--t/Makefile.am2
-rw-r--r--t/test_umberlog.c30
10 files changed, 389 insertions, 87 deletions
diff --git a/NEWS b/NEWS
index 149d550..607bb6f 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,21 @@
#+STARTUP: indent showall -*- org -*-
+* 0.2.0
+
+** Remove the json-c dependency
+
+The library used very little from the features of json-c, as all we
+did was append key-value pairs, where both key and value were always
+strings. No nesting, no other funky stuff. It's easier to do this
+directly, without having to build a separate object and then serialize
+it into a string.
+
+For this reason, the json-c dependency was removed, and the library
+does the JSON formatting itself. However, json-c is still required for
+the test suite, but not otherwise.
+
+The result is a more compact JSON, and noticably increased speed.
+
* 0.1.2 - <2012-04-08 Sun>
** Portability fixes
diff --git a/README.rst b/README.rst
index 5d30d59..3147295 100644
--- a/README.rst
+++ b/README.rst
@@ -54,9 +54,9 @@ SSH Login::
Requirements
------------
-Apart from the autotools, a C compiler, and `json\-c`_, there are no
-other hard dependencies when building, except for a sufficiently
-modern system.
+Apart from the autotools, a C compiler, and `json\-c`_ (for the test
+suite), there are no other hard dependencies when building, except for
+a sufficiently modern system.
.. _json\-c: http://oss.metaparadigm.com/json-c/
diff --git a/TODO.org b/TODO.org
index fb4451b..10c9b30 100644
--- a/TODO.org
+++ b/TODO.org
@@ -97,7 +97,14 @@ systems where we would need to copy the thing around.
We need a way to get the post-message key-value pairs some other way,
or with using va_copy() and counting format strings and whatnot.
-* TODO Remove json-c dependency
+* DONE Remove json-c dependency
+CLOSED: [2012-04-13 Fri 13:10]
+- CLOSING NOTE [2012-04-13 Fri 13:10] \\
+ Implemented proper escaping too, and added a test case to verify the behaviour.
+- Note taken on [2012-04-13 Fri 12:09] \\
+ Work in progress: the buffer handling was moved to buffer.c, it does
+ the heavy lifting and JSON formatting. It does not do escaping yet,
+ however.
We use very little of json-c, all we do is append key-value pairs,
where both keys and values are always strings. We pretty much only use
json-c to escape these for us, if so need be.
diff --git a/configure.ac b/configure.ac
index 9177a15..4717dd4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -35,11 +35,11 @@ AC_HEADER_STDC
dnl ***************************************************************************
dnl Header checks
dnl ***************************************************************************
-AC_CHECK_HEADERS([syslog.h dlfcn.h limits.h])
+AC_CHECK_HEADERS([syslog.h dlfcn.h limits.h wchar.h])
dnl ***************************************************************************
dnl Checks for libraries
-AC_CHECK_FUNCS([gethostname strdup __syslog_chk])
+AC_CHECK_FUNCS([gethostname strdup memset __syslog_chk])
dnl The dlopen() function is in the C library for *BSD and in
dnl libdl on GLIBC-based systems
@@ -56,18 +56,23 @@ AC_SEARCH_LIBS([clock_gettime], [rt], [], [
dnl ***************************************************************************
dnl JSON-C headers/libraries
dnl ***************************************************************************
-PKG_CHECK_MODULES(JSON, json >= $JSON_C_MIN_VERSION,,)
+PKG_CHECK_MODULES(JSON, json >= $JSON_C_MIN_VERSION,[enable_tests="1"],[enable_tests="0"])
dnl ***************************************************************************
dnl misc features to be enabled
dnl ***************************************************************************
AC_C_INLINE
+AC_FUNC_MALLOC
+AC_FUNC_REALLOC
AC_TYPE_PID_T
AC_TYPE_UID_T
+AC_TYPE_SIZE_T
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [package name])
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [version number])
+AM_CONDITIONAL(ENABLE_TESTS, [test "$enable_tests" = "1"])
+
AC_OUTPUT(
Makefile
data/Makefile
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 5c64fb6..672ebf6 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -4,10 +4,8 @@ LUL_AGE = 0
lib_LTLIBRARIES = libumberlog.la
libumberlog_la_LDFLAGS = -Wl,--version-script,${srcdir}/libumberlog.ld
-libumberlog_la_LIBADD = @JSON_LIBS@
-libumberlog_la_CFLAGS = @JSON_CFLAGS@
-libumberlog_la_SOURCES = umberlog.c umberlog.h
+libumberlog_la_SOURCES = umberlog.c umberlog.h buffer.c buffer.h
libumberlog_includedir = $(includedir)
libumberlog_include_HEADERS = umberlog.h
diff --git a/lib/buffer.c b/lib/buffer.c
new file mode 100644
index 0000000..4c6f0b7
--- /dev/null
+++ b/lib/buffer.c
@@ -0,0 +1,220 @@
+/* buffer.c -- Auto-growing string buffers
+ *
+ * Copyright (c) 2012 BalaBit IT Security Ltd.
+ * 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 BALABIT 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 BALABIT 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.
+ */
+
+#define _GNU_SOURCE 1
+
+#include "config.h"
+#include "buffer.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+static const unsigned char json_exceptions[] =
+ {
+ 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
+ 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e,
+ 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e,
+ 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
+ 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae,
+ 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe,
+ 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6,
+ 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce,
+ 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
+ 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde,
+ 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
+ 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee,
+ 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
+ 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe,
+ 0xff, '\0'
+ };
+
+static inline char *
+_ul_str_escape (const char *str)
+{
+ const unsigned char *p;
+ char *dest;
+ char *q;
+ static unsigned char exmap[256];
+ static int exmap_inited;
+
+ if (!str)
+ return NULL;
+
+ p = (unsigned char *)str;
+ q = dest = malloc (strlen (str) * 6 + 1);
+
+ if (!exmap_inited)
+ {
+ const unsigned char *e = json_exceptions;
+
+ memset (exmap, 0, 256);
+ while (*e)
+ {
+ exmap[*e] = 1;
+ e++;
+ }
+ exmap_inited = 1;
+ }
+
+ while (*p)
+ {
+ if (exmap[*p])
+ *q++ = *p;
+ else
+ {
+ switch (*p)
+ {
+ case '\b':
+ *q++ = '\\';
+ *q++ = 'b';
+ break;
+ case '\f':
+ *q++ = '\\';
+ *q++ = 'f';
+ break;
+ case '\n':
+ *q++ = '\\';
+ *q++ = 'n';
+ break;
+ case '\r':
+ *q++ = '\\';
+ *q++ = 'r';
+ break;
+ case '\t':
+ *q++ = '\\';
+ *q++ = 't';
+ break;
+ case '\\':
+ *q++ = '\\';
+ *q++ = '\\';
+ break;
+ case '"':
+ *q++ = '\\';
+ *q++ = '"';
+ break;
+ default:
+ if ((*p < ' ') || (*p >= 0177))
+ {
+ const char *json_hex_chars = "0123456789abcdef";
+
+ *q++ = '\\';
+ *q++ = 'u';
+ *q++ = '0';
+ *q++ = '0';
+ *q++ = json_hex_chars[(*p) >> 4];
+ *q++ = json_hex_chars[(*p) & 0xf];
+ }
+ else
+ *q++ = *p;
+ break;
+ }
+ }
+ p++;
+ }
+
+ *q = 0;
+ return dest;
+}
+
+static inline ul_buffer_t *
+_ul_buffer_ensure_size (ul_buffer_t *buffer, size_t size)
+{
+ if (buffer->alloc < size)
+ {
+ buffer->alloc += size * 2;
+ buffer->msg = realloc (buffer->msg, buffer->alloc);
+ if (!buffer->msg)
+ return NULL;
+ }
+ return buffer;
+}
+
+ul_buffer_t *
+ul_buffer_reset (ul_buffer_t *buffer)
+{
+ buffer->len = 1;
+ _ul_buffer_ensure_size (buffer, 512);
+ buffer->msg[0] = '{';
+ return buffer;
+}
+
+ul_buffer_t *
+ul_buffer_append (ul_buffer_t *buffer, const char *key, const char *value)
+{
+ char *k, *v;
+ size_t lk, lv;
+
+ k = _ul_str_escape (key);
+ if (!k)
+ return NULL;
+ v = _ul_str_escape (value);
+ if (!v)
+ {
+ free (k);
+ return NULL;
+ }
+
+ lk = strlen (k);
+ lv = strlen (v);
+
+ buffer = _ul_buffer_ensure_size (buffer, buffer->len + lk + lv + 6);
+ if (!buffer)
+ {
+ free (k);
+ free (v);
+ return NULL;
+ }
+
+ memcpy (buffer->msg + buffer->len, "\"", 1);
+ memcpy (buffer->msg + buffer->len + 1, k, lk);
+ memcpy (buffer->msg + buffer->len + 1 + lk, "\":\"", 3);
+ memcpy (buffer->msg + buffer->len + 1 + lk + 3, v, lv);
+ memcpy (buffer->msg + buffer->len + 1 + lk + 3 + lv, "\",", 2);
+ buffer->len += lk + lv + 6;
+
+ free (k);
+ free (v);
+
+ return buffer;
+}
+
+char *
+ul_buffer_finalize (ul_buffer_t *buffer)
+{
+ if (buffer->msg[buffer->len - 1] == ',')
+ buffer->msg[buffer->len - 1] = '}';
+ else
+ {
+ if (!_ul_buffer_ensure_size (buffer, buffer->len + 1))
+ return NULL;
+ buffer->msg[buffer->len++] = '}';
+ buffer->msg[buffer->len] = '\0';
+ }
+ return buffer->msg;
+}
diff --git a/lib/buffer.h b/lib/buffer.h
new file mode 100644
index 0000000..0d412e8
--- /dev/null
+++ b/lib/buffer.h
@@ -0,0 +1,48 @@
+/* buffer.h -- Auto-growing string buffers
+ *
+ * Copyright (c) 2012 BalaBit IT Security Ltd.
+ * 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 BALABIT 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 BALABIT 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.
+ */
+
+#ifndef UMBERLOG_BUFFER_H
+#define UMBERLOG_BUFFER_H 1
+
+#include <stdlib.h>
+
+typedef struct
+{
+ size_t alloc;
+ size_t len;
+ char *msg;
+} ul_buffer_t;
+
+ul_buffer_t *ul_buffer_reset (ul_buffer_t *buffer)
+ __attribute__((visibility("hidden")));
+ul_buffer_t *ul_buffer_append (ul_buffer_t *buffer,
+ const char *key, const char *value)
+ __attribute__((visibility("hidden")));
+char *ul_buffer_finalize (ul_buffer_t *buffer)
+ __attribute__((visibility("hidden")));
+
+#endif
diff --git a/lib/umberlog.c b/lib/umberlog.c
index 78697c6..fe0a6b7 100644
--- a/lib/umberlog.c
+++ b/lib/umberlog.c
@@ -31,7 +31,6 @@
#include <stdarg.h>
#include <sys/types.h>
#include <unistd.h>
-#include <json.h>
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
@@ -44,6 +43,7 @@
#include "config.h"
#include "umberlog.h"
+#include "buffer.h"
static void (*old_syslog) ();
static void (*old_vsyslog) ();
@@ -65,6 +65,7 @@ static __thread struct
char hostname[_POSIX_HOST_NAME_MAX + 1];
} ul_sys_settings;
+static __thread ul_buffer_t ul_buffer;
static __thread int ul_recurse;
static void
@@ -231,8 +232,8 @@ _get_hostname (void)
} \
}
-static inline struct json_object *
-_ul_json_vappend (struct json_object *json, va_list ap)
+static inline ul_buffer_t *
+_ul_json_vappend (ul_buffer_t *buffer, va_list ap)
{
char *key;
@@ -240,7 +241,6 @@ _ul_json_vappend (struct json_object *json, va_list ap)
{
char *fmt = (char *)va_arg (ap, char *);
char *value = NULL;
- struct json_object *jstr;
va_list aq;
va_copy (aq, ap);
@@ -254,36 +254,36 @@ _ul_json_vappend (struct json_object *json, va_list ap)
if (!value)
return NULL;
- jstr = json_object_new_string (value);
- if (!jstr)
+ buffer = ul_buffer_append (buffer, key, value);
+
+ if (buffer == NULL)
{
free (value);
return NULL;
}
- json_object_object_add (json, key, jstr);
free (value);
_ul_va_spin (fmt, ap);
}
- return json;
+ return buffer;
}
-static inline struct json_object *
-_ul_json_append (struct json_object *json, ...)
+static inline ul_buffer_t *
+_ul_json_append (ul_buffer_t *buffer, ...)
{
va_list ap;
- va_start (ap, json);
- json = _ul_json_vappend (json, ap);
+ va_start (ap, buffer);
+ buffer = _ul_json_vappend (buffer, ap);
va_end (ap);
- return json;
+ return buffer;
}
-static inline struct json_object *
-_ul_json_append_timestamp (struct json_object *jo)
+static inline ul_buffer_t *
+_ul_json_append_timestamp (ul_buffer_t *buffer)
{
struct timespec ts;
struct tm *tm;
@@ -296,40 +296,39 @@ _ul_json_append_timestamp (struct json_object *jo)
strftime (stamp, sizeof (stamp), "%FT%T", tm);
strftime (zone, sizeof (zone), "%z", tm);
- return _ul_json_append (jo, "timestamp", "%s.%lu%s",
+ return _ul_json_append (buffer, "timestamp", "%s.%lu%s",
stamp, ts.tv_nsec, zone,
NULL);
}
-static inline struct json_object *
-_ul_discover (struct json_object *jo, int priority)
+static inline ul_buffer_t *
+_ul_discover (ul_buffer_t *buffer, int priority)
{
if (ul_sys_settings.flags & LOG_UL_NODISCOVER)
- return jo;
-
- jo = _ul_json_append (jo,
- "pid", "%d", _find_pid (),
- "facility", "%s", _find_facility (),
- "priority", "%s", _find_prio (priority),
- "program", "%s", ul_sys_settings.ident,
- "uid", "%d", _get_uid (),
- "gid", "%d", _get_gid (),
- "host", "%s", _get_hostname (),
- NULL);
-
- if (ul_sys_settings.flags & LOG_UL_NOTIME || !jo)
- return jo;
-
- return _ul_json_append_timestamp (jo);
+ return buffer;
+
+ buffer = _ul_json_append (buffer,
+ "pid", "%d", _find_pid (),
+ "facility", "%s", _find_facility (),
+ "priority", "%s", _find_prio (priority),
+ "program", "%s", ul_sys_settings.ident,
+ "uid", "%d", _get_uid (),
+ "gid", "%d", _get_gid (),
+ "host", "%s", _get_hostname (),
+ NULL);
+
+ if (ul_sys_settings.flags & LOG_UL_NOTIME || !buffer)
+ return buffer;
+
+ return _ul_json_append_timestamp (buffer);
}
-static inline struct json_object *
-_ul_vformat (struct json_object *jo, int format_version,
+static inline ul_buffer_t *
+_ul_vformat (ul_buffer_t *buffer, int format_version,
int priority, const char *msg_format,
va_list ap)
{
char *value;
- struct json_object *jstr;
va_list aq;
va_copy (aq, ap);
@@ -342,38 +341,37 @@ _ul_vformat (struct json_object *jo, int format_version,
if (!value)
return NULL;
- jstr = json_object_new_string (value);
- if (!jstr)
+ buffer = ul_buffer_append (buffer, "msg", value);
+ if (buffer == NULL)
{
free (value);
return NULL;
}
- json_object_object_add (jo, "msg", jstr);
free (value);
_ul_va_spin (msg_format, ap);
if (format_version > 0)
- jo = _ul_json_vappend (jo, ap);
+ buffer = _ul_json_vappend (buffer, ap);
- if (!jo)
+ if (!buffer)
return NULL;
- return _ul_discover (jo, priority);
+ return _ul_discover (buffer, priority);
}
static inline const char *
-_ul_vformat_str (struct json_object *jo, int format_version,
+_ul_vformat_str (ul_buffer_t *buffer, int format_version,
int priority, const char *msg_format,
va_list ap)
{
- jo = _ul_vformat (jo, format_version,
- priority, msg_format, ap);
- if (!jo)
+ buffer = _ul_vformat (buffer, format_version,
+ priority, msg_format, ap);
+ if (!buffer)
return NULL;
- return json_object_to_json_string (jo);
+ return ul_buffer_finalize (buffer);
}
/** Public API **/
@@ -393,26 +391,20 @@ ul_format (int priority, const char *msg_format, ...)
char *
ul_vformat (int priority, const char *msg_format, va_list ap)
{
- struct json_object *jo = json_object_new_object ();
char *result;
const char *msg;
+ ul_buffer_t *buffer = &ul_buffer;
- if (!jo)
- {
- errno = ENOMEM;
- return NULL;
- }
+ ul_buffer_reset (buffer);
- msg = _ul_vformat_str (jo, 1, priority, msg_format, ap);
+ msg = _ul_vformat_str (buffer, 1, priority, msg_format, ap);
if (!msg)
{
- json_object_put (jo);
errno = ENOMEM;
return NULL;
}
result = strdup (msg);
- json_object_put (jo);
return result;
}
@@ -420,33 +412,17 @@ static inline int
_ul_vsyslog (int format_version, int priority,
const char *msg_format, va_list ap)
{
- struct json_object *jo;
const char *msg;
+ ul_buffer_t *buffer = &ul_buffer;
if (!(ul_sys_settings.mask & priority))
return 0;
- jo = json_object_new_object ();
- if (!jo)
+ buffer = _ul_vformat (buffer, format_version, priority, msg_format, ap);
+ if (buffer == NULL)
return -1;
- if (_ul_vformat (jo, format_version,
- priority, msg_format, ap) == NULL)
- {
- json_object_put (jo);
- return -1;
- }
-
- msg = json_object_to_json_string (jo);
- if (!msg)
- {
- json_object_put (jo);
- return -1;
- }
-
- old_syslog (priority, "@cee:%s", msg);
-
- json_object_put (jo);
+ old_syslog (priority, "@cee:%s", ul_buffer_finalize (buffer));
return 0;
}
diff --git a/t/Makefile.am b/t/Makefile.am
index c7f1589..b07c6f2 100644
--- a/t/Makefile.am
+++ b/t/Makefile.am
@@ -1,5 +1,7 @@
+if ENABLE_TESTS
TESTS = test_umberlog test_perf
check_PROGRAMS = ${TESTS}
AM_CFLAGS = -I$(top_srcdir)/lib @JSON_CFLAGS@
LDADD = $(top_builddir)/lib/libumberlog.la @JSON_LIBS@
+endif
diff --git a/t/test_umberlog.c b/t/test_umberlog.c
index f20d28b..26fbadb 100644
--- a/t/test_umberlog.c
+++ b/t/test_umberlog.c
@@ -190,6 +190,35 @@ test_no_timestamp (void)
closelog ();
}
+static void
+test_json_escape (void)
+{
+ char *msg;
+ struct json_object *jo;
+
+ openlog ("umberlog/test_json_escape", LOG_UL_NODISCOVER, LOG_LOCAL0);
+
+ msg = ul_format (LOG_DEBUG, "%s", __FUNCTION__,
+ "quotes", "Hi, \"quoted value\" speaking!",
+ "\"really\"", "yeah",
+ "control", "foo\nbar",
+ "utf8", "Árvíztűrő tükörfúrógép",
+ "junk", "\013foo",
+ NULL);
+ jo = parse_msg (msg);
+ free (msg);
+
+ verify_value (jo, "quotes", "Hi, \"quoted value\" speaking!");
+ verify_value (jo, "\"really\"", "yeah");
+ verify_value (jo, "control", "foo\nbar");
+ verify_value (jo, "utf8", "Árvíztűrő tükörfúrógép");
+ verify_value (jo, "junk", "\013foo");
+
+ json_object_put (jo);
+
+ closelog ();
+}
+
int
main (void)
{
@@ -198,6 +227,7 @@ main (void)
test_additional_fields ();
test_discover_priority ();
test_no_timestamp ();
+ test_json_escape ();
return 0;
}