mirror of
https://github.com/SteamFramelyHomebrew/framely.git
synced 2026-10-18 11:01:26 +02:00
64 lines
3.1 KiB
Python
64 lines
3.1 KiB
Python
import importlib.util
|
|
import json
|
|
import pathlib
|
|
import tarfile
|
|
import tempfile
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
SCRIPT = pathlib.Path(__file__).resolve().parents[1] / 'tools/q2f-runtime.py'
|
|
SPEC = importlib.util.spec_from_file_location('q2f_runtime', SCRIPT)
|
|
RUNTIME = importlib.util.module_from_spec(SPEC)
|
|
SPEC.loader.exec_module(RUNTIME)
|
|
|
|
|
|
class Q2FRuntimeTests(unittest.TestCase):
|
|
def test_exact_cache_is_reused_and_tampering_is_rejected(self):
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
base = pathlib.Path(directory)
|
|
identity = 'overport-test-123456789abc'
|
|
payload = base / 'payload'
|
|
(payload / 'java/bin').mkdir(parents=True)
|
|
for name in ('java/bin/java', 'overportcli.jar', 'overport-installed.json', 'OVR_PORT_LICENSE'):
|
|
(payload / name).write_text(name)
|
|
files = sorted(p for p in payload.rglob('*') if p.is_file())
|
|
sums = ''.join(f'{RUNTIME.digest(p)} {p.relative_to(payload)}\n' for p in files)
|
|
(payload / 'VERSION').write_text(identity + '\n')
|
|
(payload / 'SHA256SUMS').write_text(sums)
|
|
archive = base / f'framely-q2f-{identity}-linux-arm64.tar.gz'
|
|
with tarfile.open(archive, 'w:gz') as tar:
|
|
tar.add(payload, arcname=f'framely-q2f-{identity}')
|
|
descriptor = base / 'requirement.json'
|
|
descriptor.write_text(json.dumps({'schemaVersion': 1, 'id': identity,
|
|
'archive': archive.name, 'size': archive.stat().st_size,
|
|
'sha256': RUNTIME.digest(archive), 'url': 'https://example.invalid/q2f'}))
|
|
copies = []
|
|
def copy(_requirement, destination):
|
|
destination.write_bytes(archive.read_bytes())
|
|
copies.append(destination)
|
|
with patch.object(RUNTIME, 'download', copy):
|
|
cached = RUNTIME.prepare(descriptor, base / 'storage')
|
|
self.assertEqual(cached, RUNTIME.prepare(descriptor, base / 'storage'))
|
|
self.assertEqual(len(copies), 1)
|
|
(cached / 'overportcli.jar').write_text('changed')
|
|
with self.assertRaisesRegex(ValueError, 'checksum mismatch'):
|
|
RUNTIME.prepare(descriptor, base / 'storage')
|
|
|
|
def test_archive_rejects_link_and_escape(self):
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
base = pathlib.Path(directory)
|
|
identity = 'overport-test-123456789abc'
|
|
archive = base / 'unsafe.tar.gz'
|
|
for index, member in enumerate((f'framely-q2f-{identity}/../escape', f'framely-q2f-{identity}/link')):
|
|
with tarfile.open(archive, 'w:gz') as tar:
|
|
info = tarfile.TarInfo(member)
|
|
info.type = tarfile.SYMTYPE if member.endswith('/link') else tarfile.REGTYPE
|
|
info.size = 0
|
|
tar.addfile(info)
|
|
with self.assertRaisesRegex(ValueError, 'Unsafe'):
|
|
RUNTIME.extract(archive, base / f'target-{index}', identity)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|