diff --git a/src/TestFacility.cc b/src/TestFacility.cc index 6d5c72d6b726a2005ce468cac7d47a026eb58346..93445b70ba45ecc4148503d80ded6fb25f391464 100644 --- a/src/TestFacility.cc +++ b/src/TestFacility.cc @@ -22,38 +22,48 @@ namespace ChimeraTK { void TestFacility::runApplication() const { app.testFacilityRunApplicationCalled = true; + // send default values for all control system variables for(auto& pv : pvManager->getAllProcessVariables()) { - callForTypeNoVoid(pv->getValueType(), [&pv, this](auto arg) { - // Applies only to writeable variables. @todo FIXME It should also NOT apply for application-to-controlsystem - // variables with a return channel, despite being writeable here! + callForType(pv->getValueType(), [&pv, this](auto arg) { + using T = decltype(arg); + + // Applies only to writeable variables. + // @todo FIXME It should also NOT apply for application-to-controlsystem variables with a return channel, + // despite being writeable here! if(!pv->isWriteable()) return; + // Safety check against incorrect usage if(pv->getVersionNumber() != VersionNumber(nullptr)) { throw ChimeraTK::logic_error("The variable '" + pv->getName() + "' has been written before TestFacility::runApplication() was called. Instead use " "TestFacility::setScalarDefault() resp. setArrayDefault() to set initial values."); } - typedef decltype(arg) T; + + // Get the PV accessor auto pv_casted = boost::dynamic_pointer_cast<NDRegisterAccessor<T>>(pv); - auto table = boost::fusion::at_key<T>(defaults.table); + // If default value has been stored, copy the default value to the PV. - if(table.find(pv->getName()) != table.end()) { - /// Since pv_casted is the undecorated PV (lacking the TestableModeAccessorDecorator), we need to copy the - /// value also to the decorator. We still have to write through the undecorated PV, otherwise the tests are - /// stalled. @todo It is not understood why this happens! - /// Decorated accessors are stored in different maps for scalars are arrays... - if(pv_casted->getNumberOfSamples() == 1) { // scalar - auto accessor = this->getScalar<T>(pv->getName()); - accessor = table.at(pv->getName())[0]; - } - else { // array - auto accessor = this->getArray<T>(pv->getName()); - accessor = table.at(pv->getName()); + if constexpr(!std::is_same<T, ChimeraTK::Void>::value) { + auto table = boost::fusion::at_key<T>(defaults.table); + if(table.find(pv->getName()) != table.end()) { + /// Since pv_casted is the undecorated PV (lacking the TestableModeAccessorDecorator), we need to copy the + /// value also to the decorator. We still have to write through the undecorated PV, otherwise the tests are + /// stalled. @todo It is not understood why this happens! + /// Decorated accessors are stored in different maps for scalars are arrays... + if(pv_casted->getNumberOfSamples() == 1) { // scalar + auto accessor = this->getScalar<T>(pv->getName()); + accessor = table.at(pv->getName())[0]; + } + else { // array + auto accessor = this->getArray<T>(pv->getName()); + accessor = table.at(pv->getName()); + } + // copy value also to undecorated PV + pv_casted->accessChannel(0) = table.at(pv->getName()); } - // copy value also to undecorated PV - pv_casted->accessChannel(0) = table.at(pv->getName()); } + // Write the initial value. This must be done even if no default value has been stored, since it is expected // by the application. pv_casted->write();