36 lines
2.4 KiB
Python
36 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
from __future__ import annotations
|
|
import argparse
|
|
from dataclasses import replace
|
|
from pathlib import Path
|
|
import sys,unittest
|
|
P=argparse.ArgumentParser();P.add_argument("--root",type=Path,required=True);ROOT=P.parse_args().root;sys.path.insert(0,str(ROOT/"tools"))
|
|
from phase10df_title_observer_contract import ObserverError,ObserverPlan,Outcome,PHASE,SyntheticResult,classify_synthetic,validate_candidate,validate_inactive # noqa:E402
|
|
def inactive():return ObserverPlan(PHASE,False,*([None]*8),*([False]*9))
|
|
def query():return ObserverPlan(PHASE,True,"9.60","PPSA01659","SOURCE_BOUND_QUERY","a"*64,None,None,"b"*64,4096,True,True,False,False,False,False,False,False,False)
|
|
def result(**changes):
|
|
value=SyntheticResult("9.60","PPSA01659","SOURCE_BOUND_QUERY","b"*64,True,64,True,False,None)
|
|
return replace(value,**changes)
|
|
class Tests(unittest.TestCase):
|
|
def test_inactive(self):validate_inactive(inactive())
|
|
def test_source_query_candidate(self):validate_candidate(query())
|
|
def test_path_requires_provenance(self):
|
|
plan=replace(query(),method="EXACT_PATH_METADATA",exact_literal_path="/fixed/path",path_provenance_sha256="c"*64);validate_candidate(plan)
|
|
with self.assertRaises(ObserverError):validate_candidate(replace(plan,path_provenance_sha256=None))
|
|
def test_no_shell_or_enumeration(self):
|
|
for field in ("shell_present","directory_enumeration","title_launch","app_termination","device_write","retry","reconnect"):
|
|
with self.subTest(field=field),self.assertRaises(ObserverError):validate_candidate(replace(query(),**{field:True}))
|
|
def test_explicit_results(self):
|
|
self.assertEqual(classify_synthetic(query(),result()),Outcome.PRESENT)
|
|
self.assertEqual(classify_synthetic(query(),result(explicit_present=False,explicit_absent=True)),Outcome.ABSENT)
|
|
def test_error_and_incomplete_are_unknown(self):
|
|
self.assertEqual(classify_synthetic(query(),result(error_code=-1)),Outcome.UNKNOWN)
|
|
self.assertEqual(classify_synthetic(query(),result(complete=False)),Outcome.UNKNOWN)
|
|
def test_ambiguous_and_oversize_rejected(self):
|
|
with self.assertRaises(ObserverError):classify_synthetic(query(),result(explicit_absent=True))
|
|
with self.assertRaises(ObserverError):classify_synthetic(query(),result(result_bytes=4097))
|
|
def test_binding_mismatch_rejected(self):
|
|
with self.assertRaises(ObserverError):classify_synthetic(query(),result(title_id="OTHER"))
|
|
if __name__=="__main__":unittest.main(argv=[__file__])
|