Newer
Older
// Define a name for the test module.
#define BOOST_TEST_MODULE DoocsPVFactoryTest
// Only after defining the name include the unit test header.
#include <boost/test/included/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/mpl/list.hpp>
#include <sstream>
#include <typeinfo>
#include "DoocsPVFactory.h"
#include "DoocsProcessScalar.h"
#include "DoocsProcessArray.h"
Martin Killenberg
committed
#include "DoocsSpectrum.h"
Martin Killenberg
committed
#include <ChimeraTK/ControlSystemAdapter/ControlSystemPVManager.h>
#include <ChimeraTK/ControlSystemAdapter/DevicePVManager.h>
#include "emptyServerFunctions.h"
Martin Killenberg
committed
#include "getAllVariableNames.h"
Martin Killenberg
committed
#include "PropertyDescription.h"
using namespace boost::unit_test_framework;
Martin Killenberg
committed
using namespace ChimeraTK;
using boost::shared_ptr;
// use boost meta-programming to use test case templates
// The list of types is an mpl type
Martin Killenberg
committed
typedef boost::mpl::list<int64_t, uint64_t,
int32_t, uint32_t,
int16_t, uint16_t,
int8_t, uint8_t,
float, double> simple_test_types;
Martin Christoph Hierholzer
committed
EqFct myEqFct("MY_EQ_FCT");
Martin Killenberg
committed
template<class DOOCS_PRIMITIVE_T, class DOOCS_T>
Martin Killenberg
committed
static void testCreateProcessScalar(std::shared_ptr<PropertyDescription> const & propertyDescription,
Martin Killenberg
committed
DoocsPVFactory & factory, std::string const & expectedPropertyName){
Martin Killenberg
committed
// have the variable created and check that it is the right type
Martin Killenberg
committed
boost::shared_ptr<D_fct> doocsVariableAsDFct = factory.create( propertyDescription );
// get the raw pointer and dynamic cast it to the expected type
Martin Killenberg
committed
DoocsProcessScalar<DOOCS_PRIMITIVE_T, DOOCS_T> * doocsScalarType =
dynamic_cast< DoocsProcessScalar<DOOCS_PRIMITIVE_T, DOOCS_T> * > (doocsVariableAsDFct.get());
// if the cast succeeds the factory works as expected we are done
Martin Killenberg
committed
std::string errorMessage = std::string("testCreateProcessScalar failed for type ") + typeid(DOOCS_PRIMITIVE_T).name();
BOOST_CHECK_MESSAGE(doocsScalarType, errorMessage);
errorMessage = std::string("Error checking property name: expectedPropertyName '")
+ expectedPropertyName + "', property_name() '" + doocsVariableAsDFct->property_name() + "'";
BOOST_CHECK_MESSAGE( expectedPropertyName == doocsVariableAsDFct->property_name() , errorMessage);
}
BOOST_AUTO_TEST_SUITE( PVManagerTestSuite )
Martin Killenberg
committed
BOOST_AUTO_TEST_CASE( testAutoCreateScalars ) {
std::pair< shared_ptr<ControlSystemPVManager>,
shared_ptr<DevicePVManager> > pvManagers = createPVManager();
shared_ptr<ControlSystemPVManager> csManager = pvManagers.first;
shared_ptr<DevicePVManager> devManager = pvManagers.second;
Martin Killenberg
committed
devManager->createProcessArray<int32_t>(controlSystemToDevice,"/I/int32",1);
devManager->createProcessArray<uint32_t>(controlSystemToDevice,"/U/uint32",1);
devManager->createProcessArray<int16_t>(controlSystemToDevice,"/I/int16",1);
devManager->createProcessArray<uint16_t>(controlSystemToDevice,"/U/uint16",1);
devManager->createProcessArray<int8_t>(controlSystemToDevice,"/I/int8",1);
devManager->createProcessArray<uint8_t>(controlSystemToDevice,"/U/uint8",1);
devManager->createProcessArray<float>(controlSystemToDevice,"/FP/float",1);
devManager->createProcessArray<double>(controlSystemToDevice,"/FP/double",1);
Martin Killenberg
committed
DoocsUpdater updater;
Martin Christoph Hierholzer
committed
DoocsPVFactory factory(&myEqFct, updater, csManager);
// We insert check points with integers so we know where the algorithm kicks out in case of an error.
// These checkpoints are always true.
Martin Killenberg
committed
testCreateProcessScalar<int32_t, D_int>(
Martin Killenberg
committed
std::make_shared<AutoPropertyDescription>("I/int32", "I", "int32"), factory, "int32 ");// DOOCS property names always have a space (and potentially some description)"
BOOST_CHECK(-32);
Martin Killenberg
committed
testCreateProcessScalar<int32_t, D_int>(
Martin Killenberg
committed
std::make_shared<AutoPropertyDescription>("U/uint32", "I", "uint32"), factory, "uint32 ");
BOOST_CHECK(32);
Martin Killenberg
committed
testCreateProcessScalar<int32_t, D_int>(
Martin Killenberg
committed
std::make_shared<AutoPropertyDescription>("I/int16", "I", "int16"), factory, "int16 ");// DOOCS property names always have a space (and potentially some description)"
BOOST_CHECK(-16);
Martin Killenberg
committed
testCreateProcessScalar<int32_t, D_int>(
Martin Killenberg
committed
std::make_shared<AutoPropertyDescription>("U/uint16", "I", "uint16"), factory, "uint16 ");// DOOCS property names always have a space (and potentially some description)"
BOOST_CHECK(16);
Martin Killenberg
committed
testCreateProcessScalar<int32_t, D_int>(
Martin Killenberg
committed
std::make_shared<AutoPropertyDescription>("I/int8", "I", "int8"), factory, "int8 ");// DOOCS property names always have a space (and potentially some description)"
BOOST_CHECK(-8);
Martin Killenberg
committed
testCreateProcessScalar<int32_t, D_int>(
Martin Killenberg
committed
std::make_shared<AutoPropertyDescription>("U/uint8", "I", "uint8"), factory, "uint8 ");// DOOCS property names always have a space (and potentially some description)"
BOOST_CHECK(8);
Martin Killenberg
committed
testCreateProcessScalar<float, D_float>(
Martin Killenberg
committed
std::make_shared<AutoPropertyDescription>("FP/float", "FP", "float"), factory, "float ");// DOOCS property names always have a space (and potentially some description)"
BOOST_CHECK(0.5);
Martin Killenberg
committed
testCreateProcessScalar<double, D_double>(
Martin Killenberg
committed
std::make_shared<AutoPropertyDescription>("FP/double", "FP", "double"), factory, "double ");// DOOCS property names always have a space (and potentially some description)"
BOOST_CHECK(32);
}
Martin Killenberg
committed
//BOOST_AUTO_TEST_CASE_TEMPLATE( testCreateArray, T, simple_test_types ){
// std::pair< shared_ptr<ControlSystemPVManager>,
// shared_ptr<DevicePVManager> > pvManagers = createPVManager();
// shared_ptr<ControlSystemPVManager> csManager = pvManagers.first;
// shared_ptr<DevicePVManager> devManager = pvManagers.second;
//
// static const size_t arraySize = 10;
// devManager->createProcessArray<T>(controlSystemToDevice,"A/toDeviceArray",arraySize);
//
// DoocsPVFactory factory(&myEqFct);
Martin Killenberg
committed
//
// // have the variable created and check that it is the right type
// ProcessVariable::SharedPtr processVariable =
// csManager->getProcessArray<T>("A/toDeviceArray");
// boost::shared_ptr<D_fct> doocsVariableAsDFct = factory.create(processVariable);
//
// // get the raw pointer and dynamic cast it to the expected type
// DoocsProcessArray<T> * doocsArray =
// dynamic_cast< DoocsProcessArray<T> * > (doocsVariableAsDFct.get());
//
// // if the cast succeeds the factory works as expected we are done
// BOOST_REQUIRE(doocsArray);
// BOOST_CHECK( static_cast<size_t>(doocsArray->max_length()) == arraySize );
//}
Martin Killenberg
committed
BOOST_AUTO_TEST_CASE_TEMPLATE( testCreateSpectrum, T, simple_test_types ){
std::pair< shared_ptr<ControlSystemPVManager>,
shared_ptr<DevicePVManager> > pvManagers = createPVManager();
shared_ptr<ControlSystemPVManager> csManager = pvManagers.first;
shared_ptr<DevicePVManager> devManager = pvManagers.second;
static const size_t arraySize = 10;
// array 1 will have default settings, array 2 custom start and increment
devManager->createProcessArray<T>(controlSystemToDevice,"A/fromDeviceArray1",arraySize);
devManager->createProcessArray<T>(controlSystemToDevice,"A/fromDeviceArray2",arraySize);
// we need this later anyway, do we make a temporary variable
auto pvNames = ChimeraTK::getAllVariableNames( csManager );
Martin Killenberg
committed
DoocsUpdater updater;
DoocsPVFactory factory(&myEqFct, updater, csManager);
Martin Killenberg
committed
Martin Killenberg
committed
auto propertyDescriptions = { std::make_shared<SpectrumDescription>("A/fromDeviceArray1","A","fromDeviceArray1"), std::make_shared<SpectrumDescription>("A/fromDeviceArray2","A","fromDeviceArray2")};
Martin Killenberg
committed
Martin Killenberg
committed
// have the variable created and check that it is the right type
Martin Killenberg
committed
for (auto const & description : propertyDescriptions){
Martin Killenberg
committed
boost::shared_ptr<D_fct> doocsVariableAsDFct = factory.create(description);
Martin Killenberg
committed
// get the raw pointer and dynamic cast it to the expected type
DoocsSpectrum * doocsSpectrum =
dynamic_cast< DoocsSpectrum * > (doocsVariableAsDFct.get());
Martin Killenberg
committed
// if the cast succeeds the factory works as expected we are done
BOOST_REQUIRE(doocsSpectrum);
BOOST_CHECK( static_cast<size_t>(doocsSpectrum->max_length()) == arraySize );
}
// FIXME: add tests for x-axis config
}
Martin Killenberg
committed
void testArrayIsCorrectType(DoocsPVFactory &factory, ArrayDescription::DataType dataType, std::string name = "fromDeviceArray1"){
auto description = std::make_shared<ArrayDescription>("A/"+name,"A",name, dataType);
boost::shared_ptr<D_fct> doocsVariableAsDFct = factory.create(description);
// get the raw pointer and dynamic cast it to the expected type
DOOCS_T * doocsArray =
dynamic_cast< DOOCS_T * > (doocsVariableAsDFct.get());
// if the cast succeeds the factory works as expected we are done
BOOST_REQUIRE(doocsArray);
BOOST_CHECK( static_cast<size_t>(doocsArray->max_length()) == 10 );
}
BOOST_AUTO_TEST_CASE_TEMPLATE( testCreateArray, T, simple_test_types ){
std::pair< shared_ptr<ControlSystemPVManager>,
shared_ptr<DevicePVManager> > pvManagers = createPVManager();
shared_ptr<ControlSystemPVManager> csManager = pvManagers.first;
shared_ptr<DevicePVManager> devManager = pvManagers.second;
static const size_t arraySize = 10;
Martin Killenberg
committed
// PVs can only get one decorator, so we have to put one array for each decorator/doocs type we want to test
Martin Killenberg
committed
devManager->createProcessArray<T>(deviceToControlSystem,"A/fromDeviceArray1",arraySize);
Martin Killenberg
committed
devManager->createProcessArray<T>(deviceToControlSystem,"A/fromDeviceArray2",arraySize);
devManager->createProcessArray<T>(deviceToControlSystem,"A/fromDeviceArray3",arraySize);
devManager->createProcessArray<T>(deviceToControlSystem,"A/fromDeviceArray4",arraySize);
devManager->createProcessArray<T>(deviceToControlSystem,"A/fromDeviceArray5",arraySize);
devManager->createProcessArray<T>(deviceToControlSystem,"A/fromDeviceArray6",arraySize);
// we need this later anyway, do we make a temporary variable
auto pvNames = ChimeraTK::getAllVariableNames( csManager );
DoocsUpdater updater;
DoocsPVFactory factory(&myEqFct, updater, csManager);
Martin Killenberg
committed
testArrayIsCorrectType<D_bytearray>(factory, ArrayDescription::DataType::Byte, "fromDeviceArray1");
testArrayIsCorrectType<D_shortarray>(factory, ArrayDescription::DataType::Short, "fromDeviceArray2");
testArrayIsCorrectType<D_intarray>(factory, ArrayDescription::DataType::Int, "fromDeviceArray3");
testArrayIsCorrectType<D_longarray>(factory, ArrayDescription::DataType::Long, "fromDeviceArray4");
testArrayIsCorrectType<D_floatarray>(factory, ArrayDescription::DataType::Float, "fromDeviceArray5");
testArrayIsCorrectType<D_doublearray>(factory, ArrayDescription::DataType::Double, "fromDeviceArray6");
Martin Killenberg
committed
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
BOOST_AUTO_TEST_CASE( testAutoCreateArray ){
std::pair< shared_ptr<ControlSystemPVManager>,
shared_ptr<DevicePVManager> > pvManagers = createPVManager();
shared_ptr<ControlSystemPVManager> csManager = pvManagers.first;
shared_ptr<DevicePVManager> devManager = pvManagers.second;
static const size_t arraySize = 10;
devManager->createProcessArray<int8_t>(controlSystemToDevice,"A/toDeviceCharArray",arraySize);
devManager->createProcessArray<uint8_t>(controlSystemToDevice,"A/toDeviceUCharArray",arraySize);
devManager->createProcessArray<int16_t>(controlSystemToDevice,"A/toDeviceShortArray",arraySize);
devManager->createProcessArray<uint16_t>(controlSystemToDevice,"A/toDeviceUShortArray",arraySize);
devManager->createProcessArray<int32_t>(controlSystemToDevice,"A/toDeviceIntArray",arraySize);
devManager->createProcessArray<uint32_t>(controlSystemToDevice,"A/toDeviceUIntArray",arraySize);
devManager->createProcessArray<int64_t>(controlSystemToDevice,"A/toDeviceLongArray",arraySize);
devManager->createProcessArray<uint64_t>(controlSystemToDevice,"A/toDeviceULongArray",arraySize);
devManager->createProcessArray<float>(controlSystemToDevice,"A/toDeviceFloatArray",arraySize);
devManager->createProcessArray<double>(controlSystemToDevice,"A/toDeviceDoubleArray",arraySize);
// we need this later anyway, do we make a temporary variable
auto pvNames = ChimeraTK::getAllVariableNames( csManager );
DoocsUpdater updater;
DoocsPVFactory factory(&myEqFct, updater, csManager);
testArrayIsCorrectType<D_bytearray>(factory, ArrayDescription::DataType::Auto, "toDeviceCharArray");
testArrayIsCorrectType<D_bytearray>(factory, ArrayDescription::DataType::Auto, "toDeviceUCharArray");
testArrayIsCorrectType<D_shortarray>(factory, ArrayDescription::DataType::Auto, "toDeviceShortArray");
testArrayIsCorrectType<D_shortarray>(factory, ArrayDescription::DataType::Auto, "toDeviceUShortArray");
testArrayIsCorrectType<D_intarray>(factory, ArrayDescription::DataType::Auto, "toDeviceIntArray");
testArrayIsCorrectType<D_intarray>(factory, ArrayDescription::DataType::Auto, "toDeviceUIntArray");
testArrayIsCorrectType<D_longarray>(factory, ArrayDescription::DataType::Auto, "toDeviceLongArray");
testArrayIsCorrectType<D_longarray>(factory, ArrayDescription::DataType::Auto, "toDeviceULongArray");
testArrayIsCorrectType<D_floatarray>(factory, ArrayDescription::DataType::Auto, "toDeviceFloatArray");
testArrayIsCorrectType<D_doublearray>(factory, ArrayDescription::DataType::Auto, "toDeviceDoubleArray");
}
Martin Killenberg
committed
BOOST_AUTO_TEST_CASE( testInt64Scalar ){
std::pair< shared_ptr<ControlSystemPVManager>,
shared_ptr<DevicePVManager> > pvManagers = createPVManager();
shared_ptr<ControlSystemPVManager> csManager = pvManagers.first;
shared_ptr<DevicePVManager> devManager = pvManagers.second;
Martin Killenberg
committed
devManager->createProcessArray<int64_t>(controlSystemToDevice,"I/toDeviceInt",1);
Martin Killenberg
committed
DoocsUpdater updater;
DoocsPVFactory factory(&myEqFct, updater, csManager);
ProcessVariable::SharedPtr processScalar =
Martin Killenberg
committed
csManager->getProcessArray<int64_t>("I/toDeviceInt");
Martin Killenberg
committed
auto description = std::make_shared<AutoPropertyDescription>("I/toDeviceInt", "I", "toDeviceInt");
Martin Killenberg
committed
auto variable64 = factory.create( description );
// 64 bit integer scalars become D_longarrays because there is no 64 bit scalar representation in Doocs
BOOST_CHECK( boost::dynamic_pointer_cast<D_longarray>(variable64) );