From 2d6923f8fc2c35c5b1b13e3b08dbe93e59d42536 Mon Sep 17 00:00:00 2001 From: TryAngle Date: Mon, 25 Nov 2024 01:36:02 +0100 Subject: [PATCH 1/7] Change: ADB ip+port -> identifier Signed-off-by: TryAngle --- benchkit/devices/adb/__init__.py | 62 +++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/benchkit/devices/adb/__init__.py b/benchkit/devices/adb/__init__.py index 87eedb5..5eb5be4 100644 --- a/benchkit/devices/adb/__init__.py +++ b/benchkit/devices/adb/__init__.py @@ -8,15 +8,15 @@ import subprocess import sys import time -from typing import Iterable, Optional +from typing import Iterable, Optional, Callable from benchkit.devices.adb.usb import usb_down_up from benchkit.shell.shell import get_args, shell_out from benchkit.utils.types import Command, PathType -def _identifier_from(ip_addr: str, port: int) -> str: - return f"{ip_addr}:{port}" +# def _identifier_from(ip_addr: str, port: int) -> str: +# return f"{ip_addr}:{port}" class ADBError(Exception): @@ -43,23 +43,40 @@ def is_connected(self) -> bool: return "device" == self.status -class AndroidDebugBridge: # TODO add commlayer for "host" +# TODO: investigate the identifier and daemon. temporarily it's mirrored like HDC does it. +class AndroidDebugBridge: """Operations with the phone for high-level adb operations.""" def __init__( self, - ip_addr: str, - port: int = 5555, + # ip_addr: str, + # port: int = 5555, + identifier: str, keep_connected: bool = False, wait_connected: bool = False, expected_os: Optional[str] = None, ) -> None: - self._ip = ip_addr - self._port = port + # self._ip = ip_addr + # self._port = port + self.identifier = identifier self._keep_connected = keep_connected self._wait_connected = wait_connected self._expected_os = expected_os + @staticmethod + def from_device( + device: ADBDevice, + keep_connected: bool = False, + wait_connected: bool = False, + expected_os: Optional[str] = None, + ) -> "AndroidDebugBridge": + return AndroidDebugBridge( + identifier=device.identifier, + keep_connected=keep_connected, + wait_connected=wait_connected, + expected_os=expected_os, + ) + def __enter__(self) -> "AndroidDebugBridge": if not self.is_connected(): self._connect_daemon() @@ -74,14 +91,14 @@ def __exit__(self, exc_type, exc_value, exc_tb) -> None: if not self._keep_connected and self.is_connected(): self._disconnect() - @property - def identifier(self) -> str: - """Get adb identifier of current device. + # @property + # def identifier(self) -> str: + # """Get adb identifier of current device. - Returns: - str: adb identifier of current device. - """ - return _identifier_from(ip_addr=self._ip, port=self._port) + # Returns: + # str: adb identifier of current device. + # """ + # return _identifier_from(ip_addr=self._ip, port=self._port) def is_connected(self) -> bool: """Returns whether the device is connected to adb. @@ -219,6 +236,19 @@ def _devices() -> Iterable[ADBDevice]: devices = [ADBDevice(*line.split("\t")) for line in device_lines] return devices + + def query_devices( + self, + filter_callback: Callable[[ADBDevice], bool] = lambda _: True, + ) -> Iterable[ADBDevice]: + """Get filtered list of devices recognized by adb. + + Returns: + Iterable[ADBDevice]: filtered list of devices recognized by adb + """ + devices = self._devices() + filtered = [dev for dev in devices if filter_callback(dev)] + return filtered @staticmethod def _host_shell_out( @@ -439,4 +469,4 @@ def is_installed(self, activity_name: str) -> bool: command = f"pm list packages -e {activity_name}" output = self._target_shell_out(command) is_installed = f"package:{activity_name}" == output.strip() - return is_installed + return is_installed \ No newline at end of file From fe22ad082a5da0b16f74447f33da46893cc15619 Mon Sep 17 00:00:00 2001 From: TryAngle Date: Mon, 25 Nov 2024 01:39:34 +0100 Subject: [PATCH 2/7] Add: CommLayer for HDC and ADB Signed-off-by: TryAngle --- benchkit/devices/adb/__init__.py | 102 ++++++++++++++++++++++++++++++- benchkit/devices/hdc/__init__.py | 101 +++++++++++++++++++++++++++++- 2 files changed, 200 insertions(+), 3 deletions(-) diff --git a/benchkit/devices/adb/__init__.py b/benchkit/devices/adb/__init__.py index 5eb5be4..ec99259 100644 --- a/benchkit/devices/adb/__init__.py +++ b/benchkit/devices/adb/__init__.py @@ -10,9 +10,11 @@ import time from typing import Iterable, Optional, Callable +from benchkit.communication import CommunicationLayer +from benchkit.communication.utils import command_with_env from benchkit.devices.adb.usb import usb_down_up from benchkit.shell.shell import get_args, shell_out -from benchkit.utils.types import Command, PathType +from benchkit.utils.types import Command, Environment, PathType # def _identifier_from(ip_addr: str, port: int) -> str: @@ -469,4 +471,100 @@ def is_installed(self, activity_name: str) -> bool: command = f"pm list packages -e {activity_name}" output = self._target_shell_out(command) is_installed = f"package:{activity_name}" == output.strip() - return is_installed \ No newline at end of file + return is_installed + + +class AndroidCommLayer(CommunicationLayer): + def __init__( + self, + bridge: AndroidDebugBridge, + environment: Optional[Environment] = None, + ) -> None: + super().__init__() + self._bridge = bridge + self._additional_environment = environment if environment is not None else {} + self._command_prefix = None + + @property + def remote_host(self) -> Optional[str]: + return self._bridge.identifier + + @property + def is_local(self) -> bool: + return False + + def copy_from_host(self, source: PathType, destination: PathType) -> None: + self._bridge.push(source, destination) + + def copy_to_host(self, source: PathType, destination: PathType) -> None: + self._bridge.pull(source, destination) + + def shell( + self, + command: Command, + std_input: str | None = None, + current_dir: PathType | None = None, + environment: Environment = None, + shell: bool = False, + print_input: bool = True, + print_output: bool = True, + print_curdir: bool = True, + timeout: int | None = None, + output_is_log: bool = False, + ignore_ret_codes: Iterable[int] = (), + ignore_any_error_code: bool = False + ) -> str: + env_command = command_with_env( + command=command, + environment=environment, + additional_environment=self._additional_environment, + ) + output = self._bridge.shell_out( + command=env_command, + current_dir=current_dir, + output_is_log=output_is_log, + ) + return output + + def pipe_shell( + self, + command: Command, + current_dir: Optional[PathType] = None, + shell: bool = False, + ignore_ret_codes: Iterable[int] = () + ): + raise NotImplementedError("TODO") + + + def background_subprocess( + self, + command: Command, + stdout: PathType, + stderr: PathType, + cwd: PathType | None, + env: dict | None, + establish_new_connection: bool = False + ) -> subprocess.Popen: + dir_args = ["cd", f"{cwd}", "&&"] if cwd is not None else [] + command_args = dir_args + get_args(command) + + adb_command = [ + "adb", + "-s", + f"{self._bridge.identifier}", + "shell", + ] + command_args + + return subprocess.Popen( + adb_command, + stdout=stdout, + stderr=stderr, + env=env, + preexec_fn=os.setsid, + ) + + def get_process_status(self, process_handle: subprocess.Popen) -> str: + raise NotImplementedError("TODO") + + def get_process_nb_threads(self, process_handle: subprocess.Popen) -> int: + raise NotImplementedError("TODO") diff --git a/benchkit/devices/hdc/__init__.py b/benchkit/devices/hdc/__init__.py index c091b95..e101ecf 100644 --- a/benchkit/devices/hdc/__init__.py +++ b/benchkit/devices/hdc/__init__.py @@ -5,13 +5,17 @@ See HDC documentation: https://docs.openharmony.cn/pages/v5.0/en/application-dev/dfx/hdc.md """ from enum import Enum +import os +import subprocess from platform import system as os_system from typing import Callable, Iterable, List, Optional +from benchkit.communication import CommunicationLayer +from benchkit.communication.utils import command_with_env from benchkit.dependencies.executables import ExecutableDependency from benchkit.dependencies.packages import Dependency from benchkit.shell.shell import get_args, shell_out -from benchkit.utils.types import Command, PathType +from benchkit.utils.types import Command, Environment, PathType class HDCError(Exception): @@ -218,3 +222,98 @@ def pull( f"{local_path}", ] self._host_shell_out(command=command) + + +class OpenHarmonyCommLayer(CommunicationLayer): + def __init__( + self, + conn: OpenHarmonyDeviceConnector, + environment: Optional[Environment] = None, + ) -> None: + super().__init__() + self._conn = conn + self._additional_environment = environment if environment is not None else {} + self._command_prefix = None + + @property + def remote_host(self) -> Optional[str]: + return self._conn.identifier + + @property + def is_local(self) -> bool: + return False + + def copy_from_host(self, source: PathType, destination: PathType) -> None: + self._conn.push(source, destination) + + def copy_to_host(self, source: PathType, destination: PathType) -> None: + self._conn.pull(source, destination) + + def shell( + self, + command: Command, + std_input: str | None = None, + current_dir: PathType | None = None, + environment: Environment = None, + shell: bool = False, + print_input: bool = True, + print_output: bool = True, + print_curdir: bool = True, + timeout: int | None = None, + output_is_log: bool = False, + ignore_ret_codes: Iterable[int] = (), + ignore_any_error_code: bool = False + ) -> str: + env_command = command_with_env( + command=command, + environment=environment, + additional_environment=self._additional_environment, + ) + output = self._conn.shell_out( + command=env_command, + current_dir=current_dir, + output_is_log=output_is_log, + ) + return output + + def pipe_shell( + self, + command: Command, + current_dir: Optional[PathType] = None, + shell: bool = False, + ignore_ret_codes: Iterable[int] = () + ): + raise NotImplementedError("TODO") + + def background_subprocess( + self, + command: Command, + stdout: PathType, + stderr: PathType, + cwd: PathType | None, + env: dict | None, + establish_new_connection: bool = False + ) -> subprocess.Popen: + dir_args = ["cd", f"{cwd}", "&&"] if cwd is not None else [] + command_args = dir_args + get_args(command) + + adb_command = [ + "adb", + "-s", + f"{self._conn.identifier}", + "shell", + ] + command_args + + return subprocess.Popen( + adb_command, + stdout=stdout, + stderr=stderr, + env=env, + preexec_fn=os.setsid, + ) + + def get_process_status(self, process_handle: subprocess.Popen) -> str: + raise NotImplementedError("TODO") + + def get_process_nb_threads(self, process_handle: subprocess.Popen) -> int: + raise NotImplementedError("TODO") From e7c4559a9293be42f5dc97909d3481dc7dc092cb Mon Sep 17 00:00:00 2001 From: TryAngle Date: Mon, 25 Nov 2024 01:41:50 +0100 Subject: [PATCH 3/7] Update: ipc example to new commlayer Signed-off-by: TryAngle --- benchkit/devices/adb/__init__.py | 13 ++++++ examples/ipc/ipc.py | 79 +++++++++++++++++--------------- 2 files changed, 56 insertions(+), 36 deletions(-) diff --git a/benchkit/devices/adb/__init__.py b/benchkit/devices/adb/__init__.py index ec99259..ea2e15f 100644 --- a/benchkit/devices/adb/__init__.py +++ b/benchkit/devices/adb/__init__.py @@ -252,6 +252,19 @@ def query_devices( filtered = [dev for dev in devices if filter_callback(dev)] return filtered + def query_devices( + self, + filter_callback: Callable[[ADBDevice], bool] = lambda _: True, + ) -> Iterable[ADBDevice]: + """Get filtered list of devices recognized by hdc. + + Returns: + Iterable[HDCDevice]: filtered list of devices recognized by hdc. + """ + devices = self._devices() + filtered = [dev for dev in devices if filter_callback(dev)] + return filtered + @staticmethod def _host_shell_out( command: Command, diff --git a/examples/ipc/ipc.py b/examples/ipc/ipc.py index 2c2d1a2..9314220 100644 --- a/examples/ipc/ipc.py +++ b/examples/ipc/ipc.py @@ -10,7 +10,6 @@ from benchkit.benchmark import Benchmark, CommandAttachment, PostRunHook, PreRunHook from benchkit.campaign import Campaign, CampaignIterateVariables, CampaignSuite from benchkit.commandwrappers import CommandWrapper -from benchkit.devices.hdc import OpenHarmonyDeviceConnector from benchkit.platforms import Platform, get_current_platform from benchkit.sharedlibs import SharedLib from benchkit.utils.dir import caller_dir @@ -23,15 +22,19 @@ class Target(Enum): LOCAL = 1 - MOBILE = 2 - CONTAINER = 3 + HARMONY = 2 + ANDROID = 3 + CONTAINER = 4 + + def is_mobile(self): + return self == Target.HARMONY or self == Target.ANDROID class IPCBenchmark(Benchmark): def __init__( self, bench_dir: PathType, - mobile: bool = False, + target: Target = Target.LOCAL, skip_rebuild: bool = False, command_wrappers: Iterable[CommandWrapper] = [], command_attachments: Iterable[CommandAttachment] = [], @@ -39,7 +42,6 @@ def __init__( pre_run_hooks: Iterable[PreRunHook] = [], post_run_hooks: Iterable[PostRunHook] = [], platform: Platform | None = None, - hdc: OpenHarmonyDeviceConnector | None = None, ) -> None: super().__init__( command_wrappers=command_wrappers, @@ -48,16 +50,13 @@ def __init__( pre_run_hooks=pre_run_hooks, post_run_hooks=post_run_hooks, ) + self.target = target self.bench_dir = bench_dir - self.mobile = mobile self.skip_rebuild = skip_rebuild if platform is not None: self.platform = platform - if hdc is not None: - self.hdc = hdc - @property def bench_src_path(self) -> pathlib.Path: return self.bench_dir @@ -94,9 +93,10 @@ def parse_output_to_results( return parsed def build_bench(self, **kwargs) -> None: - if self.mobile: + if self.target.is_mobile(): + # TODO: use copy_from_host here, and compile to correct target return - + self.platform.comm.shell( command="cargo build", current_dir=self.bench_dir, @@ -104,7 +104,8 @@ def build_bench(self, **kwargs) -> None: ) def clean_bench(self) -> None: - if self.mobile: + if self.target.is_mobile(): + # TODO: remove copied file return if not self.skip_rebuild: @@ -118,28 +119,25 @@ def single_run(self, m: int, **kwargs) -> str: run_command: List[str] output: str - if self.mobile: + if self.target.is_mobile(): run_command = ["./ipc_runner", "-m", f"{m}"] - # TODO: maybe wrap as well or don't and make comm layer - output = self.hdc.shell_out(run_command, self.bench_dir) - print(output) - else: + else: run_command = ["cargo", "run", "--", "-m", f"{m}"] - wrapped_run_command, wrapped_environment = self._wrap_command( - run_command=run_command, - environment={}, - **kwargs, - ) + wrapped_run_command, wrapped_environment = self._wrap_command( + run_command=run_command, + environment={}, + **kwargs, + ) - output = self.run_bench_command( - environment={}, - run_command=run_command, - wrapped_run_command=wrapped_run_command, - current_dir=self.bench_dir, - wrapped_environment=wrapped_environment, - print_output=True, - ) + output = self.run_bench_command( + environment={}, + run_command=run_command, + wrapped_run_command=wrapped_run_command, + current_dir=self.bench_dir, + wrapped_environment=wrapped_environment, + print_output=True, + ) return output @@ -147,21 +145,31 @@ def single_run(self, m: int, **kwargs) -> str: def main() -> None: nb_runs = 2 variables = [{"m": 10**i} for i in range(1, 4)] - skip_rebuild = False + skip_rebuild = True target = Target.LOCAL bench_dir: pathlib.Path | str = caller_dir() / "ipc_runner" platform: Platform | None = None - hdc: OpenHarmonyDeviceConnector | None = None this_dir = caller_dir() match target: case Target.LOCAL: platform = get_current_platform() - case Target.MOBILE: + case Target.HARMONY: + from benchkit.devices.hdc import OpenHarmonyCommLayer, OpenHarmonyDeviceConnector + + bench_dir = "/data/testing/ipc/" + hdc = OpenHarmonyDeviceConnector.query_devices()[0] + comm = OpenHarmonyCommLayer(hdc) + platform = Platform(comm) + case Target.ANDROID: + from benchkit.devices.adb import AndroidCommLayer, AndroidDebugBridge + bench_dir = "/data/testing/ipc/" - hdc = OpenHarmonyDeviceConnector.query_devices(lambda _: True)[0] + adb = AndroidDebugBridge.query_devices()[0] + comm = AndroidCommLayer(adb) + platform = Platform(comm) case Target.CONTAINER: from rustcontainer import get_rust_docker_platform @@ -171,8 +179,7 @@ def main() -> None: benchmark = IPCBenchmark( bench_dir=bench_dir, platform=platform, - hdc=hdc, - mobile=(Target.MOBILE == target), + target=target, skip_rebuild=skip_rebuild, ) From 409b5f1ef8520a668b37b5dcb1857e652e515468 Mon Sep 17 00:00:00 2001 From: TryAngle <45734252+TriedAngle@users.noreply.github.com> Date: Mon, 25 Nov 2024 01:46:25 +0100 Subject: [PATCH 4/7] Update benchkit/devices/hdc/__init__.py Co-authored-by: Jonathan Schwender <55576758+jschwe@users.noreply.github.com> Signed-off-by: TryAngle <45734252+TriedAngle@users.noreply.github.com> --- benchkit/devices/hdc/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/benchkit/devices/hdc/__init__.py b/benchkit/devices/hdc/__init__.py index e101ecf..a7105de 100644 --- a/benchkit/devices/hdc/__init__.py +++ b/benchkit/devices/hdc/__init__.py @@ -297,15 +297,15 @@ def background_subprocess( dir_args = ["cd", f"{cwd}", "&&"] if cwd is not None else [] command_args = dir_args + get_args(command) - adb_command = [ - "adb", - "-s", + hdc_command = [ + "hdc", + "-t", f"{self._conn.identifier}", "shell", ] + command_args return subprocess.Popen( - adb_command, + hdc_command, stdout=stdout, stderr=stderr, env=env, From e9ec3d80682e70124743b612b257b405a36d22f1 Mon Sep 17 00:00:00 2001 From: TryAngle Date: Thu, 2 Jan 2025 04:52:01 +0100 Subject: [PATCH 5/7] Change: static binary and query Signed-off-by: TryAngle --- benchkit/devices/adb/__init__.py | 34 ++++++++++++++++---------------- benchkit/devices/hdc/__init__.py | 22 +++++++++++++-------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/benchkit/devices/adb/__init__.py b/benchkit/devices/adb/__init__.py index ea2e15f..09c7f84 100644 --- a/benchkit/devices/adb/__init__.py +++ b/benchkit/devices/adb/__init__.py @@ -12,6 +12,8 @@ from benchkit.communication import CommunicationLayer from benchkit.communication.utils import command_with_env +from benchkit.dependencies.dependency import Dependency +from benchkit.dependencies.executables import ExecutableDependency from benchkit.devices.adb.usb import usb_down_up from benchkit.shell.shell import get_args, shell_out from benchkit.utils.types import Command, Environment, PathType @@ -79,6 +81,14 @@ def from_device( expected_os=expected_os, ) + @staticmethod + def binary() -> str: + return "adb" + + @staticmethod + def dependencies() -> Iterable[Dependency]: + return [ExecutableDependency(AndroidDebugBridge.binary())] + def __enter__(self) -> "AndroidDebugBridge": if not self.is_connected(): self._connect_daemon() @@ -160,7 +170,8 @@ def _connect_daemon(self) -> None: with socket.socket(socket.AF_INET) as conn_sock: conn_sock.settimeout(wait_time) try: - conn_sock.connect((self._ip, self._port)) + # TODO: investigate daemon + # conn_sock.connect((self._ip, self._port)) connected = True except TimeoutError: wait_time *= 2 @@ -186,7 +197,9 @@ def _connect_daemon(self) -> None: raise ADBError("Problem with adb connection") def _connect(self, timeout: int) -> None: - ip_port = f"{self._ip}:{self._port}" + # TODO: investigate daemon + # ip_port = f"{self._ip}:{self._port}" + ip_port = "" succeed = False wait_time = 1 while not succeed: @@ -239,8 +252,8 @@ def _devices() -> Iterable[ADBDevice]: return devices + @staticmethod def query_devices( - self, filter_callback: Callable[[ADBDevice], bool] = lambda _: True, ) -> Iterable[ADBDevice]: """Get filtered list of devices recognized by adb. @@ -248,20 +261,7 @@ def query_devices( Returns: Iterable[ADBDevice]: filtered list of devices recognized by adb """ - devices = self._devices() - filtered = [dev for dev in devices if filter_callback(dev)] - return filtered - - def query_devices( - self, - filter_callback: Callable[[ADBDevice], bool] = lambda _: True, - ) -> Iterable[ADBDevice]: - """Get filtered list of devices recognized by hdc. - - Returns: - Iterable[HDCDevice]: filtered list of devices recognized by hdc. - """ - devices = self._devices() + devices = AndroidDebugBridge._devices() filtered = [dev for dev in devices if filter_callback(dev)] return filtered diff --git a/benchkit/devices/hdc/__init__.py b/benchkit/devices/hdc/__init__.py index a7105de..ce0b4f0 100644 --- a/benchkit/devices/hdc/__init__.py +++ b/benchkit/devices/hdc/__init__.py @@ -59,7 +59,6 @@ def __init__( self._keep_connected = keep_connected self._wait_connected = wait_connected self._expected_os = expected_os - self._bin = "hdc.exe" if "Windows" == os_system() else "hdc" @staticmethod def from_device( @@ -76,8 +75,13 @@ def from_device( expected_os=expected_os, ) - def dependencies(self) -> List[Dependency]: - return [ExecutableDependency(self._bin)] + @staticmethod + def binary() -> str: + return "hdc.exe" if "Windows" == os_system() else "hdc" + + @staticmethod + def dependencies() -> List[Dependency]: + return [ExecutableDependency(OpenHarmonyDeviceConnector.binary())] def _find_device(self) -> Optional[HDCDevice]: devices = [dev for dev in self._devices() if dev.identifier == self.identifier] @@ -89,13 +93,15 @@ def _find_device(self) -> Optional[HDCDevice]: case _: raise ValueError("Wrong device list.") - def _devices(self) -> List[HDCDevice]: + @staticmethod + def _devices() -> List[HDCDevice]: """Get list of devices recognized by hdc. Returns: Iterable[HDCDevice]: list of devices recognized by hdc. """ - output = OpenHarmonyDeviceConnector._host_shell_out(command=f"{self._bin} list targets") + binary = OpenHarmonyDeviceConnector.binary() + output = OpenHarmonyDeviceConnector._host_shell_out(command=f"{binary} list targets") device_ids = output.strip().splitlines() devices = [] for dev in device_ids: @@ -115,7 +121,7 @@ def query_devices( Returns: Iterable[HDCDevice]: filtered list of devices recognized by hdc. """ - devices = self._devices() + devices = OpenHarmonyDeviceConnector._devices() filtered = [dev for dev in devices if filter_callback(dev)] return filtered @@ -143,7 +149,7 @@ def _target_shell_out( dir_args = ["cd", f"{current_dir}", "&&"] if current_dir is not None else [] command_args = dir_args + get_args(command) - hdc_command = [f"{self._bin}", "-t", f"{self.identifier}", "shell"] + command_args + hdc_command = [f"{self.binary()}", "-t", f"{self.identifier}", "shell"] + command_args output = shell_out( command=hdc_command, @@ -213,7 +219,7 @@ def pull( local_path (PathType): path where to pull the file on the host. """ command = [ - f"{self._bin}", + f"{self.binary()}", "-t", f"{self.identifier}", "file", From c9c55c38fbff806e03f1f1f18d2777fd762b90d3 Mon Sep 17 00:00:00 2001 From: TryAngle Date: Thu, 2 Jan 2025 04:55:26 +0100 Subject: [PATCH 6/7] Add: commlayer test Signed-off-by: TryAngle --- tests/test_commlayer.py | 51 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 tests/test_commlayer.py diff --git a/tests/test_commlayer.py b/tests/test_commlayer.py new file mode 100644 index 0000000..87cf4b2 --- /dev/null +++ b/tests/test_commlayer.py @@ -0,0 +1,51 @@ + +# Copyright (C) 2024 Huawei Technologies Co., Ltd. All rights reserved. +# SPDX-License-Identifier: MIT +""" +Module to test the ADB and HDC commlayer api +""" +from enum import Enum +from benchkit.platforms import Platform, get_current_platform + + +class Target(Enum): + LOCAL = 1 + HARMONY = 2 + ANDROID = 3 + +def main() -> None: + target = Target.ANDROID + platform: Platform + current_dir = "./" + + match target: + case Target.LOCAL: + platform = get_current_platform() + print(platform) + case Target.HARMONY: + from benchkit.devices.hdc import OpenHarmonyDeviceConnector, OpenHarmonyCommLayer + device = list(OpenHarmonyDeviceConnector.query_devices())[0] + hdc = OpenHarmonyDeviceConnector.from_device(device) + comm = OpenHarmonyCommLayer(hdc) + print(device) + platform = Platform(comm) + case Target.ANDROID: + from benchkit.devices.adb import AndroidDebugBridge, AndroidCommLayer + device = list(AndroidDebugBridge.query_devices())[0] + adb = AndroidDebugBridge.from_device(device) + comm = AndroidCommLayer(adb) + print(device) + platform = Platform(comm) + + output = platform.comm.shell( + command="ls", + current_dir=current_dir, + environment={}, + output_is_log=False, + ) + + print(output) + + +if __name__ == "__main__": + main() From 595a83dd91b9131813efe75f6b7f9ef50b0b4242 Mon Sep 17 00:00:00 2001 From: TryAngle Date: Thu, 2 Jan 2025 06:41:56 +0100 Subject: [PATCH 7/7] Add: path_exists to adb Signed-off-by: TryAngle --- benchkit/devices/adb/__init__.py | 51 ++++++++++++++++++++++++++++---- examples/ipc/ipc.py | 20 ++++++++----- 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/benchkit/devices/adb/__init__.py b/benchkit/devices/adb/__init__.py index 09c7f84..8835deb 100644 --- a/benchkit/devices/adb/__init__.py +++ b/benchkit/devices/adb/__init__.py @@ -11,12 +11,12 @@ from typing import Iterable, Optional, Callable from benchkit.communication import CommunicationLayer -from benchkit.communication.utils import command_with_env +from benchkit.communication.utils import command_with_env, remote_shell_command from benchkit.dependencies.dependency import Dependency from benchkit.dependencies.executables import ExecutableDependency from benchkit.devices.adb.usb import usb_down_up from benchkit.shell.shell import get_args, shell_out -from benchkit.utils.types import Command, Environment, PathType +from benchkit.utils.types import Command, Environment, PathType, SplitCommand # def _identifier_from(ip_addr: str, port: int) -> str: @@ -512,6 +512,23 @@ def copy_from_host(self, source: PathType, destination: PathType) -> None: def copy_to_host(self, source: PathType, destination: PathType) -> None: self._bridge.pull(source, destination) + + def _remote_shell_command( + self, + remote_command: Command, + remote_current_dir: PathType | None = None, + ) -> SplitCommand: + dir_args = ["cd", f"{remote_current_dir}", "&&"] if remote_current_dir is not None else [] + command_args = dir_args + get_args(remote_command) + + remote_command = [ + "adb", + "-s", + f"{self._bridge.identifier}", + "shell", + ] + command_args + return remote_command + def shell( self, command: Command, @@ -532,10 +549,21 @@ def shell( environment=environment, additional_environment=self._additional_environment, ) - output = self._bridge.shell_out( - command=env_command, - current_dir=current_dir, + + full_command = self._remote_shell_command( + remote_command=env_command, + remote_current_dir=current_dir, + ) + + output = shell_out( + command=full_command, + std_input=std_input, + current_dir=None, + print_input=print_input, + print_output=print_output, + timeout=timeout, output_is_log=output_is_log, + ignore_ret_codes=ignore_ret_codes, ) return output @@ -576,6 +604,19 @@ def background_subprocess( preexec_fn=os.setsid, ) + def path_exists( + self, + path: PathType + ) -> bool: + try: + result = self.shell( + command=f"test -e {path} && echo 1 || echo 0", + output_is_log=False + ) + return bool(int(result.strip())) + except: + return False + def get_process_status(self, process_handle: subprocess.Popen) -> str: raise NotImplementedError("TODO") diff --git a/examples/ipc/ipc.py b/examples/ipc/ipc.py index 9314220..632f43b 100644 --- a/examples/ipc/ipc.py +++ b/examples/ipc/ipc.py @@ -49,6 +49,7 @@ def __init__( shared_libs=shared_libs, pre_run_hooks=pre_run_hooks, post_run_hooks=post_run_hooks, + ) self.target = target self.bench_dir = bench_dir @@ -59,7 +60,7 @@ def __init__( @property def bench_src_path(self) -> pathlib.Path: - return self.bench_dir + return pathlib.Path(self.bench_dir) @staticmethod def get_build_var_names() -> List[str]: @@ -94,7 +95,6 @@ def parse_output_to_results( def build_bench(self, **kwargs) -> None: if self.target.is_mobile(): - # TODO: use copy_from_host here, and compile to correct target return self.platform.comm.shell( @@ -146,7 +146,7 @@ def main() -> None: nb_runs = 2 variables = [{"m": 10**i} for i in range(1, 4)] skip_rebuild = True - target = Target.LOCAL + target = Target.ANDROID bench_dir: pathlib.Path | str = caller_dir() / "ipc_runner" platform: Platform | None = None @@ -159,15 +159,17 @@ def main() -> None: case Target.HARMONY: from benchkit.devices.hdc import OpenHarmonyCommLayer, OpenHarmonyDeviceConnector - bench_dir = "/data/testing/ipc/" - hdc = OpenHarmonyDeviceConnector.query_devices()[0] + bench_dir = "/data/testing/ipc/ipc_runner" + device = list(OpenHarmonyDeviceConnector.query_devices())[0] + hdc = OpenHarmonyDeviceConnector.from_device(device) comm = OpenHarmonyCommLayer(hdc) platform = Platform(comm) case Target.ANDROID: from benchkit.devices.adb import AndroidCommLayer, AndroidDebugBridge - bench_dir = "/data/testing/ipc/" - adb = AndroidDebugBridge.query_devices()[0] + bench_dir = "/data/local/tmp" + device = list(AndroidDebugBridge.query_devices())[0] + adb = AndroidDebugBridge.from_device(device) comm = AndroidCommLayer(adb) platform = Platform(comm) case Target.CONTAINER: @@ -183,6 +185,8 @@ def main() -> None: skip_rebuild=skip_rebuild, ) + benchmark._base_data_dir = None + campaign = CampaignIterateVariables( name="IPC Benching", benchmark=benchmark, @@ -191,7 +195,7 @@ def main() -> None: gdb=False, debug=False, constants=None, - enable_data_dir=True, + enable_data_dir=False, ) campaigns: List[Campaign] = [campaign]