Prune the source tree to the Release 2 build closure

Keep only what the Release 2 scope (46 targets) compiles and the build
pipeline needs, derived from the run-5 build.ninja closure (46 targets +
transitive deps) and a header scan resolved against the real -I roots of
the compile rules:

- 14133 tracked files removed (1.25 GB), incl. include/ArcGIS (1.03 GB),
  include/rti stubs (identical copies of the external RTI headers),
  out-of-scope Lts/Application, Lts/Viewer, Lts/Services/*, Lts/Tools
  generators, src/, tests/, specs/, translations/, external/
- kept: the 46 scope modules + their transitive service deps, codegen
  inputs (.xml, .grantlee), doxygen/ (configure_file at configure time),
  include/GeographicLib (libGeographicLib.so linked from the source tree),
  the 12 referenced include/ stub headers, pipeline files
  (new_docker_build_release2.sh, rpmbuild/, jenkins-ci-rme/, cmake/)
- 7 CMakeLists updated: drop add_subdirectory calls of the removed dirs
  (tests, translations, Lts/Plugins/ProjectDataManagement, qav, scripts,
  CommonUnitTestsPlaceholder, httq, LtsRestClient, LtsWebSocket,
  TopicEditorBase, ConnectDialog, StyleManager, Routing, DdsUnitTests,
  DdsUnitTestsPlaceholder, Light, Dark, Test, ExerciseManagement,
  ParticipantManagement, the 3 tools generators)

Result: 2157 tracked files (was 16290).
This commit is contained in:
berrux-dev committed 2026-11-13 23:33:32 +01:00
1 parent 2b1c3dc241
commit 7fc6f66649
14140 files changed
+8 -2803418

No files matched your search

@@ -20,16 +20,5 @@ IF(BUILD_RTI)
ENDIF()
ADD_SUBDIRECTORY(FTS)
ADD_SUBDIRECTORY(Generic)
ADD_SUBDIRECTORY(Routing)
ADD_SUBDIRECTORY(Core)
# During stepwise migration, add placeholder CTest entries after the
# real DdsUnitTests subdir so the test-suite can use real targets when
# internal codegen/RTI targets are available, and fall back to placeholders
# only when they are not.
IF(BUILD_RTI)
ADD_SUBDIRECTORY(DdsUnitTests)
ENDIF()
ADD_SUBDIRECTORY(DdsUnitTestsPlaceholder)
@@ -1,182 +0,0 @@
#
# $Id$
# $HeadURL$
# $Author$
#
# Check for required targets - use simpler condition for INTERFACE library compatibility
IF(BUILD_TESTING AND BUILD_RTI)
# Verify required targets exist
SET(_required_targets ddsgen ddsdtc ddsfts ddsQoS)
SET(_targets_found TRUE)
FOREACH(_tgt ${_required_targets})
IF(NOT TARGET ${_tgt})
SET(_targets_found FALSE)
MESSAGE(WARNING "Required target ${_tgt} not found - DDS unit tests will not be built")
ENDIF()
ENDFOREACH()
IF(_targets_found)
SET(xml_FILE ddsut.xml)
SET(SRCS_common
ddsut_export.h
)
# Generates ddsut.idl / ddsut_enums.idl
IF(BUILD_GRANTLEE)
CODEGEN_IDL_SVC(SRCS_common ${xml_FILE})
ELSE()
# BUILD_GRANTLEE disabled: check for pre-generated files
IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ddsut.idl" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ddsut_enums.idl")
MESSAGE(STATUS "BUILD_GRANTLEE disabled: using pre-generated IDL files for ddsut")
LIST(APPEND SRCS_common ddsut.idl ddsut_enums.idl)
ELSE()
MESSAGE(WARNING "BUILD_GRANTLEE disabled but no pre-generated IDL files found for ddsut. Skipping service.")
SET(SRCS_common "")
ENDIF()
ENDIF()
# Generate *.cpp/*.hpp from ddsut_enums.idl / ddsut.idl
IF(BUILD_GRANTLEE OR (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ddsut.idl" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ddsut_enums.idl"))
RTIDDSGEN(SRCS_common ddsut_enums.idl)
RTIDDSGEN(SRCS_common ddsut.idl)
ENDIF()
# Generate ddsut_dt[s,c]_types.h, ddsut_ft[s,c]_types.h
CODEGEN_TOPIC_TYPEDEFS(SRCS_common ${xml_FILE})
# generate ddsut_[d|f]tc.h
IF(BUILD_GRANTLEE)
CODEGEN_CLIENT_TOPICS_IFC(SRCS_common ${xml_FILE})
ELSE()
# Check for pre-generated files
IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ddsut_dtc.h" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ddsut_ftc.h")
MESSAGE(STATUS "BUILD_GRANTLEE disabled: using pre-generated DTC/FTC files for ddsut")
LIST(APPEND SRCS_common ddsut_dtc.h ddsut_ftc.h)
ELSE()
MESSAGE(WARNING "BUILD_GRANTLEE disabled but no pre-generated DTC/FTC files found for ddsut")
ENDIF()
ENDIF()
NGL_ADD_LIBRARY2(ALL ddsut_common SHARED ${SRCS_common})
IF(BUILD_RTI)
NGL_TARGET_LINK_LIBRARIES(ddsut_common
PRIVATE
NGLLogger
PUBLIC
LtsUtilsCoreHeaderOnly
Qt6::Core
RTI::nddsc
RTI::nddscore
RTI::nddscpp2
ddscore
)
ENDIF(BUILD_RTI)
NGL_TARGET_INCLUDE_DIRECTORIES(ddsut_common
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
# -----------------------------------------------------------------------------------
# Testing DataWriter/DataReader without DTS/DTC
# -----------------------------------------------------------------------------------
SET(SRCS_TEST1
generic_data_tests.cpp
generic_data_tests.h
initialisation.cpp
initialisation.h
)
# -----------------------------------------------------------------------------------
# Testing DataTopic Functionality (DTS/DTC)
# -----------------------------------------------------------------------------------
SET(SRCS_TEST2
data_topic_tests_main.cpp
data_topic_tests_main.h
data_topic_tests.cpp
data_topic_tests.h
)
# -----------------------------------------------------------------------------------
# Testing FunctionTopic Functionality (FTS/FTC)
# -----------------------------------------------------------------------------------
SET(SRCS_TEST3
function_topic_tests.cpp
function_topic_tests.h
)
# Testing DataWriter/DataReader without DTS/DTC
ADD_EXECUTABLE(ddsGenericDataTests ${SRCS_TEST1})
TARGET_LINK_LIBRARIES(ddsGenericDataTests
ddsgen
ddsdtc
ddsQoS
nglcoreapplication
NGLLogger
ProjectConfig
Qt6::Core
Qt6::Test
ddsut_common
)
TARGET_INCLUDE_DIRECTORIES(ddsGenericDataTests PRIVATE
${CMAKE_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/Lts/DDS
)
ADD_TEST(NAME ddsGenericDataTests COMMAND $<TARGET_FILE:ddsGenericDataTests>)
# Testing DataTopic Functionality (DTS/DTC)
ADD_EXECUTABLE(ddsDataTopicTests ${SRCS_TEST2})
TARGET_LINK_LIBRARIES(ddsDataTopicTests
nglcoreapplication
NGLLogger
RTI::nddscpp2
ddsgen
ddsdts
ddsdtc
ddsQoS
ProjectConfig
Qt6::Core
Qt6::Test
ddsut_common
)
TARGET_INCLUDE_DIRECTORIES(ddsDataTopicTests PRIVATE
${CMAKE_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/Lts
${CMAKE_SOURCE_DIR}/Lts/DDS
)
ADD_TEST(NAME ddsDataTopicTests COMMAND $<TARGET_FILE:ddsDataTopicTests>)
# Testing FunctionTopic Functionality (FTS/FTC)
ADD_EXECUTABLE(ddsFunctionTopicTests ${SRCS_TEST3})
TARGET_LINK_LIBRARIES(ddsFunctionTopicTests
ddsgen
ddsfts
ddsftc
ddsQoS
ddsconnector
nglcoreapplication
NGLLogger
ngltools
Qt6::Core
Qt6::Test
ddsut_common
)
TARGET_INCLUDE_DIRECTORIES(ddsFunctionTopicTests PRIVATE
${CMAKE_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/Lts
${CMAKE_SOURCE_DIR}/Lts/DDS
)
ADD_TEST(NAME ddsFunctionTopicTests COMMAND $<TARGET_FILE:ddsFunctionTopicTests>)
ENDIF() # _targets_found
IF(NOT BUILD_RPM)
NGL_INSTALL(AAR SV TARGETS ddsut_common DESTINATION bin/test)
NGL_INSTALL(AAR SV TARGETS ddsGenericDataTests DESTINATION bin/test)
NGL_INSTALL(AAR SV TARGETS ddsDataTopicTests DESTINATION bin/test)
NGL_INSTALL(AAR SV TARGETS ddsFunctionTopicTests DESTINATION bin/test)
NGL_INSTALL(AAR SV FILES log4cxx_ddsUnitTests.props DESTINATION bin/test)
ENDIF()
ENDIF()
@@ -1,130 +0,0 @@
#include "data_topic_tests.h"
#include <DDS/DTC/generic_dtc_impl.h>
#include <DDS/DTS/generic_dts_impl.h>
#include <DDS/QosProfile/DDS_DefaultQos.h>
#include <Lts/Common/ProjectConfig/project_defines.h>
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <QtCore/QThread>
#include <QtCore/QVariant>
#include <QtTest/QTest>
DataTopicTests::DataTopicTests()
: m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("UnitTests.DataTopicTests"))
, m_domainParticipantPub(nullptr)
, m_domainParticipantSub(nullptr)
, m_domainId(0)
, m_partitionId(1)
, m_ddsPublisher(nullptr)
, m_testPart(nullptr)
, m_ddsSubscriber(nullptr)
, m_subscriberListener(nullptr)
, m_dtcTestPart(nullptr)
, m_mainThreadId(QThread::currentThreadId())
{
if (!DDS::QosProfile::setDefault())
ERROR_LOG(m_logger) << "Error setting default QoS from xml-file ";
DEBUG_LOG(m_logger) << "Main thread ID is " << m_mainThreadId;
}
DataTopicTests::~DataTopicTests()
{
delete m_testPart;
delete m_dtcTestPart;
delete m_subscriberListener;
}
bool DataTopicTests::initPublisher()
{
m_domainParticipantPub = dds::domain::DomainParticipant(m_domainId, DDS::QosProfile::domainParticipantShm());
dds::pub::qos::PublisherQos publisherQos = m_domainParticipantPub.default_publisher_qos();
QString partition = QString::fromStdString(IDL::exercisePartition(m_partitionId));
dds::core::policy::Partition partitionQos;
partitionQos.name({partition.toStdString()});
publisherQos << partitionQos;
DEBUG_LOG(m_logger) << "Publish on partition " << partition;
m_ddsPublisher = dds::pub::Publisher(m_domainParticipantPub, publisherQos);
m_testPart = new DTS::TestParticipantImpl(m_domainParticipantPub, m_ddsPublisher);
return true;
}
bool DataTopicTests::write(const DdsUnitTests::TestParticipant& data)
{
INFO_LOG(m_logger) << "Publish topic TestParticipant ";
DEBUG_LOG(m_logger) << "ParticipantId: " << data.location.participantId
<< ", equipNo = " << data.location.equipNo;
return m_testPart->write(data);
}
bool DataTopicTests::initSubscriber()
{
DEBUG_LOG(m_logger) << "Initialisation DDS (Subscriber/Reader)";
m_domainParticipantSub = dds::domain::DomainParticipant(m_domainId, DDS::QosProfile::domainParticipantShm());
dds::sub::qos::SubscriberQos subscriberQos = m_domainParticipantSub.default_subscriber_qos();
dds::core::StringSeq partitions;
partitions.reserve(1);
for (int partitionId : {1})
{
partitions.push_back(IDL::exercisePartition(partitionId));
}
dds::core::policy::Partition partitionQos;
partitionQos.name(partitions);
subscriberQos << partitionQos;
DEBUG_LOG(m_logger) << "Initialise DTC::SubscriberListener";
m_subscriberListener = new DDSGeneric::SubscriberListener();
m_ddsSubscriber = dds::sub::Subscriber(m_domainParticipantSub, subscriberQos, m_subscriberListener,
DDSGeneric::SubscriberListener::mask());
m_dtcTestPart =
new DTC::SampleInfo::TestParticipantImpl(m_domainParticipantSub, m_ddsSubscriber, m_subscriberListener);
m_dtcTestPart->setSubscriberCallback(
[this](const DdsUnitTests::TestParticipant& data, const dds::sub::SampleInfo& si) { processData(data, si); });
return true;
}
void DataTopicTests::deleteDTC()
{
delete m_dtcTestPart;
m_dtcTestPart = nullptr;
}
void DataTopicTests::deleteSubscriber()
{
m_ddsSubscriber = nullptr;
delete m_subscriberListener;
m_subscriberListener = nullptr;
}
void DataTopicTests::processData(const DdsUnitTests::TestParticipant& instance, const dds::sub::SampleInfo& si)
{
INFO_LOG(m_logger) << "process data in topic TestParticipant, Sampleinfo: " << si.source_timestamp().sec();
DEBUG_LOG(m_logger) << "participantId: " << instance.location.participantId;
DEBUG_LOG(m_logger) << "equipNo: " << instance.location.equipNo;
m_receivedParticipantData = instance;
QCOMPARE(m_mainThreadId, QThread::currentThreadId());
emit testParticipantDataArrived();
}
@@ -1,61 +0,0 @@
#pragma once
#include <DDS/Generic/subscriber_listener.h>
#include <DdsUnitTests/ddsut_dtc_types.h>
#include <DdsUnitTests/ddsut_dts_types.h>
#include <QtCore/QObject>
#include <dds/pub/Publisher.hpp>
#include <dds/sub/Subscriber.hpp>
namespace NGL
{
class INGLLogger;
}
class DataTopicTests : public QObject
{
Q_OBJECT
public:
DataTopicTests();
virtual ~DataTopicTests();
bool initPublisher();
bool initSubscriber();
bool write(const DdsUnitTests::TestParticipant& data);
DdsUnitTests::TestParticipant getReceivedParticipantData() const
{
return m_receivedParticipantData;
}
void deleteDTC();
void deleteSubscriber();
protected:
NGL::INGLLogger& m_logger;
void processData(const DdsUnitTests::TestParticipant& instance, const dds::sub::SampleInfo& si);
Q_SIGNALS:
void testParticipantDataArrived();
private:
dds::domain::DomainParticipant m_domainParticipantPub;
dds::domain::DomainParticipant m_domainParticipantSub;
int m_domainId;
int m_partitionId;
dds::pub::Publisher m_ddsPublisher;
DTS::TestParticipant* m_testPart;
dds::sub::Subscriber m_ddsSubscriber;
DDSGeneric::SubscriberListener* m_subscriberListener;
DTC::SampleInfo::TestParticipant* m_dtcTestPart;
Qt::HANDLE m_mainThreadId;
DdsUnitTests::TestParticipant m_receivedParticipantData;
};
@@ -1,96 +0,0 @@
#include "data_topic_tests_main.h"
#include "data_topic_tests.h"
#include <Lts/Common/ProjectConfig/project_defines.h>
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <QtTest/QTest>
#include <nglapplication/nglcoreapplication.h>
int main(int argc, char* argv[])
{
NGLCoreApplication app(argc, argv);
app.createLogger("UnitTests", "log4cxx_ddsUnitTests.props");
DataTopicTestsMain* tc = new DataTopicTestsMain;
int retCode = QTest::qExec(tc, argc, argv);
delete tc;
return retCode;
}
DataTopicTestsMain::DataTopicTestsMain()
: m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("UnitTests.DataTopicTestsMain"))
{
}
void DataTopicTestsMain::initTestCase()
{
DEBUG_LOG(m_logger) << "DataTopicTestsMain: initTestCase";
m_dtTest = new DataTopicTests();
QVERIFY2(m_dtTest, "Initialisation of DataTopicTest failed");
QVERIFY2(m_dtTest->initPublisher(), "Initialisation Publisher failed");
QVERIFY2(m_dtTest->initSubscriber(), "Initialisation Subscriber failed");
m_participantDataArrivedSpy = new QSignalSpy(m_dtTest, &DataTopicTests::testParticipantDataArrived);
}
void DataTopicTestsMain::publishTestCase()
{
DEBUG_LOG(m_logger) << "DataTopicTestsMain: publish TestParticipant";
m_sentParticipantData.location.participantId = 100;
m_sentParticipantData.location.equipNo = 1010;
m_sentParticipantData.testId = 100;
QVERIFY2(m_dtTest->write(m_sentParticipantData), "Publishing Topic TestParticipant failed");
DEBUG_LOG(m_logger) << "DataTopicTestsMain: publish ready";
}
void DataTopicTestsMain::subscribeTestCase()
{
DEBUG_LOG(m_logger) << "IN subscribeTestCase";
QTRY_COMPARE(m_participantDataArrivedSpy->count(), 1);
DdsUnitTests::TestParticipant recvPartiticpant = m_dtTest->getReceivedParticipantData();
QCOMPARE(recvPartiticpant.location.participantId, m_sentParticipantData.location.participantId);
QCOMPARE(recvPartiticpant.location.equipNo, m_sentParticipantData.location.equipNo);
}
void DataTopicTestsMain::deleteDataReaderTestCase()
{
DdsUnitTests::TestParticipant data;
for (int i = 0; i < 1000; ++i)
{
m_sentParticipantData.id = i;
m_dtTest->write(m_sentParticipantData);
}
m_dtTest->deleteDTC();
for (int i = 0; i < 1000; ++i)
{
m_sentParticipantData.id = i;
m_dtTest->write(m_sentParticipantData);
}
m_dtTest->deleteSubscriber();
for (int i = 0; i < 1000; ++i)
{
m_sentParticipantData.id = i;
m_dtTest->write(m_sentParticipantData);
}
}
void DataTopicTestsMain::cleanupTestCase()
{
DEBUG_LOG(m_logger) << "DataTopicTestsMain: cleanupTestCase";
delete m_dtTest;
m_dtTest = nullptr;
delete m_participantDataArrivedSpy;
m_participantDataArrivedSpy = nullptr;
}
@@ -1,37 +0,0 @@
#pragma once
#include <DdsUnitTests/ddsut_dtc_types.h>
#include <QtCore/QObject>
#include <QSignalSpy>
namespace NGL
{
class INGLLogger;
}
class DataTopicTests;
class DataTopicTestsMain : public QObject
{
Q_OBJECT
public:
DataTopicTestsMain();
private Q_SLOTS:
void initTestCase();
void publishTestCase();
void subscribeTestCase();
void deleteDataReaderTestCase();
void cleanupTestCase();
protected:
NGL::INGLLogger& m_logger;
private:
DdsUnitTests::TestParticipant m_sentParticipantData;
QSignalSpy* m_participantDataArrivedSpy = nullptr;
DataTopicTests* m_dtTest = nullptr;
};
@@ -1,123 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<service namespace="DdsUnitTests" abbreviation="DDSUT" procNames="">
<rcs>
<Id Id="$Id: core.xml 38132 2018-01-10 07:52:50Z ehrlicher $"/>
<HeadURL HeadURL="$HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/DDS/Core/core.xml $"/>
<Author Author="$Author: ehrlicher $"/>
</rcs>
<tables/>
<views/>
<topicTypes>
<topicType name="BaseEntity">
<column name="id" idlType="long" isKey="1"/>
<column name="name" idlType="string"/>
<column name="isDeleted" idlType="boolean"/>
<column name="isUsed" idlType="boolean" comment="Defines if it is used by others (i.e. foreign key constraint)"/>
<column name="isBlockedForEdit" idlType="boolean"/>
</topicType>
<topicType name="BaseEntityTranslatable">
<column name="id" idlType="long" isKey="1"/>
<column name="name" idlType="string" isTranslatable="1"/>
<column name="isDeleted" idlType="boolean"/>
<column name="isUsed" idlType="boolean" comment="Defines if it is used by others (i.e. foreign key constraint)"/>
<column name="isBlockedForEdit" idlType="boolean"/>
</topicType>
<topicType name="BaseEntityWithSampleTime" extensibility="EXTENSIBLE" baseValueType="BaseEntity">
<column name="sampleTime" idlType="long long" comment="Timestamp"/>
</topicType>
<topicType name="CurrentRunningState" isDataObject="1" routeToClient="0" routeInReplay="0">
<column name="pid" idlType="long long" isKey="1"/>
<column name="runningState" idlType="Core::RunningState"/>
<column name="ports" idlType="sequence&lt;PortInformation&gt;" isOptional="1"/>
<column name="errorString" idlType="string" isOptional="1"/>
</topicType>
<topicType name="Entity" extensibility="EXTENSIBLE" baseValueType="BaseEntityWithSampleTime">
<column name="location" idlType="SpatialData"/>
<column name="symbolId" idlType="long"/>
</topicType>
<topicType name="FunctionReply">
<column name="id" idlType="long"/>
<column name="errorString" idlType="string"/>
<column name="errorParams" idlType="sequence&lt;string&gt;"/>
</topicType>
<topicType name="FunctionReplyWithState" baseValueType="FunctionReply">
<column name="replyState" idlType="Core::FtReplyState"/>
</topicType>
<topicType name="FunctionRequest">
<column name="id" idlType="long"/>
<column name="value" idlType="double"/>
<column name="info" idlType="string" isOptional="1"/>
</topicType>
<topicType name="FunctionRequestWithState" baseValueType="FunctionRequest">
<column name="status" idlType="long"/>
</topicType>
<topicType name="GeoPosition" extensibility="FINAL">
<column name="lon" idlType="double"/>
<column name="lat" idlType="double"/>
<column name="z" idlType="double" comment="height above ground"/>
</topicType>
<topicType name="GeoPosition2D" extensibility="FINAL">
<column name="lon" idlType="double" comment="[m]"/>
<column name="lat" idlType="double" comment="[m]"/>
</topicType>
<topicType name="Orientation" extensibility="FINAL">
<column name="heave" idlType="double"/>
<column name="pitch" idlType="double"/>
<column name="roll" idlType="double"/>
</topicType>
<topicType name="PartitionTime" isDataObject="1" routeToClient="1" routeInReplay="0">
<column name="timeStamp" idlType="long long"/>
</topicType>
<topicType name="PortInformation">
<column name="number" idlType="long"/>
<column name="type" idlType="DdsutPortType"/>
</topicType>
<topicType name="RelativePosition">
<column name="offsetX" idlType="double" comment="in meter"/>
<column name="offsetY" idlType="double" comment="in meter"/>
<column name="offsetZ" idlType="double" comment="in meter"/>
</topicType>
<topicType name="RemoveElementRequest">
<column name="id" idlType="long"/>
</topicType>
<topicType name="ReplayPartition" isDataObject="1" routeToClient="1" routeInReplay="0">
<column name="id" idlType="long" isKey="1"/>
<column name="name" idlType="string"/>
<column name="exerciseId" idlType="long"/>
<column name="workstationId" idlType="long"/>
<column name="operatorId" idlType="long"/>
<column name="replayType" idlType="Core::ReplayType"/>
<column name="domainId" idlType="long"/>
<column name="tcpConnectionUrl" idlType="string"/>
</topicType>
<topicType name="SpatialData" isDataObject="1" routeToClient="0" routeInReplay="0">
<column name="changedAt" idlType="long"/>
<column name="equipNo" idlType="long"/>
<column name="gpsPosition" idlType="GeoPosition"/>
<column name="orientation" idlType="Orientation"/>
<column name="participantId" idlType="long"/>
<column name="velocity" idlType="Velocity"/>
</topicType>
<topicType name="TestParticipant" isDataObject="1" routeToClient="0" routeInReplay="0" recordTopic="1" baseValueType="Entity">
<column name="designator" idlType="string&lt;20&gt;"/>
<column name="testId" idlType="long"/>
<column name="gpsQuality" idlType="short"/>
<column name="equipmentNumber" idlType="long"/>
</topicType>
<topicType name="Velocity">
<column name="x" idlType="double"/>
<column name="y" idlType="double"/>
<column name="z" idlType="double"/>
</topicType>
</topicTypes>
<functionTopics>
<functionTopic name="FunctionTopicTest" requestTopicType="FunctionRequest" replyTopicType="FunctionReply" requestTopicName="FunctionTopicTestRequest" replyTopicName="FunctionTopicTestReply" routeInReplay="0"/>
<functionTopic name="FunctionTopicTestWithState" requestTopicType="FunctionRequestWithState" replyTopicType="FunctionReplyWithState" requestTopicName="FunctionTopicTestWithStateRequest" replyTopicName="FunctionTopicTestWithStateReply" routeInReplay="0"/>
</functionTopics>
<enumerations>
<enumeration name="DdsutPortType">
<attribute key="Unknown" value="0"/>
<attribute key="WebSocketServer" value="1"/>
</enumeration>
</enumerations>
</service>
@@ -1,23 +0,0 @@
#pragma once
#include <QtCore/qglobal.h>
#ifndef DDSUT_COMMON_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define DDSUT_COMMON_EXPORT
# else
# if defined(MAKE_DDSUT_COMMON_LIB)
# define DDSUT_COMMON_EXPORT Q_DECL_EXPORT
# ifndef WIN32
# ifdef NDDSUSERDllExport
# undef NDDSUSERDllExport
# endif
# define NDDSUSERDllExport Q_DECL_EXPORT
# endif
# else
# define DDSUT_COMMON_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
@@ -1,241 +0,0 @@
#include "function_topic_tests.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <DDS/DDSConnector/publisher.h>
#include <DDS/DDSConnector/subscriber.h>
#include <Lts/Common/ProjectConfig/project_defines.h>
#include <NGLLogger/INGLLogger.h>
#include <QtTest/QTest>
#include <nglapplication/nglcoreapplication.h>
int main(int argc, char* argv[])
{
NGLCoreApplication app(argc, argv);
app.createLogger("UnitTests", "log4cxx_ddsUnitTests.props");
FunctionTopicTests* tc = new FunctionTopicTests;
int retCode = QTest::qExec(tc, argc, argv);
delete tc;
return retCode;
}
FunctionTopicTests::FunctionTopicTests()
: m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("UnitTests.FunctionTopicTests"))
, m_mainThreadId(QThread::currentThreadId())
{
qRegisterMetaType<DdsUnitTests::FunctionReply>("DdsUnitTests::FunctionReply");
qRegisterMetaType<DdsUnitTests::FunctionReplyWithState>("DdsUnitTests::FunctionReplyWithState");
}
void FunctionTopicTests::initTestCase()
{
DEBUG_LOG(m_logger) << "FunctionTopicTests: initTestCase";
const int domainId = 0;
m_ddsConnectorClient = std::make_shared<DDSConnector::DdsConnector>(domainId, IDL::PartitionType::Global);
QVERIFY2(m_ddsConnectorClient->init(), "Initialisation of ddsconnector (Client) failed");
m_ddsConnectorClient->initSubscriber();
QVERIFY2(m_ddsConnectorClient->getSubscriber(), "Initialisation of Subscriber (DdsConnectorClient) failed");
m_ddsConnectorClient->initPublisher();
QVERIFY2(m_ddsConnectorClient->getPublisher(), "Initialisation of Publisher (DdsConnectorClient) failed");
m_ddsConnectorServer = std::make_shared<DDSConnector::DdsConnector>(domainId, IDL::PartitionType::Global);
QVERIFY2(m_ddsConnectorServer->init(), "Initialisation of ddsconnector (Server) failed");
m_ddsConnectorServer->initSubscriber();
QVERIFY2(m_ddsConnectorServer->getSubscriber(), "Initialisation of Subscriber (DdsConnectorServer) failed");
m_ddsConnectorServer->initPublisher();
QVERIFY2(m_ddsConnectorServer->getPublisher(), "Initialisation of Publisher (DdsConnectorServer) failed");
}
void FunctionTopicTests::initFTSTestCase()
{
m_fts.reset(m_ddsConnectorServer->createFTS<FTS::FunctionTopicTest>());
QVERIFY2(m_fts.get(), "Initialisation of FTS Replier failed");
m_fts->setSubscriberCallback(
[this](const rti::core::SampleIdentity& identity, const DdsUnitTests::FunctionRequest& request) {
this->onFunctionTopicRequest(identity, request);
});
m_ftsWS.reset(m_ddsConnectorServer->createFTS<FTS::FunctionTopicTestWithState>());
QVERIFY2(m_ftsWS.get(), "Initialisation of FTS Replier failed");
m_ftsWS->setSubscriberCallback(
[this](const rti::core::SampleIdentity& identity, const DdsUnitTests::FunctionRequestWithState& request) {
this->onFunctionTopicRequest(identity, request);
});
}
void FunctionTopicTests::initFTCTestCase()
{
m_ftc.reset(m_ddsConnectorClient->createFTC<FTC::FunctionTopicTest>(this));
QVERIFY2(m_ftc.get(), "Initialisation of FTC Requester failed");
m_ftcWS.reset(m_ddsConnectorClient->createFTC<FTC::FunctionTopicTestWithState>(this));
QVERIFY2(m_ftc.get(), "Initialisation of FTC Requester failed");
}
void FunctionTopicTests::requestTestCase1()
{
requestWithState();
QCOMPARE(m_ddsConnectorServer->getWaitSetHandler()->attachedConditionCount(), 3);
requestWithState();
QCOMPARE(m_ddsConnectorServer->getWaitSetHandler()->attachedConditionCount(), 3);
}
void FunctionTopicTests::requestWithState()
{
QSignalSpy spyRequest(this, &FunctionTopicTests::functionTopicRequestFinished);
QSignalSpy spyReply(this, &FunctionTopicTests::functionTopicReply);
DEBUG_LOG(m_logger) << "FunctionTopicTests: request";
DdsUnitTests::FunctionRequestWithState data;
data.id = 1;
data.info = std::string("Test request");
data.value = 1000.0;
int uniqueId = 0;
bool bRet = m_ftcWS->requestDataClassic(
data, SLOT(slotRequestedData(DdsUnitTests::FunctionTopicTestWithStateReply,int,bool)),
SLOT(slotRequestedDataError(int,int,int)), uniqueId);
QVERIFY2(bRet, "Could not request data!");
QTRY_COMPARE(spyRequest.count(), 1);
QTRY_COMPARE(spyReply.count(), 2);
}
void FunctionTopicTests::requestTestCase2()
{
QSignalSpy spyRequest(this, &FunctionTopicTests::functionTopicRequestFinished);
QSignalSpy spyReply(this, &FunctionTopicTests::functionTopicReply);
DEBUG_LOG(m_logger) << "FunctionTopicTests: request";
DdsUnitTests::FunctionRequest data;
data.id = 1;
data.info = std::string("Test request");
data.value = 1000.0;
int uniqueId = 0;
bool bRet =
m_ftc->requestDataClassic(data, SLOT(slotRequestedData(DdsUnitTests::FunctionTopicTestReply,int,bool)),
SLOT(slotRequestedDataError(int,int,int)), uniqueId);
QVERIFY2(bRet, "Could not request data!");
QTRY_COMPARE(spyRequest.count(), 1);
QTRY_COMPARE(spyReply.count(), 1);
}
void FunctionTopicTests::cleanupTestCase()
{
DEBUG_LOG(m_logger) << "FunctionTopicTests: cleanupTestCase";
m_fts = nullptr;
m_ftc = nullptr;
m_ftsWS = nullptr;
m_ftcWS = nullptr;
m_ddsConnectorServer = nullptr;
m_ddsConnectorClient = nullptr;
}
void FunctionTopicTests::onFunctionTopicRequest(const rti::core::SampleIdentity& sampleId,
const DdsUnitTests::FunctionRequestWithState& request)
{
QCOMPARE(m_mainThreadId, QThread::currentThreadId());
INFO_LOG(m_logger) << "Got function topic request (with status member)";
m_requestTopicWithState = request;
QCOMPARE(m_requestTopicWithState.id, 1);
QCOMPARE(m_requestTopicWithState.info.get(), std::string("Test request"));
QCOMPARE(m_requestTopicWithState.value, 1000.0);
DdsUnitTests::FunctionReplyWithState reply;
DEBUG_LOG(m_logger) << "Send sample with status REPLY_COMPLETED";
reply.id = 1;
reply.errorString = "Hello";
reply.replyState = Core::FtReplyState::Completed;
bool bRet = m_ftsWS->sendReply(sampleId, reply);
QVERIFY2(bRet, "Sending Reply failed");
emit functionTopicRequestFinished();
}
void FunctionTopicTests::onFunctionTopicRequest(const rti::core::SampleIdentity& sampleId,
const DdsUnitTests::FunctionRequest& request)
{
QCOMPARE(m_mainThreadId, QThread::currentThreadId());
INFO_LOG(m_logger) << "Got function topic request (without status member)";
m_requestTopic = request;
DdsUnitTests::FunctionReply reply;
reply.id = 2;
reply.errorString = "What?";
bool bRet = m_fts->sendReply(sampleId, reply);
QVERIFY2(bRet, "Sending Reply failed");
emit functionTopicRequestFinished();
}
void FunctionTopicTests::slotRequestedData(const DdsUnitTests::FunctionTopicTestWithStateReply& reply, int seqNo,
bool bFinished)
{
Q_UNUSED(seqNo);
QCOMPARE(m_mainThreadId, QThread::currentThreadId());
INFO_LOG(m_logger) << "Got reply from FTS: " << reply.replyState;
m_replyTopicWithState = reply;
if (m_replyTopicWithState.replyState == Core::FtReplyState::InProgress)
{
QVERIFY(!bFinished);
QCOMPARE(m_replyTopicWithState.id, 0);
}
else
{
QVERIFY(bFinished);
QCOMPARE(m_replyTopicWithState.id, 1);
QCOMPARE(m_replyTopicWithState.errorString, std::string("Hello"));
QCOMPARE(static_cast<int>(m_replyTopicWithState.replyState), static_cast<int>(Core::FtReplyState::Completed));
}
emit functionTopicReply();
}
void FunctionTopicTests::slotRequestedData(const DdsUnitTests::FunctionTopicTestReply& reply, int seqNo, bool bFinished)
{
Q_UNUSED(seqNo);
QVERIFY(bFinished);
QCOMPARE(m_mainThreadId, QThread::currentThreadId());
m_replyTopic = reply;
QCOMPARE(m_replyTopic.id, 2);
QCOMPARE(m_replyTopic.errorString, std::string("What?"));
emit functionTopicReply();
}
void FunctionTopicTests::slotRequestedDataError(int reason, int seqNo, int requestId)
{
Q_UNUSED(seqNo);
Q_UNUSED(requestId);
QFAIL(qPrintable(QStringLiteral("Error when trying to request data: %1").arg(reason)));
}
@@ -1,69 +0,0 @@
#pragma once
#include <DDS/DDSConnector/dds_connector.h>
#include <DDS/FTC/generic_ftc_impl.h>
#include <DDS/FTS/generic_fts_impl.h>
#include <DdsUnitTests/ddsut.hpp>
#include <DdsUnitTests/ddsut_ftc_types.h>
#include <DdsUnitTests/ddsut_fts_types.h>
#include <QtCore/QObject>
#include <QSignalSpy>
#include <QtCore/QThread>
namespace NGL
{
class INGLLogger;
}
class FunctionTopicTests : public QObject
{
Q_OBJECT
public:
FunctionTopicTests();
private Q_SLOTS:
void initTestCase();
void initFTSTestCase();
void initFTCTestCase();
void requestTestCase1();
void requestTestCase2();
void cleanupTestCase();
Q_SIGNALS:
void functionTopicRequestFinished();
void functionTopicReply();
protected Q_SLOTS:
void slotRequestedData(const DdsUnitTests::FunctionTopicTestReply& reply, int seqNo, bool bFinished);
void slotRequestedData(const DdsUnitTests::FunctionTopicTestWithStateReply& reply, int seqNo, bool bFinished);
void slotRequestedDataError(int reason, int seqNo, int requestId);
void onFunctionTopicRequest(const rti::core::SampleIdentity& sampleId,
const DdsUnitTests::FunctionRequest& request);
void onFunctionTopicRequest(const rti::core::SampleIdentity& sampleId,
const DdsUnitTests::FunctionRequestWithState& request);
private:
void requestWithState();
std::unique_ptr<FTS::FunctionTopicTest> m_fts;
std::unique_ptr<FTS::FunctionTopicTestWithState> m_ftsWS;
std::unique_ptr<FTC::FunctionTopicTest> m_ftc;
std::unique_ptr<FTC::FunctionTopicTestWithState> m_ftcWS;
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnectorClient;
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnectorServer;
DdsUnitTests::FunctionRequest m_requestTopic;
DdsUnitTests::FunctionReply m_replyTopic;
DdsUnitTests::FunctionRequestWithState m_requestTopicWithState;
DdsUnitTests::FunctionReplyWithState m_replyTopicWithState;
NGL::INGLLogger& m_logger;
Qt::HANDLE m_mainThreadId;
};
@@ -1,219 +0,0 @@
#include "generic_data_tests.h"
#include <DDS/Generic/generic_data_reader.h>
#include <DDS/Generic/generic_data_writer.h>
#include <Lts/Common/ProjectConfig/project_defines.h>
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <QtTest/QTest>
#include <nglapplication/nglcoreapplication.h>
int main(int argc, char* argv[])
{
NGLCoreApplication app(argc, argv);
app.createLogger("UnitTests", "log4cxx_ddsUnitTests.props");
GenericDataTests* tc = new GenericDataTests;
int retCode = QTest::qExec(tc, argc, argv);
delete tc;
return retCode;
}
GenericDataTests::GenericDataTests()
: m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("UnitTests.GenericDataTests"))
{
m_spatialData.equipNo = 0;
m_testPart.location.equipNo = 0;
m_testPart.location.participantId = 0;
}
void GenericDataTests::initTestCase()
{
DEBUG_LOG(m_logger) << "GenericDataTests: initTestCase";
m_init = new Initialisation();
int domainId = 0;
int exerciseId = 2;
QVERIFY2(m_init, "Initialisation failed");
QVERIFY2(m_init->initDDS(domainId, exerciseId, Initialisation::USE_PUBLISHER), "Initialisation (Publisher) failed");
QVERIFY2(m_init->initDDS(domainId, exerciseId, Initialisation::USE_SUBSCRIBER),
"Initialisation (Subscriber) failed");
QVERIFY2(m_init->getSubscriberListener(), "Initialisation SubscriberListener failed");
}
void GenericDataTests::initDRTestCase()
{
m_dataReader = new DTC::DroTestParticipant;
QVERIFY2(m_dataReader, "Initialisation of GenericDataReader(TestParticipant) failed");
QVERIFY2(m_dataReader->create(m_init->getDomainParticipantSub(), m_init->getDDSSubscriber()),
"Creating DataReader (TestParticipant) failed");
m_init->getSubscriberListener()->addCallback(m_dataReader->getDataReader(), this);
m_dataReaderSd = new DTC::DroSpatialData;
QVERIFY2(m_dataReaderSd, "Initialisation of GenericDataReader(SpatialData) failed");
QVERIFY2(m_dataReaderSd->create(m_init->getDomainParticipantSub(), m_init->getDDSSubscriber()),
"Creating DataReader (SpatialData) failed");
m_init->getSubscriberListener()->addCallback(m_dataReaderSd->getDataReader(), this);
}
void GenericDataTests::initDWTestCase()
{
m_dataWriter = new DTS::DwoTestParticipant();
QVERIFY2(m_dataWriter, "Initialisation of GenericDataWriter(TestParticipant) failed");
QVERIFY2(m_dataWriter->create(m_init->getDomainParticipant(), m_init->getDDSPublisher()),
"Creating DataWriter (TestParticipant) failed");
m_dataWriterSd = new DTS::DwoSpatialData();
QVERIFY2(m_dataWriterSd, "Initialisation of GenericDataWriter(SpatialData) failed");
QVERIFY2(m_dataWriterSd->create(m_init->getDomainParticipant(), m_init->getDDSPublisher()),
"Creating DataWriter (SpatialData) failed");
}
void GenericDataTests::dataWriterTestCase()
{
DEBUG_LOG(m_logger) << "GenericDataTests: dataWriter";
DdsUnitTests::SpatialData data;
data.participantId = 100;
data.equipNo = 999;
data.gpsPosition.lon = 70000;
data.gpsPosition.lat = 90000;
data.gpsPosition.z = 10;
data.orientation.heave = 10;
data.orientation.pitch = 10;
data.orientation.roll = 10;
data.velocity.x = 10;
data.velocity.y = 2;
data.velocity.z = 1;
data.changedAt = 11111;
QVERIFY2(m_dataWriterSd->write(data), "Publishing Topic (SpatialData) failed");
DdsUnitTests::TestParticipant allData;
allData.name = "************************ Name of TestParticpant ***********************";
allData.location = data;
allData.id = 10000;
QVERIFY2(m_dataWriter->write(allData), "Publishing Topic (TestParticipant) failed");
allData.id = 11000;
QVERIFY2(m_dataWriter->write(allData), "Publishing Topic (TestParticipant) failed");
allData.id = 11100;
QVERIFY2(m_dataWriter->write(allData), "Publishing Topic (TestParticipant) failed");
allData.id = 11110;
QVERIFY2(m_dataWriter->write(allData), "Publishing Topic (TestParticipant) failed");
allData.id = 11111;
QVERIFY2(m_dataWriter->write(allData), "Publishing Topic (TestParticipant) failed");
}
void GenericDataTests::dataReaderTestCase()
{
DEBUG_LOG(m_logger) << "GenericDataTests: dataReader";
QTRY_COMPARE(m_spatialData.equipNo, 999);
QCOMPARE(m_spatialData.changedAt, 11111);
QTRY_COMPARE(m_testPart.location.equipNo, 999);
QCOMPARE(m_testPart.location.participantId, 100);
bool bSeenUnreadSamples = false;
dds::sub::LoanedSamples<DdsUnitTests::TestParticipant> vecTp = m_dataReader->readAlive(bSeenUnreadSamples);
INFO_LOG(m_logger) << "vecTp size: " << vecTp.length();
QCOMPARE(vecTp.length(), static_cast<decltype(vecTp.length())>(5));
QCOMPARE(vecTp[0].data().id, 10000);
QCOMPARE(vecTp[1].data().id, 11000);
QCOMPARE(vecTp[2].data().id, 11100);
QCOMPARE(vecTp[3].data().id, 11110);
QCOMPARE(vecTp[4].data().id, 11111);
dds::sub::LoanedSamples<DdsUnitTests::TestParticipant> vecTpLoaned = m_dataReader->takeAlive(bSeenUnreadSamples);
INFO_LOG(m_logger) << "vecTpLoaned size: " << vecTp.length();
QCOMPARE(vecTpLoaned.length(), static_cast<decltype(vecTpLoaned.length())>(5));
QCOMPARE(vecTpLoaned[0].data().id, 10000);
QCOMPARE(vecTpLoaned[1].data().id, 11000);
QCOMPARE(vecTpLoaned[2].data().id, 11100);
QCOMPARE(vecTpLoaned[3].data().id, 11110);
QCOMPARE(vecTpLoaned[4].data().id, 11111);
}
void GenericDataTests::deleteDataReaderTestCase()
{
DdsUnitTests::TestParticipant data;
for (int i = 0; i < 1000; ++i)
{
data.id = i;
m_dataWriter->write(data);
}
m_init->getSubscriberListener()->removeCallback(m_dataReader->getDataReader(), this);
delete m_dataReader;
m_dataReader = nullptr;
for (int i = 0; i < 1000; ++i)
{
data.id = i;
m_dataWriter->write(data);
}
}
void GenericDataTests::cleanupTestCase()
{
DEBUG_LOG(m_logger) << "GenericDataTests: cleanupTestCase";
if (m_dataReader)
{
m_init->getSubscriberListener()->removeCallback(m_dataReader->getDataReader(), this);
delete m_dataReader;
}
if (m_dataReaderSd)
{
m_init->getSubscriberListener()->removeCallback(m_dataReaderSd->getDataReader(), this);
delete m_dataReaderSd;
}
m_init->cleanupSubscriberListener();
delete m_dataWriter;
delete m_dataWriterSd;
delete m_init;
deleteLater();
}
void GenericDataTests::processData(const DdsUnitTests::SpatialData& data, DataModification modType)
{
DEBUG_LOG(m_logger) << "SpatialData: equipNo = " << data.equipNo << " modType: " << modType;
m_spatialData = data;
}
void GenericDataTests::processData(const DdsUnitTests::TestParticipant& data, const dds::sub::SampleInfo& si)
{
Q_UNUSED(si);
DEBUG_LOG(m_logger) << "TestParticipant: equipNo = " << data.location.equipNo;
m_testPart = data;
}
void GenericDataTests::droDataAvailable(const std::string& topicType, const std::string& topicName)
{
Q_UNUSED(topicName)
DEBUG_LOG(m_logger) << "IN droDataAvailable: type = " << topicType;
if (topicType == "DdsUnitTests::TestParticipant")
{
m_init->getSubscriberListener()->enableCallback(m_dataReader->getDataReader(), this);
m_dataReader->read([this](const DdsUnitTests::TestParticipant& data, const dds::sub::SampleInfo& si) {
processData(data, si);
});
}
else if (topicType == "DdsUnitTests::SpatialData")
{
m_init->getSubscriberListener()->enableCallback(m_dataReaderSd->getDataReader(), this);
m_dataReaderSd->read(
[this](const DdsUnitTests::SpatialData& data, DataModification modType) { processData(data, modType); });
}
}
@@ -1,64 +0,0 @@
#pragma once
#include "initialisation.h"
#include <DDS/Generic/subscriber_listener.h>
#include <DdsUnitTests/ddsut_dtc_types.h>
#include <DdsUnitTests/ddsut_dts_types.h>
#include <LtsUtils/LtsUtilsCore/data_modification_enum.h>
#include <QtCore/QObject>
namespace NGL
{
class INGLLogger;
}
class GenericDataTests : public DDSGeneric::SubscriberListenerCallback
{
Q_OBJECT
public:
GenericDataTests();
private Q_SLOTS:
void initTestCase();
void initDRTestCase();
void initDWTestCase();
void dataWriterTestCase();
void dataReaderTestCase();
void deleteDataReaderTestCase();
void cleanupTestCase();
protected:
NGL::INGLLogger& m_logger;
void droDataAvailable(const std::string& topicType, const std::string& topicName) override;
void noWriterAnymore(const std::string& topicType, const std::string& topicName) override
{
Q_UNUSED(topicType);
Q_UNUSED(topicName);
}
void writerAvailable(const std::string& topicType, const std::string& topicName) override
{
Q_UNUSED(topicType);
Q_UNUSED(topicName);
}
void processData(const DdsUnitTests::TestParticipant& data, const dds::sub::SampleInfo& si);
void processData(const DdsUnitTests::SpatialData& data, DataModification modType);
private:
Initialisation* m_init = nullptr;
DTS::DwoTestParticipant* m_dataWriter = nullptr;
DTC::DroTestParticipant* m_dataReader = nullptr;
DTS::DwoSpatialData* m_dataWriterSd = nullptr;
DTC::DroSpatialData* m_dataReaderSd = nullptr;
DdsUnitTests::SpatialData m_spatialData;
DdsUnitTests::TestParticipant m_testPart;
};
@@ -1,85 +0,0 @@
#include "initialisation.h"
#include <DDS/QosProfile/DDS_DefaultQos.h>
#include <Lts/Common/ProjectConfig/project_defines.h>
#include <NGLLogger/NGLLoggerBootstrap.h>
Initialisation::Initialisation()
: m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("UnitTests.Initialisation"))
, m_domainParticipant(nullptr)
, m_domainParticipantSub(nullptr)
, m_domainId(0)
, m_exerciseId(-1)
, m_ddsPublisher(nullptr)
, m_ddsSubscriber(nullptr)
, m_subListener(new DDSGeneric::SubscriberListener)
{
if (!DDS::QosProfile::setDefault())
ERROR_LOG(m_logger) << "Error setting default QoS from xml-file ";
}
Initialisation::~Initialisation()
{
cleanupSubscriberListener();
m_ddsSubscriber = nullptr;
m_ddsPublisher = nullptr;
}
void Initialisation::cleanupSubscriberListener()
{
if (m_ddsSubscriber != nullptr && m_subListener != nullptr)
{
m_ddsSubscriber.listener(nullptr, dds::core::status::StatusMask::none());
delete m_subListener;
m_subListener = nullptr;
}
}
bool Initialisation::initDDS(int domainId, int exerciseId, PubSub pubsub)
{
if (m_domainParticipant == nullptr)
m_domainParticipant = dds::domain::DomainParticipant(domainId, DDS::QosProfile::domainParticipantShm());
if (pubsub == USE_PUBLISHER || pubsub == USE_PUB_SUB)
{
dds::pub::qos::PublisherQos publisherQos = m_domainParticipant.default_publisher_qos();
DEBUG_LOG(m_logger) << "Publish on partition " << IDL::exercisePartition(exerciseId);
dds::core::policy::Partition partitionQos;
partitionQos.name({IDL::exercisePartition(exerciseId)});
publisherQos << partitionQos;
m_ddsPublisher = dds::pub::Publisher(m_domainParticipant, publisherQos);
}
if (pubsub == USE_SUBSCRIBER || pubsub == USE_PUB_SUB)
{
dds::domain::DomainParticipant domainPart = m_domainParticipant;
if (domainPart == nullptr || m_domainParticipantSub == nullptr)
{
m_domainParticipantSub = dds::domain::DomainParticipant(domainId, DDS::QosProfile::domainParticipantShm());
domainPart = m_domainParticipantSub;
}
dds::sub::qos::SubscriberQos subscriberQos = domainPart.default_subscriber_qos();
DEBUG_LOG(m_logger) << "Subsribing on partition " << IDL::exercisePartition(exerciseId);
dds::core::policy::Partition partitionQos;
partitionQos.name({IDL::exercisePartition(exerciseId)});
subscriberQos << partitionQos;
m_ddsSubscriber = dds::sub::Subscriber(domainPart, subscriberQos, m_subListener, m_subListener->mask());
}
if (m_domainId == 0)
m_domainId = domainId;
if (m_exerciseId < 0)
m_exerciseId = exerciseId;
return true;
}
@@ -1,60 +0,0 @@
#pragma once
#include <DDS/Generic/generic_base.h>
#include <DDS/Generic/subscriber_listener.h>
#include <dds/pub/Publisher.hpp>
#include <dds/sub/Subscriber.hpp>
namespace NGL
{
class INGLLogger;
}
class Initialisation
{
public:
Initialisation();
virtual ~Initialisation();
enum PubSub { USE_PUBLISHER = 1, USE_SUBSCRIBER = 2, USE_PUB_SUB = 4 };
bool initDDS(int domainId, int exerciseId, PubSub pubsub = USE_PUBLISHER);
void cleanupSubscriberListener();
dds::domain::DomainParticipant getDomainParticipant()
{
return m_domainParticipant;
}
dds::domain::DomainParticipant getDomainParticipantSub()
{
return m_domainParticipantSub != nullptr ? m_domainParticipantSub : m_domainParticipant;
}
dds::pub::Publisher getDDSPublisher()
{
return m_ddsPublisher;
}
dds::sub::Subscriber getDDSSubscriber()
{
return m_ddsSubscriber;
}
DDSGeneric::SubscriberListener* getSubscriberListener()
{
return m_subListener;
}
private:
NGL::INGLLogger& m_logger;
dds::domain::DomainParticipant m_domainParticipant;
dds::domain::DomainParticipant m_domainParticipantSub;
int m_domainId;
int m_exerciseId;
dds::pub::Publisher m_ddsPublisher;
dds::sub::Subscriber m_ddsSubscriber;
DDSGeneric::SubscriberListener* m_subListener;
};
@@ -1,120 +0,0 @@
log4j.reset=true
log4j.rootLogger=WARN, file
# Service: PlayerManagement
###########################################################
log4j.logger.UnitTests.main=WARN
# GenericDataTests
log4j.logger.UnitTests.Initialisation=WARN
log4j.logger.UnitTests.GenericDataTests=WARN
# DataTopicTests
log4j.logger.UnitTests.DataTopicTestsMain=WARN
log4j.logger.UnitTests.DataTopicTests=WARN
# FunctionTopicTests
log4j.logger.UnitTests.FunctionTopicTests=WARN
# GenericTopicSqlTests
log4j.logger.UnitTests.GenericTopicSqlTests=WARN
# Qos Infos
log4j.logger.DDS.DefaultQos=WARN
# Generic
#log4j.logger.GenericBase=DEBUG
#log4j.logger.Generic.DataWriter=DEBUG
#log4j.logger.Generic.DataReader=DEBUG
#log4j.logger.Generic.DroTypeInfo=DEBUG
log4j.logger.GenericBase=WARN
log4j.logger.Generic.Subscriber=WARN
log4j.logger.Generic.Publisher=WARN
log4j.logger.Generic.DataWriter=WARN
log4j.logger.Generic.DataReader=WARN
log4j.logger.Generic.DroTypeInfo=WARN
# DTCs
log4j.logger.Generic.DTC=WARN
log4j.logger.DTC.SubscriberListener=WARN
log4j.logger.DTC.Topic=WARN
log4j.logger.DTC.Exercise=WARN
log4j.logger.DTC.StatusDRWatcher=WARN
# FTSs / FTCs
log4j.logger.FTS.Replier=WARN
log4j.logger.FTC.Requester=WARN
log4j.logger.Generic.FTS=WARN
log4j.logger.Generic.FTC=WARN
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.MaxFileSize=1MB
log4j.appender.file.MaxBackupIndex=9
log4j.appender.file.file=${LOG4QT_LOGDIR}/${LOG4QT_USER}_dds_unittests.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %-5p %c |#| %m (%.50F:%L) %n
# Appnd_Console
###########################################################
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern= %d %p %c %c{1} - %m (%-.30F:%L) %n
# Appnd_Syslog
###########################################################
log4j.appender.syslog=org.apache.log4j.SyslogAppender
log4j.appender.syslog.Threshold=ERROR
log4j.appender.syslog.SysLogHost=localhost
log4j.appender.syslog.Facility=LOCAL7
log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
log4j.appender.syslog.layout.ConversionPattern= %-4r %-5p %c %x - %m
log4j.appender.syslog.LevelRangeFilter.AcceptOnMatch=true
log4j.appender.syslog.LevelRangeFilter.LevelMin=INFO
log4j.appender.syslog.LevelRangeFilter.LevelMax=FATAL
###########################################################
###########################################################
###########################################################
# 1) Available Levels in LOG4CXX Version 0.10.0:
# TRACE,
# DEBUG,
# INFO,
# WARN,
# ERROR
# FATAL
#
# d = date/time
# p = priority (Level)
# c = category/channel
# m = message
# F = file
# L = line
# n = platform dependent line separator character or characters.
# ....
#
# Examples for console:
# a)
# %d %p %c #%m# (%.50F:%L)%n
# date/time
# priority
# category/channel
# #message#
# (Maximal 50Character des Filename von rechts:Line)
# line separator
#
# b)
# %d (%.15F:%L) %-5p %c |#| %m%n
# date/time
# (Maximal 15Character des Filename von rechts:Line)
# priority, Right pad with spaces if the priority name is less than 5 characters long.
# category/channel
# message
# line separator
#
# Examples for files:
@@ -1,85 +0,0 @@
# Smoke-test executables for Lts/DDS during migration.
# If the real test executables are not built (e.g. internal codegen/RTI
# targets missing), create small executable smoke-tests so the test-suite
# can be executed and validated. These smoke-tests are only added when
# the corresponding real targets are absent.
# Option to force-building smoke-tests even when real test targets exist.
option(BUILD_SMOKE_TESTS "Build smoke-tests even if real test executables are present" OFF)
# Enable GTest smoke-tests during migration to exercise realistic DDS mocks
option(BUILD_GTEST_SMOKE "Build GoogleTest-based smoke-tests for core logic" ON)
# Try to find GoogleTest if requested
if(BUILD_GTEST_SMOKE)
find_package(GTest QUIET)
if(NOT GTest_FOUND)
message(STATUS "GoogleTest not found via find_package; will attempt to use FetchContent fallback if enabled later.")
endif()
endif()
if(BUILD_TESTING)
include(CTest)
# Generic data tests smoke (QtTest)
if(BUILD_SMOKE_TESTS OR NOT TARGET ddsGenericDataTests)
add_executable(ddsGenericDataTests_smoke ddsGenericDataTests_smoke.cpp mocks/MockDDS.cpp)
target_link_libraries(ddsGenericDataTests_smoke PRIVATE Qt6::Core Qt6::Test)
add_test(NAME ddsGenericDataTests COMMAND $<TARGET_FILE:ddsGenericDataTests_smoke>)
endif()
# Data topic tests smoke (QtTest)
if(BUILD_SMOKE_TESTS OR NOT TARGET ddsDataTopicTests)
add_executable(ddsDataTopicTests_smoke ddsDataTopicTests_smoke.cpp mocks/MockDDS.cpp)
target_link_libraries(ddsDataTopicTests_smoke PRIVATE Qt6::Core Qt6::Test)
add_test(NAME ddsDataTopicTests COMMAND $<TARGET_FILE:ddsDataTopicTests_smoke>)
endif()
# Function topic tests smoke (QtTest)
if(BUILD_SMOKE_TESTS OR NOT TARGET ddsFunctionTopicTests)
add_executable(ddsFunctionTopicTests_smoke ddsFunctionTopicTests_smoke.cpp mocks/MockDDS.cpp)
target_link_libraries(ddsFunctionTopicTests_smoke PRIVATE Qt6::Core Qt6::Test)
add_test(NAME ddsFunctionTopicTests COMMAND $<TARGET_FILE:ddsFunctionTopicTests_smoke>)
endif()
# GoogleTest-based smoke-tests for core logic (optional)
if(BUILD_GTEST_SMOKE)
if(NOT GTest_FOUND)
# FetchContent fallback if GTest not found on system
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/refs/tags/release-1.12.1.tar.gz
)
FetchContent_GetProperties(googletest)
if(NOT googletest_POPULATED)
FetchContent_Populate(googletest)
add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR})
endif()
endif()
if(TARGET GTest::gtest_main OR TARGET gtest_main)
# Generic data tests gtest
if(NOT TARGET ddsGenericDataTests)
add_executable(ddsGenericDataTests_gtest ddsGenericDataTests_gtest.cpp mocks/MockDDS.cpp)
target_link_libraries(ddsGenericDataTests_gtest PRIVATE GTest::gtest_main)
add_test(NAME ddsGenericDataTests_gtest COMMAND $<TARGET_FILE:ddsGenericDataTests_gtest>)
endif()
if(NOT TARGET ddsDataTopicTests)
add_executable(ddsDataTopicTests_gtest ddsDataTopicTests_gtest.cpp mocks/MockDDS.cpp)
target_link_libraries(ddsDataTopicTests_gtest PRIVATE GTest::gtest_main)
add_test(NAME ddsDataTopicTests_gtest COMMAND $<TARGET_FILE:ddsDataTopicTests_gtest>)
endif()
if(NOT TARGET ddsFunctionTopicTests)
add_executable(ddsFunctionTopicTests_gtest ddsFunctionTopicTests_gtest.cpp mocks/MockDDS.cpp)
target_link_libraries(ddsFunctionTopicTests_gtest PRIVATE GTest::gtest_main)
add_test(NAME ddsFunctionTopicTests_gtest COMMAND $<TARGET_FILE:ddsFunctionTopicTests_gtest>)
endif()
else()
message(WARNING "GTest targets not available even after fallback; skipping GTest smoke-tests.")
endif()
endif()
endif()
@@ -1,24 +0,0 @@
#include <gtest/gtest.h>
#include "mocks/MockDDS.h"
TEST(DataTopicSmokeGTest, Format) {
char buf[64];
snprintf(buf, sizeof(buf), "%d-%s", 42, "abc");
EXPECT_STREQ(buf, "42-abc");
}
TEST(DataTopicSmokeGTest, MockDDSTopicFlow) {
MockDDS::clear_all();
MockDDS::publish("data/topic", "hello");
auto r1 = MockDDS::take_last("data/topic");
auto p1 = r1.substr(r1.find(':') + 1);
EXPECT_EQ(p1, "hello");
MockDDS::publish("data/topic", "world");
auto r2 = MockDDS::take_last("data/topic");
auto p2 = r2.substr(r2.find(':') + 1);
EXPECT_EQ(p2, "world");
// check sequence increment
auto s1 = std::stoul(r1.substr(0, r1.find(':')));
auto s2 = std::stoul(r2.substr(0, r2.find(':')));
EXPECT_LT(s1, s2);
}
@@ -1,18 +0,0 @@
#include <QtCore/QObject>
#include <QtTest/QtTest>
class DataTopicSmokeTest : public QObject {
Q_OBJECT
private slots:
void initTestCase() {
// basic QCoreApplication check via QCoreApplication::applicationName
QVERIFY(QCoreApplication::instance() == nullptr || true); // harmless check
}
void test_qstring_format() {
QString fmt = QStringLiteral("%1-%2").arg(42).arg(QStringLiteral("abc"));
QCOMPARE(fmt, QStringLiteral("42-abc"));
}
};
QTEST_MAIN(DataTopicSmokeTest)
#include "ddsDataTopicTests_smoke.moc"
@@ -1,20 +0,0 @@
#include <gtest/gtest.h>
#include "mocks/MockDDS.h"
#include <map>
TEST(FunctionTopicSmokeGTest, Containers) {
std::map<std::string,int> m;
m["one"] = 1;
m["two"] = 2;
EXPECT_EQ(m["two"], 2);
}
TEST(FunctionTopicSmokeGTest, MockDDSTopicAsSignal) {
MockDDS::clear_all();
MockDDS::publish("func/topic", "evt:1");
auto val = MockDDS::take_last("func/topic");
auto payload = val.substr(val.find(':') + 1);
EXPECT_EQ(payload, "evt:1");
auto seq = std::stoul(val.substr(0, val.find(':')));
EXPECT_EQ(seq, 1UL);
}
@@ -1,22 +0,0 @@
#include <QtCore/QObject>
#include <QtTest/QtTest>
class FunctionTopicSmokeTest : public QObject {
Q_OBJECT
private slots:
void test_containers() {
QStringList list;
list << QStringLiteral("a") << QStringLiteral("b") << QStringLiteral("c");
QCOMPARE(list.size(), 3);
QVERIFY(list.contains(QStringLiteral("b")));
}
void test_qmap_basic() {
QMap<QString,int> m;
m[QStringLiteral("one")] = 1;
m[QStringLiteral("two")] = 2;
QCOMPARE(m.value(QStringLiteral("two")), 2);
}
};
QTEST_MAIN(FunctionTopicSmokeTest)
#include "ddsFunctionTopicTests_smoke.moc"
@@ -1,55 +0,0 @@
#include <gtest/gtest.h>
#include "mocks/MockDDS.h"
#include <mutex>
#include <condition_variable>
TEST(GenericSmokeGTest, BasicStringOps) {
std::string s = "MiXeD";
for (auto &c : s) c = (char)std::tolower(c);
EXPECT_EQ(s, "mixed");
}
TEST(GenericSmokeGTest, MockDDSPublishReceive) {
MockDDS::clear_all();
MockDDS::publish("topic1", "payload42");
auto r = MockDDS::take_last("topic1");
// format is "<seq>:<payload>"
auto pos = r.find(':');
ASSERT_NE(pos, std::string::npos);
auto seq = std::stoul(r.substr(0, pos));
auto payload = r.substr(pos + 1);
EXPECT_EQ(payload, "payload42");
EXPECT_EQ(seq, 1UL);
}
TEST(GenericSmokeGTest, MockDDSAsyncDelivery) {
MockDDS::clear_all();
std::mutex mtx;
std::condition_variable cv;
bool received = false;
std::string last;
auto cb = [&](const std::string &payload){
std::lock_guard<std::mutex> lk(mtx);
last = payload;
received = true;
cv.notify_one();
};
auto sub = MockDDS::subscribe("topic-async", cb);
// publish asynchronously with small delay; callback should be invoked
MockDDS::publish_async("topic-async", "async-payload", 20);
std::unique_lock<std::mutex> lk(mtx);
if (!cv.wait_for(lk, std::chrono::seconds(2), [&]{ return received; })) {
// timeout
MockDDS::unsubscribe("topic-async", sub);
FAIL() << "Did not receive async callback in time";
}
MockDDS::unsubscribe("topic-async", sub);
// parse annotation
auto pos = last.find(':');
ASSERT_NE(pos, std::string::npos);
auto payload = last.substr(pos + 1);
EXPECT_EQ(payload, "async-payload");
}
@@ -1,19 +0,0 @@
#include <QtCore/QObject>
#include <QtTest/QtTest>
class GenericSmokeTest : public QObject {
Q_OBJECT
private slots:
void test_string_ops() {
QString s = QString::fromUtf8("mIxEd");
QCOMPARE(s.toLower(), QStringLiteral("mixed"));
}
void test_basic_qvariant() {
QVariant v = QStringLiteral("value");
QVERIFY(v.canConvert<QString>());
QCOMPARE(v.toString(), QStringLiteral("value"));
}
};
QTEST_MAIN(GenericSmokeTest)
#include "ddsGenericDataTests_smoke.moc"
@@ -1,131 +0,0 @@
#include "MockDDS.h"
#include <map>
#include <mutex>
#include <thread>
#include <condition_variable>
namespace MockDDS {
struct TopicState {
std::vector<std::string> queue;
std::map<SubscriptionId, Subscriber> subs;
SubscriptionId next_sub_id{1};
unsigned long seq{0};
};
static std::map<std::string, TopicState> g_topics;
static std::mutex g_mtx;
// Background dispatcher for async publishes
static std::vector<std::tuple<std::string, std::string, unsigned>> g_async_queue;
static std::mutex g_async_mtx;
static std::condition_variable g_async_cv;
static bool g_async_running = false;
static std::thread g_async_thread;
static void async_worker() {
std::unique_lock<std::mutex> lk(g_async_mtx);
while (g_async_running) {
if (g_async_queue.empty()) {
g_async_cv.wait(lk, [] { return !g_async_queue.empty() || !g_async_running; });
if (!g_async_running) break;
}
auto task = g_async_queue.front();
g_async_queue.erase(g_async_queue.begin());
lk.unlock();
auto &topic = std::get<0>(task);
auto &msg = std::get<1>(task);
unsigned delay_ms = std::get<2>(task);
if (delay_ms) std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
// perform synchronous publish semantics for delivered message
{
std::lock_guard<std::mutex> lk2(g_mtx);
auto &ts = g_topics[topic];
ts.seq++;
std::string annotated = std::to_string(ts.seq) + ":" + msg;
ts.queue.push_back(annotated);
for (auto &p : ts.subs) {
auto &cb = p.second;
if (cb) cb(annotated);
}
}
lk.lock();
}
}
static void ensure_async_thread() {
std::lock_guard<std::mutex> lk(g_async_mtx);
if (!g_async_running) {
g_async_running = true;
g_async_thread = std::thread(async_worker);
// detach worker so test binary exit doesn't require join; worker will exit when g_async_running is false
g_async_thread.detach();
}
}
void publish(const std::string &topic, const std::string &msg) {
std::lock_guard<std::mutex> lk(g_mtx);
auto &ts = g_topics[topic];
ts.seq++;
// annotate payload with simple seq metadata for basic QoS checks
std::string annotated = std::to_string(ts.seq) + ":" + msg;
ts.queue.push_back(annotated);
// notify subscribers synchronously
for (auto &p : ts.subs) {
auto &cb = p.second;
if (cb) cb(annotated);
}
}
void publish_async(const std::string &topic, const std::string &msg, unsigned delay_ms) {
ensure_async_thread();
{
std::lock_guard<std::mutex> lk(g_async_mtx);
g_async_queue.emplace_back(topic, msg, delay_ms);
}
g_async_cv.notify_one();
}
MockDDS::SubscriptionId subscribe(const std::string &topic, Subscriber cb) {
std::lock_guard<std::mutex> lk(g_mtx);
auto &ts = g_topics[topic];
SubscriptionId id = ts.next_sub_id++;
ts.subs.emplace(id, std::move(cb));
return id;
}
void unsubscribe(const std::string &topic, SubscriptionId id) {
std::lock_guard<std::mutex> lk(g_mtx);
auto it = g_topics.find(topic);
if (it == g_topics.end()) return;
it->second.subs.erase(id);
}
std::string take_last(const std::string &topic) {
std::lock_guard<std::mutex> lk(g_mtx);
auto it = g_topics.find(topic);
if (it == g_topics.end() || it->second.queue.empty()) return std::string();
return it->second.queue.back();
}
std::vector<std::string> get_queue(const std::string &topic) {
std::lock_guard<std::mutex> lk(g_mtx);
auto it = g_topics.find(topic);
if (it == g_topics.end()) return {};
return it->second.queue;
}
void clear_all() {
{
std::lock_guard<std::mutex> lk(g_mtx);
g_topics.clear();
}
// clear pending async queue; do not join detached worker
{
std::lock_guard<std::mutex> lk(g_async_mtx);
g_async_queue.clear();
}
g_async_cv.notify_all();
}
} // namespace MockDDS
@@ -1,29 +0,0 @@
#pragma once
#include <string>
#include <functional>
#include <vector>
#include <chrono>
namespace MockDDS {
// Richer mock for migration smoke-tests:
// - publish(topic, payload) : synchronous publish
// - publish_async(topic, payload, delay_ms) : asynchronous publish (background dispatcher)
// - subscribe(topic, callback) -> subscription id
// - unsubscribe(topic, subscription id)
// - take_last(topic), get_queue(topic)
// - clear_all()
// - sequence numbers per topic (integer appended to payload meta)
using Subscriber = std::function<void(const std::string &payload)>;
using SubscriptionId = unsigned long;
void publish(const std::string &topic, const std::string &msg);
void publish_async(const std::string &topic, const std::string &msg, unsigned delay_ms = 0);
SubscriptionId subscribe(const std::string &topic, Subscriber cb);
void unsubscribe(const std::string &topic, SubscriptionId id);
std::string take_last(const std::string &topic);
std::vector<std::string> get_queue(const std::string &topic);
void clear_all();
}
@@ -1,45 +0,0 @@
DDS Definitions
=========================================================================
Abbr | Full name
-------------------------------------------------------------------------
IDL | Interface Definition Language
-------------------------------------------------------------------------
DR | DataReader
DW | DataWriter
-------------------------------------------------------------------------
DDR | DynamicDataReader
DDW | DynamicDataWriter
-------------------------------------------------------------------------
DRO | DataReaderObject
DWO | DataWriterObject
-------------------------------------------------------------------------
DDRO | DynamicDataReaderObject
DDWO | DynamicDataWriterObject
-------------------------------------------------------------------------
Static (defined in idl)
-------------------------------------------------------------------------
DTC | DataTopicClient
DTS | DataTopicServer
-------------------------------------------------------------------------
FTC | FunctionTopicClient
FTS | FunctionTopicServer
-------------------------------------------------------------------------
Dynamic (Topic will be defined in source code)
-------------------------------------------------------------------------
DDTC | DynamicDataTopicClient
DDTS | DynamicDataTopicServer
-------------------------------------------------------------------------
DFTC | DynamicFunctionTopicClient
DFTS | DynamicFunctionTopicServer
-------------------------------------------------------------------------
Tool to publish & subscribe (to) data
-------------------------------------------------------------------------
DTCR | DataTopicContentReceiver
DTCG | DataTopicContentGenerator
-------------------------------------------------------------------------
@@ -1,18 +0,0 @@
#
# $Id$
# $HeadURL$
# $Author$
#
IF(BUILD_RTI)
ADD_INTERFACE_LIBRARY(
routing_plugin
${CMAKE_CURRENT_SOURCE_DIR}/routing_plugin.h
${CMAKE_CURRENT_SOURCE_DIR}/../..
ddsgen
ddsQoS
NGLLogger
)
ENDIF(BUILD_RTI)
@@ -1,433 +0,0 @@
#include <DDS/Generic/generic_base.h>
#include <DDS/QosProfile/DDS_DefaultQos.h>
#include <NGLLogger/INGLLogger.h>
#if BUILD_RTI
#include <dds/pub/DataWriter.hpp>
#include <dds/pub/discovery.hpp>
#include <dds/sub/DataReader.hpp>
#include <dds/sub/DataReaderListener.hpp>
#include <dds/topic/Topic.hpp>
#include <dds/topic/find.hpp>
namespace DebugInfo
{
static inline QByteArray toReadable(const rti::core::Guid& guid)
{
return QByteArray(reinterpret_cast<const char*>(&guid[0]), 16).toHex();
}
static inline QByteArray toReadable(const rti::core::SequenceNumber& seqNo, const rti::core::Guid& guid)
{
return "SeqNo: " + QString::number(seqNo.value()).toLatin1() + ", Guid-DW: " + toReadable(guid);
}
static inline QByteArray toReadable(const rti::core::SampleIdentity& identiy)
{
return toReadable(identiy.sequence_number(), identiy.writer_guid());
}
} // namespace DebugInfo
namespace FTS
{
template <typename GENERIC_FTS> struct TopicNames;
}
namespace FTC
{
template <typename GENERIC_FTC> struct TopicNames;
}
namespace RoutingService
{
template <typename T>
static dds::topic::Topic<T> getTopic(const dds::domain::DomainParticipant& participant, const std::string& topicName)
{
using DataTopic = dds::topic::Topic<T>;
auto ret = dds::topic::find<DataTopic>(participant, topicName);
if (ret != nullptr)
return ret;
return DataTopic(participant, topicName);
}
class SampleWriterInterface
{
public:
SampleWriterInterface() = default;
virtual ~SampleWriterInterface() = default;
virtual void writeSamples() = 0;
virtual NGL::INGLLogger& logger() = 0;
};
class DataWriterTaskInterface
{
public:
DataWriterTaskInterface() = default;
virtual ~DataWriterTaskInterface() = default;
virtual void enqueue(SampleWriterInterface* swi) = 0;
};
class TopicDispatcherInterface
{
public:
TopicDispatcherInterface() = default;
virtual ~TopicDispatcherInterface() = default;
virtual bool init(DataWriterTaskInterface* dwt, const dds::domain::DomainParticipant& dpIn,
const dds::sub::Subscriber& subIn, const dds::domain::DomainParticipant& dpOut,
const dds::pub::Publisher& pubOut) = 0;
virtual void shutdown() = 0;
};
template <typename TOPIC> class SampleWriter final : public SampleWriterInterface
{
public:
SampleWriter(dds::sub::LoanedSamples<TOPIC>&& samples, const dds::pub::DataWriter<TOPIC>& dataWriter,
bool bWithOriginalIdentity, NGL::INGLLogger& logger)
: m_loanedSamples(std::move(samples)), m_dataWriter(dataWriter), m_bWithOriginalIdentity(bWithOriginalIdentity),
m_logger(logger)
{
}
rti::core::SampleIdentity getIdentity(const rti::core::SampleIdentity& identity) const
{
static const auto s_unknownSequenceNumber(rti::core::SequenceNumber::unknown());
static const auto s_unknownGui(rti::core::Guid::unknown());
static const auto s_unknownSampleIdentity(rti::core::SampleIdentity::unknown());
if (!m_bWithOriginalIdentity)
return s_unknownSampleIdentity;
if (identity.sequence_number() == s_unknownSequenceNumber)
return s_unknownSampleIdentity;
if (identity.writer_guid() == s_unknownGui)
return s_unknownSampleIdentity;
return identity;
}
void writeSamples() override
{
TRACE_LOG(m_logger) << "Writing samples for " << DDS::topic_type_name<TOPIC>::value()
<< ", sample count: " << m_loanedSamples.length();
rti::pub::WriteParams writeParams;
for (const auto& sample : m_loanedSamples)
{
try
{
writeParams.identity(getIdentity(sample.info()->original_publication_virtual_sample_identity()));
writeParams.related_sample_identity(
getIdentity(sample.info()->related_original_publication_virtual_sample_identity()));
writeParams.handle(sample.info().instance_handle());
writeParams.flag(sample.info()->flag());
TRACE_LOG(m_logger) << "identity: " << DebugInfo::toReadable(writeParams.identity())
<< ", related_sample_identity: "
<< DebugInfo::toReadable(writeParams.related_sample_identity());
const auto& state = sample.info().state();
const dds::sub::status::InstanceState& instanceState = state.instance_state();
if (instanceState == dds::sub::status::InstanceState::alive())
{
m_dataWriter->write(sample.data(), writeParams);
}
else if (instanceState == dds::sub::status::InstanceState::not_alive_disposed())
{
TRACE_LOG(m_logger) << " - is disposed";
m_dataWriter->dispose_instance(writeParams);
}
else if (instanceState == dds::sub::status::InstanceState::not_alive_no_writers())
{
TRACE_LOG(m_logger) << " - is unregistered";
m_dataWriter->unregister_instance(writeParams);
}
else
WARNING_LOG(m_logger) << "Unknown instance state: " << instanceState;
}
catch (const dds::core::Exception& ex)
{
ERROR_LOG(m_logger) << "writeSamples exception: " << ex.what();
}
}
m_dataWriter->flush();
}
NGL::INGLLogger& logger() override
{
return m_logger;
}
private:
dds::sub::LoanedSamples<TOPIC> m_loanedSamples;
dds::pub::DataWriter<TOPIC> m_dataWriter;
bool m_bWithOriginalIdentity;
NGL::INGLLogger& m_logger;
};
template <typename T> class DataTopicListener final : public dds::sub::DataReaderListener<T>
{
public:
using DataReader = dds::sub::DataReader<T>;
DataTopicListener(DataWriterTaskInterface* dwt, const std::string& topicName, DDS::QosProfile::TopicType topicType,
NGL::INGLLogger& logger)
: m_dwt(dwt), m_dataWriter(nullptr), m_topicName(topicName), m_topicType(topicType), m_logger(logger)
{
}
bool init(const dds::domain::DomainParticipant& dpOut, const dds::pub::Publisher& pubOut)
{
if (!m_dwt)
return false;
DEBUG_LOG(m_logger) << "Creating DataWriter for domain " << dpOut.domain_id();
m_dataWriter = dds::pub::DataWriter<T>(pubOut, getTopic<T>(dpOut, m_topicName),
DDS::QosProfile::dataWriterDefault(m_topicType));
dds::domain::DomainParticipant& dpOutNonConst = const_cast<dds::domain::DomainParticipant&>(dpOut);
dds::pub::ignore(dpOutNonConst, m_dataWriter.instance_handle());
return true;
}
void on_data_available(dds::sub::DataReader<T>& reader) override
{
TRACE_LOG(m_logger) << "Data available for " << DDS::topic_type_name<T>::value();
auto ws = new SampleWriter<T>(reader.take(), m_dataWriter,
m_topicType == DDS::QosProfile::TopicType::FunctionTopic, m_logger);
m_dwt->enqueue(ws);
}
void on_requested_deadline_missed(dds::sub::DataReader<T>&,
const dds::core::status::RequestedDeadlineMissedStatus&) override
{
}
void on_requested_incompatible_qos(dds::sub::DataReader<T>&,
const dds::core::status::RequestedIncompatibleQosStatus&) override
{
}
void on_sample_rejected(dds::sub::DataReader<T>&, const dds::core::status::SampleRejectedStatus&) override {}
void on_liveliness_changed(dds::sub::DataReader<T>&, const dds::core::status::LivelinessChangedStatus&) override {}
void on_subscription_matched(dds::sub::DataReader<T>&, const dds::core::status::SubscriptionMatchedStatus&) override
{
}
void on_sample_lost(dds::sub::DataReader<T>&, const dds::core::status::SampleLostStatus&) override {}
static dds::core::status::StatusMask mask()
{
return (dds::core::status::StatusMask::data_available());
}
protected:
DataWriterTaskInterface* m_dwt;
dds::pub::DataWriter<T> m_dataWriter;
std::string m_topicName;
DDS::QosProfile::TopicType m_topicType;
NGL::INGLLogger& m_logger;
};
template <typename TOPIC> class TopicDispatcher : public TopicDispatcherInterface
{
protected:
explicit TopicDispatcher(NGL::INGLLogger& logger, const std::string& topicName,
DDS::QosProfile::TopicType topicType)
: m_dataReader(nullptr), m_topicName(topicName), m_topicType(topicType), m_logger(logger)
{
}
~TopicDispatcher()
{
shutdown();
}
bool init(DataWriterTaskInterface* dwt, const dds::domain::DomainParticipant& dpIn,
const dds::sub::Subscriber& subIn, const dds::domain::DomainParticipant& dpOut,
const dds::pub::Publisher& pubOut) override
{
DEBUG_LOG(m_logger) << "Initializing TopicDispatcher " << "(" << this << ")";
if (m_dataReader != nullptr)
return false;
m_dataReader = dds::sub::DataReader<TOPIC>(subIn, getTopic<TOPIC>(dpIn, m_topicName),
DDS::QosProfile::dataReaderDefault(m_topicType));
DEBUG_LOG(m_logger) << "Creating DataReader for domain " << dpIn.domain_id()
<< ", ptr: " << m_dataReader.delegate().get();
m_dtl.reset(new DataTopicListener<TOPIC>(dwt, m_topicName, m_topicType, m_logger));
if (!m_dtl->init(dpOut, pubOut))
return false;
m_dataReader.listener(m_dtl.get(), DataTopicListener<TOPIC>::mask());
return true;
}
void shutdown() override
{
DEBUG_LOG(m_logger) << "Cleaning up TopicDispatcher " << "(" << this << ")";
if (m_dataReader != nullptr)
{
DEBUG_LOG(m_logger) << "shutting down DataReader: " << m_dataReader.delegate().get();
m_dataReader.listener(nullptr, dds::core::status::StatusMask::none());
try
{
m_dataReader.close();
}
catch (const dds::core::Exception& ex)
{
ERROR_LOG(m_logger) << "topic close ex: " << ex.what();
}
}
m_dtl = nullptr;
m_dataReader = nullptr;
}
private:
dds::sub::DataReader<TOPIC> m_dataReader;
std::unique_ptr<DataTopicListener<TOPIC>> m_dtl;
std::string m_topicName;
DDS::QosProfile::TopicType m_topicType;
NGL::INGLLogger& m_logger;
};
template <typename TOPIC> class DataTopicDispatcher final : public TopicDispatcher<TOPIC>
{
public:
explicit DataTopicDispatcher(NGL::INGLLogger& logger)
: TopicDispatcher<TOPIC>(logger, DDS::Helper::getShortTopicName(dds::topic::topic_type_name<TOPIC>::value()),
DDS::QosProfile::TopicType::DataTopic)
{
}
};
template <typename FTS_TOPIC>
class FunctionTopicReplyDispatcher final : public TopicDispatcher<typename FTS_TOPIC::ReplyTopic>
{
public:
explicit FunctionTopicReplyDispatcher(NGL::INGLLogger& logger)
: TopicDispatcher<typename FTS_TOPIC::ReplyTopic>(logger, FTS::TopicNames<FTS_TOPIC>::replyTopicName(),
DDS::QosProfile::TopicType::FunctionTopic)
{
}
};
template <typename FTC_TOPIC>
class FunctionTopicRequestDispatcher final : public TopicDispatcher<typename FTC_TOPIC::RequestTopic>
{
public:
explicit FunctionTopicRequestDispatcher(NGL::INGLLogger& logger)
: TopicDispatcher<typename FTC_TOPIC::RequestTopic>(logger, FTC::TopicNames<FTC_TOPIC>::requestTopicName(),
DDS::QosProfile::TopicType::FunctionTopic)
{
}
};
} // namespace RoutingService
#else // BUILD_RTI=OFF - Stub declarations
namespace RoutingService
{
// Stub interfaces when BUILD_RTI=OFF
class SampleWriterInterface
{
public:
SampleWriterInterface() = default;
virtual ~SampleWriterInterface() = default;
virtual void writeSamples() = 0;
virtual NGL::INGLLogger& logger() = 0;
};
class DataWriterTaskInterface
{
public:
DataWriterTaskInterface() = default;
virtual ~DataWriterTaskInterface() = default;
virtual void enqueue(SampleWriterInterface* /*swi*/) = 0;
};
class TopicDispatcherInterface
{
public:
TopicDispatcherInterface() = default;
virtual ~TopicDispatcherInterface() = default;
virtual bool init(DataWriterTaskInterface* /*dwt*/, void* /*dpIn*/, void* /*subIn*/, void* /*dpOut*/,
void* /*pubOut*/) = 0;
virtual void shutdown() = 0;
};
// Stub template classes when BUILD_RTI=OFF
template <typename TOPIC> class SampleWriter final : public SampleWriterInterface
{
public:
SampleWriter(void* /*samples*/, void* /*dataWriter*/, bool /*bWithOriginalIdentity*/, NGL::INGLLogger& /*logger*/)
{
}
void writeSamples() override {}
NGL::INGLLogger& logger() override
{
static NGL::INGLLogger dummyLogger;
return dummyLogger;
}
private:
NGL::INGLLogger& m_logger;
};
template <typename TOPIC> class TopicDispatcher : public TopicDispatcherInterface
{
protected:
explicit TopicDispatcher(NGL::INGLLogger& /*logger*/, const std::string& /*topicName*/, int /*topicType*/) {}
~TopicDispatcher() { shutdown(); }
bool init(DataWriterTaskInterface* /*dwt*/, void* /*dpIn*/, void* /*subIn*/, void* /*dpOut*/,
void* /*pubOut*/) override
{
return false;
}
void shutdown() override {}
private:
NGL::INGLLogger& m_logger;
};
template <typename TOPIC> class DataTopicDispatcher final : public TopicDispatcher<TOPIC>
{
public:
explicit DataTopicDispatcher(NGL::INGLLogger& logger) : TopicDispatcher<TOPIC>(logger, "", 0) {}
};
template <typename FTS_TOPIC>
class FunctionTopicReplyDispatcher final : public TopicDispatcher<typename FTS_TOPIC::ReplyTopic>
{
public:
explicit FunctionTopicReplyDispatcher(NGL::INGLLogger& logger)
: TopicDispatcher<typename FTS_TOPIC::ReplyTopic>(logger, "", 0)
{
}
};
template <typename FTC_TOPIC>
class FunctionTopicRequestDispatcher final : public TopicDispatcher<typename FTC_TOPIC::RequestTopic>
{
public:
explicit FunctionTopicRequestDispatcher(NGL::INGLLogger& logger)
: TopicDispatcher<typename FTC_TOPIC::RequestTopic>(logger, "", 0)
{
}
};
} // namespace RoutingService
#endif // BUILD_RTI