From b85f93fe825d29bb443d82be7a92437d067b6cd7 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 16 Oct 2024 19:14:45 +0200 Subject: [PATCH 1/2] feat: Add 'simulatorLogLevel' capability --- docs/reference/capabilities.md | 1 + lib/commands/log.js | 1 + lib/desired-caps.js | 3 +++ lib/device-log/ios-simulator-log.ts | 31 ++++++++++++++++++++++++----- 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/docs/reference/capabilities.md b/docs/reference/capabilities.md index 413828fbe..6822612f2 100644 --- a/docs/reference/capabilities.md +++ b/docs/reference/capabilities.md @@ -113,6 +113,7 @@ about capabilities, refer to the [Appium documentation](https://appium.io/docs/e |`appium:autoFillPasswords`| It allows you to turn on/off autofill passwords function when text field is foccused. Works only with iOS16.4+ simulators | `true` | |`appium:permissions`| Allows to set permissions for the specified application bundle on Simulator only. The capability value is expected to be a valid JSON string with `{"": {"": "", ...}, ...}` format. Since Xcode SDK 11.4 Apple provides native APIs to interact with application settings. Check the output of `xcrun simctl privacy booted` command to get the list of available permission names. Use `yes`, `no` and `unset` as values in order to `grant`, `revoke` or `reset` the corresponding permission. Below Xcode SDK 11.4 it is required that `applesimutils` package is installed and available in PATH. The list of available service names and statuses can be found at https://github.com/wix/AppleSimulatorUtils. | `{"com.apple.mobilecal": {"calendar": "YES"}}` | |`appium:iosSimulatorLogsPredicate`|Set the `--predicate` flag in the ios simulator logs|`'process != "locationd" AND process != "DTServiceHub"' AND process != "mobileassetd"`| +|`appium:simulatorLogLevel`|Allows to customize the minimum log level for logs collected from simulators. Possible values are `default` (the default value), `info` and `debug`| `debug` | |`appium:simulatorPasteboardAutomaticSync`| Handle the `-PasteboardAutomaticSync` flag when simulator process launches. It could improve launching simulator performance not to sync pasteboard with the system when this value is `off`. `on` forces the flag enabled. `system` does not provide the flag to the launching command. `on`, `off`, or `system` is available. They are case insensitive. Defaults to `off` | `system` | |`appium:simulatorDevicesSetPath`| This capability allows to set an alternative path to the simulator devices set in case you have multiple sets deployed on your local system. Such feature could be useful if you, for example, would like to save disk space on the main system volume. | `/MyVolume/Devices` | |`appium:safariGlobalPreferences`| Allows changing of Mobile Safari's preferences at the session startup. Check the documentation on arguments of [mobile: updateSafariPreferences](./execute-methods.md#mobile-updatesafaripreferences) extension to get more details on the value type requirements. Only available on real devices since driver version 7.9.0. A new Safari instance must be launched upon test startup for this capability to take effect on real devices. | `{ ShowTabBar: 0, WarnAboutFraudulentWebsites: 0 }` | diff --git a/lib/commands/log.js b/lib/commands/log.js index 439e0adf6..558815541 100644 --- a/lib/commands/log.js +++ b/lib/commands/log.js @@ -174,6 +174,7 @@ export default { sim: /** @type {import('appium-ios-simulator').Simulator} */ (this.device), showLogs: this.opts.showIOSLog, iosSimulatorLogsPredicate: this.opts.iosSimulatorLogsPredicate, + simulatorLogLevel: this.opts.simulatorLogLevel, log: this.log, }), { diff --git a/lib/desired-caps.js b/lib/desired-caps.js index cc991f06b..5c5666156 100644 --- a/lib/desired-caps.js +++ b/lib/desired-caps.js @@ -315,6 +315,9 @@ const desiredCapConstraints = /** @type {const} */ ({ iosSimulatorLogsPredicate: { isString: true, }, + simulatorLogLevel: { + isString: true, + }, appPushTimeout: { isNumber: true, }, diff --git a/lib/device-log/ios-simulator-log.ts b/lib/device-log/ios-simulator-log.ts index be4d2ec9b..4f57a3022 100644 --- a/lib/device-log/ios-simulator-log.ts +++ b/lib/device-log/ios-simulator-log.ts @@ -5,6 +5,7 @@ import type { Simulator } from 'appium-ios-simulator'; import type { AppiumLogger } from '@appium/types'; const EXECVP_ERROR_PATTERN = /execvp\(\)/; +const LOG_STREAMING_PROCESS_NAME_PATTERN = /^com\.apple\.xpc\.launchd\.oneshot\.0x[0-f]+\.log$/; const START_TIMEOUT = 10000; @@ -12,6 +13,7 @@ export interface IOSSimulatorLogOptions { sim: Simulator; showLogs?: boolean; iosSimulatorLogsPredicate?: string; + simulatorLogLevel?: string; log: AppiumLogger; } @@ -19,6 +21,7 @@ export class IOSSimulatorLog extends LineConsumingLog { private readonly sim: Simulator; private readonly showLogs: boolean; private readonly predicate?: string; + private readonly logLevel?: string; private proc: SubProcess | null; constructor(opts: IOSSimulatorLogOptions) { @@ -26,6 +29,7 @@ export class IOSSimulatorLog extends LineConsumingLog { this.sim = opts.sim; this.showLogs = !!opts.showLogs; this.predicate = opts.iosSimulatorLogsPredicate; + this.logLevel = opts.simulatorLogLevel; this.proc = null; } @@ -41,13 +45,13 @@ export class IOSSimulatorLog extends LineConsumingLog { if (this.predicate) { spawnArgs.push('--predicate', this.predicate); } + if (this.logLevel) { + spawnArgs.push('--level', this.logLevel); + } this.log.debug( - `Starting log capture for iOS Simulator with udid '${this.sim.udid}' ` + `using simctl`, + `Starting log capture for iOS Simulator with udid '${this.sim.udid}' using simctl`, ); - try { - // cleanup existing listeners if the previous session has not been terminated properly - await exec('pkill', ['-f', [this.sim.udid, ...spawnArgs].join(' ')]); - } catch (ign) {} + await this.cleanupObsoleteLogStreams(); try { this.proc = await this.sim.simctl.spawnSubProcess(spawnArgs); await this.finishStartingLogCapture(); @@ -112,6 +116,23 @@ export class IOSSimulatorLog extends LineConsumingLog { }; await this.proc.start(startDetector, START_TIMEOUT); } + + private async cleanupObsoleteLogStreams(): Promise { + const processes = await this.sim.ps(); + const pids = processes + .filter(({name}) => LOG_STREAMING_PROCESS_NAME_PATTERN.test(name)) + .map(({pid}) => pid); + if (_.isEmpty(pids)) { + return; + } + try { + await exec('kill', pids.map(String)); + } catch (e) { + this.log.warn( + `Cound not terminate one or more obsolete log streams: ${e.stderr || e.message}` + ); + } + } } export default IOSSimulatorLog; From e2438c3bc07e7c6c98894d4dc6c776ed28e9845a Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 16 Oct 2024 19:18:11 +0200 Subject: [PATCH 2/2] tune logs --- lib/device-log/ios-simulator-log.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/device-log/ios-simulator-log.ts b/lib/device-log/ios-simulator-log.ts index 4f57a3022..0a58ba313 100644 --- a/lib/device-log/ios-simulator-log.ts +++ b/lib/device-log/ios-simulator-log.ts @@ -1,5 +1,6 @@ import _ from 'lodash'; import {SubProcess, exec} from 'teen_process'; +import {util} from 'appium/support'; import { LineConsumingLog } from './line-consuming-log'; import type { Simulator } from 'appium-ios-simulator'; import type { AppiumLogger } from '@appium/types'; @@ -49,7 +50,8 @@ export class IOSSimulatorLog extends LineConsumingLog { spawnArgs.push('--level', this.logLevel); } this.log.debug( - `Starting log capture for iOS Simulator with udid '${this.sim.udid}' using simctl`, + `Starting log capture for iOS Simulator with udid '${this.sim.udid}' ` + + `via simctl using the following arguments '${util.quote(spawnArgs)}'` ); await this.cleanupObsoleteLogStreams(); try {