test(library-select): teensy41 LDF leak diagnostic (#267 follow-up)#269
Conversation
Fix 1) Per the Fix 1 investigation on #267, this `#[ignore]`-gated test runs the real LDF resolver against the cached `framework-arduinoteensy` library set with two scenarios: - Scenario A: FastLED's full local source tree (`~/dev/fastled/src`) as the project root. Selects 10 framework libs; ssd1351 is NOT one of them. - Scenario B: sketch-only project with a Blink.ino that does just `#include <FastLED.h>`. Selects 4 framework libs; ssd1351 is still NOT one of them. The test prints what's selected and stats, then asserts via output whether ssd1351 appears. It's diagnostic-only — `#[ignore]`d so it only runs on demand: soldr cargo test -p fbuild-library-select \ --test teensy41_ldf_diag -- --ignored --nocapture Requires cached `~/.fbuild/prod/cache/platforms/dl-framework-arduinoteensy-*/` and local `~/dev/fastled/src/`. Skips with a printed reason if missing so it stays harmless in CI. Lets future investigations quickly answer "does the LDF select X?" without rebuilding the issue from scratch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds a new ignored diagnostic test file that exercises the LDF resolver against real Teensyduino framework libraries and a user's local FastLED source tree. Includes helper functions for path discovery and file collection, plus two test scenarios that run the resolver and log selected libraries and source files. ChangesDiagnostic Test Infrastructure for LDF Resolver
Estimated Code Review Effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly Related Issues
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
crates/fbuild-library-select/tests/teensy41_ldf_diag.rs (1)
31-54: ⚡ Quick winAvoid hardcoding
~/.fbuild/prod/cache/platformsin test discovery.Using a fixed
prodpath can cause false skips fordevmode users or whenFBUILD_CACHE_DIRis overridden. Prefer deriving the cache root from the canonical path helper and appendingplatforms.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/fbuild-library-select/tests/teensy41_ldf_diag.rs` around lines 31 - 54, In find_teensy_libraries(), don't hardcode home/.fbuild/prod/cache/platforms; instead obtain the canonical cache root via the crate's existing helper (e.g., the canonical cache root function such as fbuild::paths::cache_root() or equivalent that respects FBUILD_CACHE_DIR and dev/prod modes) and then append "platforms" (root = canonical_cache_root().join("platforms")), keeping the rest of the directory traversal logic the same so discovery works for both dev and prod/custom cache locations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/fbuild-library-select/tests/teensy41_ldf_diag.rs`:
- Around line 130-177: The test only logs whether "ssd1351" was picked but
doesn't fail on regressions; after computing ssd1351_selected (from
selection.required_libraries) add a hard assertion such as
assert!(!ssd1351_selected, "ssd1351 leaked into Scenario A: selection={:?}",
selection.required_libraries) to fail the test if it was selected; similarly,
after computing scen_b_ssd (from sketch_sel.required_libraries) add
assert!(!scen_b_ssd, "ssd1351 leaked into Scenario B: sketch_sel={:?}",
sketch_sel.required_libraries). Use the existing boolean variables
ssd1351_selected and scen_b_ssd and include a clear message showing the relevant
selection vector for debugging.
---
Nitpick comments:
In `@crates/fbuild-library-select/tests/teensy41_ldf_diag.rs`:
- Around line 31-54: In find_teensy_libraries(), don't hardcode
home/.fbuild/prod/cache/platforms; instead obtain the canonical cache root via
the crate's existing helper (e.g., the canonical cache root function such as
fbuild::paths::cache_root() or equivalent that respects FBUILD_CACHE_DIR and
dev/prod modes) and then append "platforms" (root =
canonical_cache_root().join("platforms")), keeping the rest of the directory
traversal logic the same so discovery works for both dev and prod/custom cache
locations.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: ea77565d-9401-40eb-88d4-f8a0d7b88e59
📒 Files selected for processing (1)
crates/fbuild-library-select/tests/teensy41_ldf_diag.rs
| let ssd1351_selected = selection | ||
| .required_libraries | ||
| .iter() | ||
| .any(|n| n.eq_ignore_ascii_case("ssd1351")); | ||
| eprintln!( | ||
| "---\nssd1351 SELECTED? {}", | ||
| if ssd1351_selected { | ||
| "YES (leak — bug)" | ||
| } else { | ||
| "no" | ||
| } | ||
| ); | ||
|
|
||
| // ---- Scenario B: project has NO local FastLED visible to the walker, | ||
| // only an example sketch that does `#include <FastLED.h>`. This is | ||
| // what happens if the per-example build's src_dir doesn't include the | ||
| // repo src. Walker falls through to bundled FastLED → expect leak. | ||
| eprintln!("---\n=== Scenario B: sketch-only project (no local FastLED in roots) ==="); | ||
| let tmp = tempfile::tempdir().expect("tempdir"); | ||
| let sketch_src = tmp.path().join("src"); | ||
| std::fs::create_dir_all(&sketch_src).unwrap(); | ||
| std::fs::write( | ||
| sketch_src.join("Blink.ino"), | ||
| "#include <FastLED.h>\nvoid setup(){} void loop(){}\n", | ||
| ) | ||
| .unwrap(); | ||
| let sketch_seeds = collect_seeds(&sketch_src); | ||
| let sketch_paths = vec![sketch_src.clone()]; | ||
| let (sketch_sel, sketch_stats) = resolve_with_stats(&sketch_seeds, &sketch_paths, &libraries); | ||
| eprintln!( | ||
| "Scenario B STATS: passes={} files_read={}", | ||
| sketch_stats.passes, sketch_stats.files_read | ||
| ); | ||
| eprintln!( | ||
| "Scenario B SELECTED ({}):", | ||
| sketch_sel.required_libraries.len() | ||
| ); | ||
| for name in &sketch_sel.required_libraries { | ||
| eprintln!(" - {name}"); | ||
| } | ||
| let scen_b_ssd = sketch_sel | ||
| .required_libraries | ||
| .iter() | ||
| .any(|n| n.eq_ignore_ascii_case("ssd1351")); | ||
| eprintln!( | ||
| "Scenario B ssd1351? {}", | ||
| if scen_b_ssd { "YES (leak)" } else { "no" } | ||
| ); |
There was a problem hiding this comment.
Add hard assertions for ssd1351 absence in both scenarios.
This diagnostic currently only logs leak status; it never fails when ssd1351 is selected. That makes regressions easy to miss.
Proposed fix
@@
let ssd1351_selected = selection
.required_libraries
.iter()
.any(|n| n.eq_ignore_ascii_case("ssd1351"));
@@
eprintln!(
"---\nssd1351 SELECTED? {}",
if ssd1351_selected {
"YES (leak — bug)"
} else {
"no"
}
);
+ assert!(
+ !ssd1351_selected,
+ "Scenario A regression: ssd1351 was selected but should not be"
+ );
@@
let scen_b_ssd = sketch_sel
.required_libraries
.iter()
.any(|n| n.eq_ignore_ascii_case("ssd1351"));
@@
eprintln!(
"Scenario B ssd1351? {}",
if scen_b_ssd { "YES (leak)" } else { "no" }
);
+ assert!(
+ !scen_b_ssd,
+ "Scenario B regression: ssd1351 was selected but should not be"
+ );📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| let ssd1351_selected = selection | |
| .required_libraries | |
| .iter() | |
| .any(|n| n.eq_ignore_ascii_case("ssd1351")); | |
| eprintln!( | |
| "---\nssd1351 SELECTED? {}", | |
| if ssd1351_selected { | |
| "YES (leak — bug)" | |
| } else { | |
| "no" | |
| } | |
| ); | |
| // ---- Scenario B: project has NO local FastLED visible to the walker, | |
| // only an example sketch that does `#include <FastLED.h>`. This is | |
| // what happens if the per-example build's src_dir doesn't include the | |
| // repo src. Walker falls through to bundled FastLED → expect leak. | |
| eprintln!("---\n=== Scenario B: sketch-only project (no local FastLED in roots) ==="); | |
| let tmp = tempfile::tempdir().expect("tempdir"); | |
| let sketch_src = tmp.path().join("src"); | |
| std::fs::create_dir_all(&sketch_src).unwrap(); | |
| std::fs::write( | |
| sketch_src.join("Blink.ino"), | |
| "#include <FastLED.h>\nvoid setup(){} void loop(){}\n", | |
| ) | |
| .unwrap(); | |
| let sketch_seeds = collect_seeds(&sketch_src); | |
| let sketch_paths = vec![sketch_src.clone()]; | |
| let (sketch_sel, sketch_stats) = resolve_with_stats(&sketch_seeds, &sketch_paths, &libraries); | |
| eprintln!( | |
| "Scenario B STATS: passes={} files_read={}", | |
| sketch_stats.passes, sketch_stats.files_read | |
| ); | |
| eprintln!( | |
| "Scenario B SELECTED ({}):", | |
| sketch_sel.required_libraries.len() | |
| ); | |
| for name in &sketch_sel.required_libraries { | |
| eprintln!(" - {name}"); | |
| } | |
| let scen_b_ssd = sketch_sel | |
| .required_libraries | |
| .iter() | |
| .any(|n| n.eq_ignore_ascii_case("ssd1351")); | |
| eprintln!( | |
| "Scenario B ssd1351? {}", | |
| if scen_b_ssd { "YES (leak)" } else { "no" } | |
| ); | |
| let ssd1351_selected = selection | |
| .required_libraries | |
| .iter() | |
| .any(|n| n.eq_ignore_ascii_case("ssd1351")); | |
| eprintln!( | |
| "---\nssd1351 SELECTED? {}", | |
| if ssd1351_selected { | |
| "YES (leak — bug)" | |
| } else { | |
| "no" | |
| } | |
| ); | |
| assert!( | |
| !ssd1351_selected, | |
| "Scenario A regression: ssd1351 was selected but should not be" | |
| ); | |
| // ---- Scenario B: project has NO local FastLED visible to the walker, | |
| // only an example sketch that does `#include <FastLED.h>`. This is | |
| // what happens if the per-example build's src_dir doesn't include the | |
| // repo src. Walker falls through to bundled FastLED → expect leak. | |
| eprintln!("---\n=== Scenario B: sketch-only project (no local FastLED in roots) ==="); | |
| let tmp = tempfile::tempdir().expect("tempdir"); | |
| let sketch_src = tmp.path().join("src"); | |
| std::fs::create_dir_all(&sketch_src).unwrap(); | |
| std::fs::write( | |
| sketch_src.join("Blink.ino"), | |
| "`#include` <FastLED.h>\nvoid setup(){} void loop(){}\n", | |
| ) | |
| .unwrap(); | |
| let sketch_seeds = collect_seeds(&sketch_src); | |
| let sketch_paths = vec![sketch_src.clone()]; | |
| let (sketch_sel, sketch_stats) = resolve_with_stats(&sketch_seeds, &sketch_paths, &libraries); | |
| eprintln!( | |
| "Scenario B STATS: passes={} files_read={}", | |
| sketch_stats.passes, sketch_stats.files_read | |
| ); | |
| eprintln!( | |
| "Scenario B SELECTED ({}):", | |
| sketch_sel.required_libraries.len() | |
| ); | |
| for name in &sketch_sel.required_libraries { | |
| eprintln!(" - {name}"); | |
| } | |
| let scen_b_ssd = sketch_sel | |
| .required_libraries | |
| .iter() | |
| .any(|n| n.eq_ignore_ascii_case("ssd1351")); | |
| eprintln!( | |
| "Scenario B ssd1351? {}", | |
| if scen_b_ssd { "YES (leak)" } else { "no" } | |
| ); | |
| assert!( | |
| !scen_b_ssd, | |
| "Scenario B regression: ssd1351 was selected but should not be" | |
| ); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@crates/fbuild-library-select/tests/teensy41_ldf_diag.rs` around lines 130 -
177, The test only logs whether "ssd1351" was picked but doesn't fail on
regressions; after computing ssd1351_selected (from
selection.required_libraries) add a hard assertion such as
assert!(!ssd1351_selected, "ssd1351 leaked into Scenario A: selection={:?}",
selection.required_libraries) to fail the test if it was selected; similarly,
after computing scen_b_ssd (from sketch_sel.required_libraries) add
assert!(!scen_b_ssd, "ssd1351 leaked into Scenario B: sketch_sel={:?}",
sketch_sel.required_libraries). Use the existing boolean variables
ssd1351_selected and scen_b_ssd and include a clear message showing the relevant
selection vector for debugging.
Follow-up to #267 (Fix 1 investigation).
Summary
Adds an
#[ignore]-gated diagnostic test that runs the real LDF resolver against the cachedframework-arduinoteensylibrary set with two scenarios:#include <FastLED.h>). Selects 4 framework libs; ssd1351 NOT among them.The diagnostic was used to confirm that Bug 1 from #267 (LDF selecting ssd1351 when Blink doesn't reference it) does not reproduce on current code (v2.2.6). Full investigation summary on the issue: #267 (comment)
Why ship the diagnostic as a permanent test
Future LDF-leak investigations can quickly answer "does the resolver select X for board Y?" without rebuilding the harness from scratch. The
#[ignore]gate keeps it out of normal CI; it skips silently if the cached Teensyduino framework isn't on the host.Test plan
soldr cargo check -p fbuild-library-select --tests— cleansoldr cargo fmt --check— clean--ignored --nocapture— both scenarios pass; ssd1351 NOT selected in either#[ignore]d so doesn't run by default)🤖 Generated with Claude Code
Summary by CodeRabbit
Note: This release contains no user-facing changes or feature updates.