Skip to content
Snippets Groups Projects
testHistory.cc 8.46 KiB
Newer Older
// SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
// SPDX-License-Identifier: LGPL-3.0-or-later
#define BOOST_TEST_MODULE HistoryTest

#include "ServerHistory.h"
#include "TestFacility.h"

#include <boost/mpl/list.hpp>
#include <boost/thread.hpp>

#include <fstream>

#define BOOST_NO_EXCEPTIONS
#include <boost/test/included/unit_test.hpp>
#include <boost/test/unit_test.hpp>
using namespace boost::unit_test_framework;

// list of user types the accessors are tested with
typedef boost::mpl::list<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, float, double> test_types;

template<typename UserType>
struct Dummy : public ChimeraTK::ApplicationModule {
  using ChimeraTK::ApplicationModule::ApplicationModule;
  ChimeraTK::ScalarPushInput<UserType> in{this, "in", "", "Dummy input"};
  ChimeraTK::ScalarOutput<UserType> out{this, "out", "", "Dummy output", {"history"}};
  void mainLoop() override {
    while(true) {
      // write first so initial values are propagated
      out = static_cast<UserType>(in);
template<typename UserType>
struct DummyArray : public ChimeraTK::ApplicationModule {
  using ChimeraTK::ApplicationModule::ApplicationModule;
  ChimeraTK::ArrayPushInput<UserType> in{this, "in", "", 3, "Dummy input"};
  ChimeraTK::ArrayOutput<UserType> out{this, "out", "", 3, "Dummy output", {"history"}};
  void mainLoop() override {
    while(true) {
      for(unsigned int i = 0; i < 3; i++) {
        out[i] = in[i];
      }
 * Define a test app to test the scalar History Module.
template<typename UserType>
struct testApp : public ChimeraTK::Application {
  testApp() : Application("test") {}
  Dummy<UserType> dummy{this, "Dummy", "Dummy module"};
zenker's avatar
zenker committed
  ChimeraTK::history::ServerHistory hist{this, "history", "History of selected process variables.", 20};
zenker's avatar
zenker committed
  void initialise() override {
    Application::initialise();
    dumpConnections();
};

/**
 * Define a test app to test the array History Module.
 */
template<typename UserType>
struct testAppArray : public ChimeraTK::Application {
  testAppArray() : Application("test") {}

  DummyArray<UserType> dummy{this, "Dummy", "Dummy module"};
zenker's avatar
zenker committed
  ChimeraTK::history::ServerHistory hist{this, "history", "History of selected process variables.", 20};
zenker's avatar
zenker committed
  void initialise() override {
    Application::initialise();
    dumpConnections();
/**
 * Define a test app to test the device module in combination with the History Module.
 */
struct testAppDev : public ChimeraTK::Application {
  testAppDev() : Application("test") { ChimeraTK::BackendFactory::getInstance().setDMapFilePath("test.dmap"); }
zenker's avatar
zenker committed
  ChimeraTK::ConnectingDeviceModule dev{this, "Dummy1Mapped", "/Dummy/out"};

  DummyArray<int> dummy{this, "Dummy", "Dummy module"};

zenker's avatar
zenker committed
  ChimeraTK::history::ServerHistory hist{this, "history", "History of selected process variables.", 20, false};
zenker's avatar
zenker committed
  void initialise() override {
    hist.addSource(&dev, "", "", dummy.out);
    Application::initialise();
    dumpConnections();
BOOST_AUTO_TEST_CASE_TEMPLATE(testScalarHistory, T, test_types) {
  std::cout << "testScalarHistory " << typeid(T).name() << std::endl;
  ChimeraTK::TestFacility tf;
zenker's avatar
zenker committed
  auto i = tf.getScalar<T>("Dummy/in");
  tf.runApplication();
  i = 42.;
  i.write();
  tf.stepApplication();
  std::vector<T> v_ref(20);
  v_ref.back() = 42.;
  auto v = tf.readArray<T>("history/Dummy/out");
  BOOST_CHECK_EQUAL_COLLECTIONS(v.begin(), v.end(), v_ref.begin(), v_ref.end());
  i = 42.;
  i.write();
  tf.stepApplication();
  *(v_ref.end() - 2) = 42.;
  v = tf.readArray<T>("history/Dummy/out");
  BOOST_CHECK_EQUAL_COLLECTIONS(v.begin(), v.end(), v_ref.begin(), v_ref.end());
/* 'if constexpr' not working with gcc version < 7 so
 * add string case manually.
 */
BOOST_AUTO_TEST_CASE(testScalarHistoryString) {
  std::cout << "testScalarHistoryString" << std::endl;
  testApp<std::string> app;
  ChimeraTK::TestFacility tf;
zenker's avatar
zenker committed
  auto i = tf.getScalar<std::string>("Dummy/in");
  i.write();
  tf.stepApplication();
  std::vector<std::string> v_ref(20);
  v_ref.back() = "42";
  auto v = tf.readArray<std::string>("history/Dummy/out");
  BOOST_CHECK_EQUAL_COLLECTIONS(v.begin(), v.end(), v_ref.begin(), v_ref.end());
  i = "42";
  i.write();
  tf.stepApplication();
  *(v_ref.end() - 2) = "42";
  v = tf.readArray<std::string>("history/Dummy/out");
  BOOST_CHECK_EQUAL_COLLECTIONS(v.begin(), v.end(), v_ref.begin(), v_ref.end());
BOOST_AUTO_TEST_CASE_TEMPLATE(testArrayHistory, T, test_types) {
  std::cout << "testArrayHistory " << typeid(T).name() << std::endl;
  ChimeraTK::TestFacility tf;
zenker's avatar
zenker committed
  auto arr = tf.getArray<T>("Dummy/in");
  arr[0] = 42.;
  arr[1] = 43.;
  arr[2] = 44.;
  arr.write();
  tf.stepApplication();
zenker's avatar
zenker committed
  BOOST_CHECK_EQUAL(tf.readArray<T>("Dummy/out")[0], 42.0);
  BOOST_CHECK_EQUAL(tf.readArray<T>("Dummy/out")[1], 43.0);
  BOOST_CHECK_EQUAL(tf.readArray<T>("Dummy/out")[2], 44.0);
  std::vector<T> v_ref(20);
  for(size_t i = 0; i < 3; i++) {
    v_ref.back() = 42.0 + i;
    auto v = tf.readArray<T>("history/Dummy/out_" + std::to_string(i));
    BOOST_CHECK_EQUAL_COLLECTIONS(v.begin(), v.end(), v_ref.begin(), v_ref.end());
  arr[0] = 1.0;
  arr[1] = 2.0;
  arr[2] = 3.0;
  arr.write();
  tf.stepApplication();
  for(size_t i = 0; i < 3; i++) {
    *(v_ref.end() - 2) = 42.0 + i;
    *(v_ref.end() - 1) = 1.0 + i;
    auto v = tf.readArray<T>("history/Dummy/out_" + std::to_string(i));
    BOOST_CHECK_EQUAL_COLLECTIONS(v.begin(), v.end(), v_ref.begin(), v_ref.end());
/* 'if constexpr' not working with gcc version < 7 so
 * add string case manually.
 */
BOOST_AUTO_TEST_CASE(testArrayHistoryString) {
  std::cout << "testArrayHistoryString" << std::endl;
  testAppArray<std::string> app;
  ChimeraTK::TestFacility tf;
zenker's avatar
zenker committed
  auto arr = tf.getArray<std::string>("Dummy/in");
  arr[0] = "42";
  arr[1] = "43";
  arr[2] = "44";
  tf.stepApplication();
zenker's avatar
zenker committed
  BOOST_CHECK_EQUAL(tf.readArray<std::string>("Dummy/out")[0], "42");
  BOOST_CHECK_EQUAL(tf.readArray<std::string>("Dummy/out")[1], "43");
  BOOST_CHECK_EQUAL(tf.readArray<std::string>("Dummy/out")[2], "44");
  std::vector<std::string> v_ref(20);
  for(size_t i = 0; i < 3; i++) {
    v_ref.back() = std::to_string(42 + i);
    auto v = tf.readArray<std::string>("history/Dummy/out_" + std::to_string(i));
    BOOST_CHECK_EQUAL_COLLECTIONS(v.begin(), v.end(), v_ref.begin(), v_ref.end());
  arr[0] = "1";
  arr[1] = "2";
  arr[2] = "3";
  tf.stepApplication();
  for(size_t i = 0; i < 3; i++) {
    *(v_ref.end() - 2) = std::to_string(42 + i);
    *(v_ref.end() - 1) = std::to_string(1 + i);
    auto v = tf.readArray<std::string>("history/Dummy/out_" + std::to_string(i));
    BOOST_CHECK_EQUAL_COLLECTIONS(v.begin(), v.end(), v_ref.begin(), v_ref.end());
BOOST_AUTO_TEST_CASE(testDeviceHistory) {
  std::cout << "testDeviceHistory" << std::endl;
  testAppDev app;
  ChimeraTK::TestFacility tf;

  // We use this device directly to change its values
  ChimeraTK::Device dev;
  // Use Dummy1 to change device values, since Dummy1Mapped is read only
  dev.open("Dummy1");
  dev.write("/FixedPoint/value", 42);

  // Trigger the reading of the device
zenker's avatar
zenker committed
  auto i = tf.getScalar<int>("Dummy/in");
  tf.runApplication();
  i = 1.;
  i.write();

  tf.stepApplication();

  // check new history buffer that ends with 42
  std::vector<double> v_ref(20);
  v_ref.back() = 42;
  auto v = tf.readArray<float>("history/Device/signed32");
  BOOST_CHECK_EQUAL_COLLECTIONS(v.begin(), v.end(), v_ref.begin(), v_ref.end());

  // Trigger the reading of the device
  i = 1.;
  i.write();

  tf.stepApplication();

  // check new history buffer that ends with 42,42
  *(v_ref.end() - 2) = 42;
  v = tf.readArray<float>("history/Device/signed32");
  BOOST_CHECK_EQUAL_COLLECTIONS(v.begin(), v.end(), v_ref.begin(), v_ref.end());
  dev.write("/FixedPoint/value", 43);

  // Trigger the reading of the device
  i = 1.;
  i.write();

  tf.stepApplication();

  // check new history buffer that ends with 42,42,43
  *(v_ref.end() - 1) = 43;
  *(v_ref.end() - 3) = 42;
  v = tf.readArray<float>("history/Device/signed32");
  BOOST_CHECK_EQUAL_COLLECTIONS(v.begin(), v.end(), v_ref.begin(), v_ref.end());