doc/api/libbabeltrace2/DoxygenLayout.xml: use `topics` tab
[babeltrace.git] / tests / lib / conds / utils.hpp
index bab8caeac42737f25268f4f1154c3105e069b863..2ea53bc4e8d7739f488df13decac8f8d8f514986 100644 (file)
  * Copyright (C) 2020 Philippe Proulx <pproulx@efficios.com>
  */
 
-#ifndef TESTS_LIB_CONDS_UTILS_H
-#define TESTS_LIB_CONDS_UTILS_H
+#ifndef TESTS_LIB_CONDS_UTILS_HPP
+#define TESTS_LIB_CONDS_UTILS_HPP
 
-enum cond_trigger_func_type
-{
-    COND_TRIGGER_FUNC_TYPE_BASIC,
-    COND_TRIGGER_FUNC_TYPE_RUN_IN_COMP_CLS_INIT,
-};
+#include <functional>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
 
-enum cond_trigger_type
-{
-    COND_TRIGGER_TYPE_PRE,
-    COND_TRIGGER_TYPE_POST,
-};
+#include <babeltrace2/babeltrace.h>
 
-typedef void (*cond_trigger_basic_func)(void);
-typedef void (*cond_trigger_run_in_comp_cls_init_func)(bt_self_component *);
+#include "cpp-common/bt2c/c-string-view.hpp"
+#include "cpp-common/bt2s/span.hpp"
 
-struct cond_trigger
+#include "../utils/run-in.hpp"
+
+/*
+ * Abstract condition trigger class.
+ *
+ * A derived class must provide operator()() which triggers a condition
+ * of which the specific type (precondition or postcondition) and ID are
+ * provided at construction time.
+ */
+class CondTrigger
 {
-    enum cond_trigger_type type;
-    enum cond_trigger_func_type func_type;
-    const char *cond_id;
-    const char *suffix;
-    union
+public:
+    using UP = std::unique_ptr<CondTrigger>;
+
+    /*
+     * Condition type.
+     */
+    enum class Type
+    {
+        Pre,
+        Post,
+    };
+
+protected:
+    /*
+     * Builds a condition trigger having the type `type`, the condition
+     * ID `condId` (_without_ any `pre:` or `post:` prefix), and the
+     * optional name suffix `nameSuffix`.
+     *
+     * The concatenation of `condId` and, if it's set, `-` and
+     * `*nameSuffix`, forms the name of the condition trigger. Get the
+     * name of the created condition trigger with name().
+     */
+    explicit CondTrigger(Type type, const std::string& condId,
+                         const bt2c::CStringView nameSuffix) noexcept;
+
+public:
+    virtual ~CondTrigger() = default;
+    virtual void operator()() noexcept = 0;
+
+    Type type() const noexcept
+    {
+        return _mType;
+    }
+
+    /*
+     * Condition ID, including any `pre:` or `post:` prefix.
+     */
+    const std::string& condId() const noexcept
     {
-        cond_trigger_basic_func basic;
-        cond_trigger_run_in_comp_cls_init_func run_in_comp_cls_init;
-    } func;
+        return _mCondId;
+    }
+
+    const std::string& name() const noexcept
+    {
+        return _mName;
+    }
+
+private:
+    Type _mType;
+    std::string _mCondId;
+    std::string _mName;
 };
 
