Generic driver-agnostic autoresearch test runner Tests all channels using the specified configuration
| 600 | // Generic driver-agnostic autoresearch test runner |
| 601 | // Tests all channels using the specified configuration |
| 602 | void runTest(const char* test_name, |
| 603 | fl::AutoResearchConfig& config, |
| 604 | int& total, int& passed) { |
| 605 | // Multi-lane limitation: Only test Lane 0 (first channel) |
| 606 | // Hardware constraint: Only one TX channel can be read from via RX loopback |
| 607 | size_t channels_to_test = config.tx_configs.size() > 1 ? 1 : config.tx_configs.size(); |
| 608 | |
| 609 | if (config.tx_configs.size() > 1) { |
| 610 | FL_WARN("\n[MULTI-LANE] Testing " << config.tx_configs.size() << " lanes, testing Lane 0 only (hardware limitation)"); |
| 611 | } |
| 612 | |
| 613 | // Test enabled configs (Lane 0 only for multi-lane) |
| 614 | for (size_t config_idx = 0; config_idx < channels_to_test; config_idx++) { |
| 615 | total++; |
| 616 | |
| 617 | // Build test context for detailed error reporting |
| 618 | const auto& leds = config.tx_configs[config_idx].mLeds; |
| 619 | size_t num_leds = leds.size(); |
| 620 | |
| 621 | fl::TestContext ctx{ |
| 622 | config.driver_name, |
| 623 | config.timing_name, |
| 624 | fl::toString(config.rx_type), |
| 625 | test_name, |
| 626 | static_cast<int>(config.tx_configs.size()), |
| 627 | static_cast<int>(config_idx), |
| 628 | config.base_strip_size, |
| 629 | static_cast<int>(num_leds), |
| 630 | config.tx_configs[config_idx].getDataPin() |
| 631 | }; |
| 632 | |
| 633 | FL_WARN("\n=== " << test_name << " [Lane " << config_idx << "/" << config.tx_configs.size() |
| 634 | << ", Pin " << config.tx_configs[config_idx].getDataPin() |
| 635 | << ", LEDs " << config.tx_configs[config_idx].mLeds.size() << "] ==="); |
| 636 | |
| 637 | // Use RX channel provided via config (created in .ino file, never created dynamically here) |
| 638 | if (!config.rx_channel) { |
| 639 | FL_ERROR("[" << ctx.driver_name << "/" << ctx.timing_name << "/" << ctx.pattern_name |
| 640 | << " | Lane " << ctx.lane_index << "/" << ctx.lane_count |
| 641 | << " (Pin " << ctx.pin_number << ", " << ctx.num_leds << " LEDs) | RX:" << ctx.rx_type_name << "] " |
| 642 | << "RX channel is null - must be created in .ino and passed via AutoResearchConfig"); |
| 643 | FL_ERROR("Result: FAIL ✗ (RX channel not provided)"); |
| 644 | continue; |
| 645 | } |
| 646 | |
| 647 | size_t bytes_captured = capture(config.rx_channel, config.rx_buffer, config.timing, config.driver_name); |
| 648 | |
| 649 | if (bytes_captured == 0) { |
| 650 | FL_ERROR("[" << ctx.driver_name << "/" << ctx.timing_name << "/" << ctx.pattern_name |
| 651 | << " | Lane " << ctx.lane_index << "/" << ctx.lane_count |
| 652 | << " (Pin " << ctx.pin_number << ", " << ctx.num_leds << " LEDs) | RX:" << ctx.rx_type_name << "] " |
| 653 | << "Result: FAIL ✗ (capture failed)"); |
| 654 | continue; |
| 655 | } |
| 656 | |
| 657 | int mismatches = 0; |
| 658 | |
| 659 | if (isUCS7604(config.encoder)) { |
no test coverage detected