USB external import, and filter chips on health-dot cards
This commit is contained in:
99
tests/test_plugins/test_usb_import_pairing.py
Normal file
99
tests/test_plugins/test_usb_import_pairing.py
Normal 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
|
||||
Reference in New Issue
Block a user