|
1 | 1 | "use strict"; |
| 2 | +var child_process = require("child_process"); |
2 | 3 | var Q = require("q"); |
3 | 4 | var testUtil_1 = require("./testUtil"); |
4 | 5 | ////////////////////////////////////////////////////////////////////////////////////////// |
@@ -97,6 +98,41 @@ exports.IOS = IOS; |
97 | 98 | // bootEmulatorInternal constants |
98 | 99 | var emulatorMaxReadyAttempts = 50; |
99 | 100 | var emulatorReadyCheckDelayMs = 5 * 1000; |
| 101 | + |
| 102 | +/** |
| 103 | + * Checks whether an Android app is currently running via "pidof". Exit code 1 means the |
| 104 | + * process wasn't found, which is the expected (non-error) outcome most of the time while |
| 105 | + * polling for teardown - any other failure (e.g. adb/device unavailable) is a genuine |
| 106 | + * problem and must not be silently treated as "the app stopped". Calls child_process |
| 107 | + * directly instead of going through TestUtil.getProcessOutput, since that helper treats |
| 108 | + * every non-zero exit as an error and logs it - which would spam the console with an |
| 109 | + * "error" on every single poll where the app has (expectedly) already stopped. |
| 110 | + */ |
| 111 | +function isAndroidAppRunning(appId) { |
| 112 | + return new Promise(function (resolve, reject) { |
| 113 | + child_process.exec("adb shell pidof " + appId, function (error) { |
| 114 | + if (!error) { |
| 115 | + resolve(true); |
| 116 | + } else if (error.code === 1) { |
| 117 | + resolve(false); |
| 118 | + } else { |
| 119 | + reject(error); |
| 120 | + } |
| 121 | + }); |
| 122 | + }); |
| 123 | +} |
| 124 | + |
| 125 | +async function waitForAndroidAppToStop(appId, maxWaitMs) { |
| 126 | + var pollIntervalMs = 200; |
| 127 | + var start = Date.now(); |
| 128 | + while (true) { |
| 129 | + var isRunning = await isAndroidAppRunning(appId); |
| 130 | + if (!isRunning || Date.now() - start >= maxWaitMs) { |
| 131 | + return; |
| 132 | + } |
| 133 | + await new Promise(function (resolve) { setTimeout(resolve, pollIntervalMs); }); |
| 134 | + } |
| 135 | +} |
100 | 136 | /** |
101 | 137 | * Helper function for EmulatorManager implementations to use to boot an emulator with a given platformName and check, start, and kill methods. |
102 | 138 | */ |
@@ -241,7 +277,7 @@ var AndroidEmulatorManager = (function () { |
241 | 277 | var t0 = Date.now(); |
242 | 278 | return testUtil_1.TestUtil.getProcessOutput("adb shell am force-stop " + appId).then(function () { |
243 | 279 | var waitStart = Date.now(); |
244 | | - return Q.delay(10000).then(function () { |
| 280 | + return waitForAndroidAppToStop(appId, 10000).then(function () { |
245 | 281 | console.log("[TIMING] android endRunningApplication: force-stop took " + (Date.now() - t0) + "ms, teardown wait took " + (Date.now() - waitStart) + "ms"); |
246 | 282 | }); |
247 | 283 | }); |
|
0 commit comments