From b7237dcdc19860e883e0f689d88ff9f5156cd63a Mon Sep 17 00:00:00 2001
From: Martin Hierholzer <martin.hierholzer@desy.de>
Date: Fri, 30 Sep 2022 11:59:23 +0200
Subject: [PATCH] TestFacility: fix not sending initial values for Void
 variables

---
 src/TestFacility.cc | 48 +++++++++++++++++++++++++++------------------
 1 file changed, 29 insertions(+), 19 deletions(-)

diff --git a/src/TestFacility.cc b/src/TestFacility.cc
index 6d5c72d6..93445b70 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();
-- 
GitLab