286 lines
6.8 KiB
C++
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("========================================");
|
|
}
|