4 #define BOOST_TEST_DYN_LINK
5 #define BOOST_TEST_MODULE AsyncReadTest
6 #include <boost/test/unit_test.hpp>
7 using namespace boost::unit_test_framework;
10 #include "DeviceAccessVersion.h"
14 #include <boost/thread.hpp>
22 using namespace boost::unit_test_framework;
25 std::string
cdd =
"(AsyncTestDummy)";
37 static boost::shared_ptr<DeviceBackend>
createInstance(std::string, std::map<std::string, std::string>) {
41 template<
typename UserType>
47 buffer_2D[0].resize(1);
48 this->_readQueue = {3};
49 _backend->notificationQueue[getName()] = this->_readQueue;
63 if constexpr(!std::is_same<UserType, Void>::value) {
65 if(!hasNewData)
return;
66 buffer_2D[0][0] = _backend->registers.at(getName());
67 this->_versionNumber = {};
71 [[nodiscard]]
bool isReadOnly()
const override {
return false; }
72 [[nodiscard]]
bool isReadable()
const override {
return true; }
73 [[nodiscard]]
bool isWriteable()
const override {
return true; }
76 return {this->shared_from_this()};
80 size_t nPostReadCalled{0};
88 template<
typename UserType>
91 assert(numberOfWords == 1);
92 assert(wordOffsetInRegister == 0);
94 (void)wordOffsetInRegister;
95 boost::shared_ptr<NDRegisterAccessor<UserType>> retval =
96 boost::make_shared<Accessor<UserType>>(
this, registerPathName, flags);
97 retval->setExceptionBackend(shared_from_this());
105 _hasActiveException =
false;
108 void close()
override { _opened =
false; }
117 bool _hasActiveException{
false};
124 BackendFactory::getInstance().registerBackendType(
126 BackendFactory::getInstance().setDMapFilePath(
"dummies.dmap");
135 std::cout <<
"testAsyncRead" << std::endl;
139 auto backend = boost::dynamic_pointer_cast<AsyncTestDummy>(BackendFactory::getInstance().createBackend(
cdd));
140 BOOST_CHECK(backend !=
nullptr);
146 backend->registers[
"/REG"] = 5;
148 auto waitForRead = std::async(std::launch::async, [&accessor] { accessor.read(); });
149 auto waitStatus = waitForRead.wait_for(std::chrono::seconds(1));
150 BOOST_CHECK(waitStatus != std::future_status::ready);
152 backend->notificationQueue[
"/REG"].push();
155 BOOST_CHECK(accessor == 5);
156 BOOST_CHECK(backend->notificationQueue[
"/REG"].empty());
158 backend->registers[
"/REG"] = 6;
159 waitForRead = std::async(std::launch::async, [&accessor] { accessor.read(); });
160 waitStatus = waitForRead.wait_for(std::chrono::seconds(1));
161 BOOST_CHECK(waitStatus != std::future_status::ready);
163 backend->notificationQueue[
"/REG"].push();
166 BOOST_CHECK(accessor == 6);
167 BOOST_CHECK(backend->notificationQueue[
"/REG"].empty());
175 std::cout <<
"testReadAny" << std::endl;
179 auto backend = boost::dynamic_pointer_cast<AsyncTestDummy>(BackendFactory::getInstance().createBackend(
cdd));
180 BOOST_CHECK(backend !=
nullptr);
195 backend->registers[
"/a1"] = 42;
196 backend->registers[
"/a2"] = 123;
197 backend->registers[
"/a3"] = 120;
198 backend->registers[
"/a4"] = 345;
213 std::atomic<bool> flag{
false};
214 std::thread thread([&group, &flag, &
id] {
221 BOOST_CHECK(flag ==
false);
224 backend->notificationQueue[
"/a1"].push();
226 BOOST_CHECK(a1 == 42);
227 BOOST_CHECK(a2 == 2);
228 BOOST_CHECK(a3 == 3);
229 BOOST_CHECK(a4 == 4);
230 BOOST_CHECK(
id == a1.getId());
236 std::atomic<bool> flag{
false};
237 std::thread thread([&group, &flag, &
id] {
244 BOOST_CHECK(flag ==
false);
247 backend->notificationQueue[
"/a3"].push();
249 BOOST_CHECK(a1 == 42);
250 BOOST_CHECK(a2 == 2);
251 BOOST_CHECK(a3 == 120);
252 BOOST_CHECK(a4 == 4);
253 BOOST_CHECK(
id == a3.getId());
259 std::atomic<bool> flag{
false};
260 std::thread thread([&group, &flag, &
id] {
267 BOOST_CHECK(flag ==
false);
270 backend->registers[
"/a3"] = 121;
271 backend->notificationQueue[
"/a3"].push();
273 BOOST_CHECK(a1 == 42);
274 BOOST_CHECK(a2 == 2);
275 BOOST_CHECK(a3 == 121);
276 BOOST_CHECK(a4 == 4);
277 BOOST_CHECK(
id == a3.getId());
283 std::atomic<bool> flag{
false};
284 std::thread thread([&group, &flag, &
id] {
291 BOOST_CHECK(flag ==
false);
294 backend->notificationQueue[
"/a2"].push();
296 BOOST_CHECK(a1 == 42);
297 BOOST_CHECK(a2 == 123);
298 BOOST_CHECK(a3 == 121);
299 BOOST_CHECK(a4 == 4);
300 BOOST_CHECK(
id == a2.getId());
306 std::atomic<bool> flag{
false};
307 std::thread thread([&group, &flag, &
id] {
314 BOOST_CHECK(flag ==
false);
317 backend->notificationQueue[
"/a4"].push();
319 BOOST_CHECK(a1 == 42);
320 BOOST_CHECK(a2 == 123);
321 BOOST_CHECK(a3 == 121);
322 BOOST_CHECK(a4 == 345);
323 BOOST_CHECK(
id == a4.getId());
329 std::atomic<bool> flag{
false};
330 std::thread thread([&group, &flag, &
id] {
337 BOOST_CHECK(flag ==
false);
340 backend->notificationQueue[
"/a4"].push();
342 BOOST_CHECK(a1 == 42);
343 BOOST_CHECK(a2 == 123);
344 BOOST_CHECK(a3 == 121);
345 BOOST_CHECK(a4 == 345);
346 BOOST_CHECK(
id == a4.getId());
352 std::atomic<bool> flag{
false};
353 std::thread thread([&group, &flag, &
id] {
360 BOOST_CHECK(flag ==
false);
363 backend->registers[
"/a3"] = 122;
364 backend->notificationQueue[
"/a3"].push();
366 BOOST_CHECK(a1 == 42);
367 BOOST_CHECK(a2 == 123);
368 BOOST_CHECK(a3 == 122);
369 BOOST_CHECK(a4 == 345);
370 BOOST_CHECK(
id == a3.getId());
376 backend->registers[
"/a1"] = 55;
377 backend->notificationQueue[
"/a1"].push();
380 backend->registers[
"/a2"] = 66;
381 backend->notificationQueue[
"/a2"].push();
383 BOOST_CHECK_EQUAL((
int)a1, 42);
384 BOOST_CHECK_EQUAL((
int)a2, 123);
388 BOOST_CHECK(a1.getId() == r);
389 BOOST_CHECK_EQUAL((
int)a1, 55);
390 BOOST_CHECK_EQUAL((
int)a2, 123);
393 BOOST_CHECK(a2.getId() == r);
394 BOOST_CHECK(a1 == 55);
395 BOOST_CHECK(a2 == 66);
401 backend->registers[
"/a4"] = 11;
402 backend->notificationQueue[
"/a4"].push();
405 backend->registers[
"/a2"] = 22;
406 backend->notificationQueue[
"/a2"].push();
409 backend->registers[
"/a3"] = 33;
410 backend->notificationQueue[
"/a3"].push();
413 backend->registers[
"/a1"] = 44;
414 backend->notificationQueue[
"/a1"].push();
418 BOOST_CHECK(a4.getId() == r);
419 BOOST_CHECK(a1 == 55);
420 BOOST_CHECK(a2 == 66);
421 BOOST_CHECK(a3 == 122);
422 BOOST_CHECK(a4 == 11);
425 BOOST_CHECK(a2.getId() == r);
426 BOOST_CHECK(a1 == 55);
427 BOOST_CHECK(a2 == 22);
428 BOOST_CHECK(a3 == 122);
429 BOOST_CHECK(a4 == 11);
432 BOOST_CHECK(a3.getId() == r);
433 BOOST_CHECK(a1 == 55);
434 BOOST_CHECK(a2 == 22);
435 BOOST_CHECK(a3 == 33);
436 BOOST_CHECK(a4 == 11);
439 BOOST_CHECK(a1.getId() == r);
440 BOOST_CHECK(a1 == 44);
441 BOOST_CHECK(a2 == 22);
442 BOOST_CHECK(a3 == 33);
443 BOOST_CHECK(a4 == 11);
452 std::cout <<
"testReadAnyWithPoll" << std::endl;
456 auto backend = boost::dynamic_pointer_cast<AsyncTestDummy>(BackendFactory::getInstance().createBackend(
cdd));
457 BOOST_CHECK(backend !=
nullptr);
472 backend->registers[
"/a1"] = 42;
473 backend->registers[
"/a2"] = 123;
474 backend->registers[
"/a3"] = 120;
475 backend->registers[
"/a4"] = 345;
490 std::atomic<bool> flag{
false};
491 std::thread thread([&group, &flag, &
id] {
498 BOOST_CHECK(flag ==
false);
501 backend->notificationQueue[
"/a1"].push();
503 BOOST_CHECK(a1 == 42);
504 BOOST_CHECK(a2 == 2);
505 BOOST_CHECK(a3 == 120);
506 BOOST_CHECK(a4 == 345);
507 BOOST_CHECK(
id == a1.getId());
510 backend->registers[
"/a3"] = 121;
511 backend->registers[
"/a4"] = 346;
516 std::atomic<bool> flag{
false};
517 std::thread thread([&group, &flag, &
id] {
524 BOOST_CHECK(flag ==
false);
527 backend->notificationQueue[
"/a2"].push();
529 BOOST_CHECK(a1 == 42);
530 BOOST_CHECK(a2 == 123);
531 BOOST_CHECK(a3 == 121);
532 BOOST_CHECK(a4 == 346);
533 BOOST_CHECK(
id == a2.getId());
542 std::cout <<
"testWaitAny" << std::endl;
546 auto backend = boost::dynamic_pointer_cast<AsyncTestDummy>(BackendFactory::getInstance().createBackend(
cdd));
547 BOOST_CHECK(backend !=
nullptr);
562 backend->registers[
"/a1"] = 42;
563 backend->registers[
"/a2"] = 123;
564 backend->registers[
"/a3"] = 120;
565 backend->registers[
"/a4"] = 345;
580 std::atomic<bool> flag{
false};
581 std::thread thread([&group, &flag, ¬ification] {
582 notification = group.
waitAny();
588 BOOST_CHECK(flag ==
false);
591 backend->notificationQueue[
"/a1"].push();
593 BOOST_CHECK(notification.
getId() == a1.getId());
594 BOOST_CHECK(a1 == 1);
595 BOOST_CHECK(a2 == 2);
596 BOOST_CHECK(a3 == 3);
597 BOOST_CHECK(a4 == 4);
598 BOOST_CHECK(notification.
accept());
599 BOOST_CHECK(a1 == 42);
600 BOOST_CHECK(a2 == 2);
601 BOOST_CHECK(a3 == 3);
602 BOOST_CHECK(a4 == 4);
604 BOOST_CHECK(a1 == 42);
605 BOOST_CHECK(a2 == 2);
606 BOOST_CHECK(a3 == 120);
607 BOOST_CHECK(a4 == 345);
610 backend->registers[
"/a3"] = 121;
611 backend->registers[
"/a4"] = 346;
616 std::atomic<bool> flag{
false};
617 std::thread thread([&group, &flag, ¬ification] {
618 notification = group.
waitAny();
624 BOOST_CHECK(flag ==
false);
627 backend->notificationQueue[
"/a2"].push();
629 BOOST_CHECK(notification.
getId() == a2.getId());
630 BOOST_CHECK(a1 == 42);
631 BOOST_CHECK(a2 == 2);
632 BOOST_CHECK(a3 == 120);
633 BOOST_CHECK(a4 == 345);
634 BOOST_CHECK(notification.
accept());
636 BOOST_CHECK(a1 == 42);
637 BOOST_CHECK(a2 == 123);
638 BOOST_CHECK(a3 == 121);
639 BOOST_CHECK(a4 == 346);
648 std::cout <<
"testReadAnyException" << std::endl;
652 auto backend = boost::dynamic_pointer_cast<AsyncTestDummy>(BackendFactory::getInstance().createBackend(
cdd));
653 BOOST_CHECK(backend !=
nullptr);
660 auto a1_casted = boost::dynamic_pointer_cast<AsyncTestDummy::Accessor<uint8_t>>(a1.getHighLevelImplElement());
670 backend->registers[
"/a1"] = 42;
671 backend->registers[
"/a2"] = 123;
672 backend->registers[
"/a3"] = 120;
673 backend->registers[
"/a4"] = 345;
685 auto nPostReadCalledReference = a1_casted->nPostReadCalled;
688 bool exceptionFound{
false};
689 std::thread thread([&group, &exceptionFound] {
694 exceptionFound =
true;
703 backend->notificationQueue[
"/a1"].push_exception(std::current_exception());
706 BOOST_TEST(exceptionFound ==
true);
707 BOOST_TEST(a1_casted->nPostReadCalled == nPostReadCalledReference + 1);
712 auto nPostReadCalledReference = a1_casted->nPostReadCalled;
715 bool exceptionFound{
false};
716 std::thread thread([&group, &exceptionFound] {
720 catch(boost::thread_interrupted&) {
721 exceptionFound =
true;
726 backend->notificationQueue[
"/a1"].push_exception(
727 std::make_exception_ptr(boost::thread_interrupted()));
730 BOOST_TEST(exceptionFound ==
true);
731 BOOST_TEST(a1_casted->nPostReadCalled == nPostReadCalledReference + 1);
740 std::cout <<
"testReadAnyInvalid" << std::endl;
744 auto backend = boost::dynamic_pointer_cast<AsyncTestDummy>(BackendFactory::getInstance().createBackend(
cdd));
745 BOOST_CHECK(backend !=
nullptr);