From 2d7ecfdfc972d8dcf266c342f1b022936d17eed9 Mon Sep 17 00:00:00 2001 From: rosen-vladimirov Date: Thu, 4 May 2017 18:36:23 +0300 Subject: [PATCH 1/2] Ensure stopApplication works correctly stopApplication method calls killall command, which does not terminate the process immediately. So trying to restart the application, which is stopApplication followed by immediate startApplication call, fails with some strange error, that the app has started, but has exited since then. In order to fix this, add a timeout after stop is called, in order to ensure the app is dead. However in newer Xcode's there's a `xcrun simctl terminate` command, which really kills it. So check the version of Xcode and in case it is 8 or later, use the new command instead of killall. In this scenario we do not have to add some magic timeout as the command works correctly. However the xcrun simctl terminate command requires application identifier, while the killall command works with application name. So I've added another paramter to the stopApplication definition, which should be passed from CLI when calling this method - the applicationIdentifier will be used when Xcode 8 or later is installed, appName will be used for earlier versions. --- lib/declarations.ts | 3 ++- lib/iphone-simulator-xcode-simctl.ts | 25 +++++++++++++++++++++---- lib/simctl.ts | 4 ++++ lib/utils.ts | 12 +++++------- lib/xcode.ts | 4 ++-- 5 files changed, 34 insertions(+), 14 deletions(-) diff --git a/lib/declarations.ts b/lib/declarations.ts index 707938e..33fa51a 100644 --- a/lib/declarations.ts +++ b/lib/declarations.ts @@ -28,6 +28,7 @@ interface IDevice { interface ISimctl { launch(deviceId: string, applicationIdentifier: string): string; + terminate(deviceId: string, appIdentifier: string): string; install(deviceId: string, applicationPath: string): void; uninstall(deviceId: string, applicationIdentifier: string, opts?: any): void; notifyPost(deviceId: string, notification: string): void; @@ -49,7 +50,7 @@ interface ISimulator extends INameGetter { installApplication(deviceId: string, applicationPath: string): void; uninstallApplication(deviceId: string, appIdentifier: string): void; startApplication(deviceId: string, appIdentifier: string): string; - stopApplication(deviceId: string, appIdentifier: string): string; + stopApplication(deviceId: string, appIdentifier: string, bundleExecutable: string): string; printDeviceLog(deviceId: string, launchResult?: string): any; getDeviceLogProcess(deviceId: string): any; startSimulator(): void; diff --git a/lib/iphone-simulator-xcode-simctl.ts b/lib/iphone-simulator-xcode-simctl.ts index 314b766..3098836 100755 --- a/lib/iphone-simulator-xcode-simctl.ts +++ b/lib/iphone-simulator-xcode-simctl.ts @@ -87,9 +87,26 @@ export class XCodeSimctlSimulator extends IPhoneSimulatorNameGetter implements I return this.simctl.launch(deviceId, appIdentifier); } - public stopApplication(deviceId: string, cfBundleExecutable: string): string { + public stopApplication(deviceId: string, appIdentifier: string, bundleExecutable: string): string { try { - return childProcess.execSync(`killall ${cfBundleExecutable}`, { skipError: true }); + let xcodeMajorVersion: number = null; + try { + const xcodeVersion = xcode.getXcodeVersionData(); + xcodeMajorVersion = +xcodeVersion.major; + } catch(err) { + // Ignore the error. + } + + if (xcodeMajorVersion && xcodeMajorVersion < 8) { + // Xcode 7.x does not have support for `xcrun simctl terminate` command + const resultOfKill = childProcess.execSync(`killall ${bundleExecutable}`, { skipError: true }); + // killall command does not terminate the processes immediately and we have to wait a little bit, + // just to ensure all related processes and services are dead. + utils.sleep(0.5); + return resultOfKill; + } else { + return this.simctl.terminate(deviceId, appIdentifier); + } } catch (e) { } } @@ -157,11 +174,11 @@ export class XCodeSimctlSimulator extends IPhoneSimulatorNameGetter implements I // startSimulaltor doesn't always finish immediately, and the subsequent // install fails since the simulator is not running. // Give it some time to start before we attempt installing. - utils.sleep(1000); + utils.sleep(1); } } private killSimulator(): void { childProcess.execSync("pkill -9 -f Simulator"); } -} \ No newline at end of file +} diff --git a/lib/simctl.ts b/lib/simctl.ts index b3841ee..efc94d7 100644 --- a/lib/simctl.ts +++ b/lib/simctl.ts @@ -27,6 +27,10 @@ export class Simctl implements ISimctl { return result; } + public terminate(deviceId: string, appIdentifier: string): string { + return this.simctlExec("terminate", [deviceId, appIdentifier]); + } + public install(deviceId: string, applicationPath: string): void { return this.simctlExec("install", [deviceId, applicationPath]); } diff --git a/lib/utils.ts b/lib/utils.ts index 7de7273..206e33e 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,3 +1,5 @@ +import * as childProcess from "./child-process"; + export function stringify(arr: string[], delimiter?: string): string { delimiter = delimiter || ", "; return arr.join(delimiter); @@ -8,10 +10,6 @@ export function getCurrentEpochTime(): number { return dateTime.getTime(); } -export function sleep(ms: number): void { - let startTime = getCurrentEpochTime(); - let currentTime = getCurrentEpochTime(); - while ((currentTime - startTime) < ms) { - currentTime = getCurrentEpochTime(); - } -} \ No newline at end of file +export function sleep(seconds: number): void { + childProcess.execSync(`sleep ${seconds}`); +} diff --git a/lib/xcode.ts b/lib/xcode.ts index b3dd2e2..d9fedf0 100644 --- a/lib/xcode.ts +++ b/lib/xcode.ts @@ -6,11 +6,11 @@ export function getPathFromXcodeSelect(): string { export function getXcodeVersionData(): IXcodeVersionData { let rawData = childProcess.execSync("xcodebuild -version"); - let lines = rawData.split("\n"); + let lines = rawData.toString().split("\n"); let parts = lines[0].split(" ")[1].split("."); return { major: parts[0], minor: parts[1], build: lines[1].split("Build version ")[1] } -} \ No newline at end of file +} From c00eac7f7547fd7260d8adcedeb60ae68b5de75e Mon Sep 17 00:00:00 2001 From: rosen-vladimirov Date: Tue, 9 May 2017 08:29:23 +0300 Subject: [PATCH 2/2] Set version to 3.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e054479..4c4d193 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-sim-portable", - "version": "2.0.2", + "version": "3.0.0", "description": "", "main": "./lib/ios-sim.js", "scripts": {