Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

@@ -0,0 +1,428 @@
/**
* AES Function Topic Client test executable
* $Id$
* $HeadURL$
* $Author$
*/
#include "aes_test_explosion_area.h"
#include <QCoreApplication>
#include <QTimer>
#include <QTest>
namespace AreaEffectSimulation
{
// must be in pdm.pdm_charge_type
static const int s_ChargeTypeId1 = 371;
static const int s_ChargeTypeId2 = 372;
TestExplosionArea::TestExplosionArea(QObject *parent)
: TestBase("Test.ExplosionArea", parent)
{}
bool TestExplosionArea::init(int domainId, int exerciseId, int testId)
{
if (!TestBase::init(domainId, exerciseId, testId))
return false;
m_dtc->waitForHistoricalDataExplosionArea();
m_eaData.id(-1);
connect(m_dtc.get(), &AreaEffectSimulation::Interface::Dtc::explosionAreaChanged,
this, &TestExplosionArea::explosionAreaChanged);
connect(m_dtc.get(), &AreaEffectSimulation::Interface::Dtc::triggeredImpactsChanged,
this, &TestExplosionArea::triggeredImpactsChanged);
return true;
}
bool TestExplosionArea::checkBaseData(const AreaEffectSimulation::ExplosionArea &a,
const AreaEffectSimulation::ExplosionArea &b) const
{
if (!checkAesItem(a, b))
return false;
if (a.area() != b.area())
{
WARNING_LOG(m_logger) << "area does not match: " << a.area() << " - " << b.area();
return false;
}
if (a.cannonCount() != b.cannonCount())
{
WARNING_LOG(m_logger) << "cannonCount does not match: " << a.cannonCount() << " - " << b.cannonCount();
return false;
}
if (a.cannonRounds() != b.cannonRounds())
{
WARNING_LOG(m_logger) << "cannonCount does not match: " << a.cannonCount() << " - " << b.cannonCount();
return false;
}
return true;
}
void TestExplosionArea::tryCreateExplosionArea()
{
INFO_LOG(m_logger) << "tryCreateExplosionArea start";
m_eaData = AreaEffectSimulation::ExplosionArea();
AreaEffectSimulation::ExplosionArea eaData;
eaData.id(0);
eaData.name("af1");
eaData.effectStart((time(nullptr) + 4) * 1000); // msec
eaData.effectDuration(10000); // 10 seconds
eaData.chargeStruct().chargeTypeId(345863487);
eaData.area(AreaEffectSimulation::Area(Core::GeoPosition2D(0.16, 0.92), 50, 60, 70));
eaData.partyId(2);
eaData.participantId(1234);
eaData.cannonCount(1);
eaData.cannonRounds(2);
eaData.externalId(2);
INFO_LOG(m_logger) << "trying to send explosionAreaCreateRequest()";
m_replyError = false;
m_bExpectedFailure = true;
m_bIsCreatedRequest = true;
if (!m_ftc->explosionAreaModifyRequest(
ExplosionAreaModifyRequest(
0,
eaData.name(),
eaData.effectStart(),
eaData.effectDuration(),
eaData.effectSourceId(),
eaData.chargeStruct().chargeTypeId(),
eaData.area(),
eaData.partyId(),
eaData.participantId(),
eaData.cannonCount(),
eaData.cannonRounds(),
eaData.fireRequestTime(),
eaData.altitude(),
eaData.purpose(),
eaData.effectMarkingInTa(),
eaData.externalId()
),
this))
{
ERROR_LOG(m_logger) << "Error during explosionAreaCreateRequest()";
failExit();
return;
}
// since the chargeTypeId is not valid, we should get an error
if (!waitForData([this]() { return m_replyError == true; }))
{
ERROR_LOG(m_logger) << "Error creating area explosion object (try with error)";
failExit();
return;
}
// now with correct charge type
m_bExpectedFailure = false;
m_expectedAesId = -1;
eaData.chargeStruct().chargeTypeId(s_ChargeTypeId1);
m_bIsCreatedRequest = true;
if (!m_ftc->explosionAreaModifyRequest(
ExplosionAreaModifyRequest(
0,
eaData.name(),
eaData.effectStart(),
eaData.effectDuration(),
eaData.effectSourceId(),
eaData.chargeStruct().chargeTypeId(),
eaData.area(),
eaData.partyId(),
eaData.participantId(),
eaData.cannonCount(),
eaData.cannonRounds(),
eaData.fireRequestTime(),
eaData.altitude(),
eaData.purpose(),
eaData.effectMarkingInTa(),
eaData.externalId()),
this))
{
ERROR_LOG(m_logger) << "Error during explosionAreaCreateRequest()";
failExit();
return;
}
if (!waitForData([this]() { return m_eaData.id() == m_expectedAesId; }))
{
ERROR_LOG(m_logger) << "Error creating area explosion object";
failExit();
return;
}
if (!checkBaseData(m_eaData, eaData))
{
ERROR_LOG(m_logger) << "Creation data does not match published data";
failExit();
return;
}
QTimer::singleShot(0, this, &TestExplosionArea::tryModifyExplosionArea);
INFO_LOG(m_logger) << "tryCreateExplosionArea successful";
}
void TestExplosionArea::tryModifyExplosionArea()
{
INFO_LOG(m_logger) << "tryModifyExplosionArea start";
m_eaData.name("af2");
m_eaData.effectStart(m_eaData.effectStart().get() + 3000);
m_eaData.effectDuration(9000); // 9 sec
m_eaData.chargeStruct().chargeTypeId(s_ChargeTypeId2);
m_eaData.area(AreaEffectSimulation::Area(Core::GeoPosition2D(0.165, 0.921), 50, 60, 70));
m_eaData.partyId(3);
m_eaData.participantId(1235);
m_eaData.cannonCount(2);
m_eaData.cannonRounds(2);
m_eaData.effectMarkingInTa(true);
const AreaEffectSimulation::ExplosionArea eaData(m_eaData);
m_eaData = AreaEffectSimulation::ExplosionArea();
m_eaData.id(eaData.id());
m_bIsCreatedRequest = false;
if (!m_ftc->explosionAreaModifyRequest(
ExplosionAreaModifyRequest(
eaData.id(),
eaData.name(),
eaData.effectStart(),
eaData.effectDuration(),
eaData.effectSourceId(),
eaData.chargeStruct().chargeTypeId(),
eaData.area(),
eaData.partyId(),
eaData.participantId(),
eaData.cannonCount(),
eaData.cannonRounds(),
eaData.fireRequestTime(),
eaData.altitude(),
eaData.purpose(),
eaData.effectMarkingInTa(),
eaData.externalId()),
this))
{
ERROR_LOG(m_logger) << "Error requesting modify data";
failExit();
return;
}
if (!waitForData([this]() { return m_eaData.chargeStruct().chargeTypeId() == s_ChargeTypeId2; }))
{
ERROR_LOG(m_logger) << "Error updating area explosion object";
failExit();
return;
}
if (!checkBaseData(m_eaData, eaData))
{
ERROR_LOG(m_logger) << "Modify data does not match published data";
failExit();
return;
}
QTimer::singleShot(0, this, &TestExplosionArea::tryWaitForActivationExplosionArea);
INFO_LOG(m_logger) << "tryModifyExplosionArea successful";
}
void TestExplosionArea::tryWaitForActivationExplosionArea()
{
INFO_LOG(m_logger) << "tryWaitForActivationExplosionArea start";
if (!waitForData([this]() { return m_eaData.effectStateId() == AreaEffectSimulation::AesEffectState::EsActivated; }))
{
DEBUG_LOG(m_logger) << "Effect State = " << m_eaData.effectStateId();
ERROR_LOG(m_logger) << "Error while waiting for activation of area explosion";
failExit();
return;
}
QTimer::singleShot(0, this, &TestExplosionArea::tryPauseResumeExplosionArea);
INFO_LOG(m_logger) << "tryWaitForActivationExplosionArea end";
}
void TestExplosionArea::tryPauseResumeExplosionArea()
{
INFO_LOG(m_logger) << "tryPauseResumeExplosionArea start";
// try to resume but is already active -> expected error
m_replyError = false;
m_bExpectedFailure = true;
if (!m_ftc->explosionAreaPauseResumeRequest(
ExplosionAreaPauseResumeRequest(
m_eaData.id(),
true,
dds::core::optional<rti::core::int64>(),
dds::core::optional<int32_t>(),
dds::core::optional<int32_t>()),
this))
{
ERROR_LOG(m_logger) << "Error calling explosionAreaPauseResumeRequest(true)";
failExit();
return;
}
if (!waitForData([this]() { return m_replyError == true; }))
{
ERROR_LOG(m_logger) << "Error waiting for reply error while switching to pause of area explosion";
failExit();
return;
}
// and now pause
m_bExpectedFailure = false;
if (!m_ftc->explosionAreaPauseResumeRequest(
ExplosionAreaPauseResumeRequest(
m_eaData.id(),
false,
dds::core::optional<rti::core::int64>(),
dds::core::optional<int32_t>(),
dds::core::optional<int32_t>()),
this))
{
ERROR_LOG(m_logger) << "Error calling explosionAreaPauseResumeRequest(false)";
failExit();
return;
}
if (!waitForData([this]() { return m_eaData.effectStateId() == AreaEffectSimulation::AesEffectState::EsPaused; }))
{
ERROR_LOG(m_logger) << "Error while waiting for pause of area explosion";
failExit();
return;
}
// pause again -> expected error
m_replyError = false;
m_bExpectedFailure = true;
if (!m_ftc->explosionAreaPauseResumeRequest(
ExplosionAreaPauseResumeRequest(
m_eaData.id(),
false,
dds::core::optional<rti::core::int64>(),
dds::core::optional<int32_t>(),
dds::core::optional<int32_t>()),
this))
{
ERROR_LOG(m_logger) << "Error calling explosionAreaPauseResumeRequest(false)";
failExit();
return;
}
if (!waitForData([this]() { return m_replyError == true; }))
{
ERROR_LOG(m_logger) << "Error creating single explosion object (try with error)";
failExit();
return;
}
// and resume execution
m_bExpectedFailure = false;
if (!m_ftc->explosionAreaPauseResumeRequest(
ExplosionAreaPauseResumeRequest(
m_eaData.id(),
true,
dds::core::optional<rti::core::int64>(),
dds::core::optional<int32_t>(),
dds::core::optional<int32_t>()),
this))
{
ERROR_LOG(m_logger) << "Error calling explosionAreaPauseResumeRequest(true)";
failExit();
return;
}
if (!waitForData([this]() { return m_eaData.effectStateId() == AreaEffectSimulation::AesEffectState::EsActivated; }))
{
ERROR_LOG(m_logger) << "Error while waiting for activation of area explosion";
failExit();
return;
}
INFO_LOG(m_logger) << "tryPauseResumeExplosionArea end";
QTimer::singleShot(0, this, &TestExplosionArea::checkTriggeredExplosions);
}
void TestExplosionArea::checkTriggeredExplosions()
{
INFO_LOG(m_logger) << "checkTriggeredExplosions start";
// first we should wait for Activation
if (!waitForData([this]() { return m_eaData.effectStateId() == AreaEffectSimulation::AesEffectState::EsActivated; }))
{
ERROR_LOG(m_logger) << "Error while waiting for activation of area explosion";
failExit();
return;
}
// attn: msb is bit 7
checkTriggeredExplosionsHelper(0x70); // 0b01110000
checkTriggeredExplosionsHelper(0x30); // 0b00110000
checkTriggeredExplosionsHelper(0x10); // 0b00010000
checkTriggeredExplosionsHelper(0x00); // 0b00000000
// last step: wait for expiry
if (!waitForData([this]() { return m_eaData.effectStateId() == AreaEffectSimulation::AesEffectState::EsExpired; }))
{
ERROR_LOG(m_logger) << "Error while waiting for expiring of area explosion";
failExit();
return;
}
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
INFO_LOG(m_logger) << "checkTriggeredExplosions end";
}
void TestExplosionArea::checkTriggeredExplosionsHelper(int bitfield)
{
// since we've 9 seconds duration and the first hit is at 0, every 2.5sec should be a new TriggeredExplosions telegram
QElapsedTimer et;
et.start();
if (!waitForData([this, bitfield]() { return m_tiData.bitfield()[0] == bitfield; }))
{
ERROR_LOG(m_logger) << "Error while waiting for triggered explosison telegram with bitfield 0x" << QByteArray::number(bitfield, 16);
failExit();
return;
}
// 500ms delay through dds allowed :)
if (et.elapsed() > 3000)
{
ERROR_LOG(m_logger) << "Something went wrong - waited more than 3 seconds for next impact trigger";
failExit();
}
}
void TestExplosionArea::explosionAreaChanged(const AreaEffectSimulation::ExplosionArea &data, DataModification modType)
{
if (m_eaData.id() == -1)
return;
onAesChanged(data, modType, m_eaData);
}
void TestExplosionArea::triggeredImpactsChanged(const AreaEffectSimulation::TriggeredImpacts &data, DataModification modType)
{
if (m_eaData.id() != data.aesItemId() || modType == DataModification::eRemoved)
return;
INFO_LOG(m_logger) << "Got TriggeredImpacts data - bitfield[0] = 0x" << QByteArray::number(static_cast<int>(data.bitfield()[0]), 16);
m_tiData = data;
}
void TestExplosionArea::onExplosionAreaModifyReply(const Core::FunctionReplyObject &replyObject)
{
if (m_bIsCreatedRequest)
onAesCreateReply(replyObject);
else
onAesModifyReply(replyObject);
}
void TestExplosionArea::onExplosionAreaPauseResumeReply(const Core::FunctionReplyObject &replyObject)
{
INFO_LOG(m_logger) << "Got pause/resume reply explosion area with id " << replyObject.id()
<< ", error = " << replyObject.error()
<< " and errorString = '" << replyObject.translated() << "'";
m_replyError = replyObject.error();
if (m_replyError && !m_bExpectedFailure)
ERROR_LOG(m_logger) << "Got pause/resume reply explosion area error: " << replyObject();
}
} // namespace AreaEffectSimulation
// ------------------------------------------------------------------
int main(int argc, char **argv)
{
return AreaEffectSimulation::mainBase(argc, argv, []() { return new AreaEffectSimulation::TestExplosionArea; });
}