scanner: add regression tests for signautre load logic

This commit is contained in:
Michael Pöhn 2022-10-06 14:50:30 +02:00
parent d815a64fdb
commit e967fc61cf
1 changed files with 146 additions and 25 deletions

View File

@ -450,7 +450,9 @@ class Test_scan_binary(unittest.TestCase):
fdroidserver.scanner._SCANNER_TOOL = mock.Mock()
fdroidserver.scanner._SCANNER_TOOL.regexs = {}
fdroidserver.scanner._SCANNER_TOOL.regexs['err_code_signatures'] = {
"java/lang/Object": re.compile(r'.*java/lang/Object', re.IGNORECASE | re.UNICODE)
"java/lang/Object": re.compile(
r'.*java/lang/Object', re.IGNORECASE | re.UNICODE
)
}
fdroidserver.scanner._SCANNER_TOOL.regexs['warn_code_signatures'] = {}
@ -459,7 +461,12 @@ class Test_scan_binary(unittest.TestCase):
self.assertEqual(
1,
fdroidserver.scanner.scan_binary(apkfile),
"Did not find expected code signature '{}' in binary '{}'".format(fdroidserver.scanner._SCANNER_TOOL.regexs['err_code_signatures'].values(), apkfile),
"Did not find expected code signature '{}' in binary '{}'".format(
fdroidserver.scanner._SCANNER_TOOL.regexs[
'err_code_signatures'
].values(),
apkfile,
),
)
@unittest.skipIf(
@ -472,14 +479,20 @@ class Test_scan_binary(unittest.TestCase):
apkfile = os.path.join(self.basedir, 'apk.embedded_1.apk')
fdroidserver.scanner._SCANNER_TOOL.regexs['err_code_signatures'] = {
"org/bitbucket/tickytacky/mirrormirror/MainActivity": re.compile(
r'.*org/bitbucket/tickytacky/mirrormirror/MainActivity', re.IGNORECASE | re.UNICODE
r'.*org/bitbucket/tickytacky/mirrormirror/MainActivity',
re.IGNORECASE | re.UNICODE,
)
}
self.assertEqual(
1,
fdroidserver.scanner.scan_binary(apkfile),
"Did not find expected code signature '{}' in binary '{}'".format(fdroidserver.scanner._SCANNER_TOOL.regexs['err_code_signatures'].values(), apkfile),
"Did not find expected code signature '{}' in binary '{}'".format(
fdroidserver.scanner._SCANNER_TOOL.regexs[
'err_code_signatures'
].values(),
apkfile,
),
)
def test_top_level_signature_embedded_apk_present(self):
@ -492,14 +505,21 @@ class Test_scan_binary(unittest.TestCase):
self.assertEqual(
1,
fdroidserver.scanner.scan_binary(apkfile),
"Did not find expected code signature '{}' in binary '{}'".format(fdroidserver.scanner._SCANNER_TOOL.regexs['err_code_signatures'].values(), apkfile),
"Did not find expected code signature '{}' in binary '{}'".format(
fdroidserver.scanner._SCANNER_TOOL.regexs[
'err_code_signatures'
].values(),
apkfile,
),
)
class Test_SignatureDataController(unittest.TestCase):
# __init__
def test_init(self):
sdc = fdroidserver.scanner.SignatureDataController('nnn', 'fff.yml', 'https://example.com/test.json')
sdc = fdroidserver.scanner.SignatureDataController(
'nnn', 'fff.yml', 'https://example.com/test.json'
)
self.assertEqual(sdc.name, 'nnn')
self.assertEqual(sdc.filename, 'fff.yml')
self.assertEqual(sdc.cache_duration, timedelta(999999))
@ -507,51 +527,144 @@ class Test_SignatureDataController(unittest.TestCase):
# check_last_updated
def test_check_last_updated_ok(self):
sdc = fdroidserver.scanner.SignatureDataController('nnn', 'fff.yml', 'https://example.com/test.json')
sdc = fdroidserver.scanner.SignatureDataController(
'nnn', 'fff.yml', 'https://example.com/test.json'
)
sdc.data['last_updated'] = datetime.utcnow().timestamp()
sdc.check_last_updated()
def test_check_last_updated_exception_cache_outdated(self):
sdc = fdroidserver.scanner.SignatureDataController('nnn', 'fff.yml', 'https://example.com/test.json')
sdc = fdroidserver.scanner.SignatureDataController(
'nnn', 'fff.yml', 'https://example.com/test.json'
)
sdc.cache_duration = timedelta(days=7)
sdc.data['last_updated'] = (datetime.utcnow() - timedelta(days=30)).timestamp()
with self.assertRaises(fdroidserver.scanner.SignatureDataOutdatedException):
sdc.check_last_updated()
def test_check_last_updated_exception_not_string(self):
sdc = fdroidserver.scanner.SignatureDataController('nnn', 'fff.yml', 'https://example.com/test.json')
sdc = fdroidserver.scanner.SignatureDataController(
'nnn', 'fff.yml', 'https://example.com/test.json'
)
sdc.data['last_updated'] = 'sepp'
with self.assertRaises(fdroidserver.scanner.SignatureDataMalformedException):
sdc.check_last_updated()
def test_check_last_updated_exception_not_iso_formatted_string(self):
sdc = fdroidserver.scanner.SignatureDataController('nnn', 'fff.yml', 'https://example.com/test.json')
sdc = fdroidserver.scanner.SignatureDataController(
'nnn', 'fff.yml', 'https://example.com/test.json'
)
sdc.data['last_updated'] = '01/09/2002 10:11'
with self.assertRaises(fdroidserver.scanner.SignatureDataMalformedException):
sdc.check_last_updated()
def test_check_last_updated_no_exception_missing_when_last_updated_not_set(self):
sdc = fdroidserver.scanner.SignatureDataController('nnn', 'fff.yml', 'https://example.com/test.json')
sdc = fdroidserver.scanner.SignatureDataController(
'nnn', 'fff.yml', 'https://example.com/test.json'
)
sdc.check_last_updated()
# check_data_version
def test_check_data_version_ok(self):
sdc = fdroidserver.scanner.SignatureDataController('nnn', 'fff.yml', 'https://example.com/test.json')
sdc = fdroidserver.scanner.SignatureDataController(
'nnn', 'fff.yml', 'https://example.com/test.json'
)
sdc.data['version'] = fdroidserver.scanner.SCANNER_CACHE_VERSION
sdc.check_data_version()
def test_check_data_version_exception(self):
sdc = fdroidserver.scanner.SignatureDataController('nnn', 'fff.yml', 'https://example.com/test.json')
with self.assertRaises(fdroidserver.scanner.SignatureDataVersionMismatchException):
sdc = fdroidserver.scanner.SignatureDataController(
'nnn', 'fff.yml', 'https://example.com/test.json'
)
with self.assertRaises(
fdroidserver.scanner.SignatureDataVersionMismatchException
):
sdc.check_data_version()
def test_load_ok(self):
sdc = fdroidserver.scanner.SignatureDataController(
'nnn', 'fff.yml', 'https://example.com/test.json'
)
func_lfc = mock.Mock()
func_vd = mock.Mock()
func_clu = mock.Mock()
with mock.patch(
'fdroidserver.scanner.SignatureDataController.load_from_cache',
func_lfc,
), mock.patch(
'fdroidserver.scanner.SignatureDataController.verify_data',
func_vd,
), mock.patch(
'fdroidserver.scanner.SignatureDataController.check_last_updated',
func_clu,
):
sdc.load()
func_lfc.assert_called_once_with()
func_vd.assert_called_once_with()
func_clu.assert_called_once_with()
def test_load_initial_cache_miss(self):
sdc = fdroidserver.scanner.SignatureDataController(
'nnn', 'fff.yml', 'https://example.com/test.json'
)
func_lfc = mock.Mock(
side_effect=fdroidserver.scanner.SignatureDataCacheMissException
)
func_lfd = mock.Mock()
with mock.patch(
'fdroidserver.scanner.SignatureDataController.load_from_cache',
func_lfc,
), mock.patch(
'fdroidserver.scanner.SignatureDataController.load_from_defaults',
func_lfd,
):
sdc.load()
func_lfc.assert_called_once_with()
func_lfd.assert_called_once_with()
def test_load_cache_auto_refresh(self):
sdc = fdroidserver.scanner.SignatureDataController(
'nnn', 'fff.yml', 'https://example.com/test.json'
)
func_lfc = mock.Mock()
func_vd = mock.Mock()
func_clu = mock.Mock(
side_effect=fdroidserver.scanner.SignatureDataOutdatedException()
)
func_fsfw = mock.Mock()
func_wtc = mock.Mock()
with mock.patch(
'fdroidserver.scanner.SignatureDataController.load_from_cache',
func_lfc,
), mock.patch(
'fdroidserver.scanner.SignatureDataController.verify_data',
func_vd,
), mock.patch(
'fdroidserver.scanner.SignatureDataController.check_last_updated',
func_clu,
), mock.patch(
'fdroidserver.scanner.SignatureDataController.fetch_signatures_from_web',
func_fsfw,
), mock.patch(
'fdroidserver.scanner.SignatureDataController.write_to_cache',
func_wtc,
):
sdc.load()
func_lfc.assert_called_once_with()
func_vd.assert_called_once_with()
func_clu.assert_called_once_with()
func_fsfw.assert_called_once_with()
func_wtc.assert_called_once_with()
@unittest.skipIf(
sys.version_info < (3, 9, 0),
"mock_open doesn't allow easy access to written data in older python versions",
)
def test_write_to_cache(self):
open_func = mock.mock_open()
sdc = fdroidserver.scanner.SignatureDataController('nnn', 'fff.yml', 'https://example.com/test.json')
sdc = fdroidserver.scanner.SignatureDataController(
'nnn', 'fff.yml', 'https://example.com/test.json'
)
sdc.data = {"mocked": "data"}
with mock.patch("builtins.open", open_func), mock.patch(
@ -561,10 +674,16 @@ class Test_SignatureDataController(unittest.TestCase):
sdc.write_to_cache()
open_func.assert_called_with(pathlib.Path('fff.yml'), 'w', encoding="utf-8")
self.assertEqual(
mock_open_to_str(open_func),
"""{\n "mocked": "data"\n}"""
)
self.assertEqual(mock_open_to_str(open_func), """{\n "mocked": "data"\n}""")
class Test_ScannerTool(unittest.TestCase):
def test_load(self):
st = mock.Mock()
st.sdcs = [mock.Mock(), mock.Mock()]
fdroidserver.scanner.ScannerTool.load(st)
st.sdcs[0].load.assert_called_once_with()
st.sdcs[1].load.assert_called_once_with()
class Test_main(unittest.TestCase):
@ -630,10 +749,12 @@ if __name__ == "__main__":
(fdroidserver.common.options, args) = parser.parse_args(['--verbose'])
newSuite = unittest.TestSuite()
newSuite.addTests([
unittest.makeSuite(ScannerTest),
unittest.makeSuite(Test_scan_binary),
unittest.makeSuite(Test_SignatureDataController),
unittest.makeSuite(Test_main),
])
newSuite.addTests(
[
unittest.makeSuite(ScannerTest),
unittest.makeSuite(Test_scan_binary),
unittest.makeSuite(Test_SignatureDataController),
unittest.makeSuite(Test_main),
]
)
unittest.main(failfast=False)