X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=tests%2Flib%2Fconds%2Fclk-cls-compat-postconds-triggers.cpp;fp=tests%2Flib%2Fconds%2Fclk-cls-compat-postconds-triggers.cpp;h=a8a4d626b7f0d0ac0fd07ef3142825d0b6f68b4d;hp=0000000000000000000000000000000000000000;hb=c3211f0a28bc015d1fb04c600779d47f9896d4cc;hpb=6829fa26444f1f5c5bf31312222e900d012c3ad2 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 index 00000000..a8a4d626 --- /dev/null +++ b/tests/lib/conds/clk-cls-compat-postconds-triggers.cpp @@ -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 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>( + 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"); +}