Files
qt-migration-legatus/qt6-after/qt6-migrated-legatus/TetraIF/unit-test/coprtcnv_unit_test.cpp
T
berrux-dev cebc456bc1 Add unit tests for the TetraIF modules in a unit-test folder
New TetraIF/unit-test/ directory with one QtTest executable per
TetraIF release-scope module, wired into ctest and the DEB pipeline:

- coprtcnv_unit_test: central and radio telegram header fields,
  payload access, length checks, fragmentation/reassembly roundtrip,
  telegram-id string helpers
- logview_unit_test: IntegerCalculator arithmetic, operator priority,
  parentheses, error codes and variables (compiles the LogView class
  source directly; the class otherwise lives in the LogView
  executable)
- prtcnv_unit_test: PrtCnvMember state and fragmented-telegram
  handling (compiles the class source directly because PrtCnvLib is
  built with hidden visibility)

TetraIF/CMakeLists.txt adds the unit-test subdirectory and
new_docker_build.sh builds and ctest-runs the three new targets.
2026-10-14 16:28:03 +02:00

176 lines
6.0 KiB
C++

//
// Unit tests for the CoPrtCnv module: central telegram, radio telegram
// (header fields, payload access, fragmentation) and the string helpers.
//
#include <CoPrtCnv/CoPrtCnvCentralTelegram.hpp>
#include <CoPrtCnv/CoPrtCnvHexDumpHelper.hpp>
#include <CoPrtCnv/CoPrtCnvLogHeader.hpp>
#include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp>
#include <CoPrtCnv/tetra_telegram_ids.h>
#include <TrainingAreaBase/training_area_telegrams.h>
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <QtCore/QByteArray>
#include <QtTest/QTest>
#include <memory>
#include <vector>
class coprtcnv_unit_test : public QObject
{
Q_OBJECT
private slots:
void initTestCase();
void centralTelegramFromId();
void centralTelegramDataRoundtrip();
void centralTelegramCounter();
void radioTelegramSourceIssi();
void radioTelegramDestIssi();
void radioTelegramIdentity();
void radioTelegramCounter();
void radioTelegramPayloadBytes();
void radioTelegramLengthChecks();
void radioTelegramFragmentationRoundtrip();
void radioTelegramLoginVsNormal();
void telegramIdToString();
void wirkfeldTypToString();
};
void coprtcnv_unit_test::initTestCase()
{
NGL::NGLLoggerBootstrap::createNGLRootLogger("log4cxx.props", false);
}
void coprtcnv_unit_test::centralTelegramFromId()
{
N_CoPrtCnv::CoPrtCnvCentralTelegram tele(TrainingAreaBase::TetraIcd::BESTAETIGUNG);
QCOMPARE(tele.telegramId(), TrainingAreaBase::TetraIcd::BESTAETIGUNG);
}
void coprtcnv_unit_test::centralTelegramDataRoundtrip()
{
N_CoPrtCnv::CoPrtCnvCentralTelegram tele(TrainingAreaBase::TetraIcd::BESTAETIGUNG);
const QByteArray data(QByteArrayLiteral("central-telegram-payload"));
tele.setData(data);
QCOMPARE(tele.data(), data);
}
void coprtcnv_unit_test::centralTelegramCounter()
{
N_CoPrtCnv::CoPrtCnvCentralTelegram tele(TrainingAreaBase::TetraIcd::BESTAETIGUNG);
tele.setCounter(42);
QCOMPARE(tele.counter(), 42);
}
void coprtcnv_unit_test::radioTelegramSourceIssi()
{
N_CoPrtCnv::CoPrtCnvRadioTelegram tele(0x12345678);
QCOMPARE(tele.getSrcISSI(), 0x12345678u);
}
void coprtcnv_unit_test::radioTelegramDestIssi()
{
N_CoPrtCnv::CoPrtCnvRadioTelegram tele(0x00000001);
tele.setDestISSI(0x87654321);
QCOMPARE(tele.getDestISSI(), 0x87654321u);
}
void coprtcnv_unit_test::radioTelegramIdentity()
{
// Identity is only a field of the DataIndReq payload (the (id, size, identity) constructor); other PDU types have no identity area.
N_CoPrtCnv::CoPrtCnvRadioTelegram tele(GEF_BESTAETIGUNG, 32, 0xBEEF);
QCOMPARE(tele.getIdentity(), 0xBEEF);
}
void coprtcnv_unit_test::radioTelegramCounter()
{
N_CoPrtCnv::CoPrtCnvRadioTelegram tele(0x00000003);
tele.setZaehler(7);
QCOMPARE(tele.zaehler(), 7);
}
void coprtcnv_unit_test::radioTelegramPayloadBytes()
{
N_CoPrtCnv::CoPrtCnvRadioTelegram tele(GEF_BESTAETIGUNG, 32, 0x3333);
QCOMPARE(tele.getPayloadSize(), 32);
const uint8_t pattern[4] = {0xDE, 0xAD, 0xBE, 0xEF};
tele.setPayloadData(pattern, 4);
QCOMPARE(tele.getPayloadDataUInt8(3), 0xDE);
QCOMPARE(tele.getPayloadDataUInt8(4), 0xAD);
QCOMPARE(tele.getPayloadDataUInt8(5), 0xBE);
QCOMPARE(tele.getPayloadDataUInt8(6), 0xEF);
// getPayloadDataUInt32 assembles the bytes big endian
QCOMPARE(tele.getPayloadDataUInt32(3, 4), 0xDEADBEEFu);
}
void coprtcnv_unit_test::radioTelegramLengthChecks()
{
// isTelegramLengthOk: length <= MAX_RADIO_TELEGRAM_PAYLOAD_LENGTH
// + DATA_IND_REQ_HEADER_LENGTH - sizeof(GwHeader) - PAYLOAD_STATUS_LENGTH
// = 249 + 27 - 4 - 1 = 271
QVERIFY(N_CoPrtCnv::CoPrtCnvRadioTelegram::isTelegramLengthOk(271));
QVERIFY(!N_CoPrtCnv::CoPrtCnvRadioTelegram::isTelegramLengthOk(272));
QVERIFY(!N_CoPrtCnv::CoPrtCnvRadioTelegram::isTelegramLengthOk(1000));
}
void coprtcnv_unit_test::radioTelegramFragmentationRoundtrip()
{
// Build a big telegram whose payload must be fragmented, reassemble the
// fragments and compare the payload area against the original data.
const uint16_t payloadSize = 300;
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> bigPtr(new N_CoPrtCnv::CoPrtCnvRadioTelegram(GEF_BESTAETIGUNG, payloadSize, 0x1111));
const int payloadPart = bigPtr->getSize() - N_CoPrtCnv::CoPrtCnvRadioTelegram::DATA_IND_REQ_HEADER_LENGTH;
const uint8_t maxFragPayload = N_CoPrtCnv::CoPrtCnvRadioTelegram::MAX_RADIO_TELEGRAM_PAYLOAD_LENGTH
- N_CoPrtCnv::CoPrtCnvRadioTelegram::PAYLOAD_STATUS_LENGTH;
const uint8_t nbrFragments = static_cast<uint8_t>((payloadPart - 1) / maxFragPayload);
QVERIFY(nbrFragments >= 1);
std::vector<std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> > frags;
std::multimap<uint16_t, N_CoPrtCnv::CoPrtCnvRadioTelegram *> fragList;
for (uint8_t i = 0; i <= nbrFragments; ++i)
{
bool error = true;
auto frag = std::make_shared<N_CoPrtCnv::CoPrtCnvRadioTelegram>(bigPtr, i, error);
QVERIFY2(!error, "fragment creation failed");
frags.push_back(frag);
fragList.insert(std::make_pair(frag->getFragmentCounter(), frag.get()));
}
QCOMPARE(static_cast<int>(fragList.size()), static_cast<int>(nbrFragments) + 1);
const QByteArray unfragmented = N_CoPrtCnv::CoPrtCnvRadioTelegram::getUnfragmentedData(fragList);
QVERIFY(!unfragmented.isEmpty());
QCOMPARE(unfragmented.size(), bigPtr->data().size());
QCOMPARE(unfragmented.mid(N_CoPrtCnv::CoPrtCnvRadioTelegram::DATA_IND_REQ_HEADER_LENGTH - 1),
bigPtr->data().mid(N_CoPrtCnv::CoPrtCnvRadioTelegram::DATA_IND_REQ_HEADER_LENGTH - 1));
}
void coprtcnv_unit_test::radioTelegramLoginVsNormal()
{
N_CoPrtCnv::CoPrtCnvRadioTelegram login(N_CoPrtCnv::CoPrtCnvRadioTelegram::e_LoginRequest, 0x2222, 0x00000005);
QVERIFY(login.isLoginTelegram());
QVERIFY(!login.isNormalTelegram());
}
void coprtcnv_unit_test::telegramIdToString()
{
// telegramId2String / wirkfeldTyp2Str are declared in global scope
const QByteArray known = telegramId2String(GEF_BESTAETIGUNG);
QVERIFY(!known.isEmpty());
}
void coprtcnv_unit_test::wirkfeldTypToString()
{
const QString text = wirkfeldTyp2Str(TrainingAreaBase::TetraIcd::AreaEffectSimulationType::BeStillWarning);
QVERIFY(!text.isEmpty());
}
QTEST_MAIN(coprtcnv_unit_test)
#include "coprtcnv_unit_test.moc"