Implemented full e2e testing

This commit is contained in:
Martino Ferrari
2026-07-02 10:10:57 +02:00
parent f8c79131c9
commit f2042d624b
35 changed files with 2419 additions and 78 deletions
@@ -520,6 +520,10 @@ ErrorManagement::ErrorType DebugService::Streamer(ExecutionInfo &info) {
// b) Drain traceBuffer — pack each sample into udpsDataPayload
bool anyData = false;
bool pendingInDrain[UDPS_MAX_SLOTS];
for (uint32 i = 0u; i < udpsNumSlots; i++) {
pendingInDrain[i] = false;
}
uint32 id, size;
uint64 ts;
uint8 udpsSampleBuf[UDPS_MAX_SAMPLE_BYTES];
@@ -528,6 +532,18 @@ ErrorManagement::ErrorType DebugService::Streamer(ExecutionInfo &info) {
// Find matching slot by internalID
for (uint32 i = 0u; i < udpsNumSlots; i++) {
if (udpsSlots[i].internalID == id) {
if (pendingInDrain[i]) {
// This slot already holds an unflushed sample from earlier
// in this same drain pass — flush it now instead of
// silently overwriting it, or lossless tracing would drop
// a real sample whenever the Streamer thread falls behind
// by more than one RT cycle.
FlushUdpsFrame();
for (uint32 j = 0u; j < udpsNumSlots; j++) {
pendingInDrain[j] = false;
}
anyData = false;
}
if ((udpsDataPayload != NULL_PTR(uint8 *)) &&
(8u + udpsSlots[i].wireOffset + udpsSlots[i].wireSize <= udpsDataPayloadSize)) {
uint32 copySize = size;
@@ -535,6 +551,7 @@ ErrorManagement::ErrorType DebugService::Streamer(ExecutionInfo &info) {
memcpy(udpsDataPayload + 8u + udpsSlots[i].wireOffset, udpsSampleBuf, copySize);
udpsSlots[i].everFilled = true;
}
pendingInDrain[i] = true;
anyData = true;
break;
}
@@ -542,18 +559,22 @@ ErrorManagement::ErrorType DebugService::Streamer(ExecutionInfo &info) {
}
// c) If we have data, stamp with HRT and send via udpsServer
if (anyData && udpsNumSlots > 0u && udpsDataPayload != NULL_PTR(uint8 *)) {
if (anyData) {
FlushUdpsFrame();
} else {
Sleep::MSec(1u);
}
return ErrorManagement::NoError;
}
void DebugService::FlushUdpsFrame() {
if (udpsNumSlots > 0u && udpsDataPayload != NULL_PTR(uint8 *)) {
uint64 hrt = HighResolutionTimer::Counter();
memcpy(udpsDataPayload, &hrt, 8u);
udpsPacketCounter++;
(void)udpsServer.SendData(udpsPacketCounter, udpsDataPayload, udpsDataPayloadSize);
}
if (!anyData) {
Sleep::MSec(1u);
}
return ErrorManagement::NoError;
}
// ---------------------------------------------------------------------------
@@ -66,6 +66,20 @@ private:
*/
bool SendUDPSConfig();
/**
* @brief Stamp the current udpsDataPayload with an HRT timestamp and send
* it as one UDPS DATA packet.
* @details Factored out of Streamer() so a single drain pass of
* traceBuffer can flush more than once per tick — see the
* pendingInDrain guard in Streamer(): without an eager flush, a
* slot that is written twice within the same drain pass (e.g.
* because the Streamer thread was briefly descheduled and two
* RT cycles' worth of samples piled up in traceBuffer) would
* silently overwrite-and-lose the first of the two samples,
* defeating lossless tracing.
*/
void FlushUdpsFrame();
// -----------------------------------------------------------------------
// TCP/UDP transport configuration
// -----------------------------------------------------------------------
@@ -1091,9 +1091,9 @@ void DebugServiceBase::InfoNode(const char8 *path, StreamString &out) {
Reference ref = ObjectRegistryDatabase::Instance()->Find(path);
out += "{";
if (ref.IsValid()) {
out += "\"Name\":\"";
out += "\"Name\": \"";
EscapeJson(ref->GetName(), out);
out += "\",\"Class\":\"";
out += "\", \"Class\": \"";
EscapeJson(ref->GetClassProperties()->GetName(), out);
out += "\"";
ConfigurationDatabase db;
@@ -1110,7 +1110,7 @@ void DebugServiceBase::InfoNode(const char8 *path, StreamString &out) {
if (TypeConvert(st, at)) {
out += "\"";
EscapeJson(cn, out);
out += "\":\"";
out += "\": \"";
EscapeJson(buf, out);
out += "\"";
if (i < nc - 1u)
@@ -1129,8 +1129,8 @@ void DebugServiceBase::InfoNode(const char8 *path, StreamString &out) {
DebugSignalInfo *s = signals[aliases[i].signalIndex];
const char8 *tn =
TypeDescriptor::GetTypeNameFromTypeDescriptor(s->type);
out.Printf("\"Name\":\"%s\",\"Class\":\"Signal\",\"Type\":\"%s\","
"\"ID\":%u",
out.Printf("\"Name\": \"%s\", \"Class\": \"Signal\", \"Type\": \"%s\", "
"\"ID\": %u",
s->name.Buffer(), tn ? tn : "Unknown", s->internalID);
enrichAlias = aliases[i].name;
found = true;
@@ -1141,7 +1141,7 @@ void DebugServiceBase::InfoNode(const char8 *path, StreamString &out) {
if (found)
EnrichWithConfig(enrichAlias.Buffer(), out);
else
out += "\"Error\":\"Object not found\"";
out += "\"Error\": \"Object not found\"";
}
out += "}\nOK INFO\n";
}