Refactor TestCase files into python modules

Convert all TestCase files into standard python modules to be run and
discovered by unittest.
This commit is contained in:
SilentGhost 2024-11-19 20:36:41 +01:00 committed by Hans-Christoph Steiner
parent 4d6682bc70
commit 7ff32bc4b0
34 changed files with 471 additions and 1260 deletions

178
tests/test_signindex.py Executable file
View file

@ -0,0 +1,178 @@
#!/usr/bin/env python3
import json
import os
import shutil
import subprocess
import tempfile
import unittest
from fdroidserver import apksigcopier, common, exception, signindex, update
from pathlib import Path
from unittest.mock import patch
class Options:
allow_disabled_algorithms = False
clean = False
delete_unknown = False
nosign = False
pretty = True
rename_apks = False
verbose = False
class SignindexTest(unittest.TestCase):
basedir = Path(__file__).resolve().parent
def setUp(self):
signindex.config = None
config = common.read_config()
config['jarsigner'] = common.find_sdk_tools_cmd('jarsigner')
config['verbose'] = True
config['keystore'] = str(self.basedir / 'keystore.jks')
config['repo_keyalias'] = 'sova'
config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
signindex.config = config
self.tempdir = tempfile.TemporaryDirectory()
os.chdir(self.tempdir.name)
self.repodir = Path('repo')
self.repodir.mkdir()
def tearDown(self):
self.tempdir.cleanup()
def test_sign_index(self):
shutil.copy(str(self.basedir / 'repo/index-v1.json'), 'repo')
signindex.sign_index(str(self.repodir), 'index-v1.json')
self.assertTrue((self.repodir / 'index-v1.jar').exists())
self.assertTrue((self.repodir / 'index-v1.json').exists())
def test_sign_index_corrupt(self):
with open('repo/index-v1.json', 'w') as fp:
fp.write('corrupt JSON!')
with self.assertRaises(json.decoder.JSONDecodeError, msg='error on bad JSON'):
signindex.sign_index(str(self.repodir), 'index-v1.json')
def test_sign_entry(self):
entry = 'repo/entry.json'
v2 = 'repo/index-v2.json'
shutil.copy(self.basedir / entry, entry)
shutil.copy(self.basedir / v2, v2)
signindex.sign_index(self.repodir, 'entry.json')
self.assertTrue((self.repodir / 'entry.jar').exists())
def test_sign_entry_corrupt(self):
"""sign_index should exit with error if entry.json is bad JSON"""
entry = 'repo/entry.json'
with open(entry, 'w') as fp:
fp.write('{')
with self.assertRaises(json.decoder.JSONDecodeError, msg='error on bad JSON'):
signindex.sign_index(self.repodir, 'entry.json')
self.assertFalse((self.repodir / 'entry.jar').exists())
def test_sign_entry_corrupt_leave_entry_jar(self):
"""sign_index should not touch existing entry.jar if entry.json is corrupt"""
existing = 'repo/entry.jar'
testvalue = "Don't touch!"
with open(existing, 'w') as fp:
fp.write(testvalue)
with open('repo/entry.json', 'w') as fp:
fp.write('{')
with self.assertRaises(json.decoder.JSONDecodeError, msg='error on bad JSON'):
signindex.sign_index(self.repodir, 'entry.json')
with open(existing) as fp:
self.assertEqual(testvalue, fp.read())
def test_sign_corrupt_index_v2_json(self):
"""sign_index should exit with error if index-v2.json JSON is corrupt"""
with open('repo/index-v2.json', 'w') as fp:
fp.write('{"key": "not really an index"')
good_entry = {
"timestamp": 1676583021000,
"version": 20002,
"index": {
"name": "/index-v2.json",
"sha256": common.sha256sum('repo/index-v2.json'),
"size": os.path.getsize('repo/index-v2.json'),
"numPackages": 0,
},
}
with open('repo/entry.json', 'w') as fp:
json.dump(good_entry, fp)
with self.assertRaises(json.decoder.JSONDecodeError, msg='error on bad JSON'):
signindex.sign_index(self.repodir, 'entry.json')
self.assertFalse((self.repodir / 'entry.jar').exists())
def test_sign_index_v2_corrupt_sha256(self):
"""sign_index should exit with error if SHA-256 of file in entry is wrong"""
entry = 'repo/entry.json'
v2 = 'repo/index-v2.json'
shutil.copy(self.basedir / entry, entry)
shutil.copy(self.basedir / v2, v2)
with open(v2, 'a') as fp:
fp.write(' ')
with self.assertRaises(exception.FDroidException, msg='error on bad SHA-256'):
signindex.sign_index(self.repodir, 'entry.json')
self.assertFalse((self.repodir / 'entry.jar').exists())
def test_signindex(self):
if common.find_apksigner({}) is None: # TODO remove me for buildserver-bullseye
self.skipTest('SKIPPING test_signindex, apksigner not installed!')
os.mkdir('archive')
metadata = Path('metadata')
metadata.mkdir()
with (metadata / 'info.guardianproject.urzip.yml').open('w') as fp:
fp.write('# placeholder')
shutil.copy(str(self.basedir / 'urzip.apk'), 'repo')
index_files = []
for f in (
'entry.jar',
'entry.json',
'index-v1.jar',
'index-v1.json',
'index-v2.json',
'index.jar',
'index.xml',
):
for section in (Path('repo'), Path('archive')):
path = section / f
self.assertFalse(path.exists(), '%s should not exist yet!' % path)
index_files.append(path)
common.options = Options
with patch('sys.argv', ['fdroid update']):
update.main()
with patch('sys.argv', ['fdroid signindex', '--verbose']):
signindex.main()
for f in index_files:
self.assertTrue(f.exists(), '%s should exist!' % f)
self.assertFalse(os.path.exists('index-v2.jar')) # no JAR version of this file
# index.jar aka v0 must by signed by SHA1withRSA
f = 'repo/index.jar'
common.verify_deprecated_jar_signature(f)
self.assertIsNone(apksigcopier.extract_v2_sig(f, expected=False))
cp = subprocess.run(
['jarsigner', '-verify', '-verbose', f], stdout=subprocess.PIPE
)
self.assertTrue(b'SHA1withRSA' in cp.stdout)
# index-v1.jar must by signed by SHA1withRSA
f = 'repo/index-v1.jar'
common.verify_deprecated_jar_signature(f)
self.assertIsNone(apksigcopier.extract_v2_sig(f, expected=False))
cp = subprocess.run(
['jarsigner', '-verify', '-verbose', f], stdout=subprocess.PIPE
)
self.assertTrue(b'SHA1withRSA' in cp.stdout)
# entry.jar aka index v2 must by signed by a modern algorithm
f = 'repo/entry.jar'
common.verify_deprecated_jar_signature(f)
self.assertIsNone(apksigcopier.extract_v2_sig(f, expected=False))
cp = subprocess.run(
['jarsigner', '-verify', '-verbose', f], stdout=subprocess.PIPE
)
self.assertFalse(b'SHA1withRSA' in cp.stdout)