logger/tests/UnitTests.mq5

340 lines
12 KiB
MQL5

//+------------------------------------------------------------------+
//| UnitTests.mq5 |
//| Unit Tests for Package logger |
//| Organization: douglasrechia |
//+------------------------------------------------------------------+
#include "../knitpkg/build/BuildInfo.mqh"
#property copyright "Douglas Rechia"
#property link "https://knitpkg.dev"
#property description ""
#property description "Version: " + MANIFEST_VERSION
#property description ""
#property description "Description: Unit tests for package logger"
#property description "Organization: douglasrechia"
#property description "Author: Douglas Rechia"
#property description "License: MIT"
#property description ""
#property description "Powered by KnitPkg for MetaTrader"
#property description "https://knitpkg.dev"
#include "../knitpkg/include/douglasrechia/logger/Logger.mqh"
#include "../knitpkg/include/douglasrechia/logger/handlers/PrintLogger.mqh"
#include "../knitpkg/include/douglasrechia/logger/handlers/FileLogger.mqh"
//+------------------------------------------------------------------+
//| Asserts log file content matches expected patterns |
//+------------------------------------------------------------------+
bool AssertLogContent(string filePath, string &expectedPatterns[], string testName)
{
int fileHandle = FileOpen(filePath, FILE_READ | FILE_TXT | FILE_ANSI);
if(fileHandle == INVALID_HANDLE) {
PrintFormat("%s: Failed to open log file for verification", testName);
return false;
}
int patternIndex = 0;
bool allMatch = true;
int lineNumber = 0;
while(!FileIsEnding(fileHandle)) {
string line = FileReadString(fileHandle);
if(line == "") continue;
lineNumber++;
if(patternIndex >= ArraySize(expectedPatterns)) {
PrintFormat("%s: More lines than expected in log file", testName);
allMatch = false;
break;
}
// Check if line contains expected pattern
if(StringFind(line, expectedPatterns[patternIndex]) < 0) {
PrintFormat("%s: Line %d mismatch. Expected to contain: '%s', Got: '%s'",
testName, lineNumber, expectedPatterns[patternIndex], line);
allMatch = false;
}
patternIndex++;
if(StringFind(line, expectedPatterns[patternIndex]) < 0) {
PrintFormat("%s: Line %d mismatch. Expected to contain: '%s', Got: '%s'",
testName, lineNumber, expectedPatterns[patternIndex], line);
allMatch = false;
}
patternIndex++;
}
FileClose(fileHandle);
if(patternIndex < ArraySize(expectedPatterns)) {
PrintFormat("%s: Expected %d lines, got %d", testName, ArraySize(expectedPatterns), patternIndex);
allMatch = false;
}
return allMatch;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool TestAll()
{
douglasrechia::Logger* g_log = new douglasrechia::Logger(__FILE__, douglasrechia::LOG_LEVEL_DEBUG);
g_log.AddHandler(new douglasrechia::FileLogger("logs/log_test_all.log", true, false));
g_log.Info("TestAll", "info");
g_log.Debug("TestAll", "debug");
g_log.Warn("TestAll", "warn");
g_log.Error("TestAll", "error");
g_log.Info("TestAll info");
g_log.Debug("TestAll debug");
g_log.Warn("TestAll warn");
g_log.Error("TestAll error");
delete g_log;
string expectedPatterns[] = {
"[UnitTests.mq5][INFO ] ", "| TestAll | info",
"[UnitTests.mq5][DEBUG] ", "| TestAll | debug",
"[UnitTests.mq5][WARN ] ", "| TestAll | warn",
"[UnitTests.mq5][ERROR] ", "| TestAll | error",
"[UnitTests.mq5][INFO ] ", "| TestAll info",
"[UnitTests.mq5][DEBUG] ", "| TestAll debug",
"[UnitTests.mq5][WARN ] ", "| TestAll warn",
"[UnitTests.mq5][ERROR] ", "| TestAll error"
};
return AssertLogContent("logs/log_test_all.log", expectedPatterns, "TestAll");
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool TestInfo()
{
douglasrechia::Logger* g_log = new douglasrechia::Logger(__FILE__, douglasrechia::LOG_LEVEL_INFO);
g_log.AddHandler(new douglasrechia::FileLogger("logs/log_test_info.log", true, false));
g_log.Info("TestInfo", "info");
g_log.Debug("TestInfo", "debug");
g_log.Warn("TestInfo", "warn");
g_log.Error("TestInfo", "error");
g_log.Info("TestInfo info");
g_log.Debug("TestInfo debug");
g_log.Warn("TestInfo warn");
g_log.Error("TestInfo error");
delete g_log;
string expectedPatterns[] = {
"[UnitTests.mq5][INFO ] ", "| TestInfo | info",
"[UnitTests.mq5][WARN ] ", "| TestInfo | warn",
"[UnitTests.mq5][ERROR] ", "| TestInfo | error",
"[UnitTests.mq5][INFO ] ", "| TestInfo info",
"[UnitTests.mq5][WARN ] ", "| TestInfo warn",
"[UnitTests.mq5][ERROR] ", "| TestInfo error"
};
return AssertLogContent("logs/log_test_info.log", expectedPatterns, "TestInfo");
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool TestWarn()
{
douglasrechia::Logger* g_log = new douglasrechia::Logger(__FILE__, douglasrechia::LOG_LEVEL_WARN);
g_log.AddHandler(new douglasrechia::FileLogger("logs/log_test_warn.log", true, false));
g_log.Info("TestWarn", "info");
g_log.Debug("TestWarn", "debug");
g_log.Warn("TestWarn", "warn");
g_log.Error("TestWarn", "error");
g_log.Info("TestWarn info");
g_log.Debug("TestWarn debug");
g_log.Warn("TestWarn warn");
g_log.Error("TestWarn error");
delete g_log;
string expectedPatterns[] = {
"[UnitTests.mq5][WARN ] ", "| TestWarn | warn",
"[UnitTests.mq5][ERROR] ", "| TestWarn | error",
"[UnitTests.mq5][WARN ] ", "| TestWarn warn",
"[UnitTests.mq5][ERROR] ", "| TestWarn error"
};
return AssertLogContent("logs/log_test_warn.log", expectedPatterns, "TestWarn");
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool TestError()
{
douglasrechia::Logger* g_log = new douglasrechia::Logger(__FILE__, douglasrechia::LOG_LEVEL_ERROR);
g_log.AddHandler(new douglasrechia::FileLogger("logs/log_test_error.log", true, false));
g_log.Info("TestError", "info");
g_log.Debug("TestError", "debug");
g_log.Warn("TestError", "warn");
g_log.Error("TestError", "error");
g_log.Info("TestError info");
g_log.Debug("TestError debug");
g_log.Warn("TestError warn");
g_log.Error("TestError error");
delete g_log;
string expectedPatterns[] = {
"[UnitTests.mq5][ERROR] ", "| TestError | error",
"[UnitTests.mq5][ERROR] ", "| TestError error"
};
return AssertLogContent("logs/log_test_error.log", expectedPatterns, "TestError");
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool TestErrorAppend()
{
douglasrechia::Logger* g_log = new douglasrechia::Logger(__FILE__, douglasrechia::LOG_LEVEL_ERROR);
g_log.AddHandler(new douglasrechia::FileLogger("logs/log_test_error.log", true, false));
g_log.Info("TestError", "info");
g_log.Debug("TestError", "debug");
g_log.Warn("TestError", "warn");
g_log.Error("TestError", "error");
g_log.Info("TestError info");
g_log.Debug("TestError debug");
g_log.Warn("TestError warn");
g_log.Error("TestError error");
delete g_log;
string expectedPatterns1[] = {
"[UnitTests.mq5][ERROR] ", "| TestError | error",
"[UnitTests.mq5][ERROR] ", "| TestError error"
};
bool check1 = AssertLogContent("logs/log_test_error.log", expectedPatterns1, "TestError");
g_log = new douglasrechia::Logger(__FILE__, douglasrechia::LOG_LEVEL_ERROR);
g_log.AddHandler(new douglasrechia::FileLogger("logs/log_test_error.log", true, true));
g_log.Info("TestError", "info");
g_log.Debug("TestError", "debug");
g_log.Warn("TestError", "warn");
g_log.Error("TestError", "error");
g_log.Info("TestError info");
g_log.Debug("TestError debug");
g_log.Warn("TestError warn");
g_log.Error("TestError error");
delete g_log;
string expectedPatterns2[] = {
"[UnitTests.mq5][ERROR] ", "| TestError | error",
"[UnitTests.mq5][ERROR] ", "| TestError error",
"[UnitTests.mq5][ERROR] ", "| TestError | error",
"[UnitTests.mq5][ERROR] ", "| TestError error"
};
bool check2 = AssertLogContent("logs/log_test_error.log", expectedPatterns2, "TestError");
return check1 && check2;
}
//+------------------------------------------------------------------+
//| DoTests |
//+------------------------------------------------------------------+
void DoTests(int &testsPerformed,int &testsPassed)
{
string testName="";
//--- TestAll
testsPerformed++;
testName="TestAll";
if(TestAll())
{
testsPassed++;
PrintFormat("%s pass",testName);
}
else
PrintFormat("%s failed",testName);
//--- TestInfo
testsPerformed++;
testName="TestInfo";
if(TestInfo())
{
testsPassed++;
PrintFormat("%s pass",testName);
}
else
PrintFormat("%s failed",testName);
//--- TestWarn
testsPerformed++;
testName="TestWarn";
if(TestWarn())
{
testsPassed++;
PrintFormat("%s pass",testName);
}
else
PrintFormat("%s failed",testName);
//--- TestError
testsPerformed++;
testName="TestError";
if(TestError())
{
testsPassed++;
PrintFormat("%s pass",testName);
}
else
PrintFormat("%s failed",testName);
//--- TestErrorAppend
testsPerformed++;
testName="TestErrorAppend";
if(TestErrorAppend())
{
testsPassed++;
PrintFormat("%s pass",testName);
}
else
PrintFormat("%s failed",testName);
//---
// Add more tests here as needed
}
//+------------------------------------------------------------------+
//| UnitTests() |
//+------------------------------------------------------------------+
void UnitTests(const string packageName)
{
PrintFormat("Unit tests for Package %s\n",packageName);
//--- initial values
int testsPerformed=0;
int testsPassed=0;
//--- test distributions
DoTests(testsPerformed,testsPassed);
//--- print statistics
PrintFormat("\n%d of %d passed",testsPassed,testsPerformed);
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
UnitTests("logger");
}
//+------------------------------------------------------------------+