From 484a30244f4297ce7f0ac0ea1c0c4d566b39c46e Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Tue, 23 May 2023 14:19:42 -0400 Subject: [PATCH] tests: add framework to run code in comp cls / comp / msg iter context Add a little framework to make it easier to write tests that need a bt_self_component_class, bt_self_component or bt_self_message_iterator. This is inspired from what we have already in tests/lib/conds/utils.{hpp,cpp}, but decoupled from the pre/post-condition assertion tests. A subsequent commit will change this test to use the new framework. The framework exposes the run_in function, which accepts three callbacks that are executed at three different points in the graph's lifecycle, providing access to all three contexts. Each callback may be nullptr. For convenience, there are also three functions to run code in each individual context: - runInCompClsQuery - runInCompClsInitFunc - runInMsgIterClsInitFunc If needed, some additional hook points can be added later, to access other points of the graph's lifecycle. The run_in function makes an end-to-end run: - creates a graph - creates a source component class - makes a query on that component class - adds a source component - adds a dummy sink component, connects the ports of the two components - runs the graph Even for a test that only needs to run code in component class context, for instance, we still run the whole enchilada. This is a bit inefficient, but given that this is just for testing, we don't really care, as it still runs quick. Change-Id: Ie532b316dc330758b60fd5f6fe9499f0555f8a8a Signed-off-by: Simon Marchi Reviewed-on: https://review.lttng.org/c/babeltrace/+/10060 Reviewed-by: Philippe Proulx Tested-by: jenkins --- configure.ac | 1 + tests/lib/Makefile.am | 2 +- tests/lib/utils/Makefile.am | 2 + tests/lib/utils/run-in.cpp | 207 ++++++++++++++++++++++++++++++++++++ tests/lib/utils/run-in.hpp | 47 ++++++++ 5 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 tests/lib/utils/Makefile.am create mode 100644 tests/lib/utils/run-in.cpp create mode 100644 tests/lib/utils/run-in.hpp diff --git a/configure.ac b/configure.ac index 59c0bac1..364ee762 100644 --- a/configure.ac +++ b/configure.ac @@ -862,6 +862,7 @@ AC_CONFIG_FILES([ tests/lib/Makefile tests/lib/test-plugin-plugins/Makefile tests/lib/conds/Makefile + tests/lib/utils/Makefile tests/Makefile tests/param-validation/Makefile tests/plugins/Makefile diff --git a/tests/lib/Makefile.am b/tests/lib/Makefile.am index c1b68d7f..cc91bb2b 100644 --- a/tests/lib/Makefile.am +++ b/tests/lib/Makefile.am @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -SUBDIRS = +SUBDIRS = utils AM_CPPFLAGS += -I$(top_srcdir)/tests/utils diff --git a/tests/lib/utils/Makefile.am b/tests/lib/utils/Makefile.am new file mode 100644 index 00000000..21d90175 --- /dev/null +++ b/tests/lib/utils/Makefile.am @@ -0,0 +1,2 @@ +noinst_LTLIBRARIES = liblib-utils.la +liblib_utils_la_SOURCES = run-in.cpp run-in.hpp diff --git a/tests/lib/utils/run-in.cpp b/tests/lib/utils/run-in.cpp new file mode 100644 index 00000000..3a3a0a26 --- /dev/null +++ b/tests/lib/utils/run-in.cpp @@ -0,0 +1,207 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (C) 2020-2023 EfficiOS, inc. + */ + +#include + +#include "run-in.hpp" +#include "common/assert.h" + +struct RunInData final +{ + RunInCompClsQueryFunc compClsCtxFunc; + RunInCompClsInitFunc compCtxFunc; + RunInMsgIterClsInitFunc msgIterCtxFunc; +}; + +static const RunInData& runInDataFromMethodData(void * const methodData) +{ + return *static_cast(methodData); +} + +static bt_component_class_initialize_method_status +compClsInit(bt_self_component_source * const selfComp, bt_self_component_source_configuration *, + const bt_value *, void * const initMethodData) +{ + const auto status = + bt_self_component_source_add_output_port(selfComp, "out", initMethodData, nullptr); + + BT_ASSERT(status == BT_SELF_COMPONENT_ADD_PORT_STATUS_OK); + + auto& data = runInDataFromMethodData(initMethodData); + + if (data.compCtxFunc) { + data.compCtxFunc(bt_self_component_source_as_self_component(selfComp)); + } + + return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK; +} + +static bt_component_class_query_method_status +compClsQuery(bt_self_component_class_source * const selfCompCls, bt_private_query_executor *, + const char *, const bt_value *, void * const methodData, + const bt_value ** const result) +{ + auto& data = runInDataFromMethodData(methodData); + + if (data.compClsCtxFunc) { + data.compClsCtxFunc(bt_self_component_class_source_as_self_component_class(selfCompCls)); + } + + *result = bt_value_null; + return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_OK; +} + +static bt_message_iterator_class_initialize_method_status +msgIterClsInit(bt_self_message_iterator * const selfMsgIter, + bt_self_message_iterator_configuration *, bt_self_component_port_output * const port) +{ + auto& data = runInDataFromMethodData(bt_self_component_port_get_data( + bt_self_component_port_output_as_self_component_port(port))); + + if (data.msgIterCtxFunc) { + data.msgIterCtxFunc(selfMsgIter); + } + + return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_OK; +} + +static bt_message_iterator_class_next_method_status +msgIterClsNext(bt_self_message_iterator *, bt_message_array_const, uint64_t, uint64_t *) +{ + return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_END; +} + +void runIn(RunInCompClsQueryFunc compClsCtxFunc, RunInCompClsInitFunc compCtxFunc, + RunInMsgIterClsInitFunc msgIterCtxFunc) +{ + RunInData data {std::move(compClsCtxFunc), std::move(compCtxFunc), std::move(msgIterCtxFunc)}; + + /* Create and configure custom source component class */ + const auto msgIterCls = bt_message_iterator_class_create(msgIterClsNext); + + BT_ASSERT(msgIterCls); + + { + const auto status = + bt_message_iterator_class_set_initialize_method(msgIterCls, msgIterClsInit); + + BT_ASSERT(status == BT_MESSAGE_ITERATOR_CLASS_SET_METHOD_STATUS_OK); + } + + const auto srcCompCls = bt_component_class_source_create("yo", msgIterCls); + + BT_ASSERT(srcCompCls); + + { + const auto status = + bt_component_class_source_set_initialize_method(srcCompCls, compClsInit); + + BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK); + } + + { + const auto status = bt_component_class_source_set_query_method(srcCompCls, compClsQuery); + + BT_ASSERT(status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK); + } + + /* Execute a query (executes `compClsCtxFunc`) */ + { + const auto queryExec = bt_query_executor_create_with_method_data( + bt_component_class_source_as_component_class(srcCompCls), "", nullptr, &data); + + BT_ASSERT(queryExec); + + const bt_value *queryRes; + const auto status = bt_query_executor_query(queryExec, &queryRes); + + BT_ASSERT(status == BT_QUERY_EXECUTOR_QUERY_STATUS_OK); + + bt_value_put_ref(queryRes); + bt_query_executor_put_ref(queryExec); + } + + /* Create graph */ + const auto graph = bt_graph_create(0); + + BT_ASSERT(graph); + + /* Add custom source component (executes `compCtxFunc`) */ + const bt_component_source *srcComp; + + { + const auto status = bt_graph_add_source_component_with_initialize_method_data( + graph, srcCompCls, "whatever", NULL, &data, BT_LOGGING_LEVEL_NONE, &srcComp); + + BT_ASSERT(status == BT_GRAPH_ADD_COMPONENT_STATUS_OK); + } + + /* Find `sink.utils.dummy` component class */ + const bt_plugin *utilsPlugin = nullptr; + + { + const auto status = + bt_plugin_find("utils", BT_TRUE, BT_TRUE, BT_TRUE, BT_TRUE, BT_TRUE, &utilsPlugin); + + BT_ASSERT(status == BT_PLUGIN_FIND_STATUS_OK); + } + + /* Add `sink.utils.dummy` component */ + const bt_component_sink *sinkComp; + + { + const auto dummyCompCls = + bt_plugin_borrow_sink_component_class_by_name_const(utilsPlugin, "dummy"); + + BT_ASSERT(dummyCompCls); + + const auto status = bt_graph_add_sink_component(graph, dummyCompCls, "the-sink", nullptr, + BT_LOGGING_LEVEL_NONE, &sinkComp); + + BT_ASSERT(status == BT_GRAPH_ADD_COMPONENT_STATUS_OK); + } + + /* Connect ports */ + { + const auto outPort = bt_component_source_borrow_output_port_by_name_const(srcComp, "out"); + + BT_ASSERT(outPort); + + const auto inPort = bt_component_sink_borrow_input_port_by_name_const(sinkComp, "in"); + + BT_ASSERT(inPort); + + const auto status = bt_graph_connect_ports(graph, outPort, inPort, nullptr); + + BT_ASSERT(status == BT_GRAPH_CONNECT_PORTS_STATUS_OK); + } + + /* Run graph (executes `msgIterCtxFunc`) */ + const auto status = bt_graph_run(graph); + + BT_ASSERT(status == BT_GRAPH_RUN_STATUS_OK); + + /* Discard plugin and graph */ + bt_plugin_put_ref(utilsPlugin); + bt_graph_put_ref(graph); + bt_component_class_source_put_ref(srcCompCls); + bt_message_iterator_class_put_ref(msgIterCls); +} + +void runInCompClsQuery(RunInCompClsQueryFunc func) +{ + runIn(std::move(func), nullptr, nullptr); +} + +void runInCompClsInit(RunInCompClsInitFunc func) +{ + runIn(nullptr, std::move(func), nullptr); +} + +void runInMsgIterClsInit(RunInMsgIterClsInitFunc func) +{ + runIn(nullptr, nullptr, std::move(func)); +} diff --git a/tests/lib/utils/run-in.hpp b/tests/lib/utils/run-in.hpp new file mode 100644 index 00000000..2220b977 --- /dev/null +++ b/tests/lib/utils/run-in.hpp @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (C) 2020-2023 EfficiOS, inc. + */ + +#ifndef TESTS_LIB_UTILS_H +#define TESTS_LIB_UTILS_H + +#include +#include + +using RunInCompClsQueryFunc = std::function; +using RunInCompClsInitFunc = std::function; +using RunInMsgIterClsInitFunc = std::function; + +/* + * Runs: + * + * • `compClsCtxFunc` in the context of a component class method, + * if not `nullptr`. + * + * • `compCtxFunc` in the context of a component method, if not + * `nullptr`. + * + * • `msgIterCtxFunc` in the context of a message iterator method, if + * not `nullptr`. + */ +void runIn(RunInCompClsQueryFunc compClsCtxFunc, RunInCompClsInitFunc compCtxFunc, + RunInMsgIterClsInitFunc msgIterCtxFunc); + +/* + * Runs `func` in the context of a component class method. + */ +void runInCompClsQuery(RunInCompClsQueryFunc func); + +/* + * Runs `func` in the context of a component method. + */ +void runInCompClsInit(RunInCompClsInitFunc func); + +/* + * Runs `func` in the context of a message iterator method. + */ +void runInMsgIterClsInit(RunInMsgIterClsInitFunc func); + +#endif /* TESTS_LIB_UTILS_H */ -- 2.34.1