Migrates residual Lts sources to generated rtiddsgen API
Adds NmeaManagement tests, fixes codegen includes and Qt6 SerialPort CMake target.
This commit is contained in:
1 parent
5485a90385
commit
881d44f4dd
512 files changed
+6887
-6426
No files matched your search
@@ -129,7 +129,8 @@ if(BUILD_TESTING)
|
||||
svcAesCommon svcAlmCommon svcAsmCommon svcAvmCommon svcCodCommon
|
||||
svcEemCommon svcEsmCommon svcEscCommon svcEvlCommon svcExmCommon
|
||||
svcGimCommon svcIsmCommon svcMdmCommon svcMsgCommon svcMrkCommon
|
||||
svcNomCommon svcOpmCommon svcOssCommon svcPdmCommon svcPpmCommon
|
||||
svcNomCommon svcNmeCommon svcOpmCommon svcOssCommon svcPdmCommon
|
||||
svcPpmCommon
|
||||
svcPreCommon svcRepCommon svcSomCommon svcSrmCommon svcSrpCommon
|
||||
svcTgtCommon svcWhgCommon)
|
||||
if(TARGET ${_svc_common})
|
||||
@@ -164,6 +165,15 @@ if(BUILD_TESTING)
|
||||
add_dependencies(migration_tests svcBldCommon)
|
||||
endif()
|
||||
|
||||
# test_nme_dtc / test_nmea_handler include the server-topic
|
||||
# interfaces (nme_dts.h, nme_fts.h) that CODEGEN_SERVER_TOPICS
|
||||
# generates into the svcNmeServer target - same ordering
|
||||
# requirement as the blocks above (without it a parallel make
|
||||
# can start migration_tests before those headers exist).
|
||||
if(TARGET svcNmeServer)
|
||||
add_dependencies(migration_tests svcNmeServer)
|
||||
endif()
|
||||
|
||||
# Enable Qt Meta-Object Compiler for tests with Q_OBJECT
|
||||
set_target_properties(migration_tests PROPERTIES AUTOMOC ON)
|
||||
|
||||
@@ -270,6 +280,13 @@ endif()
|
||||
target_link_libraries(migration_tests PRIVATE nglwidgets)
|
||||
endif()
|
||||
|
||||
# NmeaManagement tests instantiate the generated nme types (nme.hpp
|
||||
# default ctors, ServiceControlEnum stream operator) and the service
|
||||
# logger (logger.cpp) - both compiled into svcNmeCommon.
|
||||
if(TARGET svcNmeCommon)
|
||||
target_link_libraries(migration_tests PRIVATE svcNmeCommon)
|
||||
endif()
|
||||
|
||||
# FLM/FLT service tests include the Q_OBJECT custom headers of the
|
||||
# migrated services (flm_db_impl_custom.h, flm_dtc_impl_custom.h).
|
||||
# Their moc output references the generated bases' staticMetaObject
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
/**
|
||||
* @file test_nme_dtc.cpp
|
||||
* @brief Verhaltenstests für die generierte NmeaManagement Dtc/Ftc/Dts/Fts-Schnittstelle
|
||||
*
|
||||
* Diese Tests prüfen die von CODEGEN_CLIENT_TOPICS_IFC / CODEGEN_SERVER_TOPICS
|
||||
* aus nme_service.xml generierten Header (NmeaManagement/nme_dtc.h, nme_ftc.h,
|
||||
* nme_dts.h, nme_fts.h) aus dem Build-Tree sowie die plainen DDS-Typ-Member
|
||||
* aus nme.hpp (BatteryState, BatteryAlarm, PositionExcon, ServiceControl,
|
||||
* TurnRadioMasterOffRequest), die der migrierte NmeaHandler, DdsHandler und
|
||||
* SocketHandler direkt als Felder und Member-Assignment nutzen.
|
||||
*/
|
||||
|
||||
#include "NmeaManagement/nme.hpp"
|
||||
#include "NmeaManagement/nme_dtc.h"
|
||||
#include "NmeaManagement/nme_dts.h"
|
||||
#include "NmeaManagement/nme_ftc.h"
|
||||
#include "NmeaManagement/nme_fts.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <gtest/gtest.h>
|
||||
#include <type_traits>
|
||||
|
||||
/**
|
||||
* @test Der generierte Dtc ist von QObject abgeleitet (Signale für
|
||||
* Topic-Updates); alle vier Interfaces sind abstrakt.
|
||||
*/
|
||||
TEST(nme_dtc_Generated, InterfacesAreAbstract)
|
||||
{
|
||||
static_assert(std::is_base_of<QObject, NmeaManagement::Interface::Dtc>::value,
|
||||
"generierter Dtc muss von QObject abgeleitet sein");
|
||||
static_assert(std::is_abstract<NmeaManagement::Interface::Dtc>::value, "Dtc muss abstrakt sein");
|
||||
static_assert(std::is_abstract<NmeaManagement::Interface::Ftc>::value, "Ftc muss abstrakt sein");
|
||||
static_assert(std::is_abstract<NmeaManagement::Interface::Dts>::value, "Dts muss abstrakt sein");
|
||||
static_assert(std::is_abstract<NmeaManagement::Interface::Fts>::value, "Fts muss abstrakt sein");
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test DdsHandler::init nutzt diese Dts-Enable-Methoden — sie müssen
|
||||
* über nme_dts.h vorliegen (Adresse ableitbar = existiert und ist
|
||||
* public).
|
||||
*/
|
||||
TEST(nme_dtc_Generated, DtsEnableMethodsExist)
|
||||
{
|
||||
using Dts = NmeaManagement::Interface::Dts;
|
||||
// Member-Funktionszeiger: auto deduziert ohne '*' (auto* kann
|
||||
// Member-Pointer-Typen nicht deduzieren).
|
||||
auto enableBatteryAlarm = &Dts::enableBatteryAlarm;
|
||||
auto enableServiceControl = &Dts::enableServiceControl;
|
||||
auto enableBatteryState = &Dts::enableBatteryState;
|
||||
auto enablePositionExcon = &Dts::enablePositionExcon;
|
||||
(void)enableBatteryAlarm;
|
||||
(void)enableServiceControl;
|
||||
(void)enableBatteryState;
|
||||
(void)enablePositionExcon;
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test SocketHandler erbt von Fts::TurnRadioMasterOffRequestHandler und
|
||||
* antwortet über Fts::turnRadioMasterOffReply — beides muss über
|
||||
* nme_fts.h vollständig vorliegen.
|
||||
*/
|
||||
TEST(nme_dtc_Generated, FtsTurnRadioMasterOffInterface)
|
||||
{
|
||||
using namespace NmeaManagement::Interface;
|
||||
static_assert(std::is_class<Fts::TurnRadioMasterOffRequestHandler>::value,
|
||||
"Fts::TurnRadioMasterOffRequestHandler fehlt");
|
||||
// turnRadioMasterOffReply ist überladen (FunctionReply / FunctionReplyObject) —
|
||||
// den vom SocketHandler genutzten FunctionReplyObject-Overload explizit nehmen.
|
||||
auto reply = static_cast<bool (Fts::*)(const rti::core::SampleIdentity&, const Core::FunctionReplyObject&)>(
|
||||
&Fts::turnRadioMasterOffReply);
|
||||
(void)reply;
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test Die DDS-Typen aus nme.hpp müssen plain-Member bereitstellen
|
||||
* (rtiddsgen 7.7): BatteryState, den der migrierte NmeaHandler
|
||||
* (IIXDR) per Member-Assignment befüllt.
|
||||
*/
|
||||
TEST(nme_dtc_Generated, BatteryStateHasPlainMembers)
|
||||
{
|
||||
using BatteryState = NmeaManagement::BatteryState;
|
||||
|
||||
static_assert(std::is_same<decltype(BatteryState{}.id), int32_t>::value, "id muss ein plain int32_t-Member sein");
|
||||
static_assert(std::is_same<decltype(BatteryState{}.battery), int32_t>::value,
|
||||
"battery muss ein plain int32_t-Member sein");
|
||||
static_assert(std::is_same<decltype(BatteryState{}.temperature), int32_t>::value,
|
||||
"temperature muss ein plain int32_t-Member sein");
|
||||
static_assert(std::is_same<decltype(BatteryState{}.frequency), int32_t>::value,
|
||||
"frequency muss ein plain int32_t-Member sein");
|
||||
static_assert(std::is_same<decltype(BatteryState{}.generic), double>::value,
|
||||
"generic muss ein plain double-Member sein");
|
||||
static_assert(std::is_same<decltype(BatteryState{}.current), int32_t>::value,
|
||||
"current muss ein plain int32_t-Member sein");
|
||||
static_assert(std::is_same<decltype(BatteryState{}.switchOrValue), bool>::value,
|
||||
"switchOrValue muss ein plain bool-Member sein");
|
||||
static_assert(std::is_same<decltype(BatteryState{}.voltage), int32_t>::value,
|
||||
"voltage muss ein plain int32_t-Member sein");
|
||||
static_assert(std::is_same<decltype(BatteryState{}.serialNumber), std::string>::value,
|
||||
"serialNumber muss ein plain std::string-Member sein");
|
||||
|
||||
// Wie im migrierten IIXDR-Pfad: Member-Assignment statt Setter.
|
||||
BatteryState bs;
|
||||
bs.id = 1;
|
||||
bs.battery = 4;
|
||||
bs.temperature = 25;
|
||||
bs.frequency = 100;
|
||||
bs.generic = 1.5;
|
||||
bs.current = 55;
|
||||
bs.switchOrValue = true;
|
||||
bs.voltage = 3300;
|
||||
bs.serialNumber = "SER123";
|
||||
EXPECT_EQ(bs.id, 1);
|
||||
EXPECT_EQ(bs.battery, 4);
|
||||
EXPECT_EQ(bs.temperature, 25);
|
||||
EXPECT_EQ(bs.frequency, 100);
|
||||
EXPECT_DOUBLE_EQ(bs.generic, 1.5);
|
||||
EXPECT_EQ(bs.current, 55);
|
||||
EXPECT_TRUE(bs.switchOrValue);
|
||||
EXPECT_EQ(bs.voltage, 3300);
|
||||
EXPECT_EQ(bs.serialNumber, "SER123");
|
||||
}
|
||||
|
||||
/**
|
||||
* @test BatteryAlarm (IIALR-Pfad) muss plain-Member bereitstellen.
|
||||
*/
|
||||
TEST(nme_dtc_Generated, BatteryAlarmHasPlainMembers)
|
||||
{
|
||||
using BatteryAlarm = NmeaManagement::BatteryAlarm;
|
||||
|
||||
static_assert(std::is_same<decltype(BatteryAlarm{}.id), int32_t>::value, "id muss ein plain int32_t-Member sein");
|
||||
static_assert(std::is_same<decltype(BatteryAlarm{}.description), std::string>::value,
|
||||
"description muss ein plain std::string-Member sein");
|
||||
static_assert(std::is_same<decltype(BatteryAlarm{}.acknowledge), bool>::value,
|
||||
"acknowledge muss ein plain bool-Member sein");
|
||||
static_assert(std::is_same<decltype(BatteryAlarm{}.condition), bool>::value,
|
||||
"condition muss ein plain bool-Member sein");
|
||||
static_assert(std::is_same<decltype(BatteryAlarm{}.uniqueAlarmNumber), int32_t>::value,
|
||||
"uniqueAlarmNumber muss ein plain int32_t-Member sein");
|
||||
static_assert(std::is_same<decltype(BatteryAlarm{}.time), int64_t>::value,
|
||||
"time muss ein plain int64_t-Member sein");
|
||||
|
||||
BatteryAlarm alarm;
|
||||
alarm.id = 0;
|
||||
alarm.time = 1700000000000LL;
|
||||
alarm.description = "overvoltage";
|
||||
alarm.acknowledge = true;
|
||||
alarm.condition = false;
|
||||
alarm.uniqueAlarmNumber = 7;
|
||||
EXPECT_EQ(alarm.id, 0);
|
||||
EXPECT_EQ(alarm.time, 1700000000000LL);
|
||||
EXPECT_EQ(alarm.description, "overvoltage");
|
||||
EXPECT_TRUE(alarm.acknowledge);
|
||||
EXPECT_FALSE(alarm.condition);
|
||||
EXPECT_EQ(alarm.uniqueAlarmNumber, 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test PositionExcon (GPGGA-Pfad): position ist Core::GeoPosition2D mit
|
||||
* plain double-Member lat/lon; valid ist plain bool.
|
||||
*/
|
||||
TEST(nme_dtc_Generated, PositionExconHasPlainMembers)
|
||||
{
|
||||
using PositionExcon = NmeaManagement::PositionExcon;
|
||||
|
||||
static_assert(std::is_same<decltype(PositionExcon{}.position), Core::GeoPosition2D>::value,
|
||||
"position muss ein plain Core::GeoPosition2D-Member sein");
|
||||
static_assert(std::is_same<decltype(PositionExcon{}.position.lat), double>::value,
|
||||
"position.lat muss ein plain double-Member sein");
|
||||
static_assert(std::is_same<decltype(PositionExcon{}.position.lon), double>::value,
|
||||
"position.lon muss ein plain double-Member sein");
|
||||
static_assert(std::is_same<decltype(PositionExcon{}.valid), bool>::value, "valid muss ein plain bool-Member sein");
|
||||
|
||||
// Wie im migrierten GPGGA-Pfad: Member-Assignment statt Setter.
|
||||
PositionExcon pos;
|
||||
pos.position.lat = 1.0;
|
||||
pos.position.lon = 2.0;
|
||||
pos.valid = true;
|
||||
EXPECT_DOUBLE_EQ(pos.position.lat, 1.0);
|
||||
EXPECT_DOUBLE_EQ(pos.position.lon, 2.0);
|
||||
EXPECT_TRUE(pos.valid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test ServiceControl (IIXDR-ServiceControl-Pfad) muss das
|
||||
* ServiceControlState-Enum-Member bereitstellen.
|
||||
*/
|
||||
TEST(nme_dtc_Generated, ServiceControlHasEnumMember)
|
||||
{
|
||||
using ServiceControl = NmeaManagement::ServiceControl;
|
||||
|
||||
static_assert(
|
||||
std::is_same<decltype(ServiceControl{}.ServiceControlState), NmeaManagement::ServiceControlEnum>::value,
|
||||
"ServiceControlState muss ein plain ServiceControlEnum-Member sein");
|
||||
|
||||
ServiceControl sc;
|
||||
sc.ServiceControlState = NmeaManagement::ServiceControlEnum::SHUTDOWN;
|
||||
EXPECT_EQ(sc.ServiceControlState, NmeaManagement::ServiceControlEnum::SHUTDOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test TurnRadioMasterOffRequest muss das plain bool-Member shutdown
|
||||
* bereitstellen (Request-Typ der Fts-Funktions-Topic).
|
||||
*/
|
||||
TEST(nme_dtc_Generated, TurnRadioMasterOffRequestHasPlainMember)
|
||||
{
|
||||
using TurnRadioMasterOffRequest = NmeaManagement::TurnRadioMasterOffRequest;
|
||||
|
||||
static_assert(std::is_same<decltype(TurnRadioMasterOffRequest{}.shutdown), bool>::value,
|
||||
"shutdown muss ein plain bool-Member sein");
|
||||
|
||||
TurnRadioMasterOffRequest req;
|
||||
req.shutdown = true;
|
||||
EXPECT_TRUE(req.shutdown);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test Include-Guard: mehrfaches Einbinden der generierten Header ist erlaubt.
|
||||
*/
|
||||
TEST(nme_dtc_Generated, MultipleIncludeGuard)
|
||||
{
|
||||
// Including the header multiple times should not cause errors
|
||||
#include "NmeaManagement/nme.hpp"
|
||||
#include "NmeaManagement/nme_dtc.h"
|
||||
#include "NmeaManagement/nme_dts.h"
|
||||
#include "NmeaManagement/nme_ftc.h"
|
||||
#include "NmeaManagement/nme_fts.h"
|
||||
SUCCEED();
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* @file test_nme_enums.cpp
|
||||
* @brief Verhaltenstests für die generierten NmeaManagement-Enumerationen
|
||||
*
|
||||
* Diese Tests prüfen den von CODEGEN_IDL_SVC + rtiddsgen aus nme_service.xml
|
||||
* generierten Header (Lts/Services/NmeaManagement/nme_enums.hpp) aus dem
|
||||
* Build-Tree. Sie sichern die Enum-Form ab, die der migrierte NmeaHandler
|
||||
* (IIXDR-Pfad) direkt nutzt: ServiceControlEnum::{PRESHUTDOWN,SHUTDOWN,STOP}
|
||||
* ohne die legacy *_def-Wrapper (rtiddsgen 7.7 generiert plain enum class).
|
||||
*/
|
||||
|
||||
#include "NmeaManagement/nme_enums.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <type_traits>
|
||||
|
||||
/**
|
||||
* @test ServiceControlEnum muss mit den Werten aus nme_service.xml generiert
|
||||
* werden (PRESHUTDOWN=0, SHUTDOWN=1, STOP=2).
|
||||
*/
|
||||
TEST(nme_enums_Generated, ServiceControlEnumValues)
|
||||
{
|
||||
static_assert(std::is_enum<::NmeaManagement::ServiceControlEnum>::value,
|
||||
"ServiceControlEnum muss aus nme_enums.hpp vorliegen");
|
||||
static_assert(static_cast<int32_t>(::NmeaManagement::ServiceControlEnum::PRESHUTDOWN) == 0,
|
||||
"ServiceControlEnum::PRESHUTDOWN muss 0 sein");
|
||||
static_assert(static_cast<int32_t>(::NmeaManagement::ServiceControlEnum::SHUTDOWN) == 1,
|
||||
"ServiceControlEnum::SHUTDOWN muss 1 sein");
|
||||
static_assert(static_cast<int32_t>(::NmeaManagement::ServiceControlEnum::STOP) == 2,
|
||||
"ServiceControlEnum::STOP muss 2 sein");
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test Die Enum-Werte müssen wie im migrierten NmeaHandler zugewiesen
|
||||
* werden können (IIXDR: ServiceControl.ServiceControlState = ...).
|
||||
*/
|
||||
TEST(nme_enums_Generated, ServiceControlEnumAssignable)
|
||||
{
|
||||
::NmeaManagement::ServiceControlEnum state = ::NmeaManagement::ServiceControlEnum::PRESHUTDOWN;
|
||||
state = ::NmeaManagement::ServiceControlEnum::SHUTDOWN;
|
||||
state = ::NmeaManagement::ServiceControlEnum::STOP;
|
||||
EXPECT_EQ(state, ::NmeaManagement::ServiceControlEnum::STOP);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test Include-Guard: mehrfaches Einbinden des generierten Headers ist erlaubt.
|
||||
*/
|
||||
TEST(nme_enums_Generated, MultipleIncludeGuard)
|
||||
{
|
||||
// Including the header multiple times should not cause errors
|
||||
#include "NmeaManagement/nme_enums.hpp"
|
||||
SUCCEED();
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* @file test_nmea_handler.cpp
|
||||
* @brief Verhaltenstests für den migrierten NmeaHandler (Lts/Services/NmeaManagement)
|
||||
*
|
||||
* Der NmeaHandler gehört zu den Executable-Quellen von svcNmeaManagement
|
||||
* (kein Library-Symbol), daher wird nmea_handler.cpp hier direkt in das
|
||||
* Test-Binary kompiliert. Vollständiges DDS-Publishing ist ohne laufende
|
||||
* DDS-Domain nicht testbar (wie bei flmTests) — getestet wird deshalb:
|
||||
*
|
||||
* - Checksummen-Verhalten (Annahme und Ablehnung),
|
||||
* - der regex-basierte NMEA-Paket-Split (Qt5 QRegExp -> Qt6
|
||||
* QRegularExpression: package.split(sep) statt package.split(sep.pattern()),
|
||||
* das letztere auf das Literal "(,|*)" splitten würde und das Parsing
|
||||
* aus dem Ruder laufen ließe),
|
||||
* - den GPRMC-Parse-Pfad End-to-end (liest pkt_data[1..11] — mit kaputtem
|
||||
* Split out-of-range und damit crash-geprüft),
|
||||
* - die Dispatch-Verdrahtung (GPGGA mit gültiger Checksumme erreicht den
|
||||
* Publish auf dem leeren DdsHandler — der Crash ist der beobachtbare
|
||||
* Nachweis, dass Dispatch statt Parse-Abbruch stattfand).
|
||||
*/
|
||||
|
||||
#include "NmeaManagement/nmea_handler.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// Die Service-Implementierung direkt in dieses Test-Binary kompilieren —
|
||||
// keine Library stellt die NmeaHandler-Symbole bereit.
|
||||
#include "../Lts/Services/NmeaManagement/nmea_handler.cpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
// NmeaHandler::NmeaHandler holt den Logger aus dem NGL-Root-Logger im
|
||||
// Konstruktor. createNGLRootLogger() ist idempotent (ignorealreadycreated),
|
||||
// daher sicher pro Test aufrufbar.
|
||||
NGL::INGLLogger& ensureRootLogger()
|
||||
{
|
||||
return NGL::NGLLoggerBootstrap::createNGLRootLogger(QString(), true, QString(), true);
|
||||
}
|
||||
|
||||
// NmeaHandler mit leerem DdsHandler: Pfade ohne Publish (GPRMC) sind damit
|
||||
// lauffähig; Pfade mit Publish (IIXDR/IIALR/GPGGA) liefern null-Deref —
|
||||
// dort ist der Crash der Observable (siehe GpggaValidChecksumDispatches).
|
||||
NmeaManagement::NmeaHandler makeHandler()
|
||||
{
|
||||
ensureRootLogger();
|
||||
std::shared_ptr<NmeaManagement::DdsHandler> noDds;
|
||||
return NmeaManagement::NmeaHandler(noDds, nullptr);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
* @test GPRMC mit gültiger Checksumme durchläuft den kompletten Parse-Pfad
|
||||
* (Split auf ,/* via QRegularExpression und pkt_data[1..11]); GPRMC
|
||||
* publiziert nicht, daher läuft der Test ohne DDS. Wäre der Split auf
|
||||
* das Literal "(,|*)" kaputt, würde pkt_data[2..11] out-of-range und
|
||||
* der Test crashen.
|
||||
*/
|
||||
TEST(nmea_handler_Decode, GprmcValidChecksumParses)
|
||||
{
|
||||
NmeaManagement::NmeaHandler handler = makeHandler();
|
||||
// Checksumme 0x6A ist gültig (XOR aller Zeichen zwischen $ und *).
|
||||
EXPECT_NO_THROW(
|
||||
handler.decode(QStringLiteral("$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test GPGGA mit gültiger Checksumme (0x73) wird nicht abgebrochen, sondern
|
||||
* nach GPGGA() publiziert — auf dem leeren DdsHandler ist das eine
|
||||
* null-Deref: der Crash beweist, dass Checksumme + Dispatch korrekt
|
||||
* sind.
|
||||
*/
|
||||
TEST(nmea_handler_Decode, GpggaValidChecksumDispatches)
|
||||
{
|
||||
NmeaManagement::NmeaHandler handler = makeHandler();
|
||||
EXPECT_DEATH(
|
||||
handler.decode(QStringLiteral("$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,54.5,M,46.9,M,00,0000*73")), ".*");
|
||||
}
|
||||
|
||||
/**
|
||||
* @test GPGGA mit ungültiger Checksumme (0x00 statt 0x73) wird verworfen:
|
||||
* kein GPGGA()-Aufruf, kein Publish, kein Crash.
|
||||
*/
|
||||
TEST(nmea_handler_Decode, GpggaBadChecksumRejected)
|
||||
{
|
||||
NmeaManagement::NmeaHandler handler = makeHandler();
|
||||
EXPECT_NO_THROW(
|
||||
handler.decode(QStringLiteral("$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,54.5,M,46.9,M,00,0000*00")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test IIXDR mit ungültiger Checksumme (0x00 statt 0x3F) wird verworfen
|
||||
* (IIXDR würde publizieren — Ablehnung muss vor dem Publish liegen);
|
||||
* leeres Paket bricht decode() früh ab.
|
||||
*/
|
||||
TEST(nmea_handler_Decode, IixdrBadChecksumRejectedAndEmptyPackage)
|
||||
{
|
||||
NmeaManagement::NmeaHandler handler = makeHandler();
|
||||
EXPECT_NO_THROW(handler.decode(QStringLiteral("$IIXDR,123519,SER123,B,42,C,25,F,100,I,55,S,0,U,3300*00")));
|
||||
EXPECT_NO_THROW(handler.decode(QStringLiteral("")));
|
||||
}
|
||||
Reference in new issue
Block a user