/** * AES Function Topic Client test executable * $Id$ * $HeadURL$ * $Author$ */ #include "aes_test_explosion_area.h" #include #include #include 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(), dds::core::optional(), dds::core::optional()), 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(), dds::core::optional(), dds::core::optional()), 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(), dds::core::optional(), dds::core::optional()), 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(), dds::core::optional(), dds::core::optional()), 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(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; }); }