#include "ClassRegistryDatabase.h" #include "ConfigurationDatabase.h" #include "DebugService.h" #include "ObjectRegistryDatabase.h" #include "ErrorManagement.h" #include "BasicTCPSocket.h" #include "BasicUDPSocket.h" #include "RealTimeApplication.h" #include "StandardParser.h" #include "StreamString.h" #include "GlobalObjectsDatabase.h" #include using namespace MARTe; #include #include void timeout_handler(int sig) { printf("Test timed out!\n"); _exit(1); } void ErrorProcessFunction(const MARTe::ErrorManagement::ErrorInformation &errorInfo, const char8 * const errorDescription) { // printf("[MARTe Error] %s: %s\n", errorInfo.className, errorDescription); } // Forward declarations of other tests void TestSchedulerControl(); void TestFullTracePipeline(); void RunValidationTest(); void TestConfigCommands(); void TestGAMSignalTracing(); int main() { signal(SIGALRM, timeout_handler); alarm(180); MARTe::ErrorManagement::SetErrorProcessFunction(&ErrorProcessFunction); printf("MARTe2 Debug Suite Integration Tests\n"); printf("\n--- Test 1: Registry Patching ---\n"); { ObjectRegistryDatabase::Instance()->Purge(); DebugService service; ConfigurationDatabase serviceData; serviceData.Write("ControlPort", (uint32)9090); service.Initialise(serviceData); printf("DebugService initialized and Registry Patched.\n"); ClassRegistryItem *item = ClassRegistryDatabase::Instance()->Find("MemoryMapInputBroker"); if (item != NULL_PTR(ClassRegistryItem *)) { Object *obj = item->GetObjectBuilder()->Build( GlobalObjectsDatabase::Instance()->GetStandardHeap()); if (obj != NULL_PTR(Object *)) { printf("Instantiated Broker Class: %s\n", obj->GetClassProperties()->GetName()); printf("Success: Broker patched and instantiated.\n"); } else { printf("Failed to build broker\n"); } } else { printf("MemoryMapInputBroker not found in registry\n"); } } Sleep::MSec(1000); printf("\n--- Test 2: Full Trace Pipeline ---\n"); TestFullTracePipeline(); Sleep::MSec(1000); printf("\n--- Test 3: Scheduler Control ---\n"); TestSchedulerControl(); Sleep::MSec(1000); printf("\n--- Test 4: 1kHz Lossless Trace Validation ---\n"); RunValidationTest(); Sleep::MSec(1000); printf("\n--- Test 5: Config & Metadata Enrichment ---\n"); // TestConfigCommands(); // Skipping for now Sleep::MSec(1000); // printf("\n--- Test 6: GAM Signal Tracing ---\n"); // TestGAMSignalTracing(); // Sleep::MSec(1000); printf("\nAll Integration Tests Finished.\n"); return 0; } // --- Test Implementation --- const char8 * const debug_test_config = "DebugService = {" " Class = DebugService " " ControlPort = 8095 " " UdpPort = 8096 " " StreamIP = \"127.0.0.1\" " "}" "App = {" " Class = RealTimeApplication " " +Functions = {" " Class = ReferenceContainer " " +GAM1 = {" " Class = IOGAM " " InputSignals = {" " Counter = { DataSource = Timer Type = uint32 Frequency = 1000 }" " }" " OutputSignals = {" " Counter = { DataSource = DDB Type = uint32 }" " }" " }" " +GAM2 = {" " Class = IOGAM " " InputSignals = {" " Counter = { DataSource = TimerSlow Type = uint32 Frequency = 10 }" " }" " OutputSignals = {" " Counter = { DataSource = Logger Type = uint32 }" " }" " }" " }" " +Data = {" " Class = ReferenceContainer " " DefaultDataSource = DDB " " +Timer = { Class = LinuxTimer SleepTime = 1000 Signals = { Counter = { Type = uint32 } } }" " +TimerSlow = { Class = LinuxTimer SleepTime = 100000 Signals = { Counter = { Type = uint32 } } }" " +Logger = { Class = LoggerDataSource 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 GAM2} } } }" " }" " +Scheduler = { Class = GAMScheduler TimingDataSource = DAMS }" "}"; bool SendCommandGAM(uint16 port, const char8* cmd, StreamString &reply) { BasicTCPSocket client; if (!client.Open()) return false; if (!client.Connect("127.0.0.1", port)) return false; uint32 s = StringHelper::Length(cmd); if (!client.Write(cmd, s)) return false; char buffer[4096]; uint32 size = 4096; TimeoutType timeout(2000); if (client.Read(buffer, size, timeout)) { reply.Write(buffer, size); client.Close(); return true; } client.Close(); return false; } void TestGAMSignalTracing() { printf("--- Test: GAM Signal Tracing Issue ---\n"); ObjectRegistryDatabase::Instance()->Purge(); ConfigurationDatabase cdb; StreamString ss = debug_test_config; ss.Seek(0); StandardParser parser(ss, cdb); if (!parser.Parse()) { printf("ERROR: Failed to parse config\n"); return; } cdb.MoveToRoot(); uint32 n = cdb.GetNumberOfChildren(); for (uint32 i=0; iGetStandardHeap()); if (!ref.IsValid()) { printf("ERROR: Could not create object %s of class %s\n", name, className.Buffer()); continue; } ref->SetName(name); if (!ref->Initialise(child)) { printf("ERROR: Failed to initialise object %s\n", name); continue; } ObjectRegistryDatabase::Instance()->Insert(ref); } ReferenceT service = ObjectRegistryDatabase::Instance()->Find("DebugService"); if (!service.IsValid()) { printf("ERROR: DebugService not found\n"); return; } service->SetFullConfig(cdb); ReferenceT app = ObjectRegistryDatabase::Instance()->Find("App"); if (!app.IsValid()) { printf("ERROR: App not found\n"); return; } if (!app->ConfigureApplication()) { printf("ERROR: ConfigureApplication failed.\n"); return; } if (app->PrepareNextState("State1") != ErrorManagement::NoError) { printf("ERROR: PrepareNextState failed.\n"); return; } if (app->StartNextStateExecution() != ErrorManagement::NoError) { printf("ERROR: StartNextStateExecution failed.\n"); return; } printf("Application started.\n"); Sleep::MSec(1000); // Step 1: Discover signals { StreamString reply; if (SendCommandGAM(8095, "DISCOVER\n", reply)) { printf("DISCOVER response received (len=%llu)\n", reply.Size()); } else { printf("ERROR: DISCOVER failed\n"); } } Sleep::MSec(500); // Step 2: Trace a DataSource signal (Timer.Counter) printf("\n--- Step 1: Trace DataSource signal (Timer.Counter) ---\n"); { StreamString reply; if (SendCommandGAM(8095, "TRACE App.Data.Timer.Counter 1\n", reply)) { printf("TRACE response: %s", reply.Buffer()); } else { printf("ERROR: TRACE failed\n"); } } Sleep::MSec(500); // Step 3: Trace a GAM input signal (GAM1.In.Counter) printf("\n--- Step 2: Trace GAM input signal (GAM1.In.Counter) ---\n"); { StreamString reply; if (SendCommandGAM(8095, "TRACE App.Functions.GAM1.In.Counter 1\n", reply)) { printf("TRACE response: %s", reply.Buffer()); } else { printf("ERROR: TRACE failed\n"); } } Sleep::MSec(500); // Step 4: Try to trace another DataSource signal (TimerSlow.Counter) printf("\n--- Step 3: Try to trace another signal (TimerSlow.Counter) ---\n"); { StreamString reply; if (SendCommandGAM(8095, "TRACE App.Data.TimerSlow.Counter 1\n", reply)) { printf("TRACE response: %s", reply.Buffer()); } else { printf("ERROR: TRACE failed\n"); } } Sleep::MSec(500); // Step 5: Check if we can still trace more signals printf("\n--- Step 4: Try to trace Logger.Counter ---\n"); { StreamString reply; if (SendCommandGAM(8095, "TRACE App.Data.Logger.Counter 1\n", reply)) { printf("TRACE response: %s", reply.Buffer()); } else { printf("ERROR: TRACE failed\n"); } } Sleep::MSec(500); // Verify UDP is still receiving data BasicUDPSocket listener; listener.Open(); listener.Listen(8096); char buffer[1024]; uint32 size = 1024; TimeoutType timeout(1000); int packetCount = 0; while (listener.Read(buffer, size, timeout)) { packetCount++; size = 1024; } printf("\n--- Results ---\n"); if (packetCount > 0) { printf("SUCCESS: Received %d UDP packets.\n", packetCount); } else { printf("FAILURE: No UDP packets received. Possible deadlock or crash.\n"); } app->StopCurrentStateExecution(); }