Add `libmsgpack` for serializing captures
authorFrancis Deslauriers <francis.deslauriers@efficios.com>
Fri, 20 Mar 2020 16:12:30 +0000 (12:12 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 26 Nov 2020 18:27:33 +0000 (13:27 -0500)
Signed-off-by: Francis Deslauriers <francis.deslauriers@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Change-Id: Ice8ed791a0452ea9e659ffcaf9e081f47288e8d5

Makefile.am
configure.ac
libmsgpack/Makefile.am [new file with mode: 0644]
libmsgpack/msgpack.c [new file with mode: 0644]
libmsgpack/msgpack.h [new file with mode: 0644]
tests/Makefile.am
tests/unit/Makefile.am
tests/unit/libmsgpack/Makefile.am [new file with mode: 0644]
tests/unit/libmsgpack/test_msgpack.c [new file with mode: 0644]

index cc923c1da4476feeca7ad2fdf62b54c3ac006155..a13c6e319f5030da484c1b379354f378e4c61af7 100644 (file)
@@ -1,6 +1,7 @@
 ACLOCAL_AMFLAGS = -I m4
 
 SUBDIRS = . include snprintf libringbuffer liblttng-ust-comm \
+               libmsgpack \
                liblttng-ust \
                liblttng-ust-ctl \
                liblttng-ust-fd \
index 14f297dea922904a73350d1015c9303d80c272af..032bb731b10268c80cc5d5d4c97e9d0c32e73619 100644 (file)
@@ -504,6 +504,7 @@ AC_CONFIG_FILES([
        include/Makefile
        include/lttng/ust-version.h
        snprintf/Makefile
+       libmsgpack/Makefile
        libringbuffer/Makefile
        liblttng-ust-comm/Makefile
        liblttng-ust/Makefile
@@ -539,6 +540,7 @@ AC_CONFIG_FILES([
        tests/compile/test-app-ctx/Makefile
        tests/benchmark/Makefile
        tests/unit/gcc-weak-hidden/Makefile
+       tests/unit/libmsgpack/Makefile
        tests/unit/Makefile
        tests/unit/libringbuffer/Makefile
        tests/unit/pthread_name/Makefile
diff --git a/libmsgpack/Makefile.am b/libmsgpack/Makefile.am
new file mode 100644 (file)
index 0000000..b157e67
--- /dev/null
@@ -0,0 +1,9 @@
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include
+AM_CFLAGS += -fno-strict-aliasing
+
+noinst_LTLIBRARIES = libmsgpack.la
+
+libmsgpack_la_SOURCES = \
+       msgpack.c msgpack.h
+
+libmsgpack_la_CFLAGS = -DUST_COMPONENT="libmsgpack" $(AM_CFLAGS)
diff --git a/libmsgpack/msgpack.c b/libmsgpack/msgpack.c
new file mode 100644 (file)
index 0000000..0803bc6
--- /dev/null
@@ -0,0 +1,517 @@
+/*
+ * msgpack.c
+ *
+ * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; only
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define _GNU_SOURCE
+#define _LGPL_SOURCE
+#include <stddef.h>
+
+#define MSGPACK_FIXSTR_ID_MASK         0xA0
+#define MSGPACK_FIXMAP_ID_MASK         0x80
+#define MSGPACK_FIXARRAY_ID_MASK       0x90
+
+#define MSGPACK_NIL_ID         0xC0
+#define MSGPACK_FALSE_ID       0xC2
+#define MSGPACK_TRUE_ID                0xC3
+#define MSGPACK_MAP16_ID       0xDE
+#define MSGPACK_ARRAY16_ID     0xDC
+
+#define MSGPACK_UINT8_ID       0xCC
+#define MSGPACK_UINT16_ID      0xCD
+#define MSGPACK_UINT32_ID      0xCE
+#define MSGPACK_UINT64_ID      0xCF
+
+#define MSGPACK_INT8_ID                0xD0
+#define MSGPACK_INT16_ID       0xD1
+#define MSGPACK_INT32_ID       0xD2
+#define MSGPACK_INT64_ID       0xD3
+
+#define MSGPACK_FLOAT64_ID     0xCB
+#define MSGPACK_STR16_ID       0xDA
+
+#define MSGPACK_FIXINT_MAX             ((1 << 7) - 1)
+#define MSGPACK_FIXINT_MIN             -(1 << 5)
+#define MSGPACK_FIXMAP_MAX_COUNT       15
+#define MSGPACK_FIXARRAY_MAX_COUNT     15
+#define MSGPACK_FIXSTR_MAX_LENGTH      31
+
+#ifdef __KERNEL__
+#include <linux/bug.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <lttng/msgpack.h>
+
+#define INT8_MIN               (-128)
+#define INT16_MIN              (-32767-1)
+#define INT32_MIN              (-2147483647-1)
+#define INT8_MAX               (127)
+#define INT16_MAX              (32767)
+#define INT32_MAX              (2147483647)
+#define UINT8_MAX              (255)
+#define UINT16_MAX             (65535)
+#define UINT32_MAX             (4294967295U)
+
+#define byteswap_host_to_be16(_tmp) cpu_to_be16(_tmp)
+#define byteswap_host_to_be32(_tmp) cpu_to_be32(_tmp)
+#define byteswap_host_to_be64(_tmp) cpu_to_be64(_tmp)
+
+#define lttng_msgpack_assert(cond) WARN_ON(!(cond))
+
+#else /* __KERNEL__ */
+
+#include <endian.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "msgpack.h"
+
+#define byteswap_host_to_be16(_tmp) htobe16(_tmp)
+#define byteswap_host_to_be32(_tmp) htobe32(_tmp)
+#define byteswap_host_to_be64(_tmp) htobe64(_tmp)
+
+#define lttng_msgpack_assert(cond) ({ \
+       if (!(cond)) \
+               fprintf(stderr, "Assertion failed. %s:%d\n", __FILE__, __LINE__); \
+       })
+#endif /* __KERNEL__ */
+
+static inline int lttng_msgpack_append_buffer(
+               struct lttng_msgpack_writer *writer,
+               const uint8_t *buf,
+               size_t length)
+{
+       int ret = 0;
+
+       lttng_msgpack_assert(buf);
+
+       /* Ensure we are not trying to write after the end of the buffer. */
+       if (writer->write_pos + length > writer->end_write_pos) {
+               ret = -1;
+               goto end;
+       }
+
+       memcpy(writer->write_pos, buf, length);
+       writer->write_pos += length;
+end:
+       return ret;
+}
+
+static inline int lttng_msgpack_append_u8(
+               struct lttng_msgpack_writer *writer, uint8_t value)
+{
+       return lttng_msgpack_append_buffer(writer, &value, sizeof(value));
+}
+
+static inline int lttng_msgpack_append_u16(
+               struct lttng_msgpack_writer *writer, uint16_t value)
+{
+       value = byteswap_host_to_be16(value);
+
+       return lttng_msgpack_append_buffer(writer, (uint8_t *) &value, sizeof(value));
+}
+
+static inline int lttng_msgpack_append_u32(
+               struct lttng_msgpack_writer *writer, uint32_t value)
+{
+       value = byteswap_host_to_be32(value);
+
+       return lttng_msgpack_append_buffer(writer, (uint8_t *) &value, sizeof(value));
+}
+
+static inline int lttng_msgpack_append_u64(
+               struct lttng_msgpack_writer *writer, uint64_t value)
+{
+       value = byteswap_host_to_be64(value);
+
+       return lttng_msgpack_append_buffer(writer, (uint8_t *) &value, sizeof(value));
+}
+
+static inline int lttng_msgpack_append_f64(
+               struct lttng_msgpack_writer *writer, double value)
+{
+
+       union {
+               double d;
+               uint64_t u;
+       } u;
+
+       u.d = value;
+
+       return lttng_msgpack_append_u64(writer, u.u);
+}
+
+static inline int lttng_msgpack_append_i8(
+               struct lttng_msgpack_writer *writer, int8_t value)
+{
+       return lttng_msgpack_append_u8(writer, (uint8_t) value);
+}
+
+static inline int lttng_msgpack_append_i16(
+               struct lttng_msgpack_writer *writer, int16_t value)
+{
+       return lttng_msgpack_append_u16(writer, (uint16_t) value);
+}
+
+static inline int lttng_msgpack_append_i32(
+               struct lttng_msgpack_writer *writer, int32_t value)
+{
+       return lttng_msgpack_append_u32(writer, (uint32_t) value);
+}
+
+static inline int lttng_msgpack_append_i64(
+               struct lttng_msgpack_writer *writer, int64_t value)
+{
+       return lttng_msgpack_append_u64(writer, (uint64_t) value);
+}
+
+static inline int lttng_msgpack_encode_f64(
+               struct lttng_msgpack_writer *writer, double value)
+{
+       int ret;
+
+       ret = lttng_msgpack_append_u8(writer, MSGPACK_FLOAT64_ID);
+       if (ret)
+               goto end;
+
+       ret = lttng_msgpack_append_f64(writer, value);
+       if (ret)
+               goto end;
+
+end:
+       return ret;
+}
+
+static inline int lttng_msgpack_encode_fixmap(
+               struct lttng_msgpack_writer *writer, uint8_t count)
+{
+       int ret = 0;
+
+       lttng_msgpack_assert(count <= MSGPACK_FIXMAP_MAX_COUNT);
+
+       ret = lttng_msgpack_append_u8(writer, MSGPACK_FIXMAP_ID_MASK | count);
+       if (ret)
+               goto end;
+
+end:
+       return ret;
+}
+
+static inline int lttng_msgpack_encode_map16(
+               struct lttng_msgpack_writer *writer, uint16_t count)
+{
+       int ret;
+
+       lttng_msgpack_assert(count > MSGPACK_FIXMAP_MAX_COUNT);
+
+       ret = lttng_msgpack_append_u8(writer, MSGPACK_MAP16_ID);
+       if (ret)
+               goto end;
+
+       ret = lttng_msgpack_append_u16(writer, count);
+       if (ret)
+               goto end;
+
+end:
+       return ret;
+}
+
+static inline int lttng_msgpack_encode_fixarray(
+               struct lttng_msgpack_writer *writer, uint8_t count)
+{
+       int ret = 0;
+
+       lttng_msgpack_assert(count <= MSGPACK_FIXARRAY_MAX_COUNT);
+
+       ret = lttng_msgpack_append_u8(writer, MSGPACK_FIXARRAY_ID_MASK | count);
+       if (ret)
+               goto end;
+
+end:
+       return ret;
+}
+
+static inline int lttng_msgpack_encode_array16(
+               struct lttng_msgpack_writer *writer, uint16_t count)
+{
+       int ret;
+
+       lttng_msgpack_assert(count > MSGPACK_FIXARRAY_MAX_COUNT);
+
+       ret = lttng_msgpack_append_u8(writer, MSGPACK_ARRAY16_ID);
+       if (ret)
+               goto end;
+
+       ret = lttng_msgpack_append_u16(writer, count);
+       if (ret)
+               goto end;
+
+end:
+       return ret;
+}
+
+static inline int lttng_msgpack_encode_fixstr(
+               struct lttng_msgpack_writer *writer,
+               const char *str,
+               uint8_t len)
+{
+       int ret;
+
+       lttng_msgpack_assert(len <= MSGPACK_FIXSTR_MAX_LENGTH);
+
+       ret = lttng_msgpack_append_u8(writer, MSGPACK_FIXSTR_ID_MASK | len);
+       if (ret)
+               goto end;
+
+       ret = lttng_msgpack_append_buffer(writer, (uint8_t *) str, len);
+       if (ret)
+               goto end;
+
+end:
+       return ret;
+}
+
+static inline int lttng_msgpack_encode_str16(
+               struct lttng_msgpack_writer *writer,
+               const char *str,
+               uint16_t len)
+{
+       int ret;
+
+       lttng_msgpack_assert(len > MSGPACK_FIXSTR_MAX_LENGTH);
+
+       ret = lttng_msgpack_append_u8(writer, MSGPACK_STR16_ID);
+       if (ret)
+               goto end;
+
+       ret = lttng_msgpack_append_u16(writer, len);
+       if (ret)
+               goto end;
+
+       ret = lttng_msgpack_append_buffer(writer, (uint8_t *) str, len);
+       if (ret)
+               goto end;
+
+end:
+       return ret;
+}
+
+int lttng_msgpack_begin_map(struct lttng_msgpack_writer *writer, size_t count)
+{
+       int ret;
+
+       if (count < 0 || count >= (1 << 16)) {
+               ret = -1;
+               goto end;
+       }
+
+       if (count <= MSGPACK_FIXMAP_MAX_COUNT)
+               ret = lttng_msgpack_encode_fixmap(writer, count);
+       else
+               ret = lttng_msgpack_encode_map16(writer, count);
+
+       writer->map_nesting++;
+end:
+       return ret;
+}
+
+int lttng_msgpack_end_map(struct lttng_msgpack_writer *writer)
+{
+       lttng_msgpack_assert(writer->map_nesting > 0);
+       writer->map_nesting--;
+       return 0;
+}
+
+int lttng_msgpack_begin_array(
+               struct lttng_msgpack_writer *writer, size_t count)
+{
+       int ret;
+
+       if (count < 0 || count >= (1 << 16)) {
+               ret = -1;
+               goto end;
+       }
+
+       if (count <= MSGPACK_FIXARRAY_MAX_COUNT)
+               ret = lttng_msgpack_encode_fixarray(writer, count);
+       else
+               ret = lttng_msgpack_encode_array16(writer, count);
+
+       writer->array_nesting++;
+end:
+       return ret;
+}
+
+int lttng_msgpack_end_array(struct lttng_msgpack_writer *writer)
+{
+       lttng_msgpack_assert(writer->array_nesting > 0);
+       writer->array_nesting--;
+       return 0;
+}
+
+int lttng_msgpack_write_str(struct lttng_msgpack_writer *writer,
+               const char *str)
+{
+       int ret;
+       size_t length = strlen(str);
+       if (length < 0 || length >= (1 << 16)) {
+               ret = -1;
+               goto end;
+       }
+
+       if (length <= MSGPACK_FIXSTR_MAX_LENGTH)
+               ret = lttng_msgpack_encode_fixstr(writer, str, length);
+       else
+               ret = lttng_msgpack_encode_str16(writer, str, length);
+
+end:
+       return ret;
+}
+
+int lttng_msgpack_write_nil(struct lttng_msgpack_writer *writer)
+{
+       return lttng_msgpack_append_u8(writer, MSGPACK_NIL_ID);
+}
+
+int lttng_msgpack_write_true(struct lttng_msgpack_writer *writer)
+{
+       return lttng_msgpack_append_u8(writer, MSGPACK_TRUE_ID);
+}
+
+int lttng_msgpack_write_false(struct lttng_msgpack_writer *writer)
+{
+       return lttng_msgpack_append_u8(writer, MSGPACK_FALSE_ID);
+}
+
+int lttng_msgpack_write_unsigned_integer(
+               struct lttng_msgpack_writer *writer, uint64_t value)
+{
+       int ret = 0;
+
+       if (value <= MSGPACK_FIXINT_MAX) {
+               ret = lttng_msgpack_append_u8(writer, (uint8_t) value);
+               if (ret)
+                       goto end;
+       } else if (value <= UINT8_MAX) {
+               ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT8_ID);
+               if (ret)
+                       goto end;
+
+               ret = lttng_msgpack_append_u8(writer, (uint8_t) value);
+               if (ret)
+                       goto end;
+       } else if (value <= UINT16_MAX) {
+               ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT16_ID);
+               if (ret)
+                       goto end;
+
+               ret = lttng_msgpack_append_u16(writer, (uint16_t) value);
+               if (ret)
+                       goto end;
+       } else if (value <= UINT32_MAX) {
+               ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT32_ID);
+               if (ret)
+                       goto end;
+
+               ret = lttng_msgpack_append_u32(writer, (uint32_t) value);
+               if (ret)
+                       goto end;
+       } else {
+               ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT64_ID);
+               if (ret)
+                       goto end;
+
+               ret = lttng_msgpack_append_u64(writer, value);
+               if (ret)
+                       goto end;
+       }
+
+end:
+       return ret;
+}
+
+int lttng_msgpack_write_signed_integer(struct lttng_msgpack_writer *writer, int64_t value)
+{
+       int ret;
+
+       if (value >= MSGPACK_FIXINT_MIN && value <= MSGPACK_FIXINT_MAX){
+               ret = lttng_msgpack_append_i8(writer, (int8_t) value);
+               if (ret)
+                       goto end;
+       } else if (value >= INT8_MIN && value <= INT8_MAX) {
+               ret = lttng_msgpack_append_u8(writer, MSGPACK_INT8_ID);
+               if (ret)
+                       goto end;
+
+               ret = lttng_msgpack_append_i8(writer, (int8_t) value);
+               if (ret)
+                       goto end;
+       } else if (value >= INT16_MIN && value <= INT16_MAX) {
+               ret = lttng_msgpack_append_u8(writer, MSGPACK_INT16_ID);
+               if (ret)
+                       goto end;
+
+               ret = lttng_msgpack_append_i16(writer, (int16_t) value);
+               if (ret)
+                       goto end;
+       } else if (value >= INT32_MIN && value <= INT32_MAX) {
+               ret = lttng_msgpack_append_u8(writer, MSGPACK_INT32_ID);
+               if (ret)
+                       goto end;
+
+               ret = lttng_msgpack_append_i32(writer, (int32_t) value);
+               if (ret)
+                       goto end;
+       } else {
+               ret = lttng_msgpack_append_u8(writer, MSGPACK_INT64_ID);
+               if (ret)
+                       goto end;
+
+               ret = lttng_msgpack_append_i64(writer, value);
+               if (ret)
+                       goto end;
+       }
+
+end:
+       return ret;
+}
+
+int lttng_msgpack_write_double(struct lttng_msgpack_writer *writer, double value)
+{
+       return lttng_msgpack_encode_f64(writer, value);
+}
+
+void lttng_msgpack_writer_init(struct lttng_msgpack_writer *writer,
+               uint8_t *buffer, size_t size)
+{
+       lttng_msgpack_assert(buffer);
+       lttng_msgpack_assert(size >= 0);
+
+       writer->buffer = buffer;
+       writer->write_pos = buffer;
+       writer->end_write_pos = buffer + size;
+
+       writer->array_nesting = 0;
+       writer->map_nesting = 0;
+}
+
+void lttng_msgpack_writer_fini(struct lttng_msgpack_writer *writer)
+{
+       memset(writer, 0, sizeof(*writer));
+}
diff --git a/libmsgpack/msgpack.h b/libmsgpack/msgpack.h
new file mode 100644 (file)
index 0000000..e5c011e
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef _LTTNG_UST_MSGPACK_H
+#define _LTTNG_UST_MSGPACK_H
+
+/*
+ * msgpack.h
+ *
+ * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; only
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stddef.h>
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else /* __KERNEL__ */
+#include <stdint.h>
+#endif /* __KERNEL__ */
+
+struct lttng_msgpack_writer {
+       uint8_t *buffer;
+       uint8_t *write_pos;
+       const uint8_t *end_write_pos;
+       uint8_t array_nesting;
+       uint8_t map_nesting;
+};
+
+void lttng_msgpack_writer_init(
+               struct lttng_msgpack_writer *writer,
+               uint8_t *buffer, size_t size);
+
+void lttng_msgpack_writer_fini(struct lttng_msgpack_writer *writer);
+
+int lttng_msgpack_write_nil(struct lttng_msgpack_writer *writer);
+int lttng_msgpack_write_true(struct lttng_msgpack_writer *writer);
+int lttng_msgpack_write_false(struct lttng_msgpack_writer *writer);
+int lttng_msgpack_write_unsigned_integer(
+               struct lttng_msgpack_writer *writer, uint64_t value);
+int lttng_msgpack_write_signed_integer(
+               struct lttng_msgpack_writer *writer, int64_t value);
+int lttng_msgpack_write_double(struct lttng_msgpack_writer *writer, double value);
+int lttng_msgpack_write_str(struct lttng_msgpack_writer *writer,
+               const char *value);
+int lttng_msgpack_begin_map(struct lttng_msgpack_writer *writer, size_t count);
+int lttng_msgpack_end_map(struct lttng_msgpack_writer *writer);
+int lttng_msgpack_begin_array(
+               struct lttng_msgpack_writer *writer, size_t count);
+int lttng_msgpack_end_array(struct lttng_msgpack_writer *writer);
+
+#endif /* _LTTNG_UST_MSGPACK_H */
index 6792b0b9b027fea97d551fe4053f6cffba2858a4..9023d0535acff26f8ce1f42b9ed5ce53a6b90759 100644 (file)
@@ -7,6 +7,7 @@ LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
 TESTS = \
        unit/libringbuffer/test_shm \
        unit/gcc-weak-hidden/test_gcc_weak_hidden \