-#define COND_TRIGGER_PRE_BASIC(_cond_id, _suffix, _func)                                           \
-    {                                                                                              \
-        .type = COND_TRIGGER_TYPE_PRE, .func_type = COND_TRIGGER_FUNC_TYPE_BASIC,                  \
-        .cond_id = _cond_id, .suffix = _suffix, .func = {                                          \
-            .basic = _func,                                                                        \
-        }                                                                                          \
+/*
+ * Simple condition trigger.
+ *
+ * Implements a condition trigger where a function provided at
+ * construction time triggers a condition.
+ */
+class SimpleCondTrigger : public CondTrigger
+{
+public:
+    explicit SimpleCondTrigger(std::function<void()> func, Type type, const std::string& condId,
+                               const bt2c::CStringView nameSuffix = {});
+
+    void operator()() noexcept override
+    {
+        _mFunc();
     }
 
-#define COND_TRIGGER_POST_BASIC(_cond_id, _suffix, _func)                                          \
-    {                                                                                              \
-        .type = COND_TRIGGER_TYPE_POST, .func_type = COND_TRIGGER_FUNC_TYPE_BASIC,                 \
-        .cond_id = _cond_id, .suffix = _suffix, .func = {                                          \
-            .basic = _func,                                                                        \
-        }                                                                                          \
+private:
+    std::function<void()> _mFunc;
+};
+
+/*
+ * Run-in condition trigger.
+ *
+ * Implements a condition trigger of which the triggering function
+ * happens in a graph or component class query context using the
+ * runIn() API.
+ */
+template <typename RunInT>
+class RunInCondTrigger : public CondTrigger
+{
+public:
+    explicit RunInCondTrigger(RunInT runIn, const Type type, const std::string& condId,
+                              const bt2c::CStringView nameSuffix = {}) :
+        CondTrigger {type, condId, nameSuffix},
+        _mRunIn {std::move(runIn)}
+    {
     }
 
-#define COND_TRIGGER_PRE_RUN_IN_COMP_CLS_INIT(_cond_id, _suffix, _func)                            \
-    {                                                                                              \
-        .type = COND_TRIGGER_TYPE_PRE, .func_type = COND_TRIGGER_FUNC_TYPE_RUN_IN_COMP_CLS_INIT,   \
-        .cond_id = _cond_id, .suffix = _suffix, .func = {                                          \
-            .run_in_comp_cls_init = _func,                                                         \
-        }                                                                                          \
+    explicit RunInCondTrigger(const Type type, const std::string& condId,
+                              const bt2c::CStringView nameSuffix = {}) :
+        RunInCondTrigger {RunInT {}, type, condId, nameSuffix}
+    {
     }
 
-#define COND_TRIGGER_POST_RUN_IN_COMP_CLS_INIT(_cond_id, _suffix, _func)                           \
-    {                                                                                              \
-        .type = COND_TRIGGER_TYPE_POST, .func_type = COND_TRIGGER_FUNC_TYPE_RUN_IN_COMP_CLS_INIT,  \
-        .cond_id = _cond_id, .suffix = _suffix, .func = {                                          \
-            .run_in_comp_cls_init = _func,                                                         \
-        }                                                                                          \
+    void operator()() noexcept override
+    {
+        runIn(_mRunIn);
     }
 
-void cond_main(int argc, const char *argv[], const struct cond_trigger triggers[],
-               size_t trigger_count);
+private:
+    RunInT _mRunIn;
+};
+
+/*
+ * List of condition triggers.
+ */
+using CondTriggers = std::vector<CondTrigger::UP>;
+
+/*
+ * The entry point of a condition trigger program.
+ *
+ * Call this from your own main() with your list of condition triggers
+ * `triggers`.
+ *
+ * Each condition trigger of `triggers` must have a unique name, as
+ * returned by CondTrigger::name().
+ *
+ * This function uses `argc` and `argv` to respond to one of the
+ * following commands:
+ *
+ * `list`:
+ *     Prints a list of condition triggers as a JSON array of objects.
+ *
+ *     Each JSON object has:
+ *
+ *     `cond-id`:
+ *         The condition ID of the trigger, as returned by
+ *         CondTrigger:condId().
+ *
+ *     `name`:
+ *         The condition ID name, as returned by CondTrigger::name().
+ *
+ * `run`:
+ *     Runs the triggering function of the condition trigger at the
+ *     index specified by the next command-line argument.
+ *
+ *     For example,
+ *
+ *         $ my-cond-trigger-program run 45
+ *
+ *     would run the function of the condition trigger `triggers[45]`.
+ *
+ *     The program is expected to abort through a libbabeltrace2
+ *     condition failure.
+ */
+void condMain(const bt2s::span<const char * const> argv, const CondTriggers& triggers) noexcept;
 
-#endif /* TESTS_LIB_CONDS_UTILS_H */
+#endif /* TESTS_LIB_CONDS_UTILS_HPP */
This page took 0.025903 seconds and 4 git commands to generate.