8 #include <boost/fusion/include/at_key.hpp>
9 #include <boost/test/unit_test.hpp>
19 #pragma GCC diagnostic ignored "-Wshadow"
63 _switchWriteOnly, _writeNeverLosesData, _testWriteOnly, _testReadOnly, _testRawTransfer, _testCatalogue,
64 _setRemoteValueIncrementsVersion>
72 _setRemoteValueIncrementsVersion>
75 "enableTestWriteNeverLosesData() and enableForceDataLossWrite() are mutually exclusive.");
79 _switchWriteOnly, _writeNeverLosesData, _testWriteOnly, _testReadOnly, _testRawTransfer, _testCatalogue,
80 _setRemoteValueIncrementsVersion>
87 _switchWriteOnly, _writeNeverLosesData, _testWriteOnly, _testReadOnly, _testRawTransfer, _testCatalogue,
88 _setRemoteValueIncrementsVersion>
93 _switchWriteOnly, _writeNeverLosesData, _testWriteOnly, _testReadOnly, _testRawTransfer, _testCatalogue,
94 _setRemoteValueIncrementsVersion>
101 _switchWriteOnly, _writeNeverLosesData, _testWriteOnly, _testReadOnly, _testRawTransfer, _testCatalogue,
102 _setRemoteValueIncrementsVersion>
107 _switchWriteOnly, _writeNeverLosesData, _testWriteOnly, _testReadOnly, _testRawTransfer, _testCatalogue,
108 _setRemoteValueIncrementsVersion>
114 constexpr
TestCapabilities<_syncRead, _forceDataLossWrite, _asyncReadInconsistency, _switchReadOnly,
115 TestCapability::enabled, _writeNeverLosesData, _testWriteOnly, _testReadOnly, _testRawTransfer, _testCatalogue,
116 _setRemoteValueIncrementsVersion>
120 constexpr
TestCapabilities<_syncRead, _forceDataLossWrite, _asyncReadInconsistency, _switchReadOnly,
122 _setRemoteValueIncrementsVersion>
132 _setRemoteValueIncrementsVersion>
135 "enableTestWriteNeverLosesData() and enableForceDataLossWrite() are mutualy exclusive.");
138 constexpr
TestCapabilities<_syncRead, _forceDataLossWrite, _asyncReadInconsistency, _switchReadOnly,
140 _setRemoteValueIncrementsVersion>
146 constexpr
TestCapabilities<_syncRead, _forceDataLossWrite, _asyncReadInconsistency, _switchReadOnly,
148 _testCatalogue, _setRemoteValueIncrementsVersion>
152 constexpr
TestCapabilities<_syncRead, _forceDataLossWrite, _asyncReadInconsistency, _switchReadOnly,
154 _testCatalogue, _setRemoteValueIncrementsVersion>
160 constexpr
TestCapabilities<_syncRead, _forceDataLossWrite, _asyncReadInconsistency, _switchReadOnly,
162 _testCatalogue, _setRemoteValueIncrementsVersion>
166 constexpr
TestCapabilities<_syncRead, _forceDataLossWrite, _asyncReadInconsistency, _switchReadOnly,
168 _testCatalogue, _setRemoteValueIncrementsVersion>
174 constexpr
TestCapabilities<_syncRead, _forceDataLossWrite, _asyncReadInconsistency, _switchReadOnly,
176 _setRemoteValueIncrementsVersion>
180 constexpr
TestCapabilities<_syncRead, _forceDataLossWrite, _asyncReadInconsistency, _switchReadOnly,
181 _switchWriteOnly, _writeNeverLosesData, _testWriteOnly, _testReadOnly,
TestCapability::enabled, _testCatalogue,
182 _setRemoteValueIncrementsVersion>
188 constexpr
TestCapabilities<_syncRead, _forceDataLossWrite, _asyncReadInconsistency, _switchReadOnly,
189 _switchWriteOnly, _writeNeverLosesData, _testWriteOnly, _testReadOnly, _testRawTransfer,
194 constexpr
TestCapabilities<_syncRead, _forceDataLossWrite, _asyncReadInconsistency, _switchReadOnly,
195 _switchWriteOnly, _writeNeverLosesData, _testWriteOnly, _testReadOnly, _testRawTransfer,
202 constexpr
TestCapabilities<_syncRead, _forceDataLossWrite, _asyncReadInconsistency, _switchReadOnly,
203 _switchWriteOnly, _writeNeverLosesData, _testWriteOnly, _testReadOnly, _testRawTransfer, _testCatalogue,
208 constexpr
TestCapabilities<_syncRead, _forceDataLossWrite, _asyncReadInconsistency, _switchReadOnly,
209 _switchWriteOnly, _writeNeverLosesData, _testWriteOnly, _testReadOnly, _testRawTransfer, _testCatalogue,
258 template<
typename VECTOR_OF_REGISTERS_T = boost::mpl::vector<>>
351 template<
typename REG_T>
363 using std::list<std::pair<std::function<void(
void)>, std::function<void(
void)>>>::list;
372 void runTests(
const std::string& cdd_,
const std::string& cdd2_ =
"");
430 template<
typename REG_T>
434 return x.isReadable();
436 template<
typename REG_T>
439 return x.isWriteable();
441 template<
typename REG_T>
446 template<
typename REG_T>
451 template<
typename REG_T>
455 template<
typename REG_T>
457 return !x.isWriteable() && x.isReadable();
459 template<
typename REG_T>
461 return x.isWriteable() && !x.isReadable();
479 _hasSeenException =
true;
488 bool ret = _hasSeenException;
489 _hasSeenException =
false;
500 boost::shared_ptr<DeviceBackend> _target;
501 bool _hasSeenException{
false};
513 std::cout <<
"Unexpected use of disabled capability." << std::endl;
532 std::cout <<
"Unexpected use of disabled capability." << std::endl;
551 std::cout <<
"Unexpected use of disabled capability." << std::endl;
570 std::cout <<
"Unexpected use of disabled capability." << std::endl;
592 std::cout <<
"Unexpected use of disabled capability." << std::endl;
612 static one test(decltype(&C::nValuesToTest));
614 static two test(...);
617 enum { value =
sizeof(test<T>(0)) ==
sizeof(
char) };
620 template<typename T, bool hasFn = has_nValuesToTest<T>::value>
649 template<
typename UserType>
656 return std::abs(a - b) <= std::numeric_limits<double>::epsilon() * 10. * std::max(std::abs(a), std::abs(b));
661 return std::abs(a - b) <= std::numeric_limits<float>::epsilon() * 10.F * std::max(std::abs(a), std::abs(b));
666 inline bool compareHelper<std::string>(std::string a, std::string b) {
672 inline std::string to_string(
const std::string& v) {
675 inline std::string to_string(
const char*& v) {
692 #define CHECK_EQUALITY(accessor, expectedValue) \
694 typedef typename decltype(expectedValue)::value_type::value_type CHECK_EQUALITY_UserType; \
696 BOOST_CHECK_EQUAL(accessor.getNChannels(), expectedValue.size()); \
697 BOOST_CHECK_EQUAL(accessor.getNElementsPerChannel(), expectedValue[0].size()); \
698 bool CHECK_EQUALITY_warnExpectedZero = true; \
699 for(size_t CHECK_EQUALITY_i = 0; CHECK_EQUALITY_i < expectedValue.size(); ++CHECK_EQUALITY_i) { \
700 for(size_t CHECK_EQUALITY_k = 0; CHECK_EQUALITY_k < expectedValue[0].size(); ++CHECK_EQUALITY_k) { \
701 if(CHECK_EQUALITY_warnExpectedZero && \
702 !compareHelper(expectedValue[CHECK_EQUALITY_i][CHECK_EQUALITY_k], CHECK_EQUALITY_UserType())) { \
704 CHECK_EQUALITY_warnExpectedZero = false; \
707 accessor[CHECK_EQUALITY_i][CHECK_EQUALITY_k], expectedValue[CHECK_EQUALITY_i][CHECK_EQUALITY_k])) { \
709 fail = "Accessor content differs from expected value. First difference at index [" + \
710 std::to_string(CHECK_EQUALITY_i) + "][" + std::to_string(CHECK_EQUALITY_k) + \
711 "]: " + std::to_string(accessor[CHECK_EQUALITY_i][CHECK_EQUALITY_k]) + \
712 " != " + std::to_string(expectedValue[CHECK_EQUALITY_i][CHECK_EQUALITY_k]); \
717 if(!fail.empty()) { \
720 if(CHECK_EQUALITY_warnExpectedZero && !std::is_same<CHECK_EQUALITY_UserType, ChimeraTK::Boolean>::value) { \
721 BOOST_ERROR("Comparison with all-zero expectedValue! Test may be insensitive! Check the " \
722 "generateValue() implementations!"); \
728 #define CHECK_EQUALITY_VECTOR(foundValue, expectedValue) \
730 typedef typename decltype(expectedValue)::value_type::value_type CHECK_EQUALITY_UserType; \
732 BOOST_CHECK_EQUAL(foundValue.size(), expectedValue.size()); \
733 BOOST_CHECK_EQUAL(foundValue[0].size(), expectedValue[0].size()); \
734 bool CHECK_EQUALITY_warnExpectedZero = true; \
735 for(size_t CHECK_EQUALITY_i = 0; CHECK_EQUALITY_i < expectedValue.size(); ++CHECK_EQUALITY_i) { \
736 for(size_t CHECK_EQUALITY_k = 0; CHECK_EQUALITY_k < expectedValue[0].size(); ++CHECK_EQUALITY_k) { \
737 if(CHECK_EQUALITY_warnExpectedZero && \
738 !compareHelper(expectedValue[CHECK_EQUALITY_i][CHECK_EQUALITY_k], CHECK_EQUALITY_UserType())) { \
740 CHECK_EQUALITY_warnExpectedZero = false; \
743 foundValue[CHECK_EQUALITY_i][CHECK_EQUALITY_k], expectedValue[CHECK_EQUALITY_i][CHECK_EQUALITY_k])) { \
745 fail = "Data content differs from expected value. First difference at index [" + \
746 std::to_string(CHECK_EQUALITY_i) + "][" + std::to_string(CHECK_EQUALITY_k) + \
747 "]: " + std::to_string(foundValue[CHECK_EQUALITY_i][CHECK_EQUALITY_k]) + \
748 " != " + std::to_string(expectedValue[CHECK_EQUALITY_i][CHECK_EQUALITY_k]); \
753 if(!fail.empty()) { \
756 if(CHECK_EQUALITY_warnExpectedZero && !std::is_same<CHECK_EQUALITY_UserType, ChimeraTK::Boolean>::value) { \
757 BOOST_ERROR("Comparison with all-zero expectedValue! Test may be insensitive! Check the " \
758 "generateValue() implementations!"); \
765 #define CHECK_EQUALITY_TIMEOUT(accessor, expectedValue, maxMilliseconds) \
767 typedef typename decltype(expectedValue)::value_type::value_type CHECK_EQUALITY_UserType; \
768 std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now(); \
769 bool CHECK_EQUALITY_warnExpectedZero = true; \
771 accessor.readLatest(); \
773 BOOST_CHECK_EQUAL(accessor.getNChannels(), expectedValue.size()); \
774 BOOST_CHECK_EQUAL(accessor.getNElementsPerChannel(), expectedValue[0].size()); \
775 for(size_t CHECK_EQUALITY_i = 0; CHECK_EQUALITY_i < expectedValue.size(); ++CHECK_EQUALITY_i) { \
776 for(size_t CHECK_EQUALITY_k = 0; CHECK_EQUALITY_k < expectedValue[0].size(); ++CHECK_EQUALITY_k) { \
777 if(CHECK_EQUALITY_warnExpectedZero && \
778 !compareHelper(expectedValue[CHECK_EQUALITY_i][CHECK_EQUALITY_k], CHECK_EQUALITY_UserType())) { \
780 CHECK_EQUALITY_warnExpectedZero = false; \
783 accessor[CHECK_EQUALITY_i][CHECK_EQUALITY_k], expectedValue[CHECK_EQUALITY_i][CHECK_EQUALITY_k])) { \
785 fail = "Accessor content differs from expected value. First difference at index [" + \
786 std::to_string(CHECK_EQUALITY_i) + "][" + std::to_string(CHECK_EQUALITY_k) + \
787 "]: " + std::to_string(accessor[CHECK_EQUALITY_i][CHECK_EQUALITY_k]) + \
788 " != " + std::to_string(expectedValue[CHECK_EQUALITY_i][CHECK_EQUALITY_k]); \
793 if(fail.empty()) break; \
794 bool timeout_reached = (std::chrono::steady_clock::now() - t0) > std::chrono::milliseconds(maxMilliseconds); \
795 BOOST_CHECK_MESSAGE(!timeout_reached, fail); \
796 if(timeout_reached) break; \
799 if(CHECK_EQUALITY_warnExpectedZero && !std::is_same<CHECK_EQUALITY_UserType, ChimeraTK::Boolean>::value) { \
800 BOOST_ERROR("Comparison with all-zero expectedValue! Test may be insensitive! Check the " \
801 "generateValue() implementations!"); \
807 #define CHECK_EQUALITY_VECTOR_TIMEOUT(foundValue, expectedValue, maxMilliseconds) \
809 typedef typename decltype(expectedValue)::value_type::value_type CHECK_EQUALITY_UserType; \
810 std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now(); \
811 bool CHECK_EQUALITY_warnExpectedZero = true; \
814 auto CHECK_EQUALITY_value = foundValue; \
815 BOOST_CHECK_EQUAL(theValue.size(), expectedValue.size()); \
816 BOOST_CHECK_EQUAL(theValue[0].size(), expectedValue[0].size()); \
817 for(size_t CHECK_EQUALITY_i = 0; CHECK_EQUALITY_i < expectedValue.size(); ++CHECK_EQUALITY_i) { \
818 for(size_t CHECK_EQUALITY_k = 0; CHECK_EQUALITY_k < expectedValue[0].size(); ++CHECK_EQUALITY_k) { \
819 if(CHECK_EQUALITY_warnExpectedZero && \
820 !compareHelper(expectedValue[CHECK_EQUALITY_i][CHECK_EQUALITY_k], CHECK_EQUALITY_UserType())) { \
822 CHECK_EQUALITY_warnExpectedZero = false; \
824 if(!compareHelper(CHECK_EQUALITY_value[CHECK_EQUALITY_i][CHECK_EQUALITY_k], \
825 expectedValue[CHECK_EQUALITY_i][CHECK_EQUALITY_k])) { \
827 fail = "Data content differs from expected value. First difference at index [" + \
828 std::to_string(CHECK_EQUALITY_i) + "][" + std::to_string(CHECK_EQUALITY_k) + \
829 "]: " + std::to_string(CHECK_EQUALITY_value[CHECK_EQUALITY_i][CHECK_EQUALITY_k]) + \
830 " != " + std::to_string(expectedValue[CHECK_EQUALITY_i][CHECK_EQUALITY_k]); \
835 if(fail.empty()) break; \
836 bool timeout_reached = (std::chrono::steady_clock::now() - t0) > std::chrono::milliseconds(maxMilliseconds); \
837 BOOST_CHECK_MESSAGE(!timeout_reached, fail); \
838 if(timeout_reached) break; \
841 if(CHECK_EQUALITY_warnExpectedZero && !std::is_same<CHECK_EQUALITY_UserType, ChimeraTK::Boolean>::value) { \
842 BOOST_ERROR("Comparison with all-zero expectedValue! Test may be insensitive! Check the " \
843 "generateValue() implementations!"); \
849 #define CHECK_TIMEOUT(condition, maxMilliseconds) \
851 std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now(); \
852 while(!(condition)) { \
853 bool timeout_reached = (std::chrono::steady_clock::now() - t0) > std::chrono::milliseconds(maxMilliseconds); \
854 BOOST_CHECK(!timeout_reached); \
855 if(timeout_reached) break; \
863 template<
typename VECTOR_OF_REGISTERS_T>
867 std::cout <<
"=== UnifiedBackendTest for " <<
cdd;
868 if(!cdd2.empty()) std::cout <<
" and " << cdd2;
869 std::cout << std::endl;
871 size_t nSyncReadRegisters = 0;
872 size_t nAsyncReadRegisters = 0;
873 size_t nWriteRegisters = 0;
874 size_t nRawRegisters = 0;
875 size_t nReadOnlyRegisters = 0;
876 size_t nWriteOnlyRegisters = 0;
877 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
878 if(this->isAsyncRead(x)) ++nAsyncReadRegisters;
879 if(this->isSyncRead(x)) ++nSyncReadRegisters;
880 if(this->isWrite(x)) ++nWriteRegisters;
881 if(this->isWrite(x) && !this->isRead(x)) ++nWriteOnlyRegisters;
882 if(!this->isWrite(x) && this->isRead(x)) ++nReadOnlyRegisters;
883 if(this->isRaw(x)) ++nRawRegisters;
885 std::cout <<
"WARNING: Register " << x.path() <<
" has unspecified capability forceDataLossWrite!" << std::endl;
888 std::cout <<
"WARNING: Register " << x.path() <<
" has unspecified capability asyncReadInconsistency!"
892 std::cout <<
"WARNING: Register " << x.path() <<
" has unspecified capability switchReadOnly!" << std::endl;
895 std::cout <<
"WARNING: Register " << x.path() <<
" has unspecified capability switchWriteOnly!" << std::endl;
898 std::cout <<
"WARNING: Register " << x.path() <<
" has unspecified capability writeNeverLosesData!"
903 std::cout <<
"Using " << nSyncReadRegisters <<
" synchronous and " << nAsyncReadRegisters
904 <<
" asynchronous read and " << nWriteRegisters <<
" write test registers." << std::endl;
905 std::cout <<
"Of those are " << nRawRegisters <<
" supporting raw mode, " << nReadOnlyRegisters
906 <<
" are read-only and " << nWriteOnlyRegisters <<
" write-only." << std::endl;
908 if(nSyncReadRegisters + nAsyncReadRegisters + nWriteRegisters == 0) {
909 std::cout <<
"ERROR: No test registers specified. Cannot perform tests." << std::endl;
913 if(nSyncReadRegisters + nAsyncReadRegisters == 0) {
914 std::cout <<
"WARNING: No read test registers specified. This is acceptable only if the backend does not "
915 <<
"support reading at all." << std::endl;
917 else if(nSyncReadRegisters == 0) {
919 <<
"WARNING: No synchronous read test registers specified. This is acceptable only if the backend has only "
920 <<
"registers which support AccessMode::wait_for_new_data." << std::endl;
922 else if(nAsyncReadRegisters == 0) {
924 <<
"WARNING: No asynchronous read test registers specified. This is acceptable only if the backend does not "
925 <<
"support AccessMode::wait_for_new_data at all." << std::endl;
927 if(nWriteRegisters == 0) {
928 std::cout <<
"WARNING: No write test registers specified. This is acceptable only if the backend does not "
929 <<
"support writing at all." << std::endl;
932 if(nRawRegisters == 0) {
933 std::cout <<
"WARNING: No raw registers specified. This is acceptable only if the backend does not "
934 <<
"support raw access mode at all." << std::endl;
936 if(nReadOnlyRegisters == 0) {
937 std::cout <<
"WARNING: No read-only registers specified." << std::endl;
939 if(nWriteOnlyRegisters == 0) {
940 std::cout <<
"WARNING: No write-only registers specified." << std::endl;
966 test_NOSPEC_newVersionAfterOpen();
979 test_NOSPEC_valueAfterConstruction();
980 test_NOSPEC_backendNotClosedAfterException();
981 test_NOSPEC_rawTransfer();
982 test_NOSPEC_catalogueRaw();
983 test_NOSPEC_catalogueReadWrite();
988 template<
typename VECTOR_OF_REGISTERS_T>
991 for(
size_t i = 0;; ++i) {
1000 BOOST_FAIL(
"Device did not recover within 60 seconds after forced ChimeraTK::runtime_error.");
1012 template<
typename VECTOR_OF_REGISTERS_T>
1014 std::cout <<
"--- test_B_3_1_2_1 - synchronous read" << std::endl;
1017 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
1018 if(!this->isRead(x))
return;
1019 typedef typename decltype(x)::minimumUserType UserType;
1020 auto registerName = x.path();
1021 std::cout <<
"... registerName = " << registerName << std::endl;
1026 std::vector<std::vector<UserType>> v1 = x.template getRemoteValue<UserType>();
1042 std::vector<std::vector<UserType>> v2;
1043 for(
size_t iter = 0; iter < this->nValuesToTest(x); ++iter) {
1046 v2 = x.template getRemoteValue<UserType>();
1074 template<
typename VECTOR_OF_REGISTERS_T>
1076 std::cout <<
"--- test_NOSPEC_write - write" << std::endl;
1082 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
1083 if(!this->isWrite(x))
return;
1084 typedef typename decltype(x)::minimumUserType UserType;
1085 auto registerName = x.path();
1087 std::cout <<
"... registerName = " << registerName << std::endl;
1091 for(
size_t iter = 0; iter < this->nValuesToTest(x); ++iter) {
1092 auto theValue = x.template generateValue<UserType>();
1114 template<
typename VECTOR_OF_REGISTERS_T>
1116 std::cout <<
"--- test_B_3_2_1_2 - write() does not destroy application buffer" << std::endl;
1122 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
1123 if(!this->isWrite(x))
return;
1124 typedef typename decltype(x)::minimumUserType UserType;
1125 auto registerName = x.path();
1126 std::cout <<
"... registerName = " << registerName << std::endl;
1130 auto theValue = x.template generateValue<UserType>();
1136 BOOST_CHECK(reg.getNChannels() == theValue.size());
1137 BOOST_CHECK(reg.getNElementsPerChannel() == theValue[0].size());
1141 BOOST_CHECK(reg.getVersionNumber() == ver);
1154 template<
typename VECTOR_OF_REGISTERS_T>
1156 std::cout <<
"--- test_B_3_2_2 - destructive write" << std::endl;
1162 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
1163 if(!this->isWrite(x))
return;
1164 typedef typename decltype(x)::minimumUserType UserType;
1165 auto registerName = x.path();
1167 std::cout <<
"... registerName = " << registerName << std::endl;
1171 auto theValue = x.template generateValue<UserType>();
1174 reg.writeDestructively(ver);
1177 BOOST_CHECK(reg.getNChannels() == theValue.size());
1178 BOOST_CHECK(reg.getNElementsPerChannel() == theValue[0].size());
1181 BOOST_CHECK(reg.getVersionNumber() == ver);
1198 #define ALTER_AND_STORE_APPLICATION_BUFFER(UserType, accessor) \
1199 std::vector<std::vector<UserType>> STORE_APPLICATION_BUFFER_data; \
1200 VersionNumber STORE_APPLICATION_BUFFER_version; \
1201 DataValidity STORE_APPLICATION_BUFFER_validity; \
1202 for(size_t i = 0; i < accessor.getNChannels(); ++i) { \
1203 if constexpr(std::is_arithmetic_v<UserType>) \
1204 std::iota(accessor[i].begin(), accessor[i].end(), std::numeric_limits<UserType>::min() + 1); \
1205 if constexpr(std::is_same_v<std::string, UserType>) std::fill(accessor[i].begin(), accessor[i].end(), "FACECAFE"); \
1206 STORE_APPLICATION_BUFFER_data.push_back(accessor[i]); \
1208 STORE_APPLICATION_BUFFER_version = accessor.getVersionNumber(); \
1209 STORE_APPLICATION_BUFFER_validity = accessor.dataValidity()
1211 #define CHECK_APPLICATION_BUFFER(UserType, accessor) \
1212 CHECK_EQUALITY(accessor, STORE_APPLICATION_BUFFER_data); \
1213 BOOST_CHECK(STORE_APPLICATION_BUFFER_version == accessor.getVersionNumber()); \
1214 BOOST_CHECK(STORE_APPLICATION_BUFFER_validity == accessor.dataValidity())
1222 template<
typename VECTOR_OF_REGISTERS_T>
1224 std::cout <<
"--- test_B_4_2_4 - transfer implementations do not change the application buffer" << std::endl;
1230 std::cout <<
"... writeTransfer()" << std::endl;
1231 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
1232 if(!this->isWrite(x))
return;
1233 typedef typename decltype(x)::minimumUserType UserType;
1234 auto registerName = x.path();
1235 std::cout <<
"... registerName = " << registerName << std::endl;
1237 auto te = reg.getHighLevelImplElement();
1240 auto theValue = x.template generateValue<UserType>();
1245 te->writeTransfer(ver);
1250 std::cout <<
"... writeTransferDestructively()" << std::endl;
1251 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
1252 if(!this->isWrite(x))
return;
1253 typedef typename decltype(x)::minimumUserType UserType;
1254 auto registerName = x.path();
1255 std::cout <<
"... registerName = " << registerName << std::endl;
1257 auto te = reg.getHighLevelImplElement();
1260 auto theValue = x.template generateValue<UserType>();
1265 te->writeTransferDestructively(ver);
1270 std::cout <<
"... readTransferSynchronously()" << std::endl;
1271 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
1272 if(!this->isRead(x))
return;
1273 typedef typename decltype(x)::minimumUserType UserType;
1274 auto registerName = x.path();
1275 std::cout <<
"... registerName = " << registerName << std::endl;
1277 auto te = reg.getHighLevelImplElement();
1280 auto theValue = x.template generateValue<UserType>();
1301 template<
typename VECTOR_OF_REGISTERS_T>
1303 if(_testOnlyTransferElement)
return;
1304 std::cout <<
"--- test_B_6_4 - application buffer unchanged after exception" << std::endl;
1307 std::cout <<
"... synchronous read " << std::endl;
1308 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
1309 if(!this->isRead(x))
return;
1310 typedef typename decltype(x)::minimumUserType UserType;
1311 auto registerName = x.path();
1312 int someNumber = 42;
1314 std::cout <<
" registerName = " << registerName << std::endl;
1318 reg[0][0] = numericToUserType<UserType>(someNumber);
1320 BOOST_CHECK(reg.getVersionNumber() ==
VersionNumber(
nullptr));
1326 BOOST_CHECK(reg[0][0] == numericToUserType<UserType>(someNumber));
1328 BOOST_CHECK(reg.getVersionNumber() ==
VersionNumber(
nullptr));
1330 for(
size_t i = 0; i < x.nRuntimeErrorCases(); ++i) {
1331 std::cout <<
" -> runtime_error case: " << i << std::endl;
1336 x.setForceRuntimeError(
true, i);
1342 BOOST_CHECK(reg[0][0] == numericToUserType<UserType>(someNumber));
1344 BOOST_CHECK(reg.getVersionNumber() ==
VersionNumber(
nullptr));
1347 x.setForceRuntimeError(
false, i);
1350 this->recoverDevice(d);
1357 std::cout <<
"... asynchronous read " << std::endl;
1358 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
1359 if(!this->isAsyncRead(x))
return;
1360 typedef typename decltype(x)::minimumUserType UserType;
1361 auto registerName = x.path();
1362 int someNumber = 42;
1364 std::cout <<
" registerName = " << registerName << std::endl;
1368 reg[0][0] = numericToUserType<UserType>(someNumber);
1370 BOOST_CHECK(reg.getVersionNumber() ==
VersionNumber(
nullptr));
1376 BOOST_CHECK(reg[0][0] == numericToUserType<UserType>(someNumber));
1378 BOOST_CHECK(reg.getVersionNumber() ==
VersionNumber(
nullptr));
1381 BOOST_CHECK_THROW(reg.readNonBlocking(),
logic_error);
1384 BOOST_CHECK(reg[0][0] == numericToUserType<UserType>(someNumber));
1386 BOOST_CHECK(reg.getVersionNumber() ==
VersionNumber(
nullptr));
1388 for(
size_t i = 0; i < x.nRuntimeErrorCases(); ++i) {
1389 std::cout <<
" -> runtime_error case: " << i << std::endl;
1396 x.setForceRuntimeError(
true, i);
1399 reg[0][0] = numericToUserType<UserType>(someNumber);
1401 auto ver = reg.getVersionNumber();
1407 BOOST_CHECK(reg[0][0] == numericToUserType<UserType>(someNumber));
1409 BOOST_CHECK(reg.getVersionNumber() == ver);
1412 x.setForceRuntimeError(
false, i);
1413 this->recoverDevice(d);
1416 x.setForceRuntimeError(
true, i);
1419 reg[0][0] = numericToUserType<UserType>(someNumber);
1421 ver = reg.getVersionNumber();
1425 while(!reg.readNonBlocking()) usleep(10000);
1431 BOOST_CHECK(reg[0][0] == numericToUserType<UserType>(someNumber));
1433 BOOST_CHECK(reg.getVersionNumber() == ver);
1436 x.setForceRuntimeError(
false, i);
1439 this->recoverDevice(d);
1446 std::cout <<
"... write " << std::endl;
1447 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
1448 if(!this->isWrite(x))
return;
1449 typedef typename decltype(x)::minimumUserType UserType;
1450 auto registerName = x.path();
1451 int someNumber = 42;
1453 std::cout <<
" registerName = " << registerName << std::endl;
1457 reg[0][0] = numericToUserType<UserType>(someNumber);
1459 BOOST_CHECK(reg.getVersionNumber() ==
VersionNumber(
nullptr));
1465 BOOST_CHECK(reg[0][0] == numericToUserType<UserType>(someNumber));
1467 BOOST_CHECK(reg.getVersionNumber() ==
VersionNumber(
nullptr));
1469 for(
size_t i = 0; i < x.nRuntimeErrorCases(); ++i) {
1470 std::cout <<
" -> runtime_error case: " << i << std::endl;
1475 x.setForceRuntimeError(
true, i);
1481 BOOST_CHECK(reg[0][0] == numericToUserType<UserType>(someNumber));
1483 BOOST_CHECK(reg.getVersionNumber() ==
VersionNumber(
nullptr));
1486 x.setForceRuntimeError(
false, i);
1489 this->recoverDevice(d);
1503 template<
typename VECTOR_OF_REGISTERS_T>
1505 std::cout <<
"--- test_B_7_2 - data loss in write" << std::endl;
1508 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
1509 if(!this->isWrite(x))
return;
1511 typedef typename decltype(x)::minimumUserType UserType;
1512 auto registerName = x.path();
1513 std::cout <<
"... registerName = " << registerName <<
" (data loss expected)" << std::endl;
1516 size_t attempts = this->writeQueueLength(x) + 1;
1517 this->setForceDataLossWrite(x, true);
1522 auto reg = d.getTwoDRegisterAccessor<UserType>(registerName);
1525 for(size_t i = 0; i < attempts; ++i) {
1526 auto theValue = x.template generateValue<UserType>();
1528 VersionNumber someVersion;
1529 bool dataLost = reg.write(someVersion);
1530 if(i < attempts - 1) {
1531 BOOST_CHECK(dataLost == false);
1534 BOOST_CHECK(dataLost == true);
1537 CHECK_EQUALITY(reg, theValue);
1538 BOOST_CHECK(reg.dataValidity() == DataValidity::ok);
1539 BOOST_CHECK(reg.getVersionNumber() == someVersion);
1543 this->setForceDataLossWrite(x,
false);
1546 auto v1 = x.template getRemoteValue<UserType>();
1553 typedef typename decltype(x)::minimumUserType UserType;
1554 auto registerName = x.path();
1555 std::cout <<
"... registerName = " << registerName <<
" (data loss never expected)" << std::endl;
1558 size_t attempts = this->writeQueueLength(x) + 1;
1563 auto reg = d.getTwoDRegisterAccessor<UserType>(registerName);
1566 for(size_t i = 0; i < attempts; ++i) {
1567 auto theValue = x.template generateValue<UserType>();
1569 VersionNumber someVersion;
1570 bool dataLost = reg.write(someVersion);
1571 BOOST_CHECK(dataLost == false);
1575 auto v1 = x.template getRemoteValue<UserType>();
1593 template<
typename VECTOR_OF_REGISTERS_T>
1595 std::cout <<
"--- test_B_8_2 - async read fills _readQueue" << std::endl;
1602 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
1603 if(!this->isAsyncRead(x))
return;
1604 typedef typename decltype(x)::minimumUserType UserType;
1605 auto registerName = x.path();
1608 std::cout <<
"... registerName = " << registerName << std::endl;
1617 BOOST_CHECK(reg.readNonBlocking() ==
false);
1621 auto v1 = x.template getRemoteValue<UserType>();
1626 BOOST_CHECK(reg.readNonBlocking() ==
false);
1630 BOOST_CHECK(reg.dataValidity() == DataValidity::ok);
1631 BOOST_CHECK(reg.getVersionNumber() > someVersion);
1632 someVersion = reg.getVersionNumber();
1635 helper.readLatest();
1639 auto v2 = x.template getRemoteValue<UserType>();
1643 auto v3 = x.template getRemoteValue<UserType>();
1647 auto v4 = x.template getRemoteValue<UserType>();
1653 BOOST_CHECK(reg.dataValidity() == DataValidity::ok);
1654 BOOST_CHECK(reg.getVersionNumber() > someVersion);
1655 someVersion = reg.getVersionNumber();
1660 BOOST_CHECK(reg.dataValidity() == DataValidity::ok);
1661 BOOST_CHECK(reg.getVersionNumber() > someVersion);
1662 someVersion = reg.getVersionNumber();
1667 BOOST_CHECK(reg.dataValidity() == DataValidity::ok);
1668 BOOST_CHECK(reg.getVersionNumber() > someVersion);
1669 someVersion = reg.getVersionNumber();
1672 BOOST_CHECK(reg.readNonBlocking() ==
false);
1674 BOOST_CHECK(reg.dataValidity() == DataValidity::ok);
1675 BOOST_CHECK(reg.getVersionNumber() == someVersion);
1692 template<
typename VECTOR_OF_REGISTERS_T>
1694 std::cout <<
"--- test_B_8_2_1 - _readQueue overrun" << std::endl;
1703 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
1704 if(!this->isAsyncRead(x))
return;
1705 typedef typename decltype(x)::minimumUserType UserType;
1706 auto registerName = x.path();
1709 std::cout <<
"... registerName = " << registerName << std::endl;
1710 auto overrunningReg = d.
getTwoDRegisterAccessor<UserType>(registerName, 0, 0, {AccessMode::wait_for_new_data});
1716 overrunningReg.read();
1717 referenceReg.read();
1719 BOOST_CHECK(overrunningReg.readNonBlocking() ==
false);
1722 for(
size_t i = 0; i < 10; ++i) {
1725 referenceReg.read();
1727 auto val = x.template getRemoteValue<UserType>();
1730 BOOST_CHECK(overrunningReg.readLatest() ==
true);
1734 BOOST_CHECK(overrunningReg.dataValidity() == DataValidity::ok);
1735 BOOST_CHECK(overrunningReg.getVersionNumber() > someVersion);
1736 someVersion = overrunningReg.getVersionNumber();
1749 template<
typename VECTOR_OF_REGISTERS_T>
1751 std::cout <<
"--- test_B_8_3 - new runtime errors are put to _readQueue in async reads" << std::endl;
1758 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
1759 if(!this->isAsyncRead(x))
return;
1760 typedef typename decltype(x)::minimumUserType UserType;
1761 auto registerName = x.path();
1764 std::cout <<
"... registerName = " << registerName << std::endl;
1769 for(
size_t i = 0; i < x.nRuntimeErrorCases(); ++i) {
1770 std::cout <<
" -> runtime_error case: " << i << std::endl;
1775 reg.getHighLevelImplElement()->preRead(TransferType::read);
1778 x.setForceRuntimeError(
true, i);
1788 reg.getHighLevelImplElement()->postRead(TransferType::read,
false);
1791 x.setForceRuntimeError(
false, i);
1794 this->recoverDevice(d);
1810 template<
typename VECTOR_OF_REGISTERS_T>
1812 if(_testOnlyTransferElement)
return;
1813 std::cout <<
"--- test_B_8_4 - async read consistency heartbeat" << std::endl;
1817 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
1818 if(!this->isAsyncRead(x) || x.capabilities.asyncReadInconsistency != TestCapability::enabled)
return;
1819 typedef typename decltype(x)::minimumUserType UserType;
1820 auto registerName = x.path();
1823 std::cout <<
"... registerName = " << registerName << std::endl;
1833 auto v1 = x.template getRemoteValue<UserType>();
1841 BOOST_CHECK(reg.dataValidity() == DataValidity::ok);
1842 BOOST_CHECK(reg.getVersionNumber() > someVersion);
1843 someVersion = reg.getVersionNumber();
1846 this->forceAsyncReadInconsistency(x);
1852 this->recoverDevice(d);
1853 auto v2 = x.template getRemoteValue<UserType>();
1861 BOOST_CHECK(reg.dataValidity() == DataValidity::ok);
1862 BOOST_CHECK(reg.getVersionNumber() > someVersion);
1863 someVersion = reg.getVersionNumber();
1876 template<
typename VECTOR_OF_REGISTERS_T>
1878 if(_testOnlyTransferElement)
return;
1879 std::cout <<
"--- test_B_8_5 - no async transfers until activateAsyncRead()" << std::endl;
1882 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
1883 if(!this->isAsyncRead(x))
return;
1884 typedef typename decltype(x)::minimumUserType UserType;
1885 auto registerName = x.path();
1886 std::cout <<
"... registerName = " << registerName << std::endl;
1890 std::chrono::duration<double> timeToInitialValue{};
1907 timeToInitialValue = t1 - t0;
1920 std::this_thread::sleep_for(timeToInitialValue * 2);
1923 BOOST_CHECK(reg.readNonBlocking() ==
false);
1927 std::this_thread::sleep_for(timeToInitialValue * 2);
1930 BOOST_CHECK(reg.readNonBlocking() ==
false);
1944 template<
typename VECTOR_OF_REGISTERS_T>
1946 if(_testOnlyTransferElement)
return;
1947 std::cout <<
"--- test_B_8_5_1 - activateAsynchronousRead" << std::endl;
1955 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
1956 if(!this->isAsyncRead(x))
return;
1957 typedef typename decltype(x)::minimumUserType UserType;
1958 auto registerName = x.path();
1959 std::cout <<
"... registerName = " << registerName << std::endl;
1966 if(!cdd2.empty()) BOOST_CHECK(reg2.readNonBlocking() ==
false);
1971 auto v1 = x.template getRemoteValue<UserType>();
1975 if(!cdd2.empty()) BOOST_CHECK(reg2.readNonBlocking() ==
false);
1988 using namespace std::chrono_literals;
1989 std::this_thread::sleep_for(10ms);
1990 BOOST_CHECK(reg2.readNonBlocking() ==
false);
2009 template<
typename VECTOR_OF_REGISTERS_T>
2011 if(_testOnlyTransferElement)
return;
2012 std::cout <<
"--- test_B_8_5_2 - initial value" << std::endl;
2014 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2015 if(!this->isAsyncRead(x))
return;
2016 typedef typename decltype(x)::minimumUserType UserType;
2017 auto registerName = x.path();
2018 std::cout <<
"... registerName = " << registerName << std::endl;
2024 auto v1 = x.template getRemoteValue<UserType>();
2056 auto v2 = x.template getRemoteValue<UserType>();
2073 template<
typename VECTOR_OF_REGISTERS_T>
2075 std::cout <<
"--- test_B_8_5_3 - accessors created after activateAsyncRead() are immediately active" << std::endl;
2082 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2083 if(!this->isAsyncRead(x))
return;
2084 typedef typename decltype(x)::minimumUserType UserType;
2085 auto registerName = x.path();
2087 std::cout <<
"... registerName = " << registerName <<
" (activated async read)" << std::endl;
2104 template<
typename VECTOR_OF_REGISTERS_T>
2106 std::cout <<
"--- test_B_8_6_6 - interrupt()" << std::endl;
2115 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2116 if(!this->isAsyncRead(x))
return;
2117 typedef typename decltype(x)::minimumUserType UserType;
2118 auto registerName = x.path();
2121 std::cout <<
"... registerName = " << registerName << std::endl;
2125 for(
size_t i = 0; i < 2; ++i) {
2127 boost::thread anotherThread([&] {
2129 BOOST_ERROR(
"boost::thread_interrupt exception expected but not thrown.");
2133 reg.getHighLevelImplElement()->interrupt();
2136 anotherThread.join();
2140 auto v1 = x.template getRemoteValue<UserType>();
2143 BOOST_CHECK(reg.dataValidity() == DataValidity::ok);
2144 BOOST_CHECK(reg.getVersionNumber() > someVersion);
2145 someVersion = reg.getVersionNumber();
2159 template<
typename VECTOR_OF_REGISTERS_T>
2161 if(_testOnlyTransferElement)
return;
2162 std::cout <<
"--- test_B_9_1 - reporting exceptions to exception backend" << std::endl;
2168 std::cout <<
"... synchronous read" << std::endl;
2169 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2170 if(!this->isRead(x))
return;
2171 if(x.nRuntimeErrorCases() == 0)
return;
2172 typedef typename decltype(x)::minimumUserType UserType;
2173 auto registerName = x.path();
2174 std::cout <<
" registerName = " << registerName << std::endl;
2178 auto erb = boost::make_shared<ExceptionReportingBackend>(d.
getBackend());
2179 reg.getHighLevelImplElement()->setExceptionBackend(erb);
2181 for(
size_t i = 0; i < x.nRuntimeErrorCases(); ++i) {
2182 std::cout <<
" -> runtime_error case: " << i << std::endl;
2184 x.setForceRuntimeError(
true, i);
2187 BOOST_CHECK(!erb->hasSeenException());
2189 BOOST_CHECK(erb->hasSeenException());
2192 x.setForceRuntimeError(
false, i);
2195 this->recoverDevice(d);
2198 BOOST_CHECK_NO_THROW(reg.read());
2199 BOOST_CHECK(!erb->hasSeenException());
2203 std::cout <<
"... asynchronous read" << std::endl;
2205 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2206 if(!this->isAsyncRead(x))
return;
2207 if(x.nRuntimeErrorCases() == 0)
return;
2208 typedef typename decltype(x)::minimumUserType UserType;
2209 auto registerName = x.path();
2210 std::cout <<
" registerName = " << registerName << std::endl;
2215 auto erb = boost::make_shared<ExceptionReportingBackend>(d.
getBackend());
2216 reg.getHighLevelImplElement()->setExceptionBackend(erb);
2218 for(
size_t i = 0; i < x.nRuntimeErrorCases(); ++i) {
2219 std::cout <<
" -> runtime_error case: " << i << std::endl;
2221 x.setForceRuntimeError(
true, i);
2224 BOOST_CHECK(!erb->hasSeenException());
2226 BOOST_CHECK(erb->hasSeenException());
2229 x.setForceRuntimeError(
false, i);
2232 this->recoverDevice(d);
2237 BOOST_CHECK_NO_THROW(reg.readNonBlocking());
2238 BOOST_CHECK(!erb->hasSeenException());
2242 std::cout <<
"... write" << std::endl;
2243 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2244 if(!this->isWrite(x))
return;
2245 if(x.nRuntimeErrorCases() == 0)
return;
2246 typedef typename decltype(x)::minimumUserType UserType;
2247 auto registerName = x.path();
2248 std::cout <<
" registerName = " << registerName << std::endl;
2252 auto erb = boost::make_shared<ExceptionReportingBackend>(d.
getBackend());
2253 reg.getHighLevelImplElement()->setExceptionBackend(erb);
2255 for(
size_t i = 0; i < x.nRuntimeErrorCases(); ++i) {
2256 std::cout <<
" -> runtime_error case: " << i << std::endl;
2258 x.setForceRuntimeError(
true, i);
2261 BOOST_CHECK(!erb->hasSeenException());
2263 BOOST_CHECK(erb->hasSeenException());
2266 x.setForceRuntimeError(
false, i);
2269 this->recoverDevice(d);
2272 BOOST_CHECK_NO_THROW(reg.write());
2273 BOOST_CHECK(!erb->hasSeenException());
2277 std::cout <<
"... isReadable" << std::endl;
2278 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2279 if(x.nRuntimeErrorCases() == 0)
return;
2280 typedef typename decltype(x)::minimumUserType UserType;
2281 auto registerName = x.path();
2282 std::cout <<
" registerName = " << registerName;
2286 auto erb = boost::make_shared<ExceptionReportingBackend>(d.
getBackend());
2287 reg.getHighLevelImplElement()->setExceptionBackend(erb);
2289 bool didThrow =
false;
2290 for(
size_t i = 0; i < x.nRuntimeErrorCases(); ++i) {
2291 std::cout <<
" -> runtime_error case: " << i << std::endl;
2293 x.setForceRuntimeError(
true, i);
2296 BOOST_CHECK(!erb->hasSeenException());
2298 [[maybe_unused]]
auto result = reg.isReadable();
2302 BOOST_CHECK(erb->hasSeenException());
2306 x.setForceRuntimeError(
false, i);
2309 this->recoverDevice(d);
2313 std::cout <<
" (doesn't throw)" << std::endl;
2316 std::cout <<
" (throws)" << std::endl;
2320 std::cout <<
"... isWriteable" << std::endl;
2321 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2322 if(x.nRuntimeErrorCases() == 0)
return;
2323 typedef typename decltype(x)::minimumUserType UserType;
2324 auto registerName = x.path();
2325 std::cout <<
" registerName = " << registerName;
2329 auto erb = boost::make_shared<ExceptionReportingBackend>(d.
getBackend());
2330 reg.getHighLevelImplElement()->setExceptionBackend(erb);
2332 bool didThrow =
false;
2333 for(
size_t i = 0; i < x.nRuntimeErrorCases(); ++i) {
2334 std::cout <<
" -> runtime_error case: " << i << std::endl;
2336 x.setForceRuntimeError(
true, i);
2339 BOOST_CHECK(!erb->hasSeenException());
2341 [[maybe_unused]]
auto result = reg.isWriteable();
2345 BOOST_CHECK(erb->hasSeenException());
2349 x.setForceRuntimeError(
false, i);
2352 this->recoverDevice(d);
2356 std::cout <<
" (doesn't throw)" << std::endl;
2359 std::cout <<
" (throws)" << std::endl;
2363 std::cout <<
"... isReadOnly" << std::endl;
2364 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2365 typedef typename decltype(x)::minimumUserType UserType;
2366 auto registerName = x.path();
2367 std::cout <<
" registerName = " << registerName;
2371 auto erb = boost::make_shared<ExceptionReportingBackend>(d.
getBackend());
2372 reg.getHighLevelImplElement()->setExceptionBackend(erb);
2374 bool didThrow =
false;
2375 for(
size_t i = 0; i < x.nRuntimeErrorCases(); ++i) {
2376 std::cout <<
" -> runtime_error case: " << i << std::endl;
2378 x.setForceRuntimeError(
true, i);
2381 BOOST_CHECK(!erb->hasSeenException());
2383 [[maybe_unused]]
auto result = reg.isReadOnly();
2387 BOOST_CHECK(erb->hasSeenException());
2391 x.setForceRuntimeError(
false, i);
2394 this->recoverDevice(d);
2398 std::cout <<
" (doesn't throw)" << std::endl;
2401 std::cout <<
" (throws)" << std::endl;
2414 template<
typename VECTOR_OF_REGISTERS_T>
2416 if(_testOnlyTransferElement)
return;
2417 std::cout <<
"--- test_B_9_2_2 - repeated setException() has no effect" << std::endl;
2423 std::list<TransferElementAbstractor> accessors;
2424 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2425 if(!this->isAsyncRead(x))
return;
2426 typedef typename decltype(x)::minimumUserType UserType;
2427 auto registerName = x.path();
2428 std::cout <<
"... registerName = " << registerName << std::endl;
2432 accessors.push_back(reg);
2442 for(
auto& accessor : accessors) {
2454 for(
auto& accessor : accessors) {
2455 BOOST_CHECK(accessor.readNonBlocking() ==
false);
2468 template<
typename VECTOR_OF_REGISTERS_T>
2470 if(_testOnlyTransferElement)
return;
2471 std::cout <<
"--- test_B_9_3_1 - setException() disables asynchronous read transfers" << std::endl;
2477 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2478 if(!this->isAsyncRead(x))
return;
2479 typedef typename decltype(x)::minimumUserType UserType;
2480 auto registerName = x.path();
2481 std::cout <<
"... registerName = " << registerName << std::endl;
2502 BOOST_CHECK(reg.readNonBlocking() ==
false);
2505 this->recoverDevice(d);
2519 template<
typename VECTOR_OF_REGISTERS_T>
2521 if(_testOnlyTransferElement)
return;
2522 std::cout <<
"--- test_B_9_3_2 - exactly one runtime_error in the _readQueue per async read accessor" << std::endl;
2528 std::list<TransferElementAbstractor> accessors;
2529 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2530 if(!this->isAsyncRead(x))
return;
2531 typedef typename decltype(x)::minimumUserType UserType;
2532 auto registerName = x.path();
2533 std::cout <<
"... registerName = " << registerName << std::endl;
2537 accessors.push_back(reg);
2549 for(
auto& accessor : accessors) {
2551 accessor.getHighLevelImplElement()->preRead(TransferType::read);
2552 BOOST_CHECK_THROW(accessor.getHighLevelImplElement()->readTransfer(),
runtime_error);
2553 accessor.getHighLevelImplElement()->postRead(TransferType::read,
false);
2555 BOOST_CHECK(accessor.readNonBlocking() ==
false);
2568 template<
typename VECTOR_OF_REGISTERS_T>
2570 if(_testOnlyTransferElement)
return;
2572 <<
"--- test_B_9_4_1 - doReadTransferSynchronously throws runtime_error after setException() until recovery"
2577 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2578 if(!this->isRead(x))
return;
2579 typedef typename decltype(x)::minimumUserType UserType;
2580 auto registerName = x.path();
2581 std::cout <<
"... registerName = " << registerName << std::endl;
2591 this->recoverDevice(d);
2594 BOOST_CHECK_NO_THROW(reg.read());
2606 template<
typename VECTOR_OF_REGISTERS_T>
2608 if(_testOnlyTransferElement)
return;
2609 std::cout <<
"--- test_B_9_5 - write operations throw after setException()" << std::endl;
2613 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2614 if(!this->isWrite(x))
return;
2615 typedef typename decltype(x)::minimumUserType UserType;
2616 auto registerName = x.path();
2617 std::cout <<
"... registerName = " << registerName << std::endl;
2627 this->recoverDevice(d);
2630 BOOST_CHECK_NO_THROW(reg.write());
2642 template<
typename VECTOR_OF_REGISTERS_T>
2644 std::cout <<
"--- test_B_11_2_1 - version number bigger for newer values" << std::endl;
2651 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2652 if(!this->isRead(x))
return;
2653 if(x.capabilities.setRemoteValueIncrementsVersion == TestCapability::disabled)
return;
2654 typedef typename decltype(x)::minimumUserType UserType;
2655 auto registerName = x.path();
2658 std::cout <<
"... registerName = " << registerName << std::endl;
2661 for(
size_t i = 0; i < 2; ++i) {
2669 BOOST_CHECK(reg.getVersionNumber() > someVersion);
2670 someVersion = reg.getVersionNumber();
2676 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2677 if(!this->isAsyncRead(x))
return;
2678 typedef typename decltype(x)::minimumUserType UserType;
2679 auto registerName = x.path();
2681 std::cout <<
"... registerName = " << registerName <<
" (async)" << std::endl;
2696 for(
size_t i = 0; i < 2; ++i) {
2698 auto val = x.template getRemoteValue<UserType>();
2700 BOOST_TEST(reg.getVersionNumber() > someVersion);
2701 someVersion = reg.getVersionNumber();
2718 template<
typename VECTOR_OF_REGISTERS_T>
2720 std::cout <<
"--- test_NOSPEC_newVersionsAfterOpen - version numbers after open() are newer" << std::endl;
2730 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2731 if(!this->isRead(x))
return;
2732 typedef typename decltype(x)::minimumUserType UserType;
2733 auto registerName = x.path();
2735 std::cout <<
"... registerName = " << registerName << std::endl;
2745 BOOST_CHECK(reg.getVersionNumber() > someVersion);
2750 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2751 if(!this->isAsyncRead(x))
return;
2752 typedef typename decltype(x)::minimumUserType UserType;
2753 auto registerName = x.path();
2755 std::cout <<
"... registerName = " << registerName <<
" (async1)" << std::endl;
2762 BOOST_CHECK(reg.getVersionNumber() > someVersion);
2769 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2770 if(!this->isAsyncRead(x))
return;
2771 typedef typename decltype(x)::minimumUserType UserType;
2772 auto registerName = x.path();
2777 std::cout <<
"... registerName = " << registerName <<
" (async2)" << std::endl;
2786 BOOST_CHECK(reg.getVersionNumber() > someVersion);
2802 template<
typename VECTOR_OF_REGISTERS_T>
2804 if(_testOnlyTransferElement)
return;
2805 std::cout <<
"--- test_B_11_2_2 - consistent data gets same VersionNumber" << std::endl;
2813 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2814 if(!this->isAsyncRead(x))
return;
2815 typedef typename decltype(x)::minimumUserType UserType;
2816 auto registerName = x.path();
2817 std::cout <<
"... registerName = " << registerName << std::endl;
2843 auto val = x.template getRemoteValue<UserType>();
2847 BOOST_CHECK_EQUAL(reg.getVersionNumber(), reg2.getVersionNumber());
2860 template<
typename VECTOR_OF_REGISTERS_T>
2862 std::cout <<
"--- B.11.6 - value after construction for the version number in the application buffer" << std::endl;
2865 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2866 typedef typename decltype(x)::minimumUserType UserType;
2867 auto registerName = x.path();
2868 std::cout <<
"... registerName = " << registerName << std::endl;
2872 BOOST_CHECK(reg.getVersionNumber() ==
VersionNumber(
nullptr));
2882 template<
typename VECTOR_OF_REGISTERS_T>
2884 if(_testOnlyTransferElement)
return;
2885 std::cout <<
"--- test_C_5_2_1_2 - logic_error for non-existing register" << std::endl;
2912 template<
typename VECTOR_OF_REGISTERS_T>
2914 if(_testOnlyTransferElement)
return;
2915 std::cout <<
"--- test_C_5_2_2_2 - logic_error for exceeding register size" << std::endl;
2918 std::map<std::string, size_t> sizeMap;
2921 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2922 typedef typename decltype(x)::minimumUserType UserType;
2923 auto registerName = x.path();
2924 std::cout <<
"... registerName = " << registerName << std::endl;
2926 sizeMap[registerName] = reg.getNElementsPerChannel();
2930 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2931 typedef typename decltype(x)::minimumUserType UserType;
2932 auto registerName = x.path();
2933 std::cout <<
"... registerName = " << registerName << std::endl;
2963 if(sizeMap[registerName] > 1) {
2965 BOOST_CHECK_NO_THROW(
2977 template<
typename VECTOR_OF_REGISTERS_T>
2979 std::cout <<
"--- test_C_5_2_3_2 - logic_error for wrong access mode flags" << std::endl;
2982 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2984 typedef typename decltype(x)::minimumUserType UserType;
2985 auto registerName = x.path();
2986 std::cout <<
"... registerName = " << registerName <<
" (wait_for_new_data throws)" << std::endl;
2990 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
2992 typedef typename decltype(x)::minimumUserType UserType;
2993 auto registerName = x.path();
2994 std::cout <<
"... registerName = " << registerName <<
" (raw throws)" << std::endl;
3005 template<
typename VECTOR_OF_REGISTERS_T>
3007 if(_testOnlyTransferElement)
return;
3008 std::cout <<
"--- test_C_5_2_5_2 - logic_error on operation while backend closed" << std::endl;
3011 std::cout <<
"... synchronous read" << std::endl;
3012 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3013 if(!this->isRead(x))
return;
3014 typedef typename decltype(x)::minimumUserType UserType;
3015 auto registerName = x.path();
3016 std::cout <<
" registerName = " << registerName << std::endl;
3021 std::cout <<
"... asynchronous read" << std::endl;
3022 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3023 if(!this->isAsyncRead(x))
return;
3024 typedef typename decltype(x)::minimumUserType UserType;
3025 auto registerName = x.path();
3026 std::cout <<
" registerName = " << registerName << std::endl;
3029 BOOST_CHECK_THROW(reg.readNonBlocking(),
logic_error);
3032 std::cout <<
"... write" << std::endl;
3033 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3034 if(!this->isWrite(x))
return;
3035 typedef typename decltype(x)::minimumUserType UserType;
3036 auto registerName = x.path();
3037 std::cout <<
" registerName = " << registerName << std::endl;
3049 template<
typename VECTOR_OF_REGISTERS_T>
3051 std::cout <<
"--- test_C_5_2_6_2 - logic_error on read operation on write-only register" << std::endl;
3054 std::cout <<
"... synchronous read" << std::endl;
3055 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3056 if(!this->isWriteOnly(x))
return;
3057 typedef typename decltype(x)::minimumUserType UserType;
3058 auto registerName = x.path();
3059 std::cout <<
" registerName = " << registerName << std::endl;
3064 std::cout <<
"... asynchronous read" << std::endl;
3065 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3066 if(!this->isWriteOnly(x))
return;
3067 typedef typename decltype(x)::minimumUserType UserType;
3068 auto registerName = x.path();
3069 std::cout <<
" registerName = " << registerName << std::endl;
3081 template<
typename VECTOR_OF_REGISTERS_T>
3083 std::cout <<
"--- test_C_5_2_7_2 - logic_error on write operation on read-only register" << std::endl;
3086 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3087 if(!this->isReadOnly(x))
return;
3088 typedef typename decltype(x)::minimumUserType UserType;
3089 auto registerName = x.path();
3090 std::cout <<
" registerName = " << registerName << std::endl;
3103 template<
typename VECTOR_OF_REGISTERS_T>
3105 std::cout <<
"--- test_C_5_3 - read-only/write-only information changes after runtime_error" << std::endl;
3110 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3111 if(!this->isRead(x) || !this->isWrite(x) || x.capabilities.switchReadOnly != TestCapability::enabled)
return;
3112 typedef typename decltype(x)::minimumUserType UserType;
3113 auto registerName = x.path();
3114 std::cout <<
" registerName = " << registerName << std::endl;
3116 this->switchReadOnly(x,
true);
3117 BOOST_CHECK(reg.isWriteable() ==
true);
3119 BOOST_CHECK(reg.isWriteable() ==
false);
3120 this->switchReadOnly(x,
false);
3124 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3125 if(!this->isRead(x) || !this->isWrite(x) || x.capabilities.switchWriteOnly != TestCapability::enabled)
return;
3126 typedef typename decltype(x)::minimumUserType UserType;
3127 auto registerName = x.path();
3128 std::cout <<
" registerName = " << registerName << std::endl;
3130 this->switchWriteOnly(x,
true);
3131 BOOST_CHECK(reg.isReadable() ==
true);
3133 BOOST_CHECK(reg.isReadable() ==
false);
3134 this->switchWriteOnly(x,
false);
3144 template<
typename VECTOR_OF_REGISTERS_T>
3146 std::cout <<
"--- test_C_5_3_2 - read-only/write-only information cached per accessor" << std::endl;
3151 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3152 if(!this->isRead(x) || !this->isWrite(x) || x.capabilities.switchReadOnly != TestCapability::enabled)
return;
3153 typedef typename decltype(x)::minimumUserType UserType;
3154 auto registerName = x.path();
3155 std::cout <<
" registerName = " << registerName << std::endl;
3158 this->switchReadOnly(x,
true);
3160 BOOST_CHECK(reg2.isWriteable() ==
true);
3161 this->switchReadOnly(x,
false);
3165 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3166 if(!this->isRead(x) || !this->isWrite(x) || x.capabilities.switchWriteOnly != TestCapability::enabled)
return;
3167 typedef typename decltype(x)::minimumUserType UserType;
3168 auto registerName = x.path();
3169 std::cout <<
" registerName = " << registerName << std::endl;
3172 this->switchWriteOnly(x,
true);
3174 BOOST_CHECK(reg2.isReadable() ==
true);
3175 this->switchWriteOnly(x,
false);
3185 template<
typename VECTOR_OF_REGISTERS_T>
3187 std::cout <<
"--- test_C_5_3_3 - read-only/write-only information always returned from cache if available"
3192 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3193 typedef typename decltype(x)::minimumUserType UserType;
3194 auto registerName = x.path();
3195 std::cout <<
" registerName = " << registerName << std::endl;
3199 auto isReadable = reg.isReadable();
3200 auto isWriteable = reg.isWriteable();
3202 for(
size_t i = 0; i < x.nRuntimeErrorCases(); ++i) {
3203 std::cout <<
" -> runtime_error case: " << i << std::endl;
3205 x.setForceRuntimeError(
true, i);
3209 BOOST_CHECK(reg.isReadable() == isReadable);
3210 BOOST_CHECK(reg.isWriteable() == isWriteable);
3213 x.setForceRuntimeError(
false, i);
3227 template<
typename VECTOR_OF_REGISTERS_T>
3229 std::cout <<
"--- test_NOSPEC_valueAfterConstruction - content of the application data buffer after construction."
3233 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3234 typedef typename decltype(x)::minimumUserType UserType;
3235 auto registerName = x.path();
3236 std::cout <<
"... registerName = " << registerName << std::endl;
3240 std::vector<UserType> v(reg.getNElementsPerChannel(), UserType());
3241 for(
size_t i = 0; i < reg.getNChannels(); ++i) BOOST_CHECK(reg[i] == v);
3251 template<
typename VECTOR_OF_REGISTERS_T>
3253 if(_testOnlyTransferElement)
return;
3254 std::cout <<
"--- test_NOSPEC_backendNotClosedAfterException - backend not closed after exception" << std::endl;
3260 std::cout <<
"... synchronous read" << std::endl;
3261 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3262 if(!this->isRead(x))
return;
3263 if(x.nRuntimeErrorCases() == 0)
return;
3264 typedef typename decltype(x)::minimumUserType UserType;
3265 auto registerName = x.path();
3266 std::cout <<
" registerName = " << registerName << std::endl;
3269 for(
size_t i = 0; i < x.nRuntimeErrorCases(); ++i) {
3270 std::cout <<
" -> runtime_error case: " << i << std::endl;
3272 x.setForceRuntimeError(
true, i);
3287 x.setForceRuntimeError(
false, i);
3290 this->recoverDevice(d);
3294 std::cout <<
"... asynchronous read" << std::endl;
3296 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3297 if(!this->isAsyncRead(x))
return;
3298 if(x.nRuntimeErrorCases() == 0)
return;
3299 typedef typename decltype(x)::minimumUserType UserType;
3300 auto registerName = x.path();
3301 std::cout <<
" registerName = " << registerName << std::endl;
3304 for(
size_t i = 0; i < x.nRuntimeErrorCases(); ++i) {
3305 std::cout <<
" -> runtime_error case: " << i << std::endl;
3309 x.setForceRuntimeError(
true, i);
3324 x.setForceRuntimeError(
false, i);
3327 this->recoverDevice(d);
3332 std::cout <<
"... write" << std::endl;
3333 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3334 if(!this->isWrite(x))
return;
3335 if(x.nRuntimeErrorCases() == 0)
return;
3336 typedef typename decltype(x)::minimumUserType UserType;
3337 auto registerName = x.path();
3338 std::cout <<
" registerName = " << registerName << std::endl;
3341 for(
size_t i = 0; i < x.nRuntimeErrorCases(); ++i) {
3342 std::cout <<
" -> runtime_error case: " << i << std::endl;
3344 x.setForceRuntimeError(
true, i);
3359 x.setForceRuntimeError(
false, i);
3362 this->recoverDevice(d);
3366 std::cout <<
"... isReadable" << std::endl;
3367 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3368 if(x.nRuntimeErrorCases() == 0)
return;
3369 typedef typename decltype(x)::minimumUserType UserType;
3370 auto registerName = x.path();
3371 std::cout <<
" registerName = " << registerName;
3374 bool didThrow =
false;
3375 for(
size_t i = 0; i < x.nRuntimeErrorCases(); ++i) {
3376 std::cout <<
" -> runtime_error case: " << i << std::endl;
3378 x.setForceRuntimeError(
true, i);
3382 [[maybe_unused]]
auto result = reg.isReadable();
3397 x.setForceRuntimeError(
false, i);
3400 this->recoverDevice(d);
3404 std::cout <<
" (doesn't throw)" << std::endl;
3407 std::cout <<
" (throws)" << std::endl;
3411 std::cout <<
"... isWriteable" << std::endl;
3412 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3413 if(x.nRuntimeErrorCases() == 0)
return;
3414 typedef typename decltype(x)::minimumUserType UserType;
3415 auto registerName = x.path();
3416 std::cout <<
" registerName = " << registerName;
3419 bool didThrow =
false;
3420 for(
size_t i = 0; i < x.nRuntimeErrorCases(); ++i) {
3421 std::cout <<
" -> runtime_error case: " << i << std::endl;
3423 x.setForceRuntimeError(
true, i);
3427 [[maybe_unused]]
auto result = reg.isWriteable();
3442 x.setForceRuntimeError(
false, i);
3445 this->recoverDevice(d);
3449 std::cout <<
" (doesn't throw)" << std::endl;
3452 std::cout <<
" (throws)" << std::endl;
3456 std::cout <<
"... isReadOnly" << std::endl;
3457 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3458 typedef typename decltype(x)::minimumUserType UserType;
3459 auto registerName = x.path();
3460 std::cout <<
" registerName = " << registerName;
3463 bool didThrow =
false;
3464 for(
size_t i = 0; i < x.nRuntimeErrorCases(); ++i) {
3465 std::cout <<
" -> runtime_error case: " << i << std::endl;
3467 x.setForceRuntimeError(
true, i);
3471 [[maybe_unused]]
auto result = reg.isReadOnly();
3486 x.setForceRuntimeError(
false, i);
3489 this->recoverDevice(d);
3493 std::cout <<
" (doesn't throw)" << std::endl;
3496 std::cout <<
" (throws)" << std::endl;
3509 template<
typename VECTOR_OF_REGISTERS_T>
3511 std::cout <<
"--- test_NOSPEC_rawTransfer - test creation and reading/writing with access mode raw." << std::endl;
3515 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3517 if constexpr(x.capabilities.testRawTransfer == TestCapability::enabled) {
3518 auto registerName = x.path();
3519 std::cout <<
"... registerName = " << registerName << std::endl;
3521 BOOST_REQUIRE_MESSAGE(this->isRaw(x),
3522 "Test configuration error: testRawTransfer is enabled for register without AccessMode::raw!");
3524 typedef typename decltype(x)::minimumUserType UserType;
3525 typedef typename decltype(x)::rawUserType RawType;
3533 if(x.isReadable()) {
3536 auto expectedRawValue = x.template getRemoteValue<RawType>(
true);
3539 auto expectedCookedValue = x.template getRemoteValue<UserType>();
3542 std::vector<std::vector<UserType>> readCookedValue;
3543 for(
size_t channel = 0; channel < reg.getNChannels(); ++channel) {
3544 std::vector<UserType> readCookedChannel;
3545 for(
size_t element = 0; element < reg.getNElementsPerChannel(); ++element) {
3546 readCookedChannel.push_back(reg.template getAsCooked<UserType>(channel, element));
3548 readCookedValue.push_back(readCookedChannel);
3552 if(x.isWriteable()) {
3553 auto newValue = x.template generateValue<RawType>(
true);
3556 auto readbackValue = x.template getRemoteValue<RawType>(
true);
3560 auto newCookedValue = x.template generateValue<UserType>();
3561 for(
size_t channel = 0; channel < reg.getNChannels(); ++channel) {
3562 for(
size_t element = 0; element < reg.getNElementsPerChannel(); ++element) {
3563 reg.template setAsCooked<UserType>(channel, element, newCookedValue[channel][element]);
3568 auto readbackCookedValue = x.template getRemoteValue<UserType>();
3572 catch(std::exception& e) {
3573 BOOST_CHECK_MESSAGE(
false, std::string(
"Unexpected expeption: ") + e.what());
3576 if(this->isRaw(x)) {
3577 if(x.capabilities.testRawTransfer == TestCapability::disabled) {
3578 BOOST_REQUIRE_MESSAGE(
false,
3579 "Test configuration error: testRawTransfer is disabled for register '" + std::string(x.path()) +
3580 "' with AccessMode::raw!");
3582 else if(x.capabilities.testRawTransfer == TestCapability::unspecified) {
3583 std::cout <<
"WARNING: testRawTransfer capability unspecified for register '" + std::string(x.path()) +
3584 "' with AccessMode::raw. This will turn into a test configuration error in a future release!"
3589 if(x.capabilities.testRawTransfer == TestCapability::unspecified) {
3590 std::cout <<
"Warning: testRawTransfer capability unspecified for register '" + std::string(x.path()) +
3591 "' without AccessMode::raw. Please explicitly disable this test."
3604 template<
typename VECTOR_OF_REGISTERS_T>
3606 std::cout <<
"--- test_NOSPEC_catalogueRaw - test catalogue entries for access mode raw." << std::endl;
3609 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3610 if(x.capabilities.testCatalogue == TestCapability::disabled) {
3614 auto registerName = x.path();
3615 std::cout <<
"... registerName = " << registerName << std::endl;
3618 if(std::string(registerName).find(
"DUMMY_WRITEABLE") != std::string::npos) {
3622 if(std::string(registerName).find(
"DUMMY_INTERRUPT_") != std::string::npos) {
3628 if(this->isRaw(x)) {
3629 BOOST_CHECK(registerInfo.getSupportedAccessModes().has(AccessMode::raw));
3630 BOOST_TEST(registerInfo.getDataDescriptor().rawDataType() != DataType::none);
3633 BOOST_CHECK(not registerInfo.getSupportedAccessModes().has(AccessMode::raw));
3634 BOOST_CHECK((registerInfo.getDataDescriptor().rawDataType() == DataType::none) ||
3635 (registerInfo.getDataDescriptor().rawDataType() == DataType::Void));
3644 template<
typename VECTOR_OF_REGISTERS_T>
3646 std::cout <<
"--- test_NOSPEC_catalogueReadWrite- test catalogue and accessor entries for read/write." << std::endl;
3649 boost::mpl::for_each<VECTOR_OF_REGISTERS_T>([&](
auto x) {
3650 if(x.capabilities.testCatalogue == TestCapability::disabled) {
3654 typedef typename decltype(x)::minimumUserType UserType;
3656 auto registerName = x.path();
3657 std::cout <<
"... registerName = " << registerName << std::endl;
3662 BOOST_CHECK_EQUAL(this->isRead(x), registerInfo.isReadable());
3663 BOOST_CHECK_EQUAL(this->isRead(x), accessor.isReadable());
3664 BOOST_CHECK_EQUAL(this->isWrite(x), registerInfo.isWriteable());
3665 BOOST_CHECK_EQUAL(this->isWrite(x), accessor.isWriteable());