Commit bf9ffd30 authored by Pavel Vainerman's avatar Pavel Vainerman

(IOControl): начало работы над тестами

parent 014bcddb
......@@ -338,6 +338,7 @@ if test ${buildtests} = true; then
AC_CONFIG_TESTDIR(extensions/ModbusMaster/tests)
AC_CONFIG_TESTDIR(extensions/UNetUDP/tests)
AC_CONFIG_TESTDIR(extensions/SharedMemory/tests)
AC_CONFIG_TESTDIR(extensions/IOControl/tests)
TESTSUITE_DIR="\$(top_builddir)/testsuite"
AC_SUBST(TESTSUITE_DIR)
......@@ -470,6 +471,7 @@ AC_CONFIG_FILES([Makefile
extensions/DBServer-PostgreSQL/libUniSet2PostgreSQL.pc
extensions/IOControl/Makefile
extensions/IOControl/libUniSet2IOControl.pc
extensions/IOControl/tests/Makefile
extensions/ModbusMaster/Makefile
extensions/ModbusMaster/libUniSet2RTU.pc
extensions/ModbusMaster/libUniSet2MBTCPMaster.pc
......
......@@ -41,7 +41,7 @@ ComediInterface::~ComediInterface()
}
// -----------------------------------------------------------------------------
int ComediInterface::getAnalogChannel( int subdev, int channel, int range, int aref )
int ComediInterface::getAnalogChannel( int subdev, int channel, int range, int aref ) const
throw(uniset::Exception)
{
lsampl_t data = 0;
......@@ -54,13 +54,13 @@ throw(uniset::Exception)
<< " channel=" << channel << " range=" << range << " aref=" << aref
<< " dev=" << dname
<< " err: " << ret << " (" << strerror(ret) << ")";
throw Exception(err.str());
throw uniset::Exception(err.str());
}
return data;
}
// -----------------------------------------------------------------------------
void ComediInterface::setAnalogChannel( int subdev, int channel, int data, int range, int aref )
void ComediInterface::setAnalogChannel( int subdev, int channel, int data, int range, int aref ) const
throw(uniset::Exception)
{
if( comedi_data_write(card, subdev, channel, range, aref, data) < 0 )
......@@ -74,7 +74,7 @@ throw(uniset::Exception)
}
}
// -----------------------------------------------------------------------------
bool ComediInterface::getDigitalChannel( int subdev, int channel ) throw(uniset::Exception)
bool ComediInterface::getDigitalChannel( int subdev, int channel ) const throw(uniset::Exception)
{
lsampl_t data = 0;
......@@ -89,7 +89,7 @@ bool ComediInterface::getDigitalChannel( int subdev, int channel ) throw(uniset:
return ((bool)(data));
}
// -----------------------------------------------------------------------------
void ComediInterface::setDigitalChannel( int subdev, int channel, bool bit )
void ComediInterface::setDigitalChannel( int subdev, int channel, bool bit ) const
throw(uniset::Exception)
{
if( comedi_dio_write(card, subdev, channel, bit) < 0 )
......@@ -102,7 +102,7 @@ throw(uniset::Exception)
}
// -----------------------------------------------------------------------------
void ComediInterface::configureChannel( int subdev, int channel, ChannelType t,
int range, int aref )
int range, int aref ) const
throw(uniset::Exception)
{
switch( t )
......@@ -161,7 +161,7 @@ throw(uniset::Exception)
throw Exception(err.str());
}
// -----------------------------------------------------------------------------
void ComediInterface::configureSubdev( int subdev, SubdevType type )
void ComediInterface::configureSubdev( int subdev, SubdevType type ) const
throw(uniset::Exception)
{
lsampl_t data[2];
......
......@@ -29,21 +29,20 @@ namespace uniset
{
public:
explicit ComediInterface( const std::string& dev );
~ComediInterface();
virtual ~ComediInterface();
int getAnalogChannel( int subdev, int channel, int range = 0, int aref = AREF_GROUND )
virtual int getAnalogChannel( int subdev, int channel, int range = 0, int aref = AREF_GROUND ) const
throw(uniset::Exception);
void setAnalogChannel( int subdev, int channel, int data, int range = 0, int aref = AREF_GROUND )
virtual void setAnalogChannel( int subdev, int channel, int data, int range = 0, int aref = AREF_GROUND ) const
throw(uniset::Exception);
bool getDigitalChannel( int subdev, int channel )
virtual bool getDigitalChannel( int subdev, int channel ) const
throw(uniset::Exception);
void setDigitalChannel( int subdev, int channel, bool bit )
virtual void setDigitalChannel( int subdev, int channel, bool bit ) const
throw(uniset::Exception);
// Конфигурирование входов / выходов
enum ChannelType
{
......@@ -65,17 +64,18 @@ namespace uniset
static std::string type2str( SubdevType t );
static SubdevType str2type( const std::string& s );
void configureSubdev( int subdev, SubdevType type ) throw(uniset::Exception);
virtual void configureSubdev( int subdev, SubdevType type ) const throw(uniset::Exception);
void configureChannel( int subdev, int channel, ChannelType type, int range = 0, int aref = 0 )
virtual void configureChannel( int subdev, int channel, ChannelType type, int range = 0, int aref = 0 ) const
throw(uniset::Exception);
inline const std::string devname()
inline const std::string devname() const
{
return dname;
}
protected:
ComediInterface():card(nullptr){}
comedi_t* card; /*!< интерфейс для работы с картами в/в */
std::string dname;
......
......@@ -47,10 +47,10 @@ namespace uniset
// -----------------------------------------------------------------------------
IOControl::IOControl(uniset::ObjectId id, uniset::ObjectId icID,
const std::shared_ptr<SharedMemory>& ic, int numcards, const std::string& prefix_ ):
const std::shared_ptr<SharedMemory>& ic, size_t numcards, const std::string& prefix_ ):
UniSetObject(id),
polltime(150),
cards(11),
cards(numcards),
noCards(true),
iomap(100),
maxItem(0),
......@@ -112,12 +112,12 @@ namespace uniset
noCards = true;
for( unsigned int i = 1; i < cards.size(); i++ )
cards[i] = NULL;
for( size_t i = 1; i < cards.size(); i++ )
cards[i] = nullptr;
buildCardsList();
for( unsigned int i = 1; i < cards.size(); i++ )
for( size_t i = 1; i < cards.size(); i++ )
{
stringstream s1;
s1 << "--" << prefix << "-dev" << i;
......@@ -131,7 +131,7 @@ namespace uniset
if( iodev == "/dev/null" )
{
if( cards[i] == NULL )
if( !cards[i] )
{
iolog3 << myname << "(init): Card N" << i
<< " DISABLED! dev='"
......@@ -145,9 +145,9 @@ namespace uniset
iolog3 << myname << "(init): ADD card" << i << " dev=" << iodev << endl;
}
if( cards[i] != NULL )
if( !cards[i] )
{
for( unsigned int s = 1; s <= 4; s++ )
for( size_t s = 1; s <= 4; s++ )
{
stringstream t1;
t1 << s1.str() << "-subdev" << s << "-type";
......@@ -180,10 +180,7 @@ namespace uniset
ioinfo << myname << "(init): result numcards=" << cards.size() << endl;
polltime = conf->getArgInt("--" + prefix + "-polltime", it.getProp("polltime"));
if( !polltime )
polltime = 100;
polltime = conf->getArgPInt("--" + prefix + "-polltime", it.getProp("polltime"), polltime);
force = conf->getArgInt("--" + prefix + "-force", it.getProp("force"));
force_out = conf->getArgInt("--" + prefix + "-force-out", it.getProp("force_out"));
......@@ -261,10 +258,10 @@ namespace uniset
sidTestSMReady = conf->getSensorID("TestMode_S");
iowarn << myname
<< "(init): Unknown ID for sm-ready-test-sid (--" << prefix << "-sm-ready-test-sid)."
<< " Use 'TestMode_S'" << endl;
<< " Use 'TestMode_S' (if present)" << endl;
}
else
ioinfo << myname << "(init): test-sid: " << sm_ready_sid << endl;
ioinfo << myname << "(init): sm-ready-test-sid: " << sm_ready_sid << endl;
// -----------------------
......@@ -304,11 +301,6 @@ namespace uniset
IOControl::~IOControl()
{
// здесь бы ещё пройтись по списку с сделать delete для
// всех cdiagram созданных через new
//
// for( unsigned int i = 0; i < cards.size(); i++ )
// delete cards[i];
}
// --------------------------------------------------------------------------------
......@@ -389,6 +381,7 @@ namespace uniset
}
catch(...) {}
ioinfo << myname << "(iothread): run..." << endl;
while( !term )
{
try
......@@ -533,7 +526,8 @@ namespace uniset
// --------------------------------------------------------------------------------
void IOControl::ioread( std::shared_ptr<IOInfo>& it )
{
// cout << conf->oind->getMapName(it->si.id) << " ignore=" << it->ignore << " ncard=" << it->ncard << endl;
// cout << uniset_conf()->oind->getMapName(it->si.id) << " ignore=" << it->ignore << " ncard=" << it->ncard << endl;
// cerr << it << endl;
if( it->ignore || it->ncard == defCardNum )
return;
......@@ -1660,11 +1654,11 @@ namespace uniset
{
std::string cname(it.getProp("name"));
int cardnum = it.getIntProp("card");
size_t cardnum = it.getIntProp("card");
if( cardnum <= 0 )
if( cardnum == 0 )
{
iolog3 << myname << "(init): Unknown card number?! card=" << it.getIntProp("card") << "(" << cname << ")" << endl;
iolog3 << myname << "(init): card number=0?! card=" << it.getIntProp("card") << "(" << cname << ")" << endl;
continue;
}
......@@ -1677,7 +1671,7 @@ namespace uniset
if( it.getIntProp("ignore") )
{
cards[cardnum] = NULL;
cards[cardnum] = nullptr;
iolog3 << myname << "(init): card=" << it.getProp("card") << "(" << cname << ")"
<< " DISABLED! ignore=1" << endl;
continue;
......@@ -1688,7 +1682,7 @@ namespace uniset
if( findArgParam( s.str(), conf->getArgc(), conf->getArgv()) != -1 )
{
cards[cardnum] = NULL;
cards[cardnum] = nullptr;
iolog3 << myname << "(init): card=" << it.getProp("card") << "(" << cname << ")"
<< " DISABLED! (" << s.str() << ")" << endl;
continue;
......@@ -1698,7 +1692,7 @@ namespace uniset
if( iodev.empty() || iodev == "/dev/null" )
{
cards[cardnum] = NULL;
cards[cardnum] = nullptr;
iolog3 << myname << "(init): card=" << it.getProp("card") << "(" << cname << ")"
<< " DISABLED! iodev='"
<< iodev << "'" << endl;
......@@ -1729,13 +1723,13 @@ namespace uniset
}
else if( cname == "UNIO48" || cname == "UNIO96" )
{
unsigned int k = 4;
size_t k = 4;
if( cname == "UNIO48" )
k = 2;
// инициализация subdev-ов
for( unsigned int i = 1; i <= k; i++ )
for( size_t i = 1; i <= k; i++ )
{
ostringstream s;
s << "subdev" << i;
......
......@@ -227,7 +227,7 @@ namespace uniset
public UniSetObject
{
public:
IOControl( uniset::ObjectId id, uniset::ObjectId icID, const std::shared_ptr<SharedMemory>& shm = nullptr, int numcards = 2, const std::string& prefix = "io" );
IOControl( uniset::ObjectId id, uniset::ObjectId icID, const std::shared_ptr<SharedMemory>& shm = nullptr, size_t numcards = 2, const std::string& prefix = "io" );
virtual ~IOControl();
/*! глобальная функция для инициализации объекта */
......@@ -398,8 +398,8 @@ namespace uniset
bool force = { false }; /*!< флаг, означающий, что надо сохранять в SM, даже если значение не менялось */
bool force_out = { false }; /*!< флаг, включающий принудительное чтения выходов */
timeout_t smReadyTimeout = { 15000 }; /*!< время ожидания готовности SM к работе, мсек */
int defCardNum = { -1 }; /*!< номер карты по умолчанию */
int maxCardNum = { 10 }; /*! максимально разрешённый номер для карты */
ssize_t defCardNum = { -1 }; /*!< номер карты по умолчанию */
size_t maxCardNum = { 10 }; /*! максимально разрешённый номер для карты */
std::mutex iopollMutex;
std::atomic_bool activated = { false };
......
/*
* Copyright (c) 2015 Pavel Vainerman.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, version 2.1.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// -------------------------------------------------------------------------
#include <sstream>
#include <iostream>
#include "FakeIOControl.h"
// -----------------------------------------------------------------------------
using namespace std;
// -----------------------------------------------------------------------------
namespace uniset
{
// -----------------------------------------------------------------------------
FakeIOControl::FakeIOControl(uniset::ObjectId id, uniset::ObjectId icID,
const std::shared_ptr<SharedMemory>& ic, int numcards, const std::string& prefix_ ):
IOControl(id,icID,ic,numcards,prefix_)
{
fcard = new FakeComediInterface();
// Подменяем все карты на fake-овые
for( size_t i=0; i < cards.size(); i++ )
{
if( cards[i] )
delete cards[i];
cards[i] = fcard;
}
noCards = false;
}
// --------------------------------------------------------------------------------
FakeIOControl::~FakeIOControl()
{
for( size_t i=0; i < cards.size(); i++ )
{
if( cards[i] )
{
delete (FakeComediInterface*)cards[i];
cards[i] = nullptr;
}
}
}
// --------------------------------------------------------------------------------
std::shared_ptr<FakeIOControl> FakeIOControl::init_iocontrol(int argc, const char* const* argv,
uniset::ObjectId icID, const std::shared_ptr<SharedMemory>& ic,
const std::string& prefix )
{
auto conf = uniset_conf();
string name = conf->getArgParam("--" + prefix + "-name", "FakeIOControl1");
if( name.empty() )
{
std::cerr << "(iocontrol): Unknown name. Use --" << prefix << "-name " << std::endl;
return 0;
}
ObjectId ID = conf->getObjectID(name);
if( ID == uniset::DefaultObjectId )
{
std::cerr << "(iocontrol): Unknown ID for " << name
<< "' Not found in <objects>" << std::endl;
return 0;
}
int numcards = conf->getArgPInt("--" + prefix + "-numcards", 1);
std::cout << "(iocontrol): name = " << name << "(" << ID << ")" << std::endl;
return std::make_shared<FakeIOControl>(ID, icID, ic, numcards, prefix);
}
// -----------------------------------------------------------------------------
FakeComediInterface::FakeComediInterface():
chInputs(maxChannelNum),
chOutputs(maxChannelNum)
{
}
// -----------------------------------------------------------------------------
FakeComediInterface::~FakeComediInterface()
{
}
// -----------------------------------------------------------------------------
int FakeComediInterface::getAnalogChannel(int subdev, int channel, int range, int aref) const
throw(uniset::Exception)
{
if( channel < 0 || channel > maxChannelNum )
{
cerr << "(FakeComediInterface::getAnalogChannel): BAD channel num=" << channel
<< " Must be [0," << maxChannelNum << "]" << endl;
std::terminate();
}
return chInputs[channel];
}
// -----------------------------------------------------------------------------
void FakeComediInterface::setAnalogChannel(int subdev, int channel, int data, int range, int aref) const
throw(uniset::Exception)
{
if( channel < 0 || channel > maxChannelNum )
{
cerr << "(FakeComediInterface::setAnalogChannel): BAD channel num=" << channel
<< " Must be [0," << maxChannelNum << "]" << endl;
std::terminate();
}
chOutputs[channel] = data;
}
// -----------------------------------------------------------------------------
bool FakeComediInterface::getDigitalChannel( int subdev, int channel ) const
throw(uniset::Exception)
{
if( channel < 0 || channel > maxChannelNum )
{
cerr << "(FakeComediInterface::getDigitalChannel): BAD channel num=" << channel
<< " Must be [0," << maxChannelNum << "]" << endl;
std::terminate();
}
return (bool)chInputs[channel];
}
// -----------------------------------------------------------------------------
void FakeComediInterface::setDigitalChannel( int subdev, int channel, bool bit ) const
throw(uniset::Exception)
{
if( channel < 0 || channel > maxChannelNum )
{
cerr << "(FakeComediInterface::setDigitalChannel): BAD channel num=" << channel
<< " Must be [0," << maxChannelNum << "]" << endl;
std::terminate();
}
chOutputs[channel] = (bit ? 1 : 0);
}
// -----------------------------------------------------------------------------
void FakeComediInterface::configureSubdev( int subdev, ComediInterface::SubdevType type ) const
throw(uniset::Exception)
{
}
// -----------------------------------------------------------------------------
void FakeComediInterface::configureChannel(int subdev, int channel, ComediInterface::ChannelType type, int range, int aref) const
throw(uniset::Exception)
{
}
// -----------------------------------------------------------------------------
} // end of namespace uniset
/*
* Copyright (c) 2015 Pavel Vainerman.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, version 2.1.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// -----------------------------------------------------------------------------
#ifndef FakeIOControl_H_
#define FakeIOControl_H_
// -----------------------------------------------------------------------------
#include <memory>
#include "IOControl.h"
// -------------------------------------------------------------------------
namespace uniset
{
/*! Специальный "управляемый тестами" интерфейс карты в/в. */
class FakeComediInterface final:
public ComediInterface
{
public:
FakeComediInterface();
virtual ~FakeComediInterface();
static const size_t maxChannelNum = 32;
// Управление тестированием
// --------------------------------------------
// для простоты массивы специально объявлены в public
// warning: надо только иметь ввиду, что доступ к ним будет из разных потоков
// из теста и из потока опроса карт в/в (IOControl)
// в данном случае это не страшно..
// --------------------------------------------
std::vector<int> chInputs; // массив значений 'входов' (для проверки чтения)
mutable std::vector<int> chOutputs; // массив значений 'выходов' (для проверки функций вывода)
// --------------------------------------------
// при тестировании параметры range,aref,subdev игнорируются!
virtual int getAnalogChannel( int subdev, int channel, int range = 0, int aref = AREF_GROUND ) const
throw(uniset::Exception) override;
virtual void setAnalogChannel( int subdev, int channel, int data, int range = 0, int aref = AREF_GROUND ) const
throw(uniset::Exception) override;
virtual bool getDigitalChannel( int subdev, int channel ) const
throw(uniset::Exception) override;
virtual void setDigitalChannel( int subdev, int channel, bool bit ) const
throw(uniset::Exception) override;
virtual void configureSubdev( int subdev, SubdevType type ) const
throw(uniset::Exception) override;
virtual void configureChannel( int subdev, int channel, ChannelType type, int range = 0, int aref = 0 ) const
throw(uniset::Exception) override;
};
// --------------------------------------------------------------------------
/*! Специальный IOControl для тестирвания подменяющий все карты в/в на FakeComediInterface */
class FakeIOControl:
public IOControl
{
public:
FakeIOControl( uniset::ObjectId id, uniset::ObjectId icID, const std::shared_ptr<SharedMemory>& shm = nullptr, int numcards = 2, const std::string& prefix = "io" );
virtual ~FakeIOControl();
/*! глобальная функция для инициализации объекта */
static std::shared_ptr<FakeIOControl> init_iocontrol( int argc, const char* const* argv,
uniset::ObjectId icID, const std::shared_ptr<SharedMemory>& ic = nullptr,
const std::string& prefix = "io" );
// намеренно делаем public для доступа в тестах
FakeComediInterface* fcard = nullptr;
protected:
private:
};
// --------------------------------------------------------------------------
} // end of namespace uniset
// -----------------------------------------------------------------------------
#endif // FakeIOControl_H_
// -----------------------------------------------------------------------------
if HAVE_TESTS
noinst_PROGRAMS = run_test_iocontrol
run_test_iocontrol_SOURCES = run_test_iocontrol.cc test_iocontrol.cc FakeIOControl.cc
run_test_iocontrol_LDADD = $(top_builddir)/lib/libUniSet2.la $(top_builddir)/extensions/lib/libUniSet2Extensions.la \
$(top_builddir)/extensions/IOControl/libUniSet2IOControl.la \
$(top_builddir)/extensions/SharedMemory/libUniSet2SharedMemory.la \
$(SIGC_LIBS) $(POCO_LIBS)
run_test_iocontrol_CPPFLAGS = -I$(top_builddir)/include -I$(top_builddir)/extensions/include \
-I$(top_builddir)/extensions/IOControl \
-I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) $(POCO_CFLAGS)
include $(top_builddir)/testsuite/testsuite-common.mk
check-local: atconfig package.m4 $(TESTSUITE) iocontrol-tests.at
$(SHELL) $(TESTSUITE) $(TESTSUITEFLAGS)
clean-local:
rm -rf $(CLEANFILES)
rm -rf $(COVERAGE_REPORT_DIR)
include $(top_builddir)/include.mk
endif
<?xml version="1.0" encoding="utf-8"?>
<UNISETPLC xmlns:xi="http://www.w3.org/2001/XInclude">
<UserData/>
<!-- Общие(стартовые) параметры по UniSet -->
<UniSet>
<NameService host="localhost" port="2809"/>
<LocalNode name="LocalhostNode"/>
<RootSection name="UNISET_PLC"/>
<CountOfNet name="1"/>
<RepeatCount name="3"/>
<RepeatTimeoutMS name="50"/>
<WatchDogTime name="0"/>
<PingNodeTime name="0"/>
<AutoStartUpTime name="1"/>
<DumpStateTime name="10"/>
<SleepTickMS name="500"/>
<UniSetDebug levels="" name="ulog"/>
<ConfDir name="./"/>
<DataDir name="./"/>
<BinDir name="./"/>
<LogDir name="./"/>
<DocDir name="./"/>
<LockDir name="./"/>
<Services></Services>
</UniSet>
<dlog name="dlog"/>
<settings>
<SharedMemory name="SharedMemory" shmID="SharedMemory"/>
<IOControl1 name="IOControl"/>
</settings>
<ObjectsMap idfromfile="1">
<!--
Краткие пояснения к полям секции 'sensors'
==========================================
node - узел на котором физически находится данный датчик
iotype - тип датчика
priority - приоритет сообщения об изменении данного датчика
textname - текстовое имя датчика
-->
<nodes port="2809">
<item id="3000" infserver="InfoServer" ip="127.0.0.1" name="LocalhostNode" textname="Локальный узел">
<iocards>
<item name="AI16-5A-3" avg="16" baddr="0x130" card="1" dev="/dev/null" module="aixx5a" module_params="1,16"/>
</iocards>
</item>
</nodes>
<!-- ************************ Датчики ********************** -->
<sensors name="Sensors">
<item id="1000" io="1" iotype="DI" name="TestDI1_S" textname="Тестовый DI1" card="1" subdev="1" channel="0"/>
<item id="1001" io="1" iotype="DI" name="TestDI2_S" textname="Тестовый DI2" card="1" subdev="1" channel="0" ioinvert="1" />
<item id="1002" io="1" iotype="DO" name="TestDO1_C" textname="Тестовый DO1" card="1" subdev="1" channel="0"/>
<item id="1003" io="1" iotype="DO" name="TestDO2_C" textname="Тестовый DO2" card="1" subdev="1" channel="1" ioinvert="1" />
<item id="1004" io="1" iotype="AO" name="Lamp1_C" textname="Lamp 1" card="1" subdev="1" channel="4" lamp="1" />
<item id="1005" io="1" iotype="AO" name="AO1_C" textname="AO1" card="1" subdev="1" channel="5"/>
<item id="1006" io="1" iotype="AO" name="AO2_C" textname="AO2" card="1" subdev="1" channel="6" cmin="-100" cmax="100" rmin="0" rmax="1000"/>
<item id="1007" io="1" iotype="AO" name="AO3_C" textname="AO3" card="1" subdev="1" channel="7" caldiagram="testcal"/>
<item id="1010" io="1" iotype="AI" name="AI_T_AS" textname="AI for threshold" card="1" subdev="1" channel="10"/>
<item id="1011" io="1" iotype="DI" name="T1_S" textname="Threshold 1" threshold_aid="AI_T_AS" lowlimit="30" hilimit="40"/>
<item id="10000" iotype="DI" name="TestMode_S" textname="Тестовый датчик"/>
</sensors>
<thresholds/>
<controllers name="Controllers">
<item id="5000" name="SharedMemory"/>
</controllers>
<!-- ******************* Идентификаторы сервисов ***************** -->
<services name="Services">
</services>
<!-- ******************* Идентификаторы объектов ***************** -->
<objects name="UniObjects">
<item id="6000" name="TestProc"/>
<item id="6004" name="IOControl1"/>
</objects>
</ObjectsMap>
<messages idfromfile="1" name="messages"/>
<Calibrations name="Calibrations">
<diagram name="testcal">
<point x="-1000" y="-300"/>
<point x="0" y="10"/>
<point x="1000" y="300"/>
</diagram>
</Calibrations>
</UNISETPLC>
AT_SETUP([IOControl tests (with SM)])
AT_CHECK([$abs_top_builddir/testsuite/at-test-launch.sh $abs_top_builddir/extensions/IOControl/tests run_test_iocontrol.sh],[0],[ignore],[ignore])
AT_CLEANUP
#define CATCH_CONFIG_RUNNER
#include <catch.hpp>
#include <string>
#include "Debug.h"
#include "UniSetActivator.h"
#include "PassiveTimer.h"
#include "SharedMemory.h"
#include "Extensions.h"
#include "FakeIOControl.h"
#include "SMInterface.h"
// --------------------------------------------------------------------------
using namespace std;
using namespace uniset;
using namespace uniset::extensions;
// --------------------------------------------------------------------------
std::shared_ptr<SharedMemory> shm;
shared_ptr<FakeIOControl> ioc;
// --------------------------------------------------------------------------
int main( int argc, const char* argv[] )
{
try
{
Catch::Session session;
if( argc > 1 && ( strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0 ) )
{
cout << "--confile - Использовать указанный конф. файл. По умолчанию configure.xml" << endl;
SharedMemory::help_print(argc, argv);
cout << endl << endl << "--------------- CATCH HELP --------------" << endl;
session.showHelp("tests_iocontrol");
return 0;
}
int returnCode = session.applyCommandLine( argc, argv, Catch::Session::OnUnusedOptions::Ignore );
if( returnCode != 0 ) // Indicates a command line error
return returnCode;
auto conf = uniset_init(argc, argv);
dlog()->logFile("./smtest.log");
bool apart = findArgParam("--apart", argc, argv) != -1;
shm = SharedMemory::init_smemory(argc, argv);
if( !shm )
return 1;
ioc = FakeIOControl::init_iocontrol(argc, argv, shm->getId(), (apart ? nullptr : shm));
if( !ioc )
return 1;
auto act = UniSetActivator::Instance();
act->add(shm);
act->add(ioc);
SystemMessage sm(SystemMessage::StartUp);
act->broadcast( sm.transport_msg() );
act->run(true);
int tout = conf->getArgPInt("--timeout", 8000);
PassiveTimer pt(tout);
while( !pt.checkTime() && !act->exist() )
msleep(100);
if( !act->exist() )
{
cerr << "(tests_iocontrol): SharedMemory not exist! (timeout=" << tout << ")" << endl;
return 1;
}
return session.run();
}
catch( const uniset::Exception& ex )
{
cerr << "(tests_iocontrol): " << ex << endl;
}
catch( const std::exception& e )
{
cerr << "(tests_iocontrol): " << e.what() << endl;
}
catch(...)
{
cerr << "(tests_iocontrol): catch(...)" << endl;
}
return 1;
}
#!/bin/sh
# '--' - нужен для отделения аргументов catch, от наших..
cd ../../../Utilities/Admin/
./uniset2-start.sh -f ./create_links.sh
./uniset2-start.sh -f ./create
./uniset2-start.sh -f ./exist | grep -q UNISET_PLC/Controllers || exit 1
cd -
./uniset2-start.sh -f ./run_test_iocontrol $* -- --confile iocontrol-test-configure.xml --e-startup-pause 10 \
--io-name IOControl1 \
--smemory-id SharedMemory \
--io-s-filter-field io \
--io-s-filter-value 1
# --io-log-add-levels any
#include <catch.hpp>
// -----------------------------------------------------------------------------
#include <time.h>
#include <limits>
#include <unordered_set>
#include <Poco/Net/NetException.h>
#include "UniSetTypes.h"
#include "MBTCPMultiMaster.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace uniset;
// -----------------------------------------------------------------------------
#include <catch.hpp>
// -----------------------------------------------------------------------------
#include <time.h>
#include <memory>
#include <limits>
#include "UniSetTypes.h"
#include "FakeIOControl.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace uniset;
// -----------------------------------------------------------------------------
static shared_ptr<UInterface> ui;
extern shared_ptr<FakeIOControl> ioc;
const uniset::timeout_t polltime = 150;
// -----------------------------------------------------------------------------
static void InitTest()
{
auto conf = uniset_conf();
CHECK( conf != nullptr );
if( !ui )
{
ui = make_shared<UInterface>();
// UI понадобиться для проверки записанных в SM значений.
CHECK( ui->getObjectIndex() != nullptr );
CHECK( ui->getConf() == conf );
}
REQUIRE( ioc != nullptr );
}
// -----------------------------------------------------------------------------
TEST_CASE("IOControl: DI", "[iocontrol][di]")
{
InitTest();
ioc->fcard->chInputs[0] = 1;
msleep(polltime+10);
REQUIRE( ui->getValue(1000) == 1 );
REQUIRE( ui->getValue(1001) == 0 ); // invert
ioc->fcard->chInputs[0] = 0;
msleep(polltime+10);
REQUIRE( ui->getValue(1000) == 0 );
REQUIRE( ui->getValue(1001) == 1 ); // invert
}
// -----------------------------------------------------------------------------
TEST_CASE("IOControl: DO", "[iocontrol][do]")
{
InitTest();
ui->setValue(1002,1);
ui->setValue(1003,1);
msleep(polltime+10);
REQUIRE( ioc->fcard->chOutputs[0] == 1 );
REQUIRE( ioc->fcard->chOutputs[1] == 0 ); // invert
ui->setValue(1002,0);
ui->setValue(1003,0);
msleep(polltime+10);
REQUIRE( ioc->fcard->chOutputs[0] == 0 );
REQUIRE( ioc->fcard->chOutputs[1] == 1 ); // invert
}
// -----------------------------------------------------------------------------
TEST_CASE("IOControl: AO (lamp)", "[iocontrol][lamp]")
{
InitTest();
auto card = ioc->fcard;
ui->setValue(1004, uniset::lmpBLINK);
// считаем количество импульсов "0 -> 1 -> 0"
size_t npulse = 0;
bool prev = false;
for( size_t i=0; i < 20 && npulse < 3; i ++ )
{
if( card->chOutputs[4] == 1 && !prev )
prev = true;
else if( card->chOutputs[4] == 0 && prev )
{
prev = false;
npulse++;
}
// чтобы не пропустить импульсы.. спим меньше
msleep( polltime / 2 );
}
REQUIRE( npulse >= 2 );
}
// -----------------------------------------------------------------------------
TEST_CASE("IOControl: AO", "[iocontrol][ao]")
{
InitTest();
auto card = ioc->fcard;
ui->setValue(1005, 10);
ui->setValue(1006, 100);
ui->setValue(1007, 300);
msleep(polltime+10);
REQUIRE( ioc->fcard->chOutputs[5] == 10 );
REQUIRE( ioc->fcard->chOutputs[6] == 1000 ); // calibration channel
REQUIRE( ioc->fcard->chOutputs[7] == 1000 ); // caldiagram
ui->setValue(1005, 100);
ui->setValue(1006, -100);
ui->setValue(1007, -300);
msleep(polltime+10);
REQUIRE( ioc->fcard->chOutputs[5] == 100 );
REQUIRE( ioc->fcard->chOutputs[6] == 0 ); // calibration channel
REQUIRE( ioc->fcard->chOutputs[7] == -1000 ); // caldiagram
}
// -----------------------------------------------------------------------------
TEST_CASE("IOControl: threshold", "[iocontrol][threshold]")
{
InitTest();
auto card = ioc->fcard;
ioc->fcard->chInputs[10] = 20;
msleep(polltime+10);
REQUIRE( ui->getValue(1010) == 20 );
REQUIRE( ui->getValue(1011) == 0 ); // threshold [30,40]
ioc->fcard->chInputs[10] = 35;
msleep(polltime+10);
REQUIRE( ui->getValue(1010) == 35 );
REQUIRE( ui->getValue(1011) == 0 ); // threshold [30,40]
ioc->fcard->chInputs[10] = 45;
msleep(polltime+10);
REQUIRE( ui->getValue(1010) == 45 );
REQUIRE( ui->getValue(1011) == 1 ); // threshold [30,40]
ioc->fcard->chInputs[10] = 35;
msleep(polltime+10);
REQUIRE( ui->getValue(1010) == 35 );
REQUIRE( ui->getValue(1011) == 1 ); // threshold [30,40]
ioc->fcard->chInputs[10] = 25;
msleep(polltime+10);
REQUIRE( ui->getValue(1010) == 25 );
REQUIRE( ui->getValue(1011) == 0 ); // < lowlimit (30)
}
// -----------------------------------------------------------------------------
m4_include(package.m4)
AT_COLOR_TESTS
AT_INIT([IOControl tests])
m4_include(iocontrol-tests.at)
../../../Utilities/scripts/uniset2-functions.sh
\ No newline at end of file
../../../Utilities/scripts/uniset2-start.sh
\ No newline at end of file
......@@ -3,7 +3,7 @@
############################################################################
if HAVE_EXTENTIONS
SUBDIRS = lib include SharedMemory SharedMemory/tests IOControl LogicProcessor LogicProcessor/tests \
SUBDIRS = lib include SharedMemory SharedMemory/tests IOControl IOControl/tests LogicProcessor LogicProcessor/tests \
ModbusMaster ModbusSlave SMViewer UniNetwork UNetUDP UNetUDP/tests \
DBServer-MySQL DBServer-SQLite DBServer-PostgreSQL MQTTPublisher \
RRDServer tests ModbusMaster/tests ModbusSlave/tests
......
......@@ -11,3 +11,4 @@ m4_include(../extensions/LogicProcessor/tests/lproc-tests.at)
m4_include(../extensions/ModbusSlave/tests/mbslave-tests.at)
m4_include(../extensions/UNetUDP/tests/unetudp-tests.at)
m4_include(../extensions/ModbusMaster/tests/mbmaster-tests.at)
m4_include(../extensions/IOControl/tests/iocontrol-tests.at)
......@@ -70,6 +70,12 @@ extensions/IOControl/IOControl.h
extensions/IOControl/iotest.cc
extensions/IOControl/libUniSet2IOControl.pc.in
extensions/IOControl/Makefile.am
extensions/IOControl/tests/Makefile.am
extensions/IOControl/tests/test_iocontrol.cc
extensions/IOControl/tests/run_test_iocontrol.cc
extensions/IOControl/tests/iocontrol-test-configure.xml
extensions/IOControl/tests/FakeIOControl.h
extensions/IOControl/tests/FakeIOControl.cc
extensions/lib/Calibration.cc
extensions/lib/DigitalFilter.cc
extensions/lib/Extensions.cc
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment