Optimised failed test
This commit is contained in:
109
Test/Integration/BrokerExecuteTest.cpp
Normal file
109
Test/Integration/BrokerExecuteTest.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
#include "DebugService.h"
|
||||
#include "DebugBrokerWrapper.h"
|
||||
#include "MemoryMapInputBroker.h"
|
||||
#include "ObjectRegistryDatabase.h"
|
||||
#include "StandardParser.h"
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
using namespace MARTe;
|
||||
|
||||
namespace MARTe {
|
||||
|
||||
class ManualDebugMemoryMapInputBroker : public DebugMemoryMapInputBroker {
|
||||
public:
|
||||
virtual bool Execute() {
|
||||
if (infoPtr) DebugBrokerHelper::Process(service, *infoPtr);
|
||||
return true;
|
||||
}
|
||||
using MemoryMapBroker::copyTable;
|
||||
};
|
||||
|
||||
class MockDS : public DataSourceI {
|
||||
public:
|
||||
CLASS_REGISTER_DECLARATION()
|
||||
MockDS() { SetName("MockDS"); }
|
||||
virtual bool AllocateMemory() { return true; }
|
||||
virtual uint32 GetNumberOfMemoryBuffers() { return 1; }
|
||||
virtual bool GetSignalMemoryBuffer(const uint32 signalIdx, const uint32 bufferIdx, void *&signalAddress) {
|
||||
static uint32 val = 0;
|
||||
signalAddress = &val;
|
||||
return true;
|
||||
}
|
||||
virtual const char8 *GetBrokerName(StructuredDataI &data, const SignalDirection direction) { return "MemoryMapInputBroker"; }
|
||||
virtual bool GetInputBrokers(ReferenceContainer &inputBrokers, const char8 *const functionName, void *const gamMem) { return true; }
|
||||
virtual bool GetOutputBrokers(ReferenceContainer &outputBrokers, const char8 *const functionName, void *const gamMem) { return true; }
|
||||
virtual bool PrepareNextState(const char8 *const currentStateName, const char8 *const nextStateName) { return true; }
|
||||
virtual bool Synchronise() { return true; }
|
||||
};
|
||||
CLASS_REGISTER(MockDS, "1.0")
|
||||
|
||||
void RunTest() {
|
||||
printf("--- Broker Execute Path Test (Isolated) ---\n");
|
||||
|
||||
DebugService* service = new DebugService();
|
||||
service->traceBuffer.Init(1024 * 1024);
|
||||
ConfigurationDatabase cfg;
|
||||
cfg.Write("ControlPort", (uint32)0);
|
||||
cfg.Write("StreamPort", (uint32)0);
|
||||
assert(service->Initialise(cfg));
|
||||
|
||||
ObjectRegistryDatabase::Instance()->Insert(Reference(service));
|
||||
|
||||
MockDS ds;
|
||||
uint32 gamMem = 42;
|
||||
|
||||
ManualDebugMemoryMapInputBroker* broker = new ManualDebugMemoryMapInputBroker();
|
||||
broker->service = service;
|
||||
|
||||
printf("Manually bootstrapping Broker for testing...\n");
|
||||
broker->copyTable = new MemoryMapBrokerCopyTableEntry[1];
|
||||
broker->copyTable[0].copySize = 4;
|
||||
broker->copyTable[0].dataSourcePointer = &gamMem;
|
||||
broker->copyTable[0].gamPointer = &gamMem;
|
||||
broker->copyTable[0].type = UnsignedInteger32Bit;
|
||||
|
||||
DebugSignalInfo** sigPtrs = NULL;
|
||||
DebugBrokerHelper::InitSignals(NULL_PTR(BrokerI*), ds, service, sigPtrs, 1, broker->copyTable, "TestGAM", InputSignals, &broker->anyActive);
|
||||
broker->infoPtr = &service->brokers[service->numberOfBrokers - 1];
|
||||
|
||||
printf("Broker ready. Registered signals in service: %u\n", service->numberOfSignals);
|
||||
|
||||
printf("Executing IDLE cycle...\n");
|
||||
broker->Execute();
|
||||
assert(service->traceBuffer.Count() == 0);
|
||||
|
||||
printf("Manually enabling TRACE for first signal...\n");
|
||||
// Directly enable tracing on the signal info to bypass name matching
|
||||
service->signals[0].isTracing = true;
|
||||
service->signals[0].decimationFactor = 1;
|
||||
service->signals[0].decimationCounter = 0;
|
||||
|
||||
printf("Updating brokers active status...\n");
|
||||
service->UpdateBrokersActiveStatus();
|
||||
assert(broker->anyActive == true);
|
||||
|
||||
printf("Executing TRACE cycle...\n");
|
||||
broker->Execute();
|
||||
|
||||
uint32 rbCount = service->traceBuffer.Count();
|
||||
printf("Trace Buffer Count: %u\n", rbCount);
|
||||
|
||||
if (rbCount > 0) {
|
||||
printf("SUCCESS: Data reached Trace Buffer via Broker!\n");
|
||||
uint32 rid, rsize; uint64 rts; uint32 rval;
|
||||
assert(service->traceBuffer.Pop(rid, rts, &rval, rsize, 4));
|
||||
printf("Value popped: %u (ID=%u, TS=%lu)\n", rval, rid, rts);
|
||||
assert(rval == 42);
|
||||
} else {
|
||||
printf("FAILURE: Trace Buffer is still empty.\n");
|
||||
}
|
||||
|
||||
ObjectRegistryDatabase::Instance()->Purge();
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
MARTe::RunTest();
|
||||
return 0;
|
||||
}
|
||||
@@ -9,3 +9,12 @@ target_link_libraries(ValidationTest marte_dev ${MARTe2_LIB} ${IOGAM_LIB} ${Linu
|
||||
|
||||
add_executable(SchedulerTest SchedulerTest.cpp)
|
||||
target_link_libraries(SchedulerTest marte_dev ${MARTe2_LIB} ${IOGAM_LIB} ${LinuxTimer_LIB})
|
||||
|
||||
add_executable(PerformanceTest PerformanceTest.cpp)
|
||||
target_link_libraries(PerformanceTest marte_dev ${MARTe2_LIB})
|
||||
|
||||
add_executable(BrokerExecuteTest BrokerExecuteTest.cpp)
|
||||
target_link_libraries(BrokerExecuteTest marte_dev ${MARTe2_LIB})
|
||||
|
||||
add_executable(FinalValidationTest FinalValidationTest.cpp)
|
||||
target_link_libraries(FinalValidationTest marte_dev ${MARTe2_LIB} ${IOGAM_LIB} ${LinuxTimer_LIB} ${LoggerDataSource_LIB})
|
||||
|
||||
217
Test/Integration/FinalValidationTest.cpp
Normal file
217
Test/Integration/FinalValidationTest.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
#include "DebugService.h"
|
||||
#include "DebugCore.h"
|
||||
#include "ObjectRegistryDatabase.h"
|
||||
#include "StandardParser.h"
|
||||
#include "RealTimeApplication.h"
|
||||
#include "GlobalObjectsDatabase.h"
|
||||
#include "BasicUDPSocket.h"
|
||||
#include "BasicTCPSocket.h"
|
||||
#include "HighResolutionTimer.h"
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
using namespace MARTe;
|
||||
|
||||
void RunFinalValidation() {
|
||||
printf("--- MARTe2 Debug Final Validation (End-to-End) ---\n");
|
||||
|
||||
ObjectRegistryDatabase::Instance()->Purge();
|
||||
|
||||
// 1. Initialise DebugService FIRST
|
||||
const char8 * const service_cfg =
|
||||
"+DebugService = {"
|
||||
" Class = DebugService "
|
||||
" ControlPort = 8080 "
|
||||
" UdpPort = 8081 "
|
||||
" StreamIP = \"127.0.0.1\" "
|
||||
"}";
|
||||
|
||||
StreamString ssSrv = service_cfg;
|
||||
ssSrv.Seek(0);
|
||||
ConfigurationDatabase cdbSrv;
|
||||
StandardParser parserSrv(ssSrv, cdbSrv);
|
||||
assert(parserSrv.Parse());
|
||||
|
||||
cdbSrv.MoveToRoot();
|
||||
if (cdbSrv.MoveRelative("+DebugService")) {
|
||||
ConfigurationDatabase child;
|
||||
cdbSrv.Copy(child);
|
||||
cdbSrv.MoveToAncestor(1u);
|
||||
Reference ref("DebugService", GlobalObjectsDatabase::Instance()->GetStandardHeap());
|
||||
ref->SetName("DebugService");
|
||||
if (!ref->Initialise(child)) {
|
||||
printf("ERROR: Failed to initialise DebugService\n");
|
||||
return;
|
||||
}
|
||||
ObjectRegistryDatabase::Instance()->Insert(ref);
|
||||
printf("[Init] DebugService started.\n");
|
||||
}
|
||||
|
||||
// 2. Minimal App configuration
|
||||
const char8 * const minimal_app_cfg =
|
||||
"+App = {"
|
||||
" Class = RealTimeApplication "
|
||||
" +Functions = {"
|
||||
" Class = ReferenceContainer "
|
||||
" +GAM1 = {"
|
||||
" Class = IOGAM "
|
||||
" InputSignals = {"
|
||||
" Counter = { DataSource = Timer Type = uint32 Frequency = 1000 }"
|
||||
" }"
|
||||
" OutputSignals = {"
|
||||
" Counter = { DataSource = DDB Type = uint32 }"
|
||||
" }"
|
||||
" }"
|
||||
" }"
|
||||
" +Data = {"
|
||||
" Class = ReferenceContainer "
|
||||
" DefaultDataSource = DDB "
|
||||
" +Timer = { Class = LinuxTimer SleepTime = 1000 Signals = { +Counter = { Type = uint32 } } }"
|
||||
" +DDB = { Class = GAMDataSource Signals = { +Counter = { Type = uint32 } } }"
|
||||
" +DAMS = { Class = TimingDataSource }"
|
||||
" }"
|
||||
" +States = {"
|
||||
" Class = ReferenceContainer "
|
||||
" +State1 = { Class = RealTimeState +Threads = { Class = ReferenceContainer +Thread1 = { Class = RealTimeThread Functions = {GAM1} } } }"
|
||||
" }"
|
||||
" +Scheduler = { Class = GAMScheduler TimingDataSource = DAMS }"
|
||||
"}";
|
||||
|
||||
StreamString ssApp = minimal_app_cfg;
|
||||
ssApp.Seek(0);
|
||||
ConfigurationDatabase cdbApp;
|
||||
StandardParser parserApp(ssApp, cdbApp);
|
||||
assert(parserApp.Parse());
|
||||
|
||||
cdbApp.MoveToRoot();
|
||||
if (cdbApp.MoveRelative("+App")) {
|
||||
ConfigurationDatabase child;
|
||||
cdbApp.Copy(child);
|
||||
cdbApp.MoveToAncestor(1u);
|
||||
Reference ref("RealTimeApplication", GlobalObjectsDatabase::Instance()->GetStandardHeap());
|
||||
ref->SetName("App");
|
||||
if (ref->Initialise(child)) {
|
||||
ObjectRegistryDatabase::Instance()->Insert(ref);
|
||||
printf("[Init] App object created.\n");
|
||||
} else {
|
||||
printf("ERROR: Failed to initialise App object.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Reference appRef = ObjectRegistryDatabase::Instance()->Find("App");
|
||||
RealTimeApplication* app = dynamic_cast<RealTimeApplication*>(appRef.operator->());
|
||||
|
||||
// 3. Start Application
|
||||
printf("Configuring Application...\n");
|
||||
if (!app->ConfigureApplication()) {
|
||||
printf("ERROR: ConfigureApplication failed.\n");
|
||||
return;
|
||||
}
|
||||
printf("Preparing State1...\n");
|
||||
if (app->PrepareNextState("State1") != ErrorManagement::NoError) {
|
||||
printf("ERROR: Failed to prepare State1.\n");
|
||||
return;
|
||||
}
|
||||
printf("Starting State1 Execution...\n");
|
||||
if (app->StartNextStateExecution() != ErrorManagement::NoError) {
|
||||
printf("ERROR: Failed to start State1 execution.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Application running. Starting client simulation...\n");
|
||||
Sleep::MSec(1000);
|
||||
|
||||
// 4. Act as Client: Send Commands
|
||||
BasicTCPSocket client;
|
||||
if (client.Connect("127.0.0.1", 8080, TimeoutType(2000))) {
|
||||
printf("[Client] Connected to DebugService.\n");
|
||||
|
||||
// Command 1: TREE
|
||||
printf("[Client] Sending TREE...\n");
|
||||
uint32 cmdLen = 5;
|
||||
client.Write("TREE\n", cmdLen);
|
||||
char buf[4096]; uint32 rsize = 4096;
|
||||
if (client.Read(buf, rsize, TimeoutType(1000))) {
|
||||
printf("[Client] TREE response received (%u bytes).\n", rsize);
|
||||
}
|
||||
|
||||
// Command 2: DISCOVER
|
||||
printf("[Client] Sending DISCOVER...\n");
|
||||
cmdLen = 9;
|
||||
client.Write("DISCOVER\n", cmdLen);
|
||||
rsize = 4096;
|
||||
if (client.Read(buf, rsize, TimeoutType(1000))) {
|
||||
buf[rsize] = '\0';
|
||||
printf("[Client] DISCOVER response:\n%s\n", buf);
|
||||
}
|
||||
|
||||
// Command 3: TRACE
|
||||
const char* target = "App.Data.Timer.Counter";
|
||||
printf("[Client] Sending TRACE %s 1...\n", target);
|
||||
StreamString traceCmd;
|
||||
traceCmd.Printf("TRACE %s 1\n", target);
|
||||
cmdLen = traceCmd.Size();
|
||||
client.Write(traceCmd.Buffer(), cmdLen);
|
||||
|
||||
rsize = 1024;
|
||||
if (client.Read(buf, rsize, TimeoutType(1000))) {
|
||||
buf[rsize] = '\0';
|
||||
printf("[Client] TRACE response: %s", buf);
|
||||
}
|
||||
client.Close();
|
||||
} else {
|
||||
printf("ERROR: Client failed to connect to 127.0.0.1:8080\n");
|
||||
}
|
||||
|
||||
// 5. Verify Telemetry
|
||||
BasicUDPSocket telemListener;
|
||||
assert(telemListener.Open());
|
||||
assert(telemListener.Listen(8081));
|
||||
|
||||
printf("Listening for UDP Telemetry on 8081...\n");
|
||||
uint32 totalSamples = 0;
|
||||
uint64 startBench = HighResolutionTimer::Counter();
|
||||
|
||||
while (totalSamples < 50 && (HighResolutionTimer::Counter() - startBench) * HighResolutionTimer::Period() < 10.0) {
|
||||
char packet[4096];
|
||||
uint32 psize = 4096;
|
||||
if (telemListener.Read(packet, psize, TimeoutType(100))) {
|
||||
if (psize < 20) continue;
|
||||
uint32 magic = *(uint32*)(&packet[0]);
|
||||
if (magic != 0xDA7A57AD) continue;
|
||||
|
||||
uint32 count = *(uint32*)(&packet[16]);
|
||||
uint32 offset = 20;
|
||||
for (uint32 j=0; j<count; j++) {
|
||||
if (offset + 16 > psize) break;
|
||||
uint32 id = *(uint32*)(&packet[offset]);
|
||||
uint64 ts = *(uint64*)(&packet[offset + 4]);
|
||||
uint32 size = *(uint32*)(&packet[offset + 12]);
|
||||
offset += 16;
|
||||
if (offset + size > psize) break;
|
||||
if (size == 4) {
|
||||
uint32 val = *(uint32*)(&packet[offset]);
|
||||
if (totalSamples % 10 == 0) printf("[Telemetry] Sample %u: ID=%u, TS=%lu, Val=%u\n", totalSamples, id, ts, val);
|
||||
totalSamples++;
|
||||
}
|
||||
offset += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (totalSamples >= 50) {
|
||||
printf("\nSUCCESS: End-to-End pipeline verified with real MARTe2 app!\n");
|
||||
} else {
|
||||
printf("\nFAILURE: Received only %u samples in 10 seconds.\n", totalSamples);
|
||||
}
|
||||
|
||||
app->StopCurrentStateExecution();
|
||||
telemListener.Close();
|
||||
ObjectRegistryDatabase::Instance()->Purge();
|
||||
}
|
||||
|
||||
int main() {
|
||||
RunFinalValidation();
|
||||
return 0;
|
||||
}
|
||||
109
Test/Integration/PerformanceTest.cpp
Normal file
109
Test/Integration/PerformanceTest.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
#include "DebugService.h"
|
||||
#include "DebugBrokerWrapper.h"
|
||||
#include "MemoryMapInputBroker.h"
|
||||
#include "HighResolutionTimer.h"
|
||||
#include "ObjectRegistryDatabase.h"
|
||||
#include "StandardParser.h"
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
using namespace MARTe;
|
||||
|
||||
namespace MARTe {
|
||||
void RunBenchmark() {
|
||||
printf("--- MARTe2 Debug Performance Benchmark V5 (Wait-Free/Branchless) ---\n");
|
||||
printf("Testing with 100 signals, 1,000,000 cycles per test.\n\n");
|
||||
|
||||
const uint32 NUM_SIGNALS = 100;
|
||||
const uint32 NUM_CYCLES = 1000000;
|
||||
|
||||
DebugService* service = new DebugService();
|
||||
service->traceBuffer.Init(128 * 1024 * 1024);
|
||||
ConfigurationDatabase cfg;
|
||||
cfg.Write("ControlPort", (uint32)0);
|
||||
cfg.Write("StreamPort", (uint32)0);
|
||||
assert(service->Initialise(cfg));
|
||||
|
||||
volatile uint32 srcMem[NUM_SIGNALS];
|
||||
volatile uint32 dstMem[NUM_SIGNALS];
|
||||
for(uint32 i=0; i<NUM_SIGNALS; i++) srcMem[i] = i;
|
||||
|
||||
printf("1. Baseline (Pure Copy): ");
|
||||
uint64 start = HighResolutionTimer::Counter();
|
||||
for(uint32 c=0; c<NUM_CYCLES; c++) {
|
||||
for(uint32 i=0; i<NUM_SIGNALS; i++) {
|
||||
dstMem[i] = srcMem[i];
|
||||
}
|
||||
}
|
||||
uint64 end = HighResolutionTimer::Counter();
|
||||
float64 baselineTime = (float64)(end - start) * HighResolutionTimer::Period();
|
||||
float64 baselineNs = (baselineTime / NUM_CYCLES) * 1e9;
|
||||
printf("%.3f ms (avg: %.3f ns)\n", baselineTime * 1000.0, baselineNs);
|
||||
|
||||
DebugMemoryMapInputBroker debugBroker;
|
||||
debugBroker.service = service;
|
||||
DebugSignalInfo** ptrs = new DebugSignalInfo*[NUM_SIGNALS];
|
||||
for(uint32 i=0; i<NUM_SIGNALS; i++) {
|
||||
StreamString name;
|
||||
name = "Sig";
|
||||
// Convert i to string without Printf
|
||||
if (i < 10) { name += (char)('0' + i); }
|
||||
else { name += (char)('0' + (i/10)); name += (char)('0' + (i%10)); }
|
||||
|
||||
ptrs[i] = service->RegisterSignal((void*)&srcMem[i], UnsignedInteger32Bit, name.Buffer());
|
||||
}
|
||||
volatile bool anyActiveFlag = false;
|
||||
service->RegisterBroker(ptrs, NUM_SIGNALS, NULL_PTR(MemoryMapBroker*), &anyActiveFlag);
|
||||
debugBroker.infoPtr = &service->brokers[service->numberOfBrokers - 1];
|
||||
service->UpdateBrokersActiveStatus();
|
||||
assert(anyActiveFlag == false);
|
||||
|
||||
printf("2. Debug Idle (Wait-Free Skip): ");
|
||||
start = HighResolutionTimer::Counter();
|
||||
for(uint32 c=0; c<NUM_CYCLES; c++) {
|
||||
for(uint32 i=0; i<NUM_SIGNALS; i++) dstMem[i] = srcMem[i];
|
||||
if (anyActiveFlag || service->IsPaused()) {
|
||||
DebugBrokerHelper::Process(service, *debugBroker.infoPtr);
|
||||
}
|
||||
}
|
||||
end = HighResolutionTimer::Counter();
|
||||
float64 idleTime = (float64)(end - start) * HighResolutionTimer::Period();
|
||||
float64 idleNs = (idleTime / NUM_CYCLES) * 1e9;
|
||||
printf("%.3f ms (avg: %.3f ns) | Delta: +%.3f ns\n",
|
||||
idleTime * 1000.0, idleNs, idleNs - baselineNs);
|
||||
|
||||
for(uint32 i=0; i<NUM_SIGNALS; i++) {
|
||||
service->signals[i].isTracing = true;
|
||||
}
|
||||
service->UpdateBrokersActiveStatus();
|
||||
assert(anyActiveFlag == true);
|
||||
|
||||
printf("3. Debug Load (100 signals branchless): ");
|
||||
start = HighResolutionTimer::Counter();
|
||||
for(uint32 c=0; c<NUM_CYCLES; c++) {
|
||||
for(uint32 i=0; i<NUM_SIGNALS; i++) dstMem[i] = srcMem[i];
|
||||
if (anyActiveFlag || service->IsPaused()) {
|
||||
DebugBrokerHelper::Process(service, *debugBroker.infoPtr);
|
||||
}
|
||||
if ((c % 1000) == 0) {
|
||||
uint32 tid, tsize; uint64 tts; uint8 tbuf[16];
|
||||
while(service->traceBuffer.Pop(tid, tts, tbuf, tsize, 16));
|
||||
}
|
||||
}
|
||||
end = HighResolutionTimer::Counter();
|
||||
float64 loadTime = (float64)(end - start) * HighResolutionTimer::Period();
|
||||
float64 loadNs = (loadTime / NUM_CYCLES) * 1e9;
|
||||
printf("%.3f ms (avg: %.3f ns) | Delta: +%.3f ns (+%.3f ns/signal)\n",
|
||||
loadTime * 1000.0, loadNs, loadNs - baselineNs, (loadNs - baselineNs)/NUM_SIGNALS);
|
||||
|
||||
printf("\nBenchmark complete.\n");
|
||||
|
||||
delete[] ptrs;
|
||||
delete service;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
MARTe::RunBenchmark();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user