+       unit/libmsgpack/test_msgpack \
        unit/pthread_name/test_pthread_name \
        unit/snprintf/test_snprintf \
        unit/ust-elf/test_ust_elf
index b1de13a1728cdfa2170a1b921cbd46a382917eaa..0c984a708497dcf695efaa8dd81d949804521588 100644 (file)
@@ -1,5 +1,6 @@
 SUBDIRS = \
        gcc-weak-hidden \
+       libmsgpack \
        libringbuffer \
        pthread_name \
        snprintf \
diff --git a/tests/unit/libmsgpack/Makefile.am b/tests/unit/libmsgpack/Makefile.am
new file mode 100644 (file)
index 0000000..784c3ef
--- /dev/null
@@ -0,0 +1,9 @@
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/tests/utils
+
+noinst_PROGRAMS = test_msgpack
+test_msgpack_SOURCES = test_msgpack.c
+test_msgpack_LDADD = \
+ $(top_builddir)/libmsgpack/libmsgpack.la \
+ $(top_builddir)/tests/utils/libtap.a
+
+test_msgpack_CFLAGS = $(AM_CFLAGS)
diff --git a/tests/unit/libmsgpack/test_msgpack.c b/tests/unit/libmsgpack/test_msgpack.c
new file mode 100644 (file)
index 0000000..a8cd144
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * test_msgpack.c
+ *
+ * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; only
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tap.h"
+
+#include "../../libmsgpack/msgpack.h"
+
+#define BUFFER_SIZE 4096
+#define NUM_TESTS 23
+
+
+/*
+ * echo 'null' | json2msgpack | xxd -i
+ */
+static const uint8_t NIL_EXPECTED[] = { 0xc0 };
+
+/*
+ * echo '"bye"' | json2msgpack | xxd -i
+ */
+static const uint8_t STRING_BYE_EXPECTED[] = { 0xa3, 0x62, 0x79, 0x65 };
+
+/*
+ * echo '1337' | json2msgpack | xxd -i
+ */
+static const uint8_t UINT_1337_EXPECTED[] = { 0xcd, 0x05, 0x39 };
+
+/*
+ * echo '127' | json2msgpack | xxd -i
+ */
+static const uint8_t UINT_127_EXPECTED[] = { 0x7f };
+
+/*
+ * echo '128' | json2msgpack | xxd -i
+ */
+static const uint8_t UINT_128_EXPECTED[] = { 0xcc, 0x80 };
+
+/*
+ * echo '256' | json2msgpack | xxd -i
+ */
+static const uint8_t UINT_256_EXPECTED[] = { 0xcd, 0x01, 0x00 };
+
+/*
+ * echo '65535' | json2msgpack | xxd -i
+ */
+static const uint8_t UINT_65535_EXPECTED[] = { 0xcd, 0xff, 0xff };
+
+/*
+ * echo '65536' | json2msgpack | xxd -i
+ */
+static const uint8_t UINT_65536_EXPECTED[] = { 0xce, 0x00, 0x01, 0x00, 0x00 };
+
+/*
+ * echo '4294967295' | json2msgpack | xxd -i
+ */
+static const uint8_t UINT_4294967295_EXPECTED[] = { 0xce, 0xff, 0xff, 0xff, 0xff };
+
+/*
+ * echo '4294967296' | json2msgpack | xxd -i
+ */
+static const uint8_t UINT_4294967296_EXPECTED[] = { 0xcf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 };
+
+/*
+ * echo '-32' | json2msgpack | xxd -i
+ */
+static const uint8_t INT_NEG_32_EXPECTED[] = { 0xe0 };
+
+/*
+ * echo '-33' | json2msgpack | xxd -i
+ */
+static const uint8_t INT_NEG_33_EXPECTED[] = { 0xd0, 0xdf };
+
+/*
+ * echo '-129' | json2msgpack | xxd -i
+ */
+static const uint8_t INT_NEG_129_EXPECTED[] = { 0xd1, 0xff, 0x7f};
+
+/*
+ * echo '-32768' | json2msgpack | xxd -i
+ */
+static const uint8_t INT_NEG_32768_EXPECTED[] = { 0xd1, 0x80, 0x00 };
+
+/*
+ * echo '-32769' | json2msgpack | xxd -i
+ */
+static const uint8_t INT_NEG_32769_EXPECTED[] = { 0xd2, 0xff, 0xff, 0x7f,
+               0xff };
+
+/*
+ * echo '-2147483648' | json2msgpack | xxd -i
+ */
+static const uint8_t INT_NEG_2147483648_EXPECTED[] = { 0xd2, 0x80, 0x00, 0x00,
+               0x00 };
+
+/*
+ * echo '-2147483649' | json2msgpack | xxd -i
+ */
+static const uint8_t INT_NEG_2147483649_EXPECTED[] = { 0xd3, 0xff, 0xff, 0xff,
+               0xff, 0x7f, 0xff, 0xff, 0xff };
+/*
+ * echo '0.0' | json2msgpack | xxd -i
+ */
+static const uint8_t DOUBLE_ZERO_EXPECTED[] = { 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x00 };
+
+/*
+ * echo '3.14159265' | json2msgpack | xxd -i
+ */
+static const uint8_t DOUBLE_PI_EXPECTED[] = { 0xcb, 0x40, 0x09, 0x21, 0xfb, 0x53,
+               0xc8, 0xd4, 0xf1 };
+
+/*
+ * echo '3.14159265' | json2msgpack | xxd -i
+ */
+static const uint8_t DOUBLE_NEG_PI_EXPECTED[] = { 0xcb, 0xc0, 0x09, 0x21, 0xfb,
+               0x53, 0xc8, 0xd4, 0xf1 };
+
+/*
+ * echo [1.1, 2.3, -12345.2] | json2msgpack | xxd -i
+ */
+static const uint8_t ARRAY_DOUBLE_EXPECTED[] = { 0x93, 0xcb, 0x3f, 0xf1, 0x99,
+               0x99, 0x99, 0x99, 0x99, 0x9a, 0xcb, 0x40, 0x02, 0x66, 0x66,
+               0x66, 0x66, 0x66, 0x66, 0xcb, 0xc0, 0xc8, 0x1c, 0x99, 0x99,
+               0x99, 0x99, 0x9a };
+
+/*
+ * echo '{"type":"enum","value":117}' | json2msgpack | xxd -i
+ */
+static const uint8_t MAP_EXPECTED[] = {
+  0x82, 0xa4, 0x74, 0x79, 0x70, 0x65, 0xa4, 0x65, 0x6e, 0x75, 0x6d, 0xa5,
+  0x76, 0x61, 0x6c, 0x75, 0x65, 0x75 };
+
+/*
+ * echo '["meow mix", 18, null, 14.197, [1980, 1995]]' | json2msgpack | xxd -i
+ */
+static const uint8_t COMPLETE_CAPTURE_EXPECTED[] = { 0x95, 0xa8, 0x6d, 0x65,
+               0x6f, 0x77, 0x20, 0x6d, 0x69, 0x78, 0x12, 0xc0, 0xcb, 0x40,
+               0x2c, 0x64, 0xdd, 0x2f, 0x1a, 0x9f, 0xbe, 0x92, 0xcd, 0x07,
+               0xbc, 0xcd, 0x07, 0xcb };
+
+static void string_test(uint8_t *buf, const char *value)
+{
+       struct lttng_msgpack_writer writer;
+
+       lttng_msgpack_writer_init(&writer, buf, BUFFER_SIZE);
+       lttng_msgpack_write_str(&writer, value);
+       lttng_msgpack_writer_fini(&writer);
+}
+
+static void int_test(uint8_t *buf, int64_t value)
+{
+       struct lttng_msgpack_writer writer;
+
+       lttng_msgpack_writer_init(&writer, buf, BUFFER_SIZE);
+       lttng_msgpack_write_signed_integer(&writer, value);
+
+       lttng_msgpack_writer_fini(&writer);
+}
+
+static void uint_test(uint8_t *buf, uint64_t value)
+{
+       struct lttng_msgpack_writer writer;
+
+       lttng_msgpack_writer_init(&writer, buf, BUFFER_SIZE);
+       lttng_msgpack_write_unsigned_integer(&writer, value);
+       lttng_msgpack_writer_fini(&writer);
+}
+
+static void double_test(uint8_t *buf, double value)
+{
+       struct lttng_msgpack_writer writer;
+
+       lttng_msgpack_writer_init(&writer, buf, BUFFER_SIZE);
+       lttng_msgpack_write_double(&writer, value);
+       lttng_msgpack_writer_fini(&writer);
+}
+
+static void array_double_test(uint8_t *buf, double *values, size_t nb_values)
+{
+       int i = 0;
+       struct lttng_msgpack_writer writer;
+
+       lttng_msgpack_writer_init(&writer, buf, BUFFER_SIZE);
+       lttng_msgpack_begin_array(&writer, nb_values);
+
+       for (i = 0; i < nb_values; i++) {
+               lttng_msgpack_write_double(&writer, values[i]);
+       }
+
+       lttng_msgpack_end_array(&writer);
+       lttng_msgpack_writer_fini(&writer);
+}
+
+static void map_test(uint8_t *buf)
+{
+       struct lttng_msgpack_writer writer;
+
+       lttng_msgpack_writer_init(&writer, buf, BUFFER_SIZE);
+
+       lttng_msgpack_begin_map(&writer, 2);
+
+       lttng_msgpack_write_str(&writer, "type");
+       lttng_msgpack_write_str(&writer, "enum");
+
+       lttng_msgpack_write_str(&writer, "value");
+       lttng_msgpack_write_unsigned_integer(&writer, 117);
+
+       lttng_msgpack_end_map(&writer);
+       lttng_msgpack_writer_fini(&writer);
+}
+
+static void complete_capture_test(uint8_t *buf)
+{
+       /*
+        * This testcase tests the following json representation:
+        * "meow mix",18, null, 14.197,[1980, 1995]]
+        */
+       struct lttng_msgpack_writer writer;
+
+       lttng_msgpack_writer_init(&writer, buf, BUFFER_SIZE);
+
+       lttng_msgpack_begin_array(&writer, 5);
+
+       lttng_msgpack_write_str(&writer, "meow mix");
+       lttng_msgpack_write_signed_integer(&writer, 18);
+       lttng_msgpack_write_nil(&writer);
+       lttng_msgpack_write_double(&writer, 14.197);
+
+       lttng_msgpack_begin_array(&writer, 2);
+
+       lttng_msgpack_write_unsigned_integer(&writer, 1980);
+       lttng_msgpack_write_unsigned_integer(&writer, 1995);
+
+       lttng_msgpack_end_array(&writer);
+
+       lttng_msgpack_end_array(&writer);
+
+       lttng_msgpack_writer_fini(&writer);
+}
+
+static void nil_test(uint8_t *buf)
+{
+       struct lttng_msgpack_writer writer;
+
+       lttng_msgpack_writer_init(&writer, buf, BUFFER_SIZE);
+       lttng_msgpack_write_nil(&writer);
+       lttng_msgpack_writer_fini(&writer);
+}
+
+int main(int argc, char *argv[])
+{
+       uint8_t buf[BUFFER_SIZE] = {0};
+       double arr_double[] = {1.1, 2.3, -12345.2};
+
+       plan_tests(NUM_TESTS);
+
+       diag("Testing msgpack implementation");
+
+       /*
+        * Expected outputs were produced using the `json2msgpack` tool.
+        * https://github.com/ludocode/msgpack-tools
+        * For example, here is the command to produce the null test expected
+        * output:
+        *  echo 'null' | json2msgpack | hexdump -v -e '"\\\x" 1/1 "%02x"'
+        *
+        * The only exception is that we always produce 64bits integer to
+        * represent integers even if they would fit into smaller objects so
+        * they need to be manually crafted in 64bits two's complement (if
+        * signed) big endian.
+        */
+       nil_test(buf);
+       ok(memcmp(buf, NIL_EXPECTED, sizeof(NIL_EXPECTED)) == 0,
+               "NIL object");
+
+       string_test(buf, "bye");
+       ok(memcmp(buf, STRING_BYE_EXPECTED, sizeof(STRING_BYE_EXPECTED)) == 0,
+               "String \"bye\" object");
+
+       uint_test(buf, 1337);
+       ok(memcmp(buf, UINT_1337_EXPECTED, sizeof(UINT_1337_EXPECTED)) == 0,
+               "Unsigned integer \"1337\" object");
+
+       uint_test(buf, 127);
+       ok(memcmp(buf, UINT_127_EXPECTED, sizeof(UINT_127_EXPECTED)) == 0,
+               "Unsigned integer \"127\" object");
+
+       uint_test(buf, 128);
+       ok(memcmp(buf, UINT_128_EXPECTED, sizeof(UINT_128_EXPECTED)) == 0,
+               "Unsigned integer \"128\" object");
+
+       uint_test(buf, 256);
+       ok(memcmp(buf, UINT_256_EXPECTED, sizeof(UINT_256_EXPECTED)) == 0,
+               "Unsigned integer \"256\" object");
+
+       uint_test(buf, 65536);
+       ok(memcmp(buf, UINT_65536_EXPECTED, sizeof(UINT_65536_EXPECTED)) == 0,
+               "Unsigned integer \"65536\" object");
+
+       uint_test(buf, 65535);
+       ok(memcmp(buf, UINT_65535_EXPECTED, sizeof(UINT_65535_EXPECTED)) == 0,
+               "Unsigned integer \"65535\" object");
+
+       uint_test(buf, 4294967295);
+       ok(memcmp(buf, UINT_4294967295_EXPECTED, sizeof(UINT_4294967295_EXPECTED)) == 0,
+               "Unsigned integer \"4294967295\" object");
+
+       uint_test(buf, 4294967296);
+       ok(memcmp(buf, UINT_4294967296_EXPECTED, sizeof(UINT_4294967296_EXPECTED)) == 0,
+               "Unsigned integer \"4294967296\" object");
+
+       int_test(buf, -32);
+       ok(memcmp(buf, INT_NEG_32_EXPECTED, sizeof(INT_NEG_32_EXPECTED)) == 0,
+               "Signed integer \"-32\" object");
+
+       int_test(buf, -33);
+       ok(memcmp(buf, INT_NEG_33_EXPECTED, sizeof(INT_NEG_33_EXPECTED)) == 0,
+               "Signed integer \"-33\" object");
+
+       int_test(buf, -129);
+       ok(memcmp(buf, INT_NEG_129_EXPECTED, sizeof(INT_NEG_129_EXPECTED)) == 0,
+               "Signed integer \"-129\" object");
+
+       int_test(buf, -32768);
+       ok(memcmp(buf, INT_NEG_32768_EXPECTED, sizeof(INT_NEG_32768_EXPECTED)) == 0,
+               "Signed integer \"-32768\" object");
+
+       int_test(buf, -32769);
+       ok(memcmp(buf, INT_NEG_32769_EXPECTED, sizeof(INT_NEG_32769_EXPECTED)) == 0,
+               "Signed integer \"-32769\" object");
+
+       int_test(buf, -2147483648);
+       ok(memcmp(buf, INT_NEG_2147483648_EXPECTED, sizeof(INT_NEG_2147483648_EXPECTED)) == 0,
+               "Signed integer \"-2147483648\" object");
+
+       int_test(buf, -2147483649);
+       ok(memcmp(buf, INT_NEG_2147483649_EXPECTED, sizeof(INT_NEG_2147483649_EXPECTED)) == 0,
+               "Signed integer \"-2147483649\" object");
+
+       double_test(buf, 0.0);
+       ok(memcmp(buf, DOUBLE_ZERO_EXPECTED, sizeof(DOUBLE_ZERO_EXPECTED)) == 0,
+               "double \"0.0\" object");
+
+       double_test(buf, 3.14159265);
+       ok(memcmp(buf, DOUBLE_PI_EXPECTED, sizeof(DOUBLE_PI_EXPECTED)) == 0,
+               "double \"PI\" object");
+
+       double_test(buf, -3.14159265);
+       ok(memcmp(buf, DOUBLE_NEG_PI_EXPECTED, sizeof(DOUBLE_NEG_PI_EXPECTED)) == 0,
+               "double \"-PI\" object");
+
+       array_double_test(buf, arr_double, 3);
+       ok(memcmp(buf, ARRAY_DOUBLE_EXPECTED, sizeof(ARRAY_DOUBLE_EXPECTED)) == 0,
+               "Array of double object");
+
+       map_test(buf);
+       ok(memcmp(buf, MAP_EXPECTED, sizeof(MAP_EXPECTED)) == 0,
+               "Map object");
+
+       complete_capture_test(buf);
+       ok(memcmp(buf, COMPLETE_CAPTURE_EXPECTED, sizeof(COMPLETE_CAPTURE_EXPECTED)) == 0,
+               "Complete capture object");
+
+       return EXIT_SUCCESS;
+}
This page took 0.036095 seconds and 4 git commands to generate.