From 098d6c65df26c518635752b7c129b8501d70c077 Mon Sep 17 00:00:00 2001
From: Martin Hierholzer <martin.hierholzer@desy.de>
Date: Wed, 5 Feb 2020 13:54:25 +0100
Subject: [PATCH] TestFacility: fix initial for bidirectional variables

The default value was properly propagated but not visible to the test until a value was sent through the return channel.
---
 include/TestFacility.h | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/include/TestFacility.h b/include/TestFacility.h
index 6d2be730..401ab5be 100644
--- a/include/TestFacility.h
+++ b/include/TestFacility.h
@@ -41,7 +41,10 @@ namespace ChimeraTK {
       // send default values for all control system variables
       for(auto& pv : pvManager->getAllProcessVariables()) {
         callForType(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!
           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 "
@@ -50,9 +53,25 @@ namespace ChimeraTK {
           typedef decltype(arg) T;
           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());
+            }
+            // 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