Implemented full e2e testing
This commit is contained in:
@@ -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";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user