Skip to content

v.5.8.3

Yauheni Akhotnikau edited this page Oct 25, 2024 · 1 revision

This page describes changes and new features of v.5.8.3.

New features for testing of agents

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>());

Individual trace of message/signal delivery

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());
   });

The null_mutex_t helper class can now be used as no-op shared_mutex

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.

A problem with message limit and state's time_limit resolved

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.

Clone this wiki locally