- Add optional modifier-only Super binding whose tap is cancelled by other input, focus changes, grabs, locks, and session teardown. - Ship the native ferese-rime user service, Rime defaults, installer inventory, package dependencies, session environment, and docs. - Vendor Smithay 8a27023 with the SHM texture-cache format fix and add GPU regressions for format changes and resize snapshots. - Release reused CRTC owners before staging output modes, then restore changed outputs before former owners when a transaction fails. - Wait for resize-capture GPU completion, expand filtered surface damage, and preserve IME popup origin under fractional scaling. - Mark weekends like holidays in both calendar layouts.
151 lines
8.2 KiB
Python
151 lines
8.2 KiB
Python
"""Package layout and release-input regressions; no root or network needed."""
|
|
import importlib.util
|
|
import json
|
|
from pathlib import Path
|
|
import tempfile
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
SPEC = importlib.util.spec_from_file_location('package', Path(__file__).resolve().parents[1] / 'package.py')
|
|
PACKAGE = importlib.util.module_from_spec(SPEC)
|
|
SPEC.loader.exec_module(PACKAGE)
|
|
|
|
|
|
class PackageTests(unittest.TestCase):
|
|
def test_release_tag_must_match_workspace_version(self):
|
|
PACKAGE.check_tag('v0.1.0', '0.1.0')
|
|
PACKAGE.check_tag('v0.2.0-rc.1', '0.2.0-rc.1')
|
|
with self.assertRaises(ValueError):
|
|
PACKAGE.check_tag('v0.2.0', '0.1.0')
|
|
|
|
def test_refuses_live_root(self):
|
|
with self.assertRaises(ValueError):
|
|
PACKAGE.stage('/', '/missing', 'fedora')
|
|
|
|
def test_refuses_existing_content_and_symlink_destinations(self):
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
root = Path(directory)
|
|
destination = root / 'dest'
|
|
destination.mkdir()
|
|
(destination / 'keep').write_text('existing')
|
|
link = root / 'link'
|
|
link.symlink_to(destination)
|
|
for path in (destination, link):
|
|
with self.assertRaises(ValueError):
|
|
PACKAGE.stage(path, root / 'missing', 'fedora')
|
|
|
|
self.assertEqual((destination / 'keep').read_text(), 'existing')
|
|
|
|
def test_missing_binary_fails_before_staging(self):
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
root = Path(directory)
|
|
with self.assertRaises(ValueError):
|
|
PACKAGE.stage(root / 'dest', root / 'missing', 'fedora')
|
|
|
|
self.assertFalse((root / 'dest').exists())
|
|
|
|
def test_complete_package_layout_and_both_pam_policies(self):
|
|
inventory = json.loads((PACKAGE.ROOT / 'scripts/installer/inventory.json').read_text())
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
root = Path(directory)
|
|
binaries = root / 'bin'
|
|
binaries.mkdir()
|
|
for entry in inventory['files']:
|
|
if entry['source'].startswith('target/release/'):
|
|
(binaries / entry['target']).write_bytes(b'fixture')
|
|
|
|
for pam in ('fedora', 'arch'):
|
|
with self.subTest(pam=pam), patch.object(PACKAGE, 'licenses'), patch.object(PACKAGE, 'run', return_value='{}'):
|
|
dest = root / pam
|
|
PACKAGE.stage(dest, binaries, pam)
|
|
for entry in inventory['files']:
|
|
if entry.get('link'):
|
|
name = Path(entry['source']).name
|
|
link = dest / 'usr/bin' / name
|
|
self.assertEqual(link.readlink(), Path('/usr/libexec/ferese') / name)
|
|
self.assertTrue((dest / str(link.readlink()).lstrip('/')).is_file())
|
|
|
|
for file in dest.rglob('*'):
|
|
if file.is_file() and not file.is_symlink() and file.suffix in ('.desktop', '.service'):
|
|
self.assertNotIn('/usr/local/', file.read_text())
|
|
|
|
self.assertFalse((dest / 'usr/local').exists())
|
|
self.assertIn('system-auth', (dest / 'etc/pam.d/ferese-lock').read_text())
|
|
wallpaper = dest / 'usr/libexec/ferese/wallpapers'
|
|
self.assertEqual(wallpaper.readlink(), Path('/usr/share/ferese/wallpapers'))
|
|
self.assertTrue((dest / 'usr/share/ferese/wallpapers/ferese.png').is_file())
|
|
self.assertEqual((dest / 'usr/libexec/ferese/ferese-session').stat().st_mode & 0o777, 0o755)
|
|
self.assertEqual((dest / 'usr/libexec/ferese').stat().st_mode & 0o777, 0o755)
|
|
self.assertTrue((dest / 'usr/libexec/ferese/ferese-rime').is_file())
|
|
self.assertIn('schema: luna_pinyin_simp',
|
|
(dest / 'usr/libexec/ferese/rime/default.custom.yaml').read_text())
|
|
provenance = dest / 'usr/share/doc/ferese/vendor/smithay'
|
|
for name in ('UPSTREAM.md', 'shm-texture-cache-format.patch'):
|
|
origin = PACKAGE.ROOT / 'vendor/smithay' / (
|
|
name if name == 'UPSTREAM.md' else 'patches/' + name)
|
|
self.assertEqual((provenance / name).read_bytes(), origin.read_bytes())
|
|
|
|
def test_same_version_from_different_sources_keeps_both_licenses(self):
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
root = Path(directory)
|
|
packages = []
|
|
for source in ('registry+first', 'registry+second'):
|
|
folder = root / source.removeprefix('registry+')
|
|
folder.mkdir()
|
|
(folder / 'LICENSE').write_text(source)
|
|
packages.append({'name': 'dpi', 'version': '0.1.2', 'source': source,
|
|
'manifest_path': str(folder / 'Cargo.toml'),
|
|
'license': 'MIT', 'license_file': None})
|
|
|
|
PACKAGE.licenses(root / 'notices', {'packages': packages})
|
|
texts = {path.read_text() for path in (root / 'notices').glob('dpi-*/LICENSE')}
|
|
self.assertEqual(texts, {'registry+first', 'registry+second'})
|
|
|
|
def test_dependency_license_report_contains_source_and_license(self):
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
root = Path(directory)
|
|
(root / 'Cargo.toml').write_text('')
|
|
(root / 'LICENSE-MIT').write_text('test license')
|
|
metadata = {'packages': [{'name': 'fixture', 'version': '1.0.0',
|
|
'source': 'registry+test', 'manifest_path': str(root / 'Cargo.toml'),
|
|
'license': 'MIT', 'license_file': None}]}
|
|
PACKAGE.licenses(root / 'notices', metadata)
|
|
self.assertEqual(next((root / 'notices').glob('fixture-1.0.0-*/LICENSE-MIT')).read_text(), 'test license')
|
|
report = json.loads((root / 'notices/dependencies.json').read_text())
|
|
self.assertEqual(report[0]['license'], 'MIT')
|
|
self.assertEqual(report[0]['source'], 'registry+test')
|
|
|
|
def test_vendored_notices_exclude_workspace_members_and_are_relocatable(self):
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
root = Path(directory)
|
|
reports = []
|
|
for checkout in ('first-checkout', 'second-checkout'):
|
|
workspace = root / checkout / 'ferese'
|
|
packages = []
|
|
for name, folder, license_text in (
|
|
('ferese', workspace / 'compositor', 'workspace notice'),
|
|
('smithay', workspace / 'vendor/smithay', 'Smithay MIT notice'),
|
|
('external', workspace.parent / 'shared/external', 'external notice')):
|
|
folder.mkdir(parents=True)
|
|
(folder / 'LICENSE.txt').write_text(license_text)
|
|
packages.append({'id': f'path+file://{folder}#{name}@0.7.0',
|
|
'name': name, 'version': '0.7.0', 'source': None,
|
|
'manifest_path': str(folder / 'Cargo.toml'),
|
|
'license': 'MIT', 'license_file': None})
|
|
destination = workspace / 'notices'
|
|
PACKAGE.licenses(destination, {'packages': packages,
|
|
'workspace_members': [packages[0]['id']], 'workspace_root': str(workspace)})
|
|
report = json.loads((destination / 'dependencies.json').read_text())
|
|
self.assertEqual({p['name']: p['source'] for p in report}, {
|
|
'smithay': 'path+vendor/smithay', 'external': 'path+../shared/external'})
|
|
notices = {p['name']: (destination / p['notice_directory'] / 'LICENSE.txt').read_text()
|
|
for p in report}
|
|
self.assertEqual(notices, {'smithay': 'Smithay MIT notice', 'external': 'external notice'})
|
|
self.assertNotIn(str(root), (destination / 'dependencies.json').read_text())
|
|
reports.append(report)
|
|
self.assertEqual(reports[0], reports[1])
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|