tests/lib/conds: test clock compatibility post conditions
authorSimon Marchi <simon.marchi@efficios.com>
Thu, 21 Mar 2024 18:15:52 +0000 (14:15 -0400)
committerSimon Marchi <simon.marchi@efficios.com>
Tue, 26 Mar 2024 18:56:36 +0000 (14:56 -0400)
Add tests for the clock class compatibility post conditions in
`iterator.c`.  There is one test for each `BT_ASSERT_POST_DEV` in
`assert_post_dev_clock_classes_are_compatible_one`.

`addClockClsCompatTriggers()` adds a bunch of triggers that make a
message iterator return two messages with incompatible clock classes.
The message types that play a role in the clock compatibility checks are
"stream beginning" and "message iterator inactivity".
`addClockClsCompatTriggers()` adds all possible combinations of using
these two message types for the first and second message.  Since it's
not possible to send a message iterator inactivity message without a
clock class, some cases are skipped.

The change in `Makefile.am` is needed for the test to work in builds
with `--enable-built-in-plugins`, for the `RunIn` utility to be able to
find the `utils` plugin.  This was not needed before, because all the
existing triggers make the program stop before `RunIn` attempts to load
the `utils` plugin.

Change-Id: Ib6c22923e4e9f02de64a87efddaee3c23d3891ea
Signed-off-by: Simon Marchi <simon.marchi@efficios.com>
Reviewed-on: https://review.lttng.org/c/babeltrace/+/11811
Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
Tested-by: jenkins <jenkins@lttng.org>
tests/lib/Makefile.am
tests/lib/conds/clk-cls-compat-postconds-triggers.cpp [new file with mode: 0644]
tests/lib/conds/clk-cls-compat-postconds-triggers.hpp [new file with mode: 0644]
tests/lib/conds/conds-triggers.cpp

index e389f34b6693c467d087ef26c0cb8dcd1e1bb9ee..229e53c0f4ce363fa96d13b0097333b5f7291fa3 100644 (file)
@@ -1,5 +1,7 @@
 # SPDX-License-Identifier: MIT
 
+include $(top_srcdir)/src/Makefile.common.inc
+
 AM_CPPFLAGS += -I$(top_srcdir)/tests/utils
 
 noinst_LTLIBRARIES =
@@ -22,8 +24,6 @@ test_fields_bin_LDADD = $(COMMON_TEST_LDADD) \
 
 if ENABLE_BUILT_IN_PLUGINS
 
-include $(top_srcdir)/src/Makefile.common.inc
-
 test_fields_bin_LDFLAGS = $(call pluginarchive,utils)
 test_fields_bin_LDADD += \
        $(top_builddir)/src/plugins/common/param-validation/libparam-validation.la
@@ -135,13 +135,23 @@ noinst_PROGRAMS += conds/conds-triggers
 conds_conds_triggers_SOURCES = \
        conds/conds-triggers.cpp \
        conds/utils.cpp \
-       conds/utils.hpp
+       conds/utils.hpp \
+       conds/clk-cls-compat-postconds-triggers.cpp \
+       conds/clk-cls-compat-postconds-triggers.hpp
 
 conds_conds_triggers_LDADD = \
        $(COMMON_TEST_LDADD) \
        $(top_builddir)/src/lib/libbabeltrace2.la \
        $(top_builddir)/src/cpp-common/vendor/fmt/libfmt.la
 
+if ENABLE_BUILT_IN_PLUGINS
+
+conds_conds_triggers_LDFLAGS = $(call pluginarchive,utils)
+conds_conds_triggers_LDADD += \
+       $(top_builddir)/src/plugins/common/param-validation/libparam-validation.la
+
+endif # ENABLE_BUILT_IN_PLUGINS
+
 dist_check_SCRIPTS += conds/test-conds.sh conds/test.py
 
 endif
diff --git a/tests/lib/conds/clk-cls-compat-postconds-triggers.cpp b/tests/lib/conds/clk-cls-compat-postconds-triggers.cpp
new file mode 100644 (file)
index 0000000..a8a4d62
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Copyright (C) 2024 EfficiOS Inc.
+ */
+
+#include "cpp-common/bt2s/make-unique.hpp"
+#include "cpp-common/vendor/fmt/format.h" /* IWYU pragma: keep */
+
+#include "../utils/run-in.hpp"
+#include "clk-cls-compat-postconds-triggers.hpp"
+
+namespace {
+
+/*
+ * `RunIn` implementation to trigger clock (in)compatibility postcondition
+ * assertions.
+ */
+class ClockClsCompatRunIn final : public RunIn
+{
+public:
+    enum class MsgType
+    {
+        STREAM_BEG,
+        MSG_ITER_INACTIVITY,
+    };
+
+    using CreateClockCls = bt2::ClockClass::Shared (*)(bt2::SelfComponent);
+
+    explicit ClockClsCompatRunIn(const MsgType msgType1, const CreateClockCls createClockCls1,
+                                 const MsgType msgType2,
+                                 const CreateClockCls createClockCls2) noexcept :
+        _mMsgType1 {msgType1},
+        _mMsgType2 {msgType2}, _mCreateClockCls1 {createClockCls1}, _mCreateClockCls2 {
+                                                                        createClockCls2}
+    {
+    }
+
+    void onMsgIterNext(bt2::SelfMessageIterator self, bt2::ConstMessageArray& msgs) override
+    {
+        /* In case the expected assertion doesn't trigger, avoid looping indefinitely. */
+        BT_ASSERT(!_mBeenThere);
+
+        const auto traceCls = self.component().createTraceClass();
+        const auto trace = traceCls->instantiate();
+
+        msgs.append(this->_createOneMsg(self, _mMsgType1, _mCreateClockCls1, *trace));
+        msgs.append(this->_createOneMsg(self, _mMsgType2, _mCreateClockCls2, *trace));
+        _mBeenThere = true;
+    }
+
+private:
+    static bt2::Message::Shared _createOneMsg(const bt2::SelfMessageIterator self,
+                                              const MsgType msgType,
+                                              const CreateClockCls createClockCls,
+                                              const bt2::Trace trace)
+    {
+        const auto clockCls = createClockCls(self.component());
+
+        switch (msgType) {
+        case MsgType::STREAM_BEG:
+        {
+            const auto streamCls = trace.cls().createStreamClass();
+
+            if (clockCls) {
+                streamCls->defaultClockClass(*clockCls);
+            }
+
+            return self.createStreamBeginningMessage(*streamCls->instantiate(trace));
+        }
+
+        case MsgType::MSG_ITER_INACTIVITY:
+            BT_ASSERT(clockCls);
+            return self.createMessageIteratorInactivityMessage(*clockCls, 12);
+        };
+
+        bt_common_abort();
+    }
+
+    MsgType _mMsgType1, _mMsgType2;
+    CreateClockCls _mCreateClockCls1, _mCreateClockCls2;
+    bool _mBeenThere = false;
+};
+
+__attribute__((used)) const char *format_as(const ClockClsCompatRunIn::MsgType msgType)
+{
+    switch (msgType) {
+    case ClockClsCompatRunIn::MsgType::STREAM_BEG:
+        return "sb";
+
+    case ClockClsCompatRunIn::MsgType::MSG_ITER_INACTIVITY:
+        return "mii";
+    }
+
+    bt_common_abort();
+}
+
+bt2::ClockClass::Shared noClockClass(bt2::SelfComponent) noexcept
+{
+    return bt2::ClockClass::Shared {};
+}
+
+const bt2c::Uuid uuidA {"f00aaf65-ebec-4eeb-85b2-fc255cf1aa8a"};
+const bt2c::Uuid uuidB {"03482981-a77b-4d7b-94c4-592bf9e91785"};
+
+} /* namespace */
+
+/*
+ * Add clock class compatibility postcondition failures triggers.
+ *
+ * Each trigger below makes a message iterator return two messages with
+ * incompatible clock classes, leading to a postcondition failure.
+ */
+void addClkClsCompatTriggers(CondTriggers& triggers)
+{
+    const auto addValidCases = [&triggers](
+                                   const ClockClsCompatRunIn::CreateClockCls createClockCls1,
+                                   const ClockClsCompatRunIn::CreateClockCls createClockCls2,
+                                   const char * const condId) {
+        /*
+         * Add triggers for all possible combinations of message types.
+         *
+         * It's not possible to create message iterator inactivity messages
+         * without a clock class.
+         */
+        static constexpr std::array<ClockClsCompatRunIn::MsgType, 2> msgTypes {
+            ClockClsCompatRunIn::MsgType::STREAM_BEG,
+            ClockClsCompatRunIn::MsgType::MSG_ITER_INACTIVITY,
+        };
+
+        const auto isInvalidCase = [](const ClockClsCompatRunIn::MsgType msgType,
+                                      const ClockClsCompatRunIn::CreateClockCls createClockCls) {
+            return msgType == ClockClsCompatRunIn::MsgType::MSG_ITER_INACTIVITY &&
+                   createClockCls == noClockClass;
+        };
+
+        for (const auto msgType1 : msgTypes) {
+            if (isInvalidCase(msgType1, createClockCls1)) {
+                continue;
+            }
+
+            for (const auto msgType2 : msgTypes) {
+                if (isInvalidCase(msgType2, createClockCls2)) {
+                    continue;
+                }
+
+                triggers.emplace_back(bt2s::make_unique<RunInCondTrigger<ClockClsCompatRunIn>>(
+                    ClockClsCompatRunIn {msgType1, createClockCls1, msgType2, createClockCls2},
+                    CondTrigger::Type::POST, condId, fmt::format("{}-{}", msgType1, msgType2)));
+            }
+        }
+    };
+
+    addValidCases(
+        noClockClass,
+        [](const bt2::SelfComponent self) {
+            return self.createClockClass();
+        },
+        "message-iterator-class-next-method:stream-class-has-no-clock-class");
+
+    addValidCases(
+        [](const bt2::SelfComponent self) {
+            return self.createClockClass();
+        },
+        noClockClass,
+        "message-iterator-class-next-method:stream-class-has-clock-class-with-unix-epoch-origin");
+
+    addValidCases(
+        [](const bt2::SelfComponent self) {
+            return self.createClockClass();
+        },
+        [](const bt2::SelfComponent self) {
+            const auto clockCls = self.createClockClass();
+
+            clockCls->originIsUnixEpoch(false);
+            return clockCls;
+        },
+        "message-iterator-class-next-method:clock-class-has-unix-epoch-origin");
+
+    addValidCases(
+        [](const bt2::SelfComponent self) {
+            const auto clockCls = self.createClockClass();
+
+            clockCls->originIsUnixEpoch(false).uuid(uuidA);
+            return clockCls;
+        },
+        noClockClass, "message-iterator-class-next-method:stream-class-has-clock-class-with-uuid");
+
+    addValidCases(
+        [](const bt2::SelfComponent self) {
+            const auto clockCls = self.createClockClass();
+
+            clockCls->originIsUnixEpoch(false).uuid(uuidA);
+            return clockCls;
+        },
+        [](const bt2::SelfComponent self) {
+            return self.createClockClass();
+        },
+        "message-iterator-class-next-method:clock-class-has-non-unix-epoch-origin");
+
+    addValidCases(
+        [](const bt2::SelfComponent self) {
+            const auto clockCls = self.createClockClass();
+
+            clockCls->originIsUnixEpoch(false).uuid(uuidA);
+            return clockCls;
+        },
+        [](const bt2::SelfComponent self) {
+            const auto clockCls = self.createClockClass();
+
+            clockCls->originIsUnixEpoch(false);
+            return clockCls;
+        },
+        "message-iterator-class-next-method:clock-class-has-uuid");
+
+    addValidCases(
+        [](const bt2::SelfComponent self) {
+            const auto clockCls = self.createClockClass();
+
+            clockCls->originIsUnixEpoch(false).uuid(uuidA);
+            return clockCls;
+        },
+        [](const bt2::SelfComponent self) {
+            const auto clockCls = self.createClockClass();
+
+            clockCls->originIsUnixEpoch(false).uuid(uuidB);
+            return clockCls;
+        },
+        "message-iterator-class-next-method:clock-class-has-expected-uuid");
+
+    addValidCases(
+        [](const bt2::SelfComponent self) {
+            const auto clockCls = self.createClockClass();
+
+            clockCls->originIsUnixEpoch(false);
+            return clockCls;
+        },
+        noClockClass, "message-iterator-class-next-method:stream-class-has-clock-class");
+
+    addValidCases(
+        [](const bt2::SelfComponent self) {
+            const auto clockCls = self.createClockClass();
+
+            clockCls->originIsUnixEpoch(false);
+            return clockCls;
+        },
+        [](const bt2::SelfComponent self) {
+            const auto clockCls = self.createClockClass();
+
+            clockCls->originIsUnixEpoch(false);
+            return clockCls;
+        },
+        "message-iterator-class-next-method:clock-class-is-expected");
+}
diff --git a/tests/lib/conds/clk-cls-compat-postconds-triggers.hpp b/tests/lib/conds/clk-cls-compat-postconds-triggers.hpp
new file mode 100644 (file)
index 0000000..cabf25c
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Copyright (C) 2024 EfficiOS Inc.
+ */
+
+#ifndef TESTS_LIB_CONDS_CLK_CLS_COMPAT_POSTCONDS_TRIGGERS_HPP
+#define TESTS_LIB_CONDS_CLK_CLS_COMPAT_POSTCONDS_TRIGGERS_HPP
+
+#include "utils.hpp"
+
+void addClkClsCompatTriggers(CondTriggers& triggers);
+
+#endif
index 857cfbcc59284764ef82018c13f0714ae14a1a4b..3e1cfe864140ee0afe0fee53ba262a913ade2cab 100644 (file)
@@ -13,6 +13,7 @@
 #include "cpp-common/bt2c/span.hpp"
 #include "cpp-common/bt2s/make-unique.hpp"
 
+#include "clk-cls-compat-postconds-triggers.hpp"
 #include "utils.hpp"
 
 namespace {
@@ -107,5 +108,6 @@ int main(const int argc, const char ** const argv)
         },
         CondTrigger::Type::PRE, "field-class-integer-set-field-value-range:not-null:field-class"));
 
+    addClkClsCompatTriggers(triggers);
     condMain(bt2c::makeSpan(argv, argc), triggers);
 }
This page took 0.028057 seconds and 4 git commands to generate.