Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
const {cmd, args} = this.getCommand(buildOnly);
log.debug(`Beginning ${buildOnly ? 'build' : 'test'} with command '${cmd} ${args.join(' ')}' ` +
`in directory '${this.bootstrapPath}'`);
const env = Object.assign({}, process.env, {
USE_PORT: this.wdaRemotePort,
WDA_PRODUCT_BUNDLE_IDENTIFIER: this.updatedWDABundleId || WDA_RUNNER_BUNDLE_ID,
});
if (this.mjpegServerPort) {
// https://github.com/appium/WebDriverAgent/pull/105
env.MJPEG_SERVER_PORT = this.mjpegServerPort;
}
const upgradeTimestamp = await getWDAUpgradeTimestamp(this.bootstrapPath);
if (upgradeTimestamp) {
env.UPGRADE_TIMESTAMP = upgradeTimestamp;
}
const xcodebuild = new SubProcess(cmd, args, {
cwd: this.bootstrapPath,
env,
detached: true,
stdio: ['ignore', 'pipe', 'pipe'],
});
let logXcodeOutput = !!this.showXcodeLog;
const logMsg = _.isBoolean(this.showXcodeLog)
? `Output from xcodebuild ${this.showXcodeLog ? 'will' : 'will not'} be logged`
: 'Output from xcodebuild will only be logged if any errors are present there';
log.debug(`${logMsg}. To change this, use 'showXcodeLog' desired capability`);
xcodebuild.on('output', (stdout, stderr) => {
let out = stdout || stderr;
// we want to pull out the log file that is created, and highlight it
// for diagnostic purposes
if (out.includes('Writing diagnostic log for test session to')) {
const getApksignerOutput = async (apksignerPath) => {
let binaryPath = apksignerPath;
if (system.isWindows() && util.isSubPath(binaryPath, originalFolder)) {
// Workaround for https://github.com/nodejs/node-v0.x-archive/issues/25895
binaryPath = path.basename(binaryPath);
}
const {stdout, stderr} = await exec(binaryPath, args, {
cwd: originalFolder
});
for (let [name, stream] of [['stdout', stdout], ['stderr', stderr]]) {
if (!stream) {
continue;
}
if (name === 'stdout') {
// Make the output less talkative
stream = stream.split('\n')
.filter((line) => !line.includes('WARNING:'))
.join('\n');
}
log.debug(`apksigner ${name}: ${stream}`);
}
return stdout;
createIWDPProcess () {
// (see https://github.com/google/ios-webkit-debug-proxy for reference)
const process = new SubProcess(IWDP_CMD, ['-c', `${this.udid}:${this.port}`, '-d']);
process.on('exit', () => this.onExit());
process.on('lines-stderr', iwdpLogger.error);
if (this.logStdout) {
process.on('lines-stdout', iwdpLogger.debug);
}
return process;
}
return await new B(async (_resolve, _reject) => { // eslint-disable-line promise/param-names
const resolve = function (...args) {
started = true;
_resolve(...args);
};
const reject = function (...args) {
started = true;
_reject(...args);
};
if (this.clearLogs) {
await this.clear();
}
log.debug('Starting logcat capture');
this.proc = new SubProcess(this.adb.path, this.adb.defaultArgs.concat(['logcat', '-v', 'threadtime']));
this.proc.on('exit', (code, signal) => {
log.error(`Logcat terminated with code ${code}, signal ${signal}`);
this.proc = null;
if (!started) {
log.warn('Logcat not started. Continuing');
resolve();
}
});
this.proc.on('lines-stderr', (lines) => {
for (let line of lines) {
if (/execvp\(\)/.test(line)) {
log.error('Logcat process failed to start');
reject(new Error(`Logcat process failed to start. stderr: ${line}`));
}
this.outputHandler(_.trim(line), 'STDERR: ');
}
return await new B(async (resolve, reject) => {
let args = this.executable.defaultArgs
.concat(['shell', 'am', 'instrument', '-e', 'coverage', 'true', '-w'])
.concat([instrumentClass]);
log.debug(`Collecting coverage data with: ${[this.executable.path].concat(args).join(' ')}`);
try {
// am instrument runs for the life of the app process.
this.instrumentProc = new SubProcess(this.executable.path, args);
await this.instrumentProc.start(0);
this.instrumentProc.on('output', (stdout, stderr) => {
if (stderr) {
reject(new Error(`Failed to run instrumentation. Original error: ${stderr}`));
}
});
await this.waitForActivity(waitPkg, waitActivity);
resolve();
} catch (e) {
reject(new Error(`Android coverage failed. Original error: ${e.message}`));
}
});
};
// escape any argument that has a space in it
if (_.isString(arg) && arg.indexOf(' ') !== -1) {
return `"${arg}"`;
}
// otherwise just use the argument
return arg;
});
log.debug(`Spawning instruments with command: '${instrumentsExecArgs.join(' ')}'`);
if (this.withoutDelay) {
log.debug('And extra without-delay env: ' + JSON.stringify({
DYLD_INSERT_LIBRARIES: env.DYLD_INSERT_LIBRARIES,
LIB_PATH: env.LIB_PATH
}));
}
log.debug(`And launch timeouts (in ms): ${JSON.stringify(this.launchTimeout)}`);
return await spawn(this.instrumentsPath, args, {env});
}
// escape any argument that has a space in it
if (_.isString(arg) && arg.indexOf(' ') !== -1) {
return `"${arg}"`;
}
// otherwise just use the argument
return arg;
});
log.debug(`Spawning instruments with command: '${instrumentsExecArgs.join(' ')}'`);
if (this.withoutDelay) {
log.debug('And extra without-delay env: ' + JSON.stringify({
DYLD_INSERT_LIBRARIES: env.DYLD_INSERT_LIBRARIES,
LIB_PATH: env.LIB_PATH
}));
}
log.debug(`And launch timeouts (in ms): ${JSON.stringify(this.launchTimeout)}`);
return await spawn(this.instrumentsPath, args, {env});
}
await finishPerfRecord(proc, true);
if (!await fs.exists(localPath)) {
log.errorAndThrow(`There is no .trace file found for performance profile '${profileName}' ` +
`and device ${this.opts.device.udid}. ` +
`Make sure the profile is supported on this device. ` +
`You can use 'instruments -s' command to see the list of all available profiles.`);
}
const zipPath = `${localPath}.zip`;
const zipArgs = [
'-9', '-r', zipPath,
path.basename(localPath),
];
log.info(`Found perf trace record '${localPath}'. Compressing it with 'zip ${zipArgs.join(' ')}'`);
try {
await exec('zip', zipArgs, {
cwd: path.dirname(localPath),
});
return await uploadTrace(zipPath, remotePath, {user, pass, method});
} finally {
delete runningRecorders[this.opts.device.udid];
if (await fs.exists(localPath)) {
await fs.rimraf(localPath);
}
}
};
async cleanupObsoleteProcesses () {
const obsoletePids = await getPIDsListeningOnPort(this.url.port,
(cmdLine) => cmdLine.includes('/WebDriverAgentRunner') &&
!cmdLine.toLowerCase().includes(this.device.udid.toLowerCase()));
if (_.isEmpty(obsoletePids)) {
log.debug(`No obsolete cached processes from previous WDA sessions ` +
`listening on port ${this.url.port} have been found`);
return;
}
log.info(`Detected ${obsoletePids.length} obsolete cached process${obsoletePids.length === 1 ? '' : 'es'} ` +
`from previous WDA sessions. Cleaning them up`);
try {
await exec('kill', obsoletePids);
} catch (e) {
log.warn(`Failed to kill obsolete cached process${obsoletePids.length === 1 ? '' : 'es'} '${obsoletePids}'. ` +
`Original error: ${e.message}`);
}
}
systemCallMethods.getConnectedDevices = async function () {
log.debug("Getting connected devices...");
try {
let { stdout } = await exec(this.executable.path, ['devices']);
let startingIndex = stdout.indexOf("List of devices attached");
stdout = stdout.slice(startingIndex);
if (stdout.length < 1) {
throw new Error("Could not find device.");
} else {
let devices = [];
for (let line of stdout.split("\n")) {
if (line.trim() !== "" && line.indexOf("List of devices") === -1) {
let lineInfo = line.split("\t");
devices.push({ udid: lineInfo[0].trim(), state: lineInfo[1].trim(), platform: lineInfo[2].trim() });
}
}
log.debug(`${devices.length} device(s) connected`);
return devices;
}