Multi-run autoresearch test runner Runs the same test multiple times and tracks errors across runs
| 744 | // Multi-run autoresearch test runner |
| 745 | // Runs the same test multiple times and tracks errors across runs |
| 746 | void runMultiTest(const char* test_name, |
| 747 | fl::AutoResearchConfig& config, |
| 748 | const fl::MultiRunConfig& multi_config, |
| 749 | int& total, int& passed, |
| 750 | fl::vector<fl::RunResult>* out_results) { |
| 751 | |
| 752 | fl::sstream ss; |
| 753 | ss << "\n╔════════════════════════════════════════════════════════════════╗\n"; |
| 754 | ss << "║ MULTI-RUN TEST: " << test_name << "\n"; |
| 755 | ss << "║ Runs: " << multi_config.num_runs << " | Print Mode: " |
| 756 | << (multi_config.print_all_runs ? "All" : "Errors ONLY") << "\n"; |
| 757 | ss << "╚════════════════════════════════════════════════════════════════╝"; |
| 758 | FL_WARN(ss.str()); |
| 759 | |
| 760 | fl::vector<fl::RunResult> run_results; |
| 761 | |
| 762 | // Multi-lane limitation: Only test Lane 0 |
| 763 | size_t channels_to_test = config.tx_configs.size() > 1 ? 1 : config.tx_configs.size(); |
| 764 | |
| 765 | if (config.tx_configs.size() > 1) { |
| 766 | FL_WARN("[MULTI-LANE] Testing " << config.tx_configs.size() << " lanes, testing Lane 0 only"); |
| 767 | } |
| 768 | |
| 769 | // Execute multiple runs |
| 770 | for (int run = 1; run <= multi_config.num_runs; run++) { |
| 771 | // Print progress to keep output flowing (prevents auto-exit timeout) |
| 772 | if (run % 3 == 1 || multi_config.num_runs <= 5) { |
| 773 | FL_WARN("[Run " << run << "/" << multi_config.num_runs << "] Testing..."); |
| 774 | } |
| 775 | |
| 776 | fl::RunResult result; |
| 777 | result.run_number = run; |
| 778 | |
| 779 | // Test Lane 0 only |
| 780 | for (size_t config_idx = 0; config_idx < channels_to_test; config_idx++) { |
| 781 | const auto& leds = config.tx_configs[config_idx].mLeds; |
| 782 | size_t num_leds = leds.size(); |
| 783 | result.total_leds = num_leds; |
| 784 | result.totalBytes = num_leds * 3; |
| 785 | |
| 786 | // Capture RX data |
| 787 | size_t bytes_captured = capture(config.rx_channel, config.rx_buffer, config.timing, config.driver_name); |
| 788 | |
| 789 | if (bytes_captured == 0) { |
| 790 | FL_WARN("[Run " << run << "] Capture failed"); |
| 791 | result.passed = false; |
| 792 | break; |
| 793 | } |
| 794 | |
| 795 | // Check pixel data |
| 796 | int mismatches = 0; |
| 797 | |
| 798 | // DEBUG: Print first 24 bytes of captured data |
| 799 | FL_WARN("[RUN " << run << "] Driver=" << config.driver_name << ", bytes_captured=" << bytes_captured); |
| 800 | FL_WARN("[RUN " << run << "] First 24 bytes:"); |
| 801 | for (size_t i = 0; i < 24 && i < bytes_captured; i++) { |
| 802 | FL_WARN(" [" << i << "] = 0x" << fl::hex << static_cast<int>(config.rx_buffer[i]) << fl::dec); |
| 803 | } |