Skip to content

Commit

Permalink
Merge pull request doronz88#780 from codeskyblue/feature_xcuitest_squash
Browse files Browse the repository at this point in the history
add feature XCUITest
  • Loading branch information
doronz88 authored Jan 22, 2024
2 parents 8892853 + 051ed4f commit 57aa99e
Show file tree
Hide file tree
Showing 7 changed files with 470 additions and 13 deletions.
15 changes: 15 additions & 0 deletions pymobiledevice3/cli/developer.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
from pymobiledevice3.services.dvt.instruments.process_control import ProcessControl
from pymobiledevice3.services.dvt.instruments.screenshot import Screenshot
from pymobiledevice3.services.dvt.instruments.sysmontap import Sysmontap
from pymobiledevice3.services.dvt.testmanaged.xcuitest import XCUITestService
from pymobiledevice3.services.remote_fetch_symbols import RemoteFetchSymbolsService
from pymobiledevice3.services.remote_server import RemoteServer
from pymobiledevice3.services.screenshot import ScreenshotService
Expand Down Expand Up @@ -271,6 +272,20 @@ def screenshot(service_provider: LockdownClient, out):
out.write(Screenshot(dvt).get_screenshot())


@dvt.command('xcuitest', cls=Command)
@click.argument('bundle-id')
def xcuitest(service_provider: LockdownClient, bundle_id: str) -> None:
"""\b
start XCUITest
Usage example:
iOS<17:
python3 -m pymobiledevice3 developer dvt xcuitest com.facebook.WebDriverAgentRunner.xctrunner
iOS>=17:
python3 -m pymobiledevice3 developer dvt xcuitest com.facebook.WebDriverAgentRunner.xctrunner --tunnel $UDID
"""
XCUITestService(service_provider).run(bundle_id)


@dvt.group('sysmon')
def sysmon():
""" System monitor options. """
Expand Down
4 changes: 4 additions & 0 deletions pymobiledevice3/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,10 @@ class AppInstallError(PyMobileDevice3Exception):
pass


class AppNotInstalledError(PyMobileDevice3Exception):
pass


class CoreDeviceError(PyMobileDevice3Exception):
pass

Expand Down
23 changes: 23 additions & 0 deletions pymobiledevice3/services/dvt/dvt_testmanaged_proxy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from packaging.version import Version

from pymobiledevice3.lockdown_service_provider import LockdownServiceProvider
from pymobiledevice3.remote.remote_service_discovery import RemoteServiceDiscoveryService
from pymobiledevice3.services.remote_server import RemoteServer


class DvtTestmanagedProxyService(RemoteServer):
SERVICE_NAME = 'com.apple.testmanagerd.lockdown.secure'
OLD_SERVICE_NAME = 'com.apple.testmanagerd.lockdown'
RSD_SERVICE_NAME = 'com.apple.dt.testmanagerd.remote'

# TODO: there is also service named 'com.apple.dt.testmanagerd.remote.automation', but not used

def __init__(self, lockdown: LockdownServiceProvider):
if isinstance(lockdown, RemoteServiceDiscoveryService): # only happends when >=17.0
service_name = self.RSD_SERVICE_NAME
elif Version(lockdown.product_version) >= Version('14.0'):
service_name = self.SERVICE_NAME
else:
service_name = self.OLD_SERVICE_NAME

super().__init__(lockdown, service_name, remove_ssl_context=False)
17 changes: 11 additions & 6 deletions pymobiledevice3/services/dvt/instruments/process_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import datetime
import typing

from pymobiledevice3.services.dvt.dvt_secure_socket_proxy import DvtSecureSocketProxyService
from pymobiledevice3.services.remote_server import MessageAux


Expand All @@ -24,7 +25,7 @@ def create(cls, message) -> 'OutputReceivedEvent':
class ProcessControl:
IDENTIFIER = 'com.apple.instruments.server.services.processcontrol'

def __init__(self, dvt):
def __init__(self, dvt: DvtSecureSocketProxyService):
self._channel = dvt.make_channel(self.IDENTIFIER)

def signal(self, pid: int, sig: int):
Expand All @@ -44,23 +45,27 @@ def kill(self, pid: int):
self._channel.killPid_(MessageAux().append_obj(pid), expects_reply=False)

def launch(self, bundle_id: str, arguments=None, kill_existing: bool = True, start_suspended: bool = False,
environment: typing.Mapping = None) -> int:
environment: typing.Mapping = None, extra_options: typing.Mapping = None) -> int:
"""
Launch a process.
:param bundle_id: Bundle id of the process.
:param list arguments: List of argument to pass to process.
:param kill_existing: Whether to kill an existing instance of this process.
:param start_suspended: Same as WaitForDebugger.
:param environment: Environment variables to pass to process.
:param extra_options: Extra options to pass to process.
:return: PID of created process.
"""
arguments = [] if arguments is None else arguments
environment = {} if environment is None else environment
options = {
'StartSuspendedKey': start_suspended,
'KillExisting': kill_existing,
}
if extra_options:
options.update(extra_options)
args = MessageAux().append_obj('').append_obj(bundle_id).append_obj(environment).append_obj(
arguments).append_obj({
'StartSuspendedKey': start_suspended,
'KillExisting': kill_existing,
})
arguments).append_obj(options)
self._channel.launchSuspendedProcessWithDevicePath_bundleIdentifier_environment_arguments_options_(args)
result = self._channel.receive_plist()
assert result
Expand Down
5 changes: 4 additions & 1 deletion pymobiledevice3/services/dvt/instruments/screenshot.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from pymobiledevice3.services.dvt.dvt_secure_socket_proxy import DvtSecureSocketProxyService


class Screenshot:
IDENTIFIER = 'com.apple.instruments.server.services.screenshot'

def __init__(self, dvt):
def __init__(self, dvt: DvtSecureSocketProxyService):
self._channel = dvt.make_channel(self.IDENTIFIER)

def get_screenshot(self) -> bytes:
Expand Down
Loading

0 comments on commit 57aa99e

Please sign in to comment.