Skip to content

Commit 3db81cc

Browse files
committed
refactor unexpected shutdown, and fix lint so we can use upgraded appium eslint
1 parent ec7de82 commit 3db81cc

File tree

5 files changed

+70
-16
lines changed

5 files changed

+70
-16
lines changed

gulpfile.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/* eslint no-console:0 */
2+
/* eslint-disable promise/prefer-await-to-callbacks */
23
"use strict";
34

45
// turn all logging on since we have tests that rely on npmlog logs actually
@@ -32,10 +33,12 @@ gulp.task('fixShrinkwrap', function (done) {
3233
boilerplate({
3334
build: 'appium',
3435
jscs: false,
36+
jshint: false,
3537
test: {
3638
files: ['${testDir}/**/*-specs.js']
3739
},
3840
extraPrepublishTasks: ['fixShrinkwrap'],
41+
preCommitTasks: ['eslint', 'once'],
3942
});
4043

4144
// generates server arguments readme
@@ -66,7 +69,7 @@ gulp.task('docs', ['transpile'], function () {
6669
}
6770

6871
// handle empty objects
69-
if (JSON.stringify(argOpts.defaultValue) === '{}'){
72+
if (JSON.stringify(argOpts.defaultValue) === '{}') {
7073
argOpts.defaultValue = '{}';
7174
}
7275

lib/appium.js

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -150,18 +150,11 @@ class AppiumDriver extends BaseDriver {
150150
let [innerSessionId, dCaps] = await d.createSession(caps, reqCaps, curSessions);
151151
this.sessions[innerSessionId] = d;
152152

153-
// Remove the session on unexpected shutdown, so that we are in a position
154-
// to open another session later on.
155-
// TODO: this should be removed and replaced by a onShutdown callback.
156-
d.onUnexpectedShutdown
157-
.then(() => { throw new Error('Unexpected shutdown'); })
158-
.catch(B.CancellationError, () => {})
159-
.catch((err) => {
160-
log.warn(`Closing session, cause was '${err.message}'`);
161-
log.info(`Removing session ${innerSessionId} from our master session list`);
162-
delete this.sessions[innerSessionId];
163-
})
164-
.done();
153+
// this is an async function but we don't await it because it handles
154+
// an out-of-band promise which is fulfilled if the inner driver
155+
// unexpectedly shuts down
156+
this.attachUnexpectedShutdownHandler(d, innerSessionId);
157+
165158

166159
log.info(`New ${InnerDriver.name} session created successfully, session ` +
167160
`${innerSessionId} added to master session list`);
@@ -172,6 +165,26 @@ class AppiumDriver extends BaseDriver {
172165
return [innerSessionId, dCaps];
173166
}
174167

168+
async attachUnexpectedShutdownHandler (driver, innerSessionId) {
169+
// Remove the session on unexpected shutdown, so that we are in a position
170+
// to open another session later on.
171+
// TODO: this should be removed and replaced by a onShutdown callback.
172+
try {
173+
await driver.onUnexpectedShutdown; // this is a cancellable promise
174+
// if we get here, we've had an unexpected shutdown, so error
175+
throw new Error('Unexpected shutdown');
176+
} catch (e) {
177+
if (e instanceof B.CancellationError) {
178+
// if we cancelled the unexpected shutdown promise, that means we
179+
// no longer care about it, and can safely ignore it
180+
return;
181+
}
182+
log.warn(`Closing session, cause was '${e.message}'`);
183+
log.info(`Removing session ${innerSessionId} from our master session list`);
184+
delete this.sessions[innerSessionId];
185+
}
186+
}
187+
175188
curSessionDataForDriver (InnerDriver) {
176189
let data = _.values(this.sessions)
177190
.filter((s) => s.constructor.name === InnerDriver.name)

lib/logsink.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ function timestamp () {
5353
// having to create 2 loggers.
5454
function applyStripColorPatch (transport) {
5555
let _log = transport.log.bind(transport);
56-
transport.log = function (level, msg, meta, callback) {
56+
transport.log = function (level, msg, meta, callback) { // eslint-disable-line promise/prefer-await-to-callbacks
5757
let code = /\u001b\[(\d+(;\d+)*)?m/g;
5858
msg = ('' + msg).replace(code, '');
5959
_log(level, msg, meta, callback);

test/driver-specs.js

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ import chai from 'chai';
99
import chaiAsPromised from 'chai-as-promised';
1010
import { XCUITestDriver } from 'appium-xcuitest-driver';
1111
import { IosDriver } from 'appium-ios-driver';
12+
import { sleep } from 'asyncbox';
1213

13-
14+
chai.should();
1415
chai.use(chaiAsPromised);
1516

1617
const BASE_CAPS = {platformName: 'Fake', deviceName: 'Fake', app: TEST_FAKE_APP};
@@ -172,6 +173,42 @@ describe('AppiumDriver', () => {
172173
});
173174
describe('sessionExists', () => {
174175
});
176+
describe('attachUnexpectedShutdownHandler', () => {
177+
let appium
178+
, mockFakeDriver;
179+
beforeEach(() => {
180+
[appium, mockFakeDriver] = getDriverAndFakeDriver();
181+
});
182+
afterEach(() => {
183+
mockFakeDriver.restore();
184+
appium.args.defaultCapabilities = {};
185+
});
186+
187+
it('should remove session if inner driver unexpectedly exits with an error', async () => {
188+
let [sessionId,] = await appium.createSession(_.clone(BASE_CAPS)); // eslint-disable-line comma-spacing
189+
_.keys(appium.sessions).should.contain(sessionId);
190+
appium.sessions[sessionId].unexpectedShutdownDeferred.reject(new Error("Oops"));
191+
// let event loop spin so rejection is handled
192+
await sleep(1);
193+
_.keys(appium.sessions).should.not.contain(sessionId);
194+
});
195+
it('should remove session if inner driver unexpectedly exits with no error', async () => {
196+
let [sessionId,] = await appium.createSession(_.clone(BASE_CAPS)); // eslint-disable-line comma-spacing
197+
_.keys(appium.sessions).should.contain(sessionId);
198+
appium.sessions[sessionId].unexpectedShutdownDeferred.resolve();
199+
// let event loop spin so rejection is handled
200+
await sleep(1);
201+
_.keys(appium.sessions).should.not.contain(sessionId);
202+
});
203+
it('should not remove session if inner driver cancels unexpected exit', async () => {
204+
let [sessionId,] = await appium.createSession(_.clone(BASE_CAPS)); // eslint-disable-line comma-spacing
205+
_.keys(appium.sessions).should.contain(sessionId);
206+
appium.sessions[sessionId].onUnexpectedShutdown.cancel();
207+
// let event loop spin so rejection is handled
208+
await sleep(1);
209+
_.keys(appium.sessions).should.contain(sessionId);
210+
});
211+
});
175212
describe('getDriverForCaps', () => {
176213
it('should not blow up if user does not provide platformName', () => {
177214
let appium = new AppiumDriver({});

test/helpers.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import path from 'path';
22
import wd from 'wd';
3+
import B from 'bluebird';
34

45
const TEST_HOST = 'localhost';
56
const TEST_PORT = 4723;
@@ -18,7 +19,7 @@ function initSession (caps) {
1819
after(async () => {
1920
await driver.quit();
2021
});
21-
return new Promise((_resolve) => {
22+
return new B((_resolve) => {
2223
resolve = _resolve;
2324
});
2425
}

0 commit comments

Comments
 (0)