From 55b1df443f5ed78d85692c0845d166400018c9f4 Mon Sep 17 00:00:00 2001 From: Jonathan Rajotte Date: Thu, 7 Apr 2022 13:45:34 -0400 Subject: [PATCH] Base lttng_trace_format_descriptor Implements an internal lttng::trace_format_descriptor c++ based object as the backing object for lttng_trace_format_descriptor (C API). TODO: MI might be better off using a visitor? Config also? Same for serialize? Signed-off-by: Jonathan Rajotte Change-Id: I588f9da11d2cbc697f26b91e006bdc23074ac9fd --- include/Makefile.am | 2 + include/lttng/lttng.h | 5 +- .../trace-format-descriptor-internal.hpp | 163 +++++++ include/lttng/trace-format-descriptor.h | 57 +++ src/common/Makefile.am | 1 + src/common/config/config-session-abi.hpp | 4 + src/common/config/session-config.cpp | 5 + src/common/trace-format-descriptor.cpp | 417 ++++++++++++++++++ src/lib/lttng-ctl/liblttng-ctl.sym | 4 + tests/unit/Makefile.am | 6 + tests/unit/test_trace_format_descriptor.cpp | 138 ++++++ 11 files changed, 800 insertions(+), 2 deletions(-) create mode 100644 include/lttng/trace-format-descriptor-internal.hpp create mode 100644 include/lttng/trace-format-descriptor.h create mode 100644 src/common/trace-format-descriptor.cpp create mode 100644 tests/unit/test_trace_format_descriptor.cpp diff --git a/include/Makefile.am b/include/Makefile.am index d840d58dc..e445d9035 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -123,6 +123,7 @@ lttnginclude_HEADERS = \ lttng/session.h \ lttng/snapshot.h \ lttng/tracker.h \ + lttng/trace-format-descriptor.h \ lttng/userspace-probe.h lttngactioninclude_HEADERS= \ @@ -208,6 +209,7 @@ noinst_HEADERS = \ lttng/session-internal.hpp \ lttng/snapshot-internal.hpp \ lttng/trigger/trigger-internal.hpp \ + lttng/trace-format-descriptor-internal.hpp \ lttng/userspace-probe-internal.hpp \ version.hpp \ version.i diff --git a/include/lttng/lttng.h b/include/lttng/lttng.h index dbfe9a7db..5833d0ba4 100644 --- a/include/lttng/lttng.h +++ b/include/lttng/lttng.h @@ -42,13 +42,13 @@ #include #include #include -#include #include #include #include -#include #include #include +#include +#include #include #include #include @@ -66,6 +66,7 @@ #include #include #include +#include #include #include #include diff --git a/include/lttng/trace-format-descriptor-internal.hpp b/include/lttng/trace-format-descriptor-internal.hpp new file mode 100644 index 000000000..6a142e2bd --- /dev/null +++ b/include/lttng/trace-format-descriptor-internal.hpp @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2022 Jonathan Rajotte + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_TRACE_FORMAT_DESCRIPTOR_INTERNAL_HPP +#define LTTNG_TRACE_FORMAT_DESCRIPTOR_INTERNAL_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct lttng_payload; +struct lttng_payload_view; +struct mi_writer; + +struct lttng_trace_format_descriptor_comm { + uint8_t type; +}; + +namespace lttng { +class trace_format_descriptor { +public: + using uptr = std::unique_ptr; + using sptr = std::shared_ptr; + explicit trace_format_descriptor(enum lttng_trace_format_descriptor_type type) : _type(type) + { + } + + virtual ~trace_format_descriptor(); + virtual uptr clone() const = 0; // Virtual constructor (copying) + + enum lttng_trace_format_descriptor_type type() const + { + return _type; + } + + virtual lttng_error_code mi_serialize(mi_writer *writer) const final; + virtual lttng_error_code config_serialize(config_writer *writer) const final; + virtual int serialize(lttng_payload *payload) const; + static ssize_t create_from_payload(lttng_payload_view *view, uptr& descriptor); + + friend bool operator==( + trace_format_descriptor const& lhs, trace_format_descriptor const& rhs) + { + if (lhs.type() != rhs.type()) { + return false; + } + return lhs.equal_to(rhs); + } + + friend bool operator!=( + trace_format_descriptor const& lhs, trace_format_descriptor const& rhs) + { + return !(lhs == rhs); + } + +protected: + using DeserializerFunction = + std::function; + using deserializer_map = + std::unordered_map; + + static deserializer_map _deserializer_map; + virtual bool equal_to(trace_format_descriptor const& rhs) const = 0; + +private: + enum lttng_trace_format_descriptor_type _type = LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_UNKNOWN; + + virtual lttng_error_code subtype_mi_serialize(mi_writer *writer) const = 0; + virtual lttng_error_code subtype_config_serialize(config_writer *writer) const = 0; +}; + +class trace_format_descriptor_ctf1 : public trace_format_descriptor { +public: + trace_format_descriptor_ctf1() : + trace_format_descriptor(LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_1) + { + } // Default constructor. + + trace_format_descriptor_ctf1(trace_format_descriptor_ctf1 const&) : + trace_format_descriptor_ctf1() + { + } // Copy constructor + + uptr clone() const + { + return uptr(new trace_format_descriptor_ctf1(*this)); + } + + uint64_t getMajor() const + { + return _major; + } + uint64_t getMinor() const + { + return _minor; + } + +protected: + static ssize_t deserialize(lttng_payload_view *view, uptr& descriptor); + bool equal_to(trace_format_descriptor const& rhs) const override; + +private: + lttng_error_code subtype_mi_serialize(mi_writer *writer) const override; + lttng_error_code subtype_config_serialize(config_writer *writer) const override; + + const uint64_t _major = 1; + const uint64_t _minor = 8; +}; + +class trace_format_descriptor_ctf2 : public trace_format_descriptor { +public: + trace_format_descriptor_ctf2() : + trace_format_descriptor(LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_2) + { + } + + trace_format_descriptor_ctf2(trace_format_descriptor_ctf2 const&) : + trace_format_descriptor_ctf2() + { + } // Copy constructor + + uptr clone() const + { + return uptr(new trace_format_descriptor_ctf2(*this)); + } + + uint64_t getMajor() const + { + return _major; + } + uint64_t getMinor() const + { + return _minor; + } + +protected: + static ssize_t deserialize(lttng_payload_view *view, uptr& descriptor); + bool equal_to(trace_format_descriptor const& rhs) const override; + +private: + lttng_error_code subtype_mi_serialize(mi_writer *writer) const override; + lttng_error_code subtype_config_serialize(config_writer *writer) const override; + const uint64_t _major = 2; + const uint64_t _minor = 0; +}; +} // namespace lttng + +#endif /* LTTNG_TRACE_FORMAT_DESCRIPTOR_INTERNAL_HPP */ diff --git a/include/lttng/trace-format-descriptor.h b/include/lttng/trace-format-descriptor.h new file mode 100644 index 000000000..ade822582 --- /dev/null +++ b/include/lttng/trace-format-descriptor.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2022 Jonathan Rajotte + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_TRACE_FORMAT_DESCRIPTOR_H +#define LTTNG_TRACE_FORMAT_DESCRIPTOR_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct lttng_trace_format_descriptor; + +enum lttng_trace_format_descriptor_status { + LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID = -1, + LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_OK = 0, +}; + +enum lttng_trace_format_descriptor_type { + LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_UNKNOWN = -1, + LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_1 = 0, + LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_2 = 1, +}; + +LTTNG_EXPORT extern enum lttng_trace_format_descriptor_type lttng_trace_format_get_type( + const struct lttng_trace_format_descriptor *descriptor); + +LTTNG_EXPORT extern struct lttng_trace_format_descriptor * +lttng_trace_format_ctf_1_descriptor_create(void); + +LTTNG_EXPORT extern enum lttng_trace_format_descriptor_status lttng_trace_format_ctf_1_get_version( + const struct lttng_trace_format_descriptor *descriptor, + uint64_t *major, + uint64_t *minor); + +LTTNG_EXPORT extern struct lttng_trace_format_descriptor * +lttng_trace_format_ctf_2_descriptor_create(void); + +LTTNG_EXPORT extern enum lttng_trace_format_descriptor_status lttng_trace_format_ctf_2_get_version( + const struct lttng_trace_format_descriptor *descriptor, + uint64_t *major, + uint64_t *minor); + +LTTNG_EXPORT void lttng_trace_format_descriptor_destroy( + struct lttng_trace_format_descriptor *descriptor); + +#ifdef __cplusplus +} +#endif + +#endif /* LTTNG_TRACE_FORMAT_DESCRIPTOR_H */ diff --git a/src/common/Makefile.am b/src/common/Makefile.am index a7d43b39c..607b65971 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -105,6 +105,7 @@ libcommon_lgpl_la_SOURCES = \ spawn-viewer.cpp spawn-viewer.hpp \ thread.cpp thread.hpp \ time.cpp \ + trace-format-descriptor.cpp \ tracker.cpp tracker.hpp \ trigger.cpp \ unix.cpp unix.hpp \ diff --git a/src/common/config/config-session-abi.hpp b/src/common/config/config-session-abi.hpp index f921a7363..c61ea4a4f 100644 --- a/src/common/config/config-session-abi.hpp +++ b/src/common/config/config-session-abi.hpp @@ -179,4 +179,8 @@ extern const char * const config_event_context_vgid; extern const char * const config_event_context_vegid; extern const char * const config_event_context_vsgid; +extern const char * const config_element_session_trace_format; +extern const char * const config_element_session_trace_format_ctf1; +extern const char * const config_element_session_trace_format_ctf2; + #endif /* CONFIG_SESSION_INTERNAL_H */ diff --git a/src/common/config/session-config.cpp b/src/common/config/session-config.cpp index 8f96b7f21..f9d9d0eca 100644 --- a/src/common/config/session-config.cpp +++ b/src/common/config/session-config.cpp @@ -227,6 +227,11 @@ const char * const config_event_context_vgid = "VGID"; const char * const config_event_context_vegid = "VEGID"; const char * const config_event_context_vsgid = "VSGID"; +const char * const config_element_session_trace_format = "trace_format"; +const char * const config_element_session_trace_format_ctf1 = "ctf1"; +const char * const config_element_session_trace_format_ctf2 = "ctf2"; + + /* Deprecated symbols */ LTTNG_EXPORT const char *config_element_perf; diff --git a/src/common/trace-format-descriptor.cpp b/src/common/trace-format-descriptor.cpp new file mode 100644 index 000000000..d9d3ef510 --- /dev/null +++ b/src/common/trace-format-descriptor.cpp @@ -0,0 +1,417 @@ +/* + * Copyright (C) 2022 Jonathan Rajotte + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace lttng { +/* Initialize deserializer map */ +trace_format_descriptor::deserializer_map trace_format_descriptor::_deserializer_map; + +template +class deserializer_register { +private: + class initializer : public type { + public: + initializer() + { + type::_deserializer_map[enumType] = type::deserialize; + } + }; + +public: + deserializer_register() + { + deserializer_register::initializer i; + } +}; + +/* Default destructor for the base type */ +trace_format_descriptor::~trace_format_descriptor() = default; + +static deserializer_register + ctf1Deserializer; +static deserializer_register + ctf2Deserializer; + +enum lttng_error_code trace_format_descriptor::mi_serialize(struct mi_writer *writer) const +{ + int ret; + enum lttng_error_code ret_code; + + LTTNG_ASSERT(writer); + + /* Open trace format element. */ + ret = mi_lttng_writer_open_element(writer, config_element_session_trace_format); + if (ret) { + goto mi_error; + } + + /* Serialize underlying descriptor. */ + ret_code = this->subtype_mi_serialize(writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Close trace format element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + ret_code = LTTNG_OK; + goto end; +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + +lttng_error_code trace_format_descriptor_ctf1::subtype_mi_serialize(mi_writer *writer) const +{ + int ret; + enum lttng_error_code ret_code; + + LTTNG_ASSERT(writer); + + /* Open ctf1 element. */ + ret = mi_lttng_writer_open_element(writer, config_element_session_trace_format_ctf1); + if (ret) { + goto mi_error; + } + + ret = mi_lttng_writer_write_element_unsigned_int( + writer, mi_lttng_element_version_major, _major); + if (ret) { + goto mi_error; + } + + ret = mi_lttng_writer_write_element_unsigned_int( + writer, mi_lttng_element_version_minor, _minor); + if (ret) { + goto mi_error; + } + + /* Close ctf1 element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + ret_code = LTTNG_OK; + goto end; +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + +lttng_error_code trace_format_descriptor_ctf2::subtype_mi_serialize(mi_writer *writer) const +{ + int ret; + enum lttng_error_code ret_code; + + LTTNG_ASSERT(writer); + + /* Open ctf2 element. */ + ret = mi_lttng_writer_open_element(writer, config_element_session_trace_format_ctf2); + if (ret) { + goto mi_error; + } + + ret = mi_lttng_writer_write_element_unsigned_int( + writer, mi_lttng_element_version_major, _major); + if (ret) { + goto mi_error; + } + + ret = mi_lttng_writer_write_element_unsigned_int( + writer, mi_lttng_element_version_minor, _minor); + if (ret) { + goto mi_error; + } + + /* Close ctf2 element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + ret_code = LTTNG_OK; + goto end; +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + +enum lttng_error_code trace_format_descriptor::config_serialize(config_writer *writer) const +{ + int ret; + enum lttng_error_code ret_code; + + LTTNG_ASSERT(writer); + + /* Open trace format element. */ + ret = config_writer_open_element(writer, config_element_session_trace_format); + if (ret) { + goto mi_error; + } + + /* Serialize underlying descriptor. */ + ret_code = this->subtype_config_serialize(writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Close trace format element. */ + ret = config_writer_close_element(writer); + if (ret) { + goto mi_error; + } + ret_code = LTTNG_OK; + goto end; +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + +lttng_error_code trace_format_descriptor_ctf1::subtype_config_serialize(config_writer *writer) const +{ + int ret; + enum lttng_error_code ret_code; + + LTTNG_ASSERT(writer); + + /* Open ctf1 element. */ + ret = config_writer_open_element(writer, config_element_session_trace_format_ctf1); + if (ret) { + goto error; + } + + /* Close ctf1 element. */ + ret = config_writer_close_element(writer); + if (ret) { + goto error; + } + ret_code = LTTNG_OK; + goto end; +error: + ret_code = LTTNG_ERR_SAVE_IO_FAIL; +end: + return ret_code; +} + +lttng_error_code trace_format_descriptor_ctf2::subtype_config_serialize(config_writer *writer) const +{ + int ret; + enum lttng_error_code ret_code; + + LTTNG_ASSERT(writer); + + /* Open ctf2 element. */ + ret = config_writer_open_element(writer, config_element_session_trace_format_ctf2); + if (ret) { + goto error; + } + + /* Close ctf2 element. */ + ret = config_writer_close_element(writer); + if (ret) { + goto error; + } + ret_code = LTTNG_OK; + goto end; +error: + ret_code = LTTNG_ERR_SAVE_IO_FAIL; +end: + return ret_code; +} + +int trace_format_descriptor::serialize(lttng_payload *payload) const +{ + struct lttng_trace_format_descriptor_comm comm = {}; + + LTTNG_ASSERT(payload); + + comm.type = (int8_t) this->type(); + + return lttng_dynamic_buffer_append(&payload->buffer, &comm, sizeof(comm)); +} + +ssize_t trace_format_descriptor_ctf1::deserialize(lttng_payload_view *view, uptr& descriptor) +{ + int ret = 0; + + /* Nothing to deserialize */ + (void) view; + + trace_format_descriptor::uptr local_descriptor(new trace_format_descriptor_ctf1); + descriptor = std::move(local_descriptor); + + return ret; +} +bool trace_format_descriptor_ctf1::equal_to(const trace_format_descriptor& rhs) const +{ + trace_format_descriptor_ctf1 const *p = + static_cast(&rhs); + + return _major == p->_major && _minor == p->_minor; +} + +ssize_t trace_format_descriptor_ctf2::deserialize(lttng_payload_view *view, uptr& descriptor) +{ + int ret = 0; + + /* Nothing to deserialize */ + (void) view; + + trace_format_descriptor::uptr local_descriptor(new trace_format_descriptor_ctf2); + descriptor = std::move(local_descriptor); + + return ret; +} +bool trace_format_descriptor_ctf2::equal_to(const trace_format_descriptor& rhs) const +{ + trace_format_descriptor_ctf2 const *p = + static_cast(&rhs); + + return _major == p->_major && _minor == p->_minor; +} + +ssize_t trace_format_descriptor::create_from_payload(lttng_payload_view *view, uptr& descriptor) +{ + ssize_t ret = 0, consumed = 0; + const struct lttng_trace_format_descriptor_comm *comm; + const struct lttng_payload_view comm_view = + lttng_payload_view_from_view(view, 0, sizeof(*comm)); + + if (!view) { + return -1; + } + + if (!lttng_payload_view_is_valid(&comm_view)) { + /* Payload not large enough to contain the header. */ + return -1; + } + + comm = (typeof(comm)) comm_view.buffer.data; + consumed += sizeof(*comm); + + lttng_trace_format_descriptor_type type = (lttng_trace_format_descriptor_type) comm->type; + ret = _deserializer_map[type](view, descriptor); + if (ret < 0) { + return ret; + } + consumed += ret; + + ret = consumed; + + return ret; +} +} // namespace lttng + +struct lttng_trace_format_descriptor *lttng_trace_format_ctf_1_descriptor_create() +{ + lttng::trace_format_descriptor *descriptor = new lttng::trace_format_descriptor_ctf1(); + return reinterpret_cast(descriptor); +} + +struct lttng_trace_format_descriptor *lttng_trace_format_ctf_2_descriptor_create() +{ + lttng::trace_format_descriptor *descriptor = new lttng::trace_format_descriptor_ctf2(); + return reinterpret_cast(descriptor); +} + +void lttng_trace_format_descriptor_destroy(lttng_trace_format_descriptor *descriptor) +{ + if (descriptor == nullptr) { + return; + } + + lttng::trace_format_descriptor *_descriptor = + reinterpret_cast(descriptor); + + delete _descriptor; +} + +enum lttng_trace_format_descriptor_status lttng_trace_format_ctf_1_get_version( + const struct lttng_trace_format_descriptor *descriptor, + uint64_t *major, + uint64_t *minor) +{ + lttng_trace_format_descriptor_status status; + const lttng::trace_format_descriptor *tf; + const lttng::trace_format_descriptor_ctf1 *ctf1; + + if (descriptor == nullptr || major == nullptr || minor == nullptr) { + status = LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID; + goto end; + } + + tf = reinterpret_cast(descriptor); + + if (tf->type() != LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_1) { + status = LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID; + goto end; + } + + ctf1 = static_cast(tf); + + *major = ctf1->getMajor(); + *minor = ctf1->getMinor(); + status = LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_OK; + +end: + return status; +} + +enum lttng_trace_format_descriptor_status lttng_trace_format_ctf_2_get_version( + const struct lttng_trace_format_descriptor *descriptor, + uint64_t *major, + uint64_t *minor) +{ + lttng_trace_format_descriptor_status status; + const lttng::trace_format_descriptor *tf; + const lttng::trace_format_descriptor_ctf2 *ctf2; + + if (descriptor == nullptr || major == nullptr || minor == nullptr) { + status = LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID; + goto end; + } + + tf = reinterpret_cast(descriptor); + + if (tf->type() != LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_2) { + status = LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID; + goto end; + } + + ctf2 = static_cast(tf); + + *major = ctf2->getMajor(); + *minor = ctf2->getMinor(); + status = LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_OK; + +end: + return status; +} +enum lttng_trace_format_descriptor_type lttng_trace_format_get_type( + const struct lttng_trace_format_descriptor *descriptor) +{ + if (!descriptor) { + return LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_UNKNOWN; + } + + auto tf = reinterpret_cast(descriptor); + + return tf->type(); +} diff --git a/src/lib/lttng-ctl/liblttng-ctl.sym b/src/lib/lttng-ctl/liblttng-ctl.sym index b69e78df9..e72e121ba 100644 --- a/src/lib/lttng-ctl/liblttng-ctl.sym +++ b/src/lib/lttng-ctl/liblttng-ctl.sym @@ -504,6 +504,10 @@ lttng_trace_archive_location_relay_get_data_port lttng_trace_archive_location_relay_get_host lttng_trace_archive_location_relay_get_protocol_type lttng_trace_archive_location_relay_get_relative_path +lttng_trace_format_ctf_1_get_version +lttng_trace_format_ctf_2_get_version +lttng_trace_format_descriptor_destroy +lttng_trace_format_get_type lttng_track_pid lttng_trigger_create lttng_trigger_destroy diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am index d1b526d30..8bc59b3fe 100644 --- a/tests/unit/Makefile.am +++ b/tests/unit/Makefile.am @@ -32,6 +32,7 @@ TESTS = \ test_utils_expand_path \ test_utils_parse_size_suffix \ test_utils_parse_time_suffix \ + test_trace_format_descriptor \ test_uuid LIBTAP=$(top_builddir)/tests/utils/tap/libtap.la @@ -62,6 +63,7 @@ noinst_PROGRAMS = \ test_relayd_backward_compat_group_by_session \ test_session \ test_string_utils \ + test_trace_format_descriptor \ test_unix_socket \ test_uri \ test_utils_compat_poll \ @@ -189,3 +191,7 @@ test_log_level_rule_LDADD = $(LIBTAP) $(LIBCOMMON_GPL) $(LIBLTTNG_CTL) $(DL_LIBS # Action api test_action_SOURCES = test_action.cpp test_action_LDADD = $(LIBTAP) $(LIBCOMMON_GPL) $(LIBLTTNG_CTL) $(DL_LIBS) + +# Trace format descriptor +test_trace_format_descriptor_SOURCES = test_trace_format_descriptor.cpp +test_trace_format_descriptor_LDADD = $(LIBTAP) $(LIBCOMMON_GPL) $(LIBLTTNG_CTL) $(DL_LIBS) diff --git a/tests/unit/test_trace_format_descriptor.cpp b/tests/unit/test_trace_format_descriptor.cpp new file mode 100644 index 000000000..a9d3d3aa8 --- /dev/null +++ b/tests/unit/test_trace_format_descriptor.cpp @@ -0,0 +1,138 @@ +/* + * Unit tests for the trace format descriptor API. + * + * Copyright (C) 2022 Jonathan Rajotte + * + * SPDX-License-Identifier: MIT + * + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +/* For error.h */ +int lttng_opt_quiet = 1; +int lttng_opt_verbose; +int lttng_opt_mi; + +#define NUM_TESTS 28 + +static void test_trace_format_descriptor_base(void) +{ + lttng_trace_format_descriptor_status status; + uint64_t major; + uint64_t minor; + + lttng_trace_format_descriptor *ctf1 = lttng_trace_format_ctf_1_descriptor_create(); + lttng_trace_format_descriptor *ctf2 = lttng_trace_format_ctf_2_descriptor_create(); + ok1(ctf1); + ok1(ctf2); + + /* Ctf 1 */ + status = lttng_trace_format_ctf_1_get_version(nullptr, nullptr, nullptr); + ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID); + status = lttng_trace_format_ctf_1_get_version(nullptr, nullptr, &minor); + ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID); + status = lttng_trace_format_ctf_1_get_version(nullptr, &major, nullptr); + ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID); + status = lttng_trace_format_ctf_1_get_version(nullptr, &major, &minor); + ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID); + status = lttng_trace_format_ctf_1_get_version(ctf1, nullptr, nullptr); + ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID); + status = lttng_trace_format_ctf_1_get_version(ctf1, nullptr, &minor); + ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID); + status = lttng_trace_format_ctf_1_get_version(ctf1, &major, nullptr); + ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID); + + /* Wrong object type */ + status = lttng_trace_format_ctf_1_get_version(ctf2, &major, &minor); + ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID); + + status = lttng_trace_format_ctf_1_get_version(ctf1, &major, &minor); + ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_OK); + ok1(major == 1); + ok1(minor == 8); + + /* Ctf 2 */ + status = lttng_trace_format_ctf_2_get_version(nullptr, nullptr, nullptr); + ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID); + status = lttng_trace_format_ctf_2_get_version(nullptr, nullptr, &minor); + ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID); + status = lttng_trace_format_ctf_2_get_version(nullptr, &major, nullptr); + ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID); + status = lttng_trace_format_ctf_2_get_version(nullptr, &major, &minor); + ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID); + status = lttng_trace_format_ctf_2_get_version(ctf2, nullptr, nullptr); + ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID); + status = lttng_trace_format_ctf_2_get_version(ctf2, nullptr, &minor); + ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID); + status = lttng_trace_format_ctf_2_get_version(ctf2, &major, nullptr); + ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID); + + /* Wrong object type */ + status = lttng_trace_format_ctf_1_get_version(ctf2, &major, &minor); + ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID); + + status = lttng_trace_format_ctf_2_get_version(ctf2, &major, &minor); + ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_OK); + ok1(major == 2); + ok1(minor == 0); + + lttng_trace_format_descriptor_destroy(ctf1); + lttng_trace_format_descriptor_destroy(ctf2); +} + +static void test_trace_format_descriptor_ctf1_ser_des(void) +{ + struct lttng_payload buffer; + lttng_payload_init(&buffer); + + lttng::trace_format_descriptor::uptr descriptor_from_buffer; + lttng::trace_format_descriptor::uptr ctf1(new lttng::trace_format_descriptor_ctf1); + lttng::trace_format_descriptor::uptr ctf2(new lttng::trace_format_descriptor_ctf2); + + /* Ctf1 ser/des */ + ctf1->serialize(&buffer); + { + struct lttng_payload_view view = lttng_payload_view_from_payload(&buffer, 0, -1); + + (void) lttng::trace_format_descriptor::create_from_payload( + &view, descriptor_from_buffer); + } + + ok1(*descriptor_from_buffer == *ctf1); + ok1(*descriptor_from_buffer != *ctf2); + + lttng_payload_reset(&buffer); + + /* Ctf2 ser/des */ + ctf2->serialize(&buffer); + { + struct lttng_payload_view view = lttng_payload_view_from_payload(&buffer, 0, -1); + + (void) lttng::trace_format_descriptor::create_from_payload( + &view, descriptor_from_buffer); + } + + ok1(*descriptor_from_buffer != *ctf1); + ok1(*descriptor_from_buffer == *ctf2); + + lttng_payload_reset(&buffer); +} + +int main(void) +{ + plan_tests(NUM_TESTS); + test_trace_format_descriptor_base(); + test_trace_format_descriptor_ctf1_ser_des(); + return exit_status(); +} -- 2.34.1