| //+------------------------------------------------------------------+
|
| //| CArchitectureTests.mqh - Comprehensive Test Suite for P0-P5 |
|
| //| Tests all new architectural systems: Config, Error, Resources |
|
| //+------------------------------------------------------------------+
|
| #ifndef CARCHITECTURE_TESTS_MQH
|
| #define CARCHITECTURE_TESTS_MQH
|
|
|
| #include "CArchitectureConfig.mqh"
|
| #include "CErrorHandling.mqh"
|
| #include "CResourceManager.mqh"
|
|
|
| //+------------------------------------------------------------------+
|
| //| Test Result Structure |
|
| //+------------------------------------------------------------------+
|
| struct STestResult
|
| {
|
| string test_name;
|
| bool passed;
|
| string message;
|
| double execution_time_ms;
|
|
|
| void Set(const string name, bool p, const string msg, double exec_time)
|
| {
|
| test_name = name;
|
| passed = p;
|
| message = msg;
|
| execution_time_ms = exec_time;
|
| }
|
|
|
| string ToString()
|
| {
|
| return StringFormat("[%s] %s: %s (%.2f ms)",
|
| passed ? "PASS" : "FAIL",
|
| test_name,
|
| message,
|
| execution_time_ms);
|
| }
|
| };
|
|
|
| //+------------------------------------------------------------------+
|
| //| Architecture Test Suite Class |
|
| //+------------------------------------------------------------------+
|
| class CArchitectureTestSuite
|
| {
|
| private:
|
| STestResult m_results[];
|
| int m_result_count;
|
| int m_passed_count;
|
| int m_failed_count;
|
| datetime m_start_time;
|
|
|
| public:
|
| CArchitectureTestSuite()
|
| {
|
| m_result_count = 0;
|
| m_passed_count = 0;
|
| m_failed_count = 0;
|
| ArrayResize(m_results, 100);
|
| m_start_time = TimeCurrent();
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| Run All Tests |
|
| //+------------------------------------------------------------------+
|
| bool RunAllTests()
|
| {
|
| Print("\n========================================");
|
| Print(" P0-P5 ARCHITECTURE TEST SUITE");
|
| Print("========================================\n");
|
|
|
| ulong suite_start = GetMicrosecondCount();
|
|
|
| // Phase 1: Configuration Tests
|
| Test_Config_Validation();
|
| Test_Config_GateSystemDefaults();
|
| Test_Config_RiskEngineDefaults();
|
| Test_Config_InvalidRanges();
|
|
|
| // Phase 2: Error Handling Tests
|
| Test_Error_Logging();
|
| Test_Error_Categories();
|
| Test_Error_CircuitBreaker();
|
| Test_Error_History();
|
|
|
| // Phase 3: Resource Manager Tests
|
| Test_Resource_IndicatorTracking();
|
| Test_Resource_FileTracking();
|
| Test_Resource_Ownership();
|
| Test_Resource_LeakDetection();
|
|
|
| // Phase 4: Integration Tests
|
| Test_Integration_AllSystems();
|
|
|
| ulong suite_end = GetMicrosecondCount();
|
| double suite_time_ms = (suite_end - suite_start) / 1000.0;
|
|
|
| // Print Results
|
| PrintResults(suite_time_ms);
|
|
|
| return m_failed_count == 0;
|
| }
|
|
|
| private:
|
| //+------------------------------------------------------------------+
|
| //| Configuration Tests |
|
| //+------------------------------------------------------------------+
|
| void Test_Config_Validation()
|
| {
|
| ulong start = GetMicrosecondCount();
|
|
|
| CArchitectureConfig config;
|
| config.SetAllDefaults();
|
| bool valid = config.ValidateAll();
|
|
|
| ulong end = GetMicrosecondCount();
|
| double time_ms = (end - start) / 1000.0;
|
|
|
| if(valid)
|
| AddResult("Config_Validation", true, "All configurations valid", time_ms);
|
| else
|
| AddResult("Config_Validation", false, "Validation failed:\n" + config.GetValidationReport(), time_ms);
|
| }
|
|
|
| void Test_Config_GateSystemDefaults()
|
| {
|
| ulong start = GetMicrosecondCount();
|
|
|
| CArchitectureConfig config;
|
| config.SetAllDefaults();
|
|
|
| bool budget_ok = true;
|
| for(int i = 0; i < 8; i++)
|
| {
|
| if(config.GateSystem.gate_budgets_us[i] != 2000)
|
| budget_ok = false;
|
| }
|
|
|
| ulong end = GetMicrosecondCount();
|
| double time_ms = (end - start) / 1000.0;
|
|
|
| AddResult("Config_GateDefaults", budget_ok,
|
| StringFormat("Gate budgets: %d us per gate", config.GateSystem.total_budget_us),
|
| time_ms);
|
| }
|
|
|
| void Test_Config_RiskEngineDefaults()
|
| {
|
| ulong start = GetMicrosecondCount();
|
|
|
| CArchitectureConfig config;
|
| config.SetAllDefaults();
|
|
|
| bool defaults_ok = (
|
| config.RiskEngine.max_drawdown_pct == 10.0 &&
|
| config.RiskEngine.kelly_fraction == 0.25 &&
|
| config.RiskEngine.var_confidence == 0.95
|
| );
|
|
|
| ulong end = GetMicrosecondCount();
|
| double time_ms = (end - start) / 1000.0;
|
|
|
| AddResult("Config_RiskDefaults", defaults_ok,
|
| StringFormat("MaxDD=%.1f%%, Kelly=%.2f, VaR=%.2f",
|
| config.RiskEngine.max_drawdown_pct,
|
| config.RiskEngine.kelly_fraction,
|
| config.RiskEngine.var_confidence),
|
| time_ms);
|
| }
|
|
|
| void Test_Config_InvalidRanges()
|
| {
|
| ulong start = GetMicrosecondCount();
|
|
|
| CArchitectureConfig config;
|
| config.SetAllDefaults();
|
|
|
| // Set invalid values
|
| config.RiskEngine.max_drawdown_pct = -5.0; // Invalid
|
| config.RiskEngine.kelly_fraction = 2.0; // Invalid (> 1.0)
|
|
|
| bool validation_caught = !config.ValidateAll();
|
|
|
| ulong end = GetMicrosecondCount();
|
| double time_ms = (end - start) / 1000.0;
|
|
|
| AddResult("Config_InvalidRanges", validation_caught,
|
| "Validation correctly caught invalid ranges",
|
| time_ms);
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| Error Handling Tests |
|
| //+------------------------------------------------------------------+
|
| void Test_Error_Logging()
|
| {
|
| ulong start = GetMicrosecondCount();
|
|
|
| CErrorHandler handler;
|
| handler.Info(ERR_CAT_SYSTEM, "Test", "TestFunc", "Test info message");
|
| handler.Warning(ERR_CAT_FILE, "Test", "TestFunc", 123, "Test warning");
|
| handler.Error(ERR_CAT_NETWORK, "Test", "TestFunc", 456, "Test error");
|
|
|
| int total = handler.GetErrorCount(ERR_SEVERITY_INFO) +
|
| handler.GetErrorCount(ERR_SEVERITY_WARNING) +
|
| handler.GetErrorCount(ERR_SEVERITY_ERROR);
|
|
|
| ulong end = GetMicrosecondCount();
|
| double time_ms = (end - start) / 1000.0;
|
|
|
| AddResult("Error_Logging", total == 3,
|
| StringFormat("Logged %d errors correctly", total),
|
| time_ms);
|
| }
|
|
|
| void Test_Error_Categories()
|
| {
|
| ulong start = GetMicrosecondCount();
|
|
|
| CErrorHandler handler;
|
|
|
| // Log one error per category
|
| for(int cat = ERR_CAT_INIT; cat <= ERR_CAT_SYSTEM; cat++)
|
| {
|
| handler.Error((ENUM_ERROR_CATEGORY)cat, "Test", "TestFunc", cat, "Category test");
|
| }
|
|
|
| int total_categories = 0;
|
| for(int cat = ERR_CAT_INIT; cat <= ERR_CAT_SYSTEM; cat++)
|
| {
|
| if(handler.GetCategoryCount((ENUM_ERROR_CATEGORY)cat) > 0)
|
| total_categories++;
|
| }
|
|
|
| ulong end = GetMicrosecondCount();
|
| double time_ms = (end - start) / 1000.0;
|
|
|
| AddResult("Error_Categories", total_categories == 9,
|
| StringFormat("Logged errors in %d/9 categories", total_categories),
|
| time_ms);
|
| }
|
|
|
| void Test_Error_CircuitBreaker()
|
| {
|
| ulong start = GetMicrosecondCount();
|
|
|
| CErrorHandler handler;
|
|
|
| // Trip circuit breaker
|
| for(int i = 0; i < 15; i++)
|
| {
|
| handler.Error(ERR_CAT_SYSTEM, "Test", "TestFunc", i, "Circuit breaker test");
|
| }
|
|
|
| bool tripped = handler.IsCircuitBreakerTripped();
|
|
|
| ulong end = GetMicrosecondCount();
|
| double time_ms = (end - start) / 1000.0;
|
|
|
| AddResult("Error_CircuitBreaker", tripped,
|
| "Circuit breaker tripped after 10 errors",
|
| time_ms);
|
| }
|
|
|
| void Test_Error_History()
|
| {
|
| ulong start = GetMicrosecondCount();
|
|
|
| CErrorHandler handler;
|
|
|
| // Log some errors
|
| for(int i = 0; i < 5; i++)
|
| {
|
| handler.Error(ERR_CAT_SYSTEM, "Test", "TestFunc", i, "History test");
|
| }
|
|
|
| string recent = handler.GetRecentErrors(3);
|
| bool has_history = StringFind(recent, "History test") >= 0;
|
|
|
| ulong end = GetMicrosecondCount();
|
| double time_ms = (end - start) / 1000.0;
|
|
|
| AddResult("Error_History", has_history,
|
| "Error history correctly maintained",
|
| time_ms);
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| Resource Manager Tests |
|
| //+------------------------------------------------------------------+
|
| void Test_Resource_IndicatorTracking()
|
| {
|
| ulong start = GetMicrosecondCount();
|
|
|
| CResourceManager manager;
|
|
|
| // Simulate indicator handle (use a dummy value)
|
| int dummy_handle = 12345;
|
| manager.TrackIndicator(dummy_handle, "Test", "Test MA indicator", __FILE__, __LINE__);
|
|
|
| // Release it
|
| bool released = manager.ReleaseIndicator(dummy_handle, "Test");
|
|
|
| ulong end = GetMicrosecondCount();
|
| double time_ms = (end - start) / 1000.0;
|
|
|
| AddResult("Resource_Indicator", released,
|
| "Indicator handle tracked and released",
|
| time_ms);
|
| }
|
|
|
| void Test_Resource_FileTracking()
|
| {
|
| ulong start = GetMicrosecondCount();
|
|
|
| CResourceManager manager;
|
|
|
| // Simulate file handle
|
| int dummy_handle = 67890;
|
| manager.TrackFile(dummy_handle, "Test", "Test log file", __FILE__, __LINE__);
|
|
|
| // Release it
|
| bool released = manager.ReleaseFile(dummy_handle, "Test");
|
|
|
| ulong end = GetMicrosecondCount();
|
| double time_ms = (end - start) / 1000.0;
|
|
|
| AddResult("Resource_File", released,
|
| "File handle tracked and released",
|
| time_ms);
|
| }
|
|
|
| void Test_Resource_Ownership()
|
| {
|
| ulong start = GetMicrosecondCount();
|
|
|
| CResourceManager manager;
|
|
|
| // Track multiple resources for different owners
|
| manager.TrackIndicator(1001, "OwnerA", "MA20", __FILE__, __LINE__);
|
| manager.TrackIndicator(1002, "OwnerA", "RSI14", __FILE__, __LINE__);
|
| manager.TrackIndicator(1003, "OwnerB", "MACD", __FILE__, __LINE__);
|
|
|
| // Release all for OwnerA
|
| int released = manager.ReleaseAllForOwner("OwnerA");
|
|
|
| ulong end = GetMicrosecondCount();
|
| double time_ms = (end - start) / 1000.0;
|
|
|
| AddResult("Resource_Ownership", released == 2,
|
| StringFormat("Released %d resources for OwnerA", released),
|
| time_ms);
|
| }
|
|
|
| void Test_Resource_LeakDetection()
|
| {
|
| ulong start = GetMicrosecondCount();
|
|
|
| CResourceManager manager;
|
|
|
| // Track resources but don't release some
|
| manager.TrackIndicator(2001, "Test", "Released", __FILE__, __LINE__);
|
| manager.TrackIndicator(2002, "Test", "Leaked", __FILE__, __LINE__);
|
|
|
| // Only release one
|
| manager.ReleaseIndicator(2001, "Test");
|
|
|
| // Check stats
|
| string stats = manager.GetStatistics();
|
| bool has_leak_info = StringFind(stats, "Leaked") >= 0 || StringFind(stats, "Alloc") >= 0;
|
|
|
| ulong end = GetMicrosecondCount();
|
| double time_ms = (end - start) / 1000.0;
|
|
|
| AddResult("Resource_LeakDetection", has_leak_info,
|
| "Leak detection statistics available",
|
| time_ms);
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| Integration Tests |
|
| //+------------------------------------------------------------------+
|
| void Test_Integration_AllSystems()
|
| {
|
| ulong start = GetMicrosecondCount();
|
|
|
| // Test all systems working together
|
| CArchitectureConfig config;
|
| config.SetAllDefaults();
|
|
|
| CErrorHandler errors;
|
| CResourceManager resources;
|
|
|
| // Simulate a scenario: Config validation fails
|
| config.GateSystem.total_budget_us = 100; // Too small
|
|
|
| if(!config.ValidateAll())
|
| {
|
| errors.Error(ERR_CAT_CONFIG, "Integration", "Test", 1, "Config validation failed");
|
| }
|
|
|
| // Simulate resource allocation
|
| resources.TrackIndicator(3001, "Integration", "Test Indicator", __FILE__, __LINE__);
|
|
|
| bool all_working = (
|
| errors.GetErrorCount(ERR_SEVERITY_ERROR) > 0 &&
|
| StringFind(resources.GetStatistics(), "Alloc") >= 0
|
| );
|
|
|
| ulong end = GetMicrosecondCount();
|
| double time_ms = (end - start) / 1000.0;
|
|
|
| AddResult("Integration_AllSystems", all_working,
|
| "All architectural systems integrated and functional",
|
| time_ms);
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| Result Management |
|
| //+------------------------------------------------------------------+
|
| void AddResult(const string name, bool passed, const string msg, double time_ms)
|
| {
|
| int idx = m_result_count;
|
| if(idx >= ArraySize(m_results))
|
| {
|
| ArrayResize(m_results, ArraySize(m_results) + 50);
|
| }
|
|
|
| m_results[idx].Set(name, passed, msg, time_ms);
|
| m_result_count++;
|
|
|
| if(passed)
|
| m_passed_count++;
|
| else
|
| m_failed_count++;
|
| }
|
|
|
| void PrintResults(double total_time_ms)
|
| {
|
| Print("\n----------------------------------------");
|
| Print(" TEST RESULTS SUMMARY");
|
| Print("----------------------------------------\n");
|
|
|
| for(int i = 0; i < m_result_count; i++)
|
| {
|
| Print(m_results[i].ToString());
|
| }
|
|
|
| Print("\n----------------------------------------");
|
| Print(StringFormat(" TOTAL: %d tests | %d passed | %d failed",
|
| m_result_count, m_passed_count, m_failed_count));
|
| Print(StringFormat(" Execution Time: %.2f ms", total_time_ms));
|
| Print(StringFormat(" Success Rate: %.1f%%",
|
| (double)m_passed_count / m_result_count * 100.0));
|
| Print("----------------------------------------\n");
|
|
|
| if(m_failed_count == 0)
|
| {
|
| Print(" ✅ ALL TESTS PASSED - Architecture ready for production");
|
| }
|
| else
|
| {
|
| Print(StringFormat(" ⚠️ %d TESTS FAILED - Review failures above", m_failed_count));
|
| }
|
|
|
| Print("========================================\n");
|
| }
|
| };
|
|
|
| //+------------------------------------------------------------------+
|
| //| Global Test Function |
|
| //+------------------------------------------------------------------+
|
| bool RunArchitectureTests()
|
| {
|
| CArchitectureTestSuite test_suite;
|
| return test_suite.RunAllTests();
|
| }
|
|
|
| #endif // CARCHITECTURE_TESTS_MQH
|