Some checks failed
Compile apt-layer (v2) / compile (push) Failing after 3h9m6s
- D-Bus methods, properties, and signals all working correctly - Shell integration tests pass 16/19 tests - Core daemon fully decoupled from D-Bus dependencies - Clean architecture with thin D-Bus wrappers established - Signal emission using correct dbus-next pattern - Updated test scripts for apt-ostreed service name - Fixed dbus-next signal definitions and emission patterns - Updated TODO and CHANGELOG for Phase 3 completion
99 lines
No EOL
4 KiB
Python
99 lines
No EOL
4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Modern D-Bus integration test for apt-ostreed daemon using dbus-next only.
|
|
Tests all major methods, properties, and signals.
|
|
"""
|
|
import asyncio
|
|
import sys
|
|
from dbus_next.aio import MessageBus
|
|
from dbus_next import BusType, Message
|
|
|
|
SERVICE = 'org.debian.aptostree1'
|
|
SYSROOT_PATH = '/org/debian/aptostree1/Sysroot'
|
|
OS_PATH = '/org/debian/aptostree1/OS/default'
|
|
SYSROOT_IFACE = 'org.debian.aptostree1.Sysroot'
|
|
OS_IFACE = 'org.debian.aptostree1.OS'
|
|
PROPS_IFACE = 'org.freedesktop.DBus.Properties'
|
|
|
|
async def main():
|
|
bus = await MessageBus(bus_type=BusType.SYSTEM).connect()
|
|
failures = 0
|
|
def ok(msg): print(f'\033[32m✔ {msg}\033[0m')
|
|
def fail(msg):
|
|
nonlocal failures
|
|
print(f'\033[31m✘ {msg}\033[0m')
|
|
failures += 1
|
|
|
|
# Test methods
|
|
async def call_method(path, iface, member, body=None):
|
|
try:
|
|
m = Message(destination=SERVICE, path=path, interface=iface, member=member, body=body or [])
|
|
reply = await bus.call(m)
|
|
ok(f'{iface}.{member} succeeded')
|
|
return reply
|
|
except Exception as e:
|
|
fail(f'{iface}.{member} failed: {e}')
|
|
return None
|
|
|
|
await call_method(SYSROOT_PATH, SYSROOT_IFACE, 'GetStatus')
|
|
await call_method(SYSROOT_PATH, SYSROOT_IFACE, 'InstallPackages', [['curl'], False])
|
|
await call_method(SYSROOT_PATH, SYSROOT_IFACE, 'RemovePackages', [['curl'], False])
|
|
await call_method(SYSROOT_PATH, SYSROOT_IFACE, 'Deploy', ['test-deployment'])
|
|
await call_method(SYSROOT_PATH, SYSROOT_IFACE, 'Upgrade')
|
|
await call_method(SYSROOT_PATH, SYSROOT_IFACE, 'Rollback')
|
|
# CreateComposeFSLayer, RegisterClient, UnregisterClient not in current interface
|
|
await call_method(SYSROOT_PATH, SYSROOT_IFACE, 'Reload')
|
|
await call_method(SYSROOT_PATH, SYSROOT_IFACE, 'ReloadConfig')
|
|
await call_method(SYSROOT_PATH, SYSROOT_IFACE, 'GetOS')
|
|
await call_method(OS_PATH, OS_IFACE, 'GetBootedDeployment')
|
|
await call_method(OS_PATH, OS_IFACE, 'GetDefaultDeployment')
|
|
await call_method(OS_PATH, OS_IFACE, 'ListDeployments')
|
|
|
|
# Test properties
|
|
async def get_prop(path, iface, prop):
|
|
try:
|
|
m = Message(destination=SERVICE, path=path, interface=PROPS_IFACE, member='Get', body=[iface, prop])
|
|
reply = await bus.call(m)
|
|
ok(f'Property {iface}.{prop} accessible')
|
|
except Exception as e:
|
|
fail(f'Property {iface}.{prop} failed: {e}')
|
|
|
|
# Test Sysroot properties (only those that exist in the interface)
|
|
for prop in ['Booted', 'ActiveTransaction', 'ActiveTransactionPath', 'Deployments', 'AutomaticUpdatePolicy', 'Path']:
|
|
await get_prop(SYSROOT_PATH, SYSROOT_IFACE, prop)
|
|
# OS interface doesn't have properties in current implementation
|
|
|
|
# Test GetAll
|
|
try:
|
|
m = Message(destination=SERVICE, path=SYSROOT_PATH, interface=PROPS_IFACE, member='GetAll', body=[SYSROOT_IFACE])
|
|
reply = await bus.call(m)
|
|
ok('GetAll properties succeeded')
|
|
except Exception as e:
|
|
fail(f'GetAll properties failed: {e}')
|
|
|
|
# Test signal subscription (TransactionProgress as example)
|
|
signal_received = asyncio.Event()
|
|
def on_signal(msg):
|
|
if msg.message_type == 2 and msg.interface == SYSROOT_IFACE and msg.member == 'TransactionProgress':
|
|
ok('TransactionProgress signal received')
|
|
signal_received.set()
|
|
bus.add_message_handler(on_signal)
|
|
# Trigger a method that emits a signal
|
|
await call_method(SYSROOT_PATH, SYSROOT_IFACE, 'Deploy', ['signal-test'])
|
|
try:
|
|
await asyncio.wait_for(signal_received.wait(), timeout=3)
|
|
except asyncio.TimeoutError:
|
|
fail('TransactionProgress signal not received')
|
|
|
|
# Test error handling
|
|
try:
|
|
await call_method(SYSROOT_PATH, SYSROOT_IFACE, 'InvalidMethod')
|
|
fail('InvalidMethod should have failed')
|
|
except Exception as e:
|
|
ok(f'InvalidMethod properly rejected: {e}')
|
|
|
|
print(f'\nTotal failures: {failures}')
|
|
sys.exit(1 if failures else 0)
|
|
|
|
if __name__ == '__main__':
|
|
asyncio.run(main()) |