UNPKG

appium-xcuitest-driver

Version:

Appium driver for iOS using XCUITest for backend

116 lines 4.36 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.IOSSimulatorLog = void 0; const lodash_1 = __importDefault(require("lodash")); const teen_process_1 = require("teen_process"); const support_1 = require("appium/support"); const line_consuming_log_1 = require("./line-consuming-log"); const EXECVP_ERROR_PATTERN = /execvp\(\)/; const LOG_STREAMING_PROCESS_NAME_PATTERN = /^com\.apple\.xpc\.launchd\.oneshot\.0x[0-f]+\.log$/; const START_TIMEOUT = 10000; class IOSSimulatorLog extends line_consuming_log_1.LineConsumingLog { constructor(opts) { super({ log: opts.log }); this.sim = opts.sim; this.showLogs = !!opts.showLogs; this.predicate = opts.iosSimulatorLogsPredicate; this.logLevel = opts.simulatorLogLevel; this.proc = null; } async startCapture() { if (lodash_1.default.isUndefined(this.sim.udid)) { throw new Error(`Log capture requires a sim udid`); } if (!(await this.sim.isRunning())) { throw new Error(`iOS Simulator with udid '${this.sim.udid}' is not running`); } const spawnArgs = ['log', 'stream', '--style', 'compact']; 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}' ` + `via simctl using the following arguments '${support_1.util.quote(spawnArgs)}'`); await this.cleanupObsoleteLogStreams(); try { this.proc = await this.sim.simctl.spawnSubProcess(spawnArgs); await this.finishStartingLogCapture(); } catch (e) { throw new Error(`Simulator log capture failed. Original error: ${e.message}`); } } async stopCapture() { if (!this.proc) { return; } await this.killLogSubProcess(); this.proc = null; } get isCapturing() { return Boolean(this.proc && this.proc.isRunning); } onOutput(logRow, prefix = '') { this.broadcast(logRow); if (this.showLogs) { const space = prefix.length > 0 ? ' ' : ''; this.log.info(`[IOS_SYSLOG_ROW${space}${prefix}] ${logRow}`); } } async killLogSubProcess() { if (!this.proc?.isRunning) { return; } this.log.debug('Stopping iOS log capture'); try { await this.proc.stop('SIGTERM', 1000); } catch { if (!this.proc.isRunning) { return; } this.log.warn('Cannot stop log capture process. Sending SIGKILL'); await this.proc.stop('SIGKILL'); } } async finishStartingLogCapture() { if (!this.proc) { throw this.log.errorWithException('Could not capture simulator log'); } for (const streamName of ['stdout', 'stderr']) { this.proc.on(`line-${streamName}`, (line) => { this.onOutput(line, ...(streamName === 'stderr' ? ['STDERR'] : [])); }); } const startDetector = (stdout, stderr) => { if (EXECVP_ERROR_PATTERN.test(stderr)) { throw new Error('iOS log capture process failed to start'); } return Boolean(stdout || stderr); }; await this.proc.start(startDetector, START_TIMEOUT); } async cleanupObsoleteLogStreams() { const processes = await this.sim.ps(); const pids = processes .filter(({ name }) => LOG_STREAMING_PROCESS_NAME_PATTERN.test(name)) .map(({ pid }) => pid); if (lodash_1.default.isEmpty(pids)) { return; } try { await (0, teen_process_1.exec)('kill', pids.map(String)); } catch (e) { this.log.warn(`Cound not terminate one or more obsolete log streams: ${e.stderr || e.message}`); } } } exports.IOSSimulatorLog = IOSSimulatorLog; exports.default = IOSSimulatorLog; //# sourceMappingURL=ios-simulator-log.js.map