CharGraph-FW/lib/CharGraphTimeLogic/blackboxtest/blackboxtest.ino
2026-01-25 20:44:07 +01:00

286 lines
6.8 KiB
C++

/**
* CharGraph TimeLogic - Black Box Test
*
* Automated test suite for CharGraphTimeLogic library
* Tests multiple patterns across a configurable time window
*/
#include "config.h"
#include "../src/CharGraphTimeLogic.h"
// ============================================================================
// GLOBAL TEST STATISTICS
// ============================================================================
struct TestStats {
uint32_t totalTests;
uint32_t passedTests;
uint32_t failedTests;
};
TestStats stats = {0, 0, 0};
// ============================================================================
// SETUP AND INITIALIZATION
// ============================================================================
void setup() {
Serial.begin(SERIAL_BAUD);
delay(1000);
Serial.println("\n\n");
Serial.println("========================================");
Serial.println("CharGraph TimeLogic - Black Box Test");
Serial.println("========================================\n");
Serial.print("Test Patterns: ");
Serial.println(numPatterns);
Serial.print("Time Window: ");
Serial.print(hourStart);
Serial.print(":");
if (minuteStart < 10) Serial.print("0");
Serial.print(minuteStart);
Serial.print(" to ");
Serial.print(hourEnd);
Serial.print(":");
if (minuteEnd < 10) Serial.print("0");
Serial.print(minuteEnd);
Serial.println();
Serial.print("Minute Hops: ");
Serial.println(hops);
Serial.println();
// Run all tests
for (uint8_t patternIdx = 0; patternIdx < numPatterns; patternIdx++) {
runPatternTest(patternIdx, testpatterns[patternIdx]);
}
// Print summary
printTestSummary();
Serial.println("\nTest completed. Ready for next test.\n");
}
void loop() {
// Loop does nothing - tests run in setup
delay(1000);
}
// ============================================================================
// MAIN TEST RUNNER
// ============================================================================
void runPatternTest(uint8_t patternIdx, const char* pattern) {
Serial.println("========================================");
Serial.print("Pattern ");
Serial.print(patternIdx + 1);
Serial.println();
Serial.println("========================================");
Serial.print("Pattern: ");
Serial.println(pattern);
// Verify pattern length
if (strlen(pattern) != GRID_SIZE) {
Serial.print("ERROR: Pattern length ");
Serial.print(strlen(pattern));
Serial.print(" != ");
Serial.println(GRID_SIZE);
return;
}
Serial.println("\nUhrzeit | Text | MinutenLeds | Links | Rechts");
Serial.println("--------|------|-------------|-------|-------");
// Calculate total test count
uint16_t testCount = calculateTestCount();
// Iterate through time window
uint8_t hour = hourStart;
uint8_t minute = minuteStart;
uint16_t count = 0;
while (count < testCount) {
// Get words for this time
CharGraphTimeWords result;
bool success = getCharGraphWords(pattern, hour, minute, result);
// Print result line
printResultLine(hour, minute, result, success);
// Update statistics
stats.totalTests++;
if (success) {
stats.passedTests++;
} else {
stats.failedTests++;
}
// Advance time by hop increment
minute += hops;
if (minute > 59) {
minute -= 60;
hour++;
if (hour > 23) {
hour = 0;
}
}
count++;
}
Serial.println();
}
// ============================================================================
// HELPER FUNCTIONS
// ============================================================================
uint16_t calculateTestCount() {
/**
* Calculate how many minutes will be tested based on:
* - Start and end times
* - Hop increment
*/
uint16_t count = 0;
uint8_t hour = hourStart;
uint8_t minute = minuteStart;
// Safety limit: maximum 10000 iterations to prevent infinite loops
for (uint16_t i = 0; i < 10000; i++) {
count++;
// Check if we've reached the end
if (hour == hourEnd && minute == minuteEnd) {
break;
}
// Advance time
minute += hops;
if (minute > 59) {
minute -= 60;
hour++;
if (hour > 23) {
hour = 0;
}
}
}
return count;
}
void printResultLine(uint8_t hour, uint8_t minute, const CharGraphTimeWords& result, bool success) {
/**
* Print one result line in table format:
* Uhrzeit | Text | MinutenLeds | Links | Rechts
*/
// Uhrzeit
if (hour < 10) Serial.print("0");
Serial.print(hour);
Serial.print(":");
if (minute < 10) Serial.print("0");
Serial.print(minute);
Serial.print(" | ");
// Text (first 37 chars max, padded)
char textBuf[100];
if (success) {
buildTextFromWords(result.words, result.wordCount, textBuf);
} else {
strcpy(textBuf, "ERROR");
}
int len = strlen(textBuf);
Serial.print(textBuf);
for (int i = len; i < 37; i++) {
Serial.print(" ");
}
Serial.print(" | ");
// MinutenLeds (LED count display)
if (result.ledCount > 0) {
for (uint8_t i = 0; i < result.ledCount; i++) {
Serial.print("*"); // Use * instead of emoji for reliability
}
}
for (uint8_t i = result.ledCount; i < 11; i++) {
Serial.print(" ");
}
Serial.print(" | ");
// Links / Rechts
if (result.ledCount > 0) {
if (result.ledDirection == LEFT) {
Serial.print("L");
Serial.print(" | ");
Serial.print("R");
} else {
Serial.print("R");
Serial.print(" | ");
Serial.print("L");
}
} else {
Serial.print(" ");
Serial.print(" | ");
Serial.print(" ");
}
Serial.println();
}
void buildTextFromWords(const char* const* words, uint8_t wordCount, char* outText) {
/**
* Build readable text from word array
*/
if (!words || !outText || wordCount == 0) {
outText[0] = '\0';
return;
}
uint16_t pos = 0;
const uint16_t maxLen = 99;
for (uint8_t i = 0; i < wordCount; i++) {
if (i > 0 && pos < maxLen) {
outText[pos++] = ' ';
}
// Load word from PROGMEM and copy
char wordBuf[11];
strcpy_P(wordBuf, words[i]);
for (uint8_t j = 0; wordBuf[j] != '\0' && pos < maxLen; j++) {
outText[pos++] = wordBuf[j];
}
}
outText[pos] = '\0';
}
void printTestSummary() {
/**
* Print test statistics summary
*/
Serial.println("\n========================================");
Serial.println("TEST SUMMARY");
Serial.println("========================================");
Serial.print("Total Tests: ");
Serial.println(stats.totalTests);
Serial.print("Passed: ");
Serial.println(stats.passedTests);
Serial.print("Failed: ");
Serial.println(stats.failedTests);
if (stats.failedTests == 0) {
Serial.println("\n✓ ALL TESTS PASSED");
} else {
Serial.print("\n");
Serial.print(stats.failedTests);
Serial.println(" TESTS FAILED");
}
Serial.println("========================================");
}