Catch2: Problem with polling in tests
When running a test which needs event subscriptions only setting up polling server-side actually works.
When a client (test code) enables polling the subscription fails with
Error reason = API_AttributePollingNotStarted
Desc : The polling (necessary to send events) for the attribute attr_client is not started
even though the is_attribute_polled
call returns true
.
Below is a example of a test code where first scenario (server enabled polling) passes, and second one (client enabled polling) fails:
Click to expand
#include <tango/tango.h>
#include <memory>
#include "utils/utils.h"
// Test device class with two attributes:
// - attr_server, where polling is configured by server code
// - attr_client, where polling is configured by client code
template <class Base>
class PollingDev : public Base
{
public:
using Base::Base;
~PollingDev() override { }
void init_device() override
{
attr_value = 0;
}
void read_attribute(Tango::Attribute &att)
{
att.set_value_date_quality(&attr_value, std::chrono::system_clock::now(), Tango::ATTR_VALID);
}
static void attribute_factory(std::vector<Tango::Attr *> &attrs)
{
Tango::UserDefaultAttrProp props;
props.set_event_abs_change("0.0001");
// polling enabled by server code
auto attr_server = new TangoTest::AutoAttr<&PollingDev::read_attribute>("attr_server", Tango::DEV_DOUBLE);
attr_server->set_polling_period(100);
attr_server->set_default_properties(props);
attrs.push_back(attr_server);
// polling supposed to be enabled by client code
auto attr_client = new TangoTest::AutoAttr<&PollingDev::read_attribute>("attr_client", Tango::DEV_DOUBLE);
attr_client->set_default_properties(props);
attrs.push_back(attr_client);
}
private:
Tango::DevDouble attr_value;
};
// Simple event callback, which essentialy does nothing
class EvCb : public Tango::CallBack
{
public:
EvCb() { }
void push_event(Tango::EventData* ev)
{
double value;
*(ev->attr_value) >> value;
std::cout << "push_event: type=" << ev->event << "; value=" << value << "; quality=" << ev->attr_value->quality << "\n";
}
};
TANGO_TEST_AUTO_DEV_TMPL_INSTANTIATE(PollingDev, 4)
SCENARIO("Attribute with server configured polling can be subscribed to")
{
int idlver = GENERATE(range(4, 7));
GIVEN("a device proxy to a simple IDLv" << idlver << " device")
{
TangoTest::Context ctx{"polling", "PollingDev", idlver};
INFO(ctx.info());
auto device = ctx.get_proxy();
REQUIRE(idlver == device->get_idl_version());
AND_GIVEN("a server-side polled attribute")
{
std::string att{"attr_server"};
WHEN("we check that the attribute is polled")
{
bool is_polled = false;
REQUIRE_NOTHROW(is_polled = device->is_attribute_polled(att));
THEN("it is polled")
{
REQUIRE(is_polled);
}
}
WHEN("we subscribe to an event")
{
EvCb callback;
int evid;
THEN("the subscription succeeds")
{
REQUIRE_NOTHROW(evid = device->subscribe_event(att, Tango::CHANGE_EVENT, &callback));
}
}
}
}
}
SCENARIO("Attribute with client configured polling can be subscribed to")
{
int idlver = GENERATE(range(4, 7));
GIVEN("a device proxy to a simple IDLv" << idlver << " device")
{
TangoTest::Context ctx{"polling", "PollingDev", idlver};
INFO(ctx.info());
auto device = ctx.get_proxy();
REQUIRE(idlver == device->get_idl_version());
AND_GIVEN("a client-side polled attribute")
{
std::string att{"attr_client"};
WHEN("we enable attribute polling")
{
REQUIRE_NOTHROW(device->poll_attribute(att, 100));
THEN("it is polled")
{
bool is_polled = false;
REQUIRE_NOTHROW(is_polled = device->is_attribute_polled(att));
REQUIRE(is_polled);
}
}
WHEN("we subscribe to an event")
{
EvCb callback;
int evid;
THEN("the subscription succeeds")
{
REQUIRE_NOTHROW(evid = device->subscribe_event(att, Tango::CHANGE_EVENT, &callback));
}
}
}
}
}