test: salvage the orphaned labels/disc triage, and extract build_labels
Thirteen agents triaging src/labels and src/disc died on a saturated
machine, leaving 5,836 insertions across 28 files uncommitted in a
worktree. Recovered by 3-way apply onto twelve commits of drift; zero
conflicts. The diff was archived to freemkv-private first, because a
worktree is not a backup and this one had already nearly been lost.
One production change, and it is the right one: mpls_universal::parse
read every playlist off the disc AND converted the entries to labels in
a single function, so the conversion — stream-type mapping, dedup key,
the dense global counters — could only be reached through a synthetic
UDF image. Extracted to build_labels(&[Playlist]), which unit tests can
drive from already-parsed values. Behaviour-preserving: same iteration
order, same skip-on-error.
Two collisions resolved by hand:
A second mod pass_progress_tests, written independently against the
same survivors as the one committed in c610285. Kept mine — it covers
the distinct-counters case and the Progress blanket impl, which theirs
does not — but theirs had three clamp tests mine lacked: good_pct,
bad_pct and pending_pct also clamp an overshoot, and I had only tested
that for work_pct. Merged those in as one test and proved each of the
three clamps load-bearing by removing them individually.
An unused_parens warning in a new fixture.
Method note, recorded because it cost real time: git apply --3way
STAGES its result, so `git diff` reads empty and the tree looks
untouched. I nearly concluded the patch had silently failed. Worse, the
first attempt piped through `head -20`, so `echo exit=$?` reported
head's status rather than git's — the same mistake this audit has
already documented once. Check the real exit status, and check
--cached, not just the working tree.
This commit is contained in:
+25
-1
@@ -306,7 +306,7 @@ pub(super) fn drive_has_disc(path: &Path) -> Result<bool> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{K_MAX_CDB_SIZE, OPEN, bsd_name_of, drive_has_disc};
|
||||
use super::{K_MAX_CDB_SIZE, OPEN, bsd_name_of, cstr_to_str, drive_has_disc};
|
||||
use crate::error::Error;
|
||||
use std::path::Path;
|
||||
use std::sync::atomic::Ordering;
|
||||
@@ -318,6 +318,30 @@ mod tests {
|
||||
assert_eq!(bsd_name_of(Path::new("disk4")).unwrap(), "disk4");
|
||||
}
|
||||
|
||||
/// The shim's fixed-width `[u8; N]` fields are C strings: NUL-terminated,
|
||||
/// with trailing bytes undefined/garbage past the terminator. `cstr_to_str`
|
||||
/// must stop at the first NUL, not read the full fixed width, and must
|
||||
/// never panic on a non-UTF-8 tail the shim could hand back.
|
||||
#[test]
|
||||
fn cstr_to_str_stops_at_first_nul() {
|
||||
let mut bytes = [0xAAu8; 8]; // 0xAA is not valid UTF-8 on its own
|
||||
bytes[..5].copy_from_slice(b"BU40N");
|
||||
bytes[5] = 0; // terminator; bytes[6..8] remain 0xAA "garbage"
|
||||
assert_eq!(cstr_to_str(&bytes), "BU40N");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cstr_to_str_no_nul_uses_whole_buffer() {
|
||||
let bytes = *b"HL-DT-ST";
|
||||
assert_eq!(cstr_to_str(&bytes), "HL-DT-ST");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cstr_to_str_invalid_utf8_returns_empty_not_panic() {
|
||||
let bytes = [0xFFu8, 0xFE, 0x00, 0x00];
|
||||
assert_eq!(cstr_to_str(&bytes), "");
|
||||
}
|
||||
|
||||
/// `drive_has_disc` is documented as a cheap, side-effect-free presence
|
||||
/// probe. It used to be implemented by constructing a FULL exclusive
|
||||
/// transport, whose first act is `diskutil unmountDisk force` on the target
|
||||
|
||||
@@ -1205,6 +1205,57 @@ mod scsi_sense_predicate_tests {
|
||||
assert_eq!(ScsiSense::NONE.sense_key, SENSE_KEY_NO_SENSE);
|
||||
assert!(ScsiSense::NONE.is_marginal());
|
||||
}
|
||||
|
||||
/// `is_css_locked` must be the exact triple `05/6F/03` (MMC "READ OF
|
||||
/// SCRAMBLED SECTOR WITHOUT AUTHENTICATION"), all three fields ANDed
|
||||
/// together — not any single field, and not an OR of the three. The
|
||||
/// CSS crack scan keys on this to positively distinguish "encrypted but
|
||||
/// locked" from "unreadable"; a false positive on a bare ILLEGAL REQUEST
|
||||
/// (e.g. a malformed CDB) would make the scanner treat an unrelated
|
||||
/// error as proof of CSS scrambling.
|
||||
#[test]
|
||||
fn is_css_locked_requires_exact_key_asc_ascq_triple() {
|
||||
// The real signature: true.
|
||||
assert!(
|
||||
ScsiSense {
|
||||
sense_key: SENSE_KEY_ILLEGAL_REQUEST,
|
||||
asc: 0x6F,
|
||||
ascq: 0x03,
|
||||
}
|
||||
.is_css_locked()
|
||||
);
|
||||
// Right key, wrong ASC only -> must be false (rules out `||`
|
||||
// between key and asc, and rules out the `true` constant mutant).
|
||||
assert!(
|
||||
!ScsiSense {
|
||||
sense_key: SENSE_KEY_ILLEGAL_REQUEST,
|
||||
asc: 0x00,
|
||||
ascq: 0x03,
|
||||
}
|
||||
.is_css_locked()
|
||||
);
|
||||
// Right key, right ASC, wrong ASCQ -> must be false (rules out `||`
|
||||
// between asc and ascq).
|
||||
assert!(
|
||||
!ScsiSense {
|
||||
sense_key: SENSE_KEY_ILLEGAL_REQUEST,
|
||||
asc: 0x6F,
|
||||
ascq: 0x00,
|
||||
}
|
||||
.is_css_locked()
|
||||
);
|
||||
// Right ASC/ASCQ but wrong key (e.g. a bare ILLEGAL REQUEST with
|
||||
// unrelated ASC/ASCQ would already fail above; here flip the key
|
||||
// instead) -> must be false.
|
||||
assert!(
|
||||
!ScsiSense {
|
||||
sense_key: SENSE_KEY_MEDIUM_ERROR,
|
||||
asc: 0x6F,
|
||||
ascq: 0x03,
|
||||
}
|
||||
.is_css_locked()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user