//! Contract tests for lesavka-core gadget rebuild guardrails. //! //! Scope: statically guard the shell logic in `scripts/daemon/lesavka-core.sh`. //! Targets: incomplete gadget recovery behavior. //! Why: the gadget can be bound but half-applied, and the core script must //! rebuild that state instead of refusing reset forever. const CORE_SCRIPT: &str = include_str!("../../scripts/daemon/lesavka-core.sh"); #[test] fn core_script_rebuilds_incomplete_bound_gadgets() { for expected in [ "GADGET_NEEDS_REBUILD=0", "gadget is configured but missing expected functions; continuing toward rebuild.", "GADGET_NEEDS_REBUILD=1", "if [[ -n $BOUND_UDC && -z $ALLOW_RESET && \"$GADGET_NEEDS_REBUILD\" != \"1\" ]]; then", "if [[ -z $ALLOW_RESET ]] && is_attached_state \"$UDC_STATE\" && [[ \"$GADGET_NEEDS_REBUILD\" != \"1\" ]]; then", "incomplete gadget detected; rebuilding even though the old gadget is still bound.", ] { assert!( CORE_SCRIPT.contains(expected), "lesavka-core guardrail missing: {expected}" ); } } #[test] fn core_script_skips_soft_connect_for_dwc2() { for expected in [ "udc_driver()", "udc_supports_soft_connect()", "[[ $driver == \"dwc2\" ]] && return 1", "if udc_supports_soft_connect \"$udc\"; then", ] { assert!( CORE_SCRIPT.contains(expected), "lesavka-core soft_connect guard missing: {expected}" ); } } #[test] fn core_script_uses_kernel_doc_control_header_links() { for expected in [ "pushd \"$F/control\" >/dev/null", "ln -s header/h class/fs", "ln -s header/h class/ss", ] { assert!( CORE_SCRIPT.contains(expected), "lesavka-core control-header guard missing: {expected}" ); } assert!( !CORE_SCRIPT.contains("mkdir -p \"$F/control/class/$s\""), "lesavka-core should not build the UVC control class as nested directories" ); }