USB external import, and filter chips on health-dot cards

This commit is contained in:
2026-08-29 13:02:45 -04:00
parent b08ae79989
commit b26bbd0456
10 changed files with 610 additions and 7 deletions

View File

@@ -0,0 +1,99 @@
"""Folding an external check-in/out LOG into self-hosted checkout PAIRS.
The external cmmc_usb database records one row per action; the self-hosted
usbcheckouts table records one row per checkout, carrying both times. The
import has to convert between them, and the interesting cases are all the ways
a real log is untidy after years of use: a drive still out, a return nobody
has a matching issue for, two issues in a row.
The rule these tests pin down is that NOTHING is invented and NOTHING vanishes
silently. An unclosed checkout stays unclosed; anything that cannot be paired
is reported. A quieter import that guessed the missing halves would produce a
tidier database and a false audit history, which for removable-media records is
the worst of the available outcomes.
"""
from plugins.usb.cli import _pair, _tri
def _row(action, when, badge='B1'):
return {'action': action, 'timestamp': when, 'badge_number': badge}
def test_a_clean_out_and_in_becomes_one_closed_checkout():
problems = []
pairs = _pair([_row('check-out', 1), _row('check-in', 2)], problems, 'DEV1')
assert len(pairs) == 1
out, back = pairs[0]
assert out['timestamp'] == 1
assert back['timestamp'] == 2
assert problems == []
def test_a_drive_still_out_stays_open_and_is_not_reported_as_a_problem():
# This is the normal state of any drive currently issued to somebody, not
# a data fault, so it must not appear in the problem list.
problems = []
pairs = _pair([_row('check-out', 1)], problems, 'DEV1')
assert len(pairs) == 1
out, back = pairs[0]
assert back is None
assert problems == []
def test_a_return_with_no_matching_issue_is_skipped_and_reported():
problems = []
pairs = _pair([_row('check-in', 5)], problems, 'DEV1')
assert pairs == []
assert len(problems) == 1
assert 'no matching check-out' in problems[0]
assert 'DEV1' in problems[0]
def test_two_issues_in_a_row_leave_the_first_open_rather_than_inventing_a_return():
problems = []
pairs = _pair([_row('check-out', 1, 'ALICE'),
_row('check-out', 2, 'BOB'),
_row('check-in', 3, 'BOB')], problems, 'DEV1')
assert len(pairs) == 2
first, second = pairs
assert first[0]['badge_number'] == 'ALICE'
assert first[1] is None, 'the first checkout must not be given a return time'
assert second[0]['badge_number'] == 'BOB'
assert second[1]['timestamp'] == 3
assert len(problems) == 1
assert 'still out' in problems[0]
def test_an_unrecognised_action_is_skipped_and_reported():
problems = []
pairs = _pair([_row('destroyed', 1)], problems, 'DEV1')
assert pairs == []
assert len(problems) == 1
assert 'unrecognised action' in problems[0]
def test_action_spelling_variants_are_accepted():
# Years of a hand-maintained log produce more than one spelling.
for out_word, in_word in (('check-out', 'check-in'),
('checkout', 'checkin'),
('out', 'in'),
('CHECK_OUT', 'RETURN')):
problems = []
pairs = _pair([_row(out_word, 1), _row(in_word, 2)], problems, 'DEV1')
assert len(pairs) == 1, out_word
assert pairs[0][1] is not None, out_word
assert problems == [], out_word
def test_unrecorded_flags_stay_unknown_rather_than_becoming_false():
# NULL in the source means nobody wrote it down. False would assert that
# the drive was checked and failed, which is a different claim entirely.
assert _tri(None) is None
assert _tri(0) is False
assert _tri(1) is True