v.5.8.3 - Stiffstream/sobjectizer GitHub Wiki
This page describes changes and new features of v.5.8.3.
There are several new features in so_5::experimental::testing
namespace for simplification of testing of agents.
A possibility to inspect the content of the message before invocation of the event handler:
namespace tests = so_5::experimental::testing;
tests::testing_env_t sobj;
...
sobj.scenario().define_step("step-with-inspection")
.when(*some_agent
& tests::reacts_to<some_message>()
// Do inspection of the incoming message and store it with
// `inspection-result` tag for the step.
& tests::inspect_msg("inspection-result",
[](const some_message & msg) -> std::string {
if(msg.field_one != expected_value) return "field_one mismatch";
if(msg.field_two != another_expected_value) return "field_two mismatch";
... // And so on.
return "OK"; // Everything is fine.
})
);
...
sobj.scenario().run_for(100ms);
REQUIRE(tests::complected() == sobj.scenario().result());
REQUIRE("OK" == sobj.scenario().stored_msg_inspection_result(
"step-with-inspection", "inspection-result"));
...
Explicit wait for completion of an event handler before the completion of the testing scenario:
namespace tests = so_5::experimental::testing;
tests::testing_env_t sobj;
...
std::string shared_data; // An agent has to modify this object during message processing.
my_agent * agent_to_check = sobj.environment().introduce_coop(
[&shared_data](so_5::coop_t & coop) {
// Agent will store a reference to shared_data and the use it.
return coop.make_agent<my_agent>(shared_data);
});
sobj.scenario().define_step("the-only-step")
.intact<some_message>(*agent_to_check)
.when(*agent_to_check
& tests::reacts_to<some_message>()
// Without this modificator the scenario completes when agent receives message,
// but the actual message processing may not be completed yet.
& tests::wait_event_handler_completion());
sobj.scenario().run_for(100ms);
REQUIRE(tests::complected() == sobj.scenario().result());
// Now it's safe to check the shared_data because the agent_to_check has completed
// the message processing.
REQUIRE(some_expected_value == shared_data));
A possibility to check that a message is sent to a mbox:
namespace tests = so_5::experimental::testing;
tests::testing_env_t sobj;
...
auto mbox_to_check = sobj.environment().create_mbox();
...
sobj.scenario().define_step("message-is-sent")
.when(mbox_to_check & tests::receives<some_message>());
It's possible to trace a signle message/signal delivery:
so_5::send<MsgToTrace>(so_5::msg_tracing::individual_trace(dest), ...);
To use this feature a special delivery tracing filter has to be set:
so_5::launch([](so_5::environment_t & env) {...},
[](so_5::environment_params_t & params) {
params.message_delivery_tracer(
so_5::msg_tracing::std_cout_tracer());
params.message_delivery_tracer_filter(
so_5::msg_tracing::make_individual_trace_filter());
});
There are empty methods lock_shared
and unlock_shared
in so_5::null_mutex_t
class so this class can now be used in places where std::shared_mutex
(or something like that) is expected.
There was a problem in previous versions of SObjectizer: if a message limit is defined for an agent then it's impossible to use time_limit
for agent's states. An attempt to do so led to the crash of the application because time_limit
tried to send an internal message for that message limit wasn't defined, it led to raising of an exception in a noexcept-context and it led to std::terminate
.
Since v.5.8.3 this problem is solved: if a user specifies message limit(s) for an agent then a hidden limit is automatically added. This is a special no-op limit for internal message used by time_limit
method. So now time_limit
can send this message and it won't lead to an exception.