appium-xcuitest-driver-conan
Version:
Appium driver for iOS using XCUITest for backend
516 lines (401 loc) • 25.2 kB
JavaScript
;
var _regeneratorRuntime = require('babel-runtime/regenerator')['default'];
var _getIterator = require('babel-runtime/core-js/get-iterator')['default'];
var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];
Object.defineProperty(exports, '__esModule', {
value: true
});
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _appiumIosSimulator = require('appium-ios-simulator');
var _nodeSimctl = require('node-simctl');
var _asyncbox = require('asyncbox');
var _teen_process = require('teen_process');
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _logger = require('./logger');
var _logger2 = _interopRequireDefault(_logger);
// returns true if sim is booted. false if not booted or doesnt exist
function simBooted(sim) {
var stat;
return _regeneratorRuntime.async(function simBooted$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
context$1$0.next = 2;
return _regeneratorRuntime.awrap(sim.stat());
case 2:
stat = context$1$0.sent;
return context$1$0.abrupt('return', stat.state === 'Booted');
case 4:
case 'end':
return context$1$0.stop();
}
}, null, this);
}
// returns sim for desired caps
function createSim(caps, sessionId) {
var name, udid;
return _regeneratorRuntime.async(function createSim$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
name = 'appiumTest-' + sessionId;
context$1$0.next = 3;
return _regeneratorRuntime.awrap((0, _nodeSimctl.createDevice)(name, caps.deviceName, caps.platformVersion));
case 3:
udid = context$1$0.sent;
context$1$0.next = 6;
return _regeneratorRuntime.awrap((0, _appiumIosSimulator.getSimulator)(udid));
case 6:
return context$1$0.abrupt('return', context$1$0.sent);
case 7:
case 'end':
return context$1$0.stop();
}
}, null, this);
}
function getExistingSim(deviceName, platformVersion) {
var devices, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, device;
return _regeneratorRuntime.async(function getExistingSim$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
context$1$0.next = 2;
return _regeneratorRuntime.awrap((0, _nodeSimctl.getDevices)(platformVersion));
case 2:
devices = context$1$0.sent;
_iteratorNormalCompletion = true;
_didIteratorError = false;
_iteratorError = undefined;
context$1$0.prev = 6;
_iterator = _getIterator(_lodash2['default'].values(devices));
case 8:
if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
context$1$0.next = 17;
break;
}
device = _step.value;
if (!(device.name === deviceName)) {
context$1$0.next = 14;
break;
}
context$1$0.next = 13;
return _regeneratorRuntime.awrap((0, _appiumIosSimulator.getSimulator)(device.udid));
case 13:
return context$1$0.abrupt('return', context$1$0.sent);
case 14:
_iteratorNormalCompletion = true;
context$1$0.next = 8;
break;
case 17:
context$1$0.next = 23;
break;
case 19:
context$1$0.prev = 19;
context$1$0.t0 = context$1$0['catch'](6);
_didIteratorError = true;
_iteratorError = context$1$0.t0;
case 23:
context$1$0.prev = 23;
context$1$0.prev = 24;
if (!_iteratorNormalCompletion && _iterator['return']) {
_iterator['return']();
}
case 26:
context$1$0.prev = 26;
if (!_didIteratorError) {
context$1$0.next = 29;
break;
}
throw _iteratorError;
case 29:
return context$1$0.finish(26);
case 30:
return context$1$0.finish(23);
case 31:
return context$1$0.abrupt('return', null);
case 32:
case 'end':
return context$1$0.stop();
}
}, null, this, [[6, 19, 23, 31], [24,, 26, 30]]);
}
function prepareSafariForCleanup() {
var timeout = arguments.length <= 0 || arguments[0] === undefined ? 5000 : arguments[0];
return _regeneratorRuntime.async(function prepareSafariForCleanup$(context$1$0) {
var _this = this;
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
context$1$0.prev = 0;
context$1$0.next = 3;
return _regeneratorRuntime.awrap((0, _asyncbox.waitForCondition)(function callee$1$0() {
return _regeneratorRuntime.async(function callee$1$0$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
context$2$0.prev = 0;
context$2$0.next = 3;
return _regeneratorRuntime.awrap((0, _teen_process.exec)('pgrep', ['-x', 'MobileSafari']));
case 3:
context$2$0.next = 19;
break;
case 5:
context$2$0.prev = 5;
context$2$0.t0 = context$2$0['catch'](0);
if (!(context$2$0.t0.code === 1)) {
context$2$0.next = 9;
break;
}
return context$2$0.abrupt('return', true);
case 9:
context$2$0.prev = 9;
context$2$0.next = 12;
return _regeneratorRuntime.awrap((0, _teen_process.exec)('pkill', ['-9', '-x', 'MobileSafari']));
case 12:
context$2$0.next = 19;
break;
case 14:
context$2$0.prev = 14;
context$2$0.t1 = context$2$0['catch'](9);
if (!(context$2$0.t1.code === 1)) {
context$2$0.next = 18;
break;
}
return context$2$0.abrupt('return', true);
case 18:
_logger2['default'].warn(context$2$0.t1.message);
case 19:
return context$2$0.abrupt('return', false);
case 20:
case 'end':
return context$2$0.stop();
}
}, null, _this, [[0, 5], [9, 14]]);
}, {
waitMs: timeout,
intervalMs: 200
}));
case 3:
_logger2['default'].debug('Mobile Safari process is not running. Continuing with cleanup');
context$1$0.next = 9;
break;
case 6:
context$1$0.prev = 6;
context$1$0.t0 = context$1$0['catch'](0);
_logger2['default'].warn('Mobile Safari is still running after ' + timeout + ' ms');
case 9:
case 'end':
return context$1$0.stop();
}
}, null, this, [[0, 6]]);
}
function runSimulatorReset(device, opts) {
var isSafari;
return _regeneratorRuntime.async(function runSimulatorReset$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
if (!(opts.noReset && !opts.fullReset)) {
context$1$0.next = 3;
break;
}
// noReset === true && fullReset === false
_logger2['default'].debug('Reset: noReset is on. Leaving simulator as is');
return context$1$0.abrupt('return');
case 3:
if (device) {
context$1$0.next = 6;
break;
}
_logger2['default'].debug('Reset: no device available. Skipping');
return context$1$0.abrupt('return');
case 6:
if (!opts.fullReset) {
context$1$0.next = 14;
break;
}
_logger2['default'].debug('Reset: fullReset is on. Cleaning simulator');
// The simulator process must be ended before we delete applications.
context$1$0.next = 10;
return _regeneratorRuntime.awrap(endSimulator(device));
case 10:
context$1$0.next = 12;
return _regeneratorRuntime.awrap(fullResetSimulator(device));
case 12:
context$1$0.next = 51;
break;
case 14:
if (!opts.bundleId) {
context$1$0.next = 51;
break;
}
context$1$0.next = 17;
return _regeneratorRuntime.awrap(simBooted(device));
case 17:
if (!context$1$0.sent) {
context$1$0.next = 31;
break;
}
if (!(device.xcodeVersion.major >= 8)) {
context$1$0.next = 29;
break;
}
context$1$0.prev = 19;
context$1$0.next = 22;
return _regeneratorRuntime.awrap((0, _nodeSimctl.terminate)(device.udid, opts.bundleId));
case 22:
context$1$0.next = 27;
break;
case 24:
context$1$0.prev = 24;
context$1$0.t0 = context$1$0['catch'](19);
_logger2['default'].warn('Reset: failed to terminate Simulator application with id "' + opts.bundleId + '"');
case 27:
context$1$0.next = 31;
break;
case 29:
context$1$0.next = 31;
return _regeneratorRuntime.awrap(endSimulator(device));
case 31:
if (!opts.app) {
context$1$0.next = 34;
break;
}
_logger2['default'].info('Not scrubbing third party app in anticipation of uninstall');
return context$1$0.abrupt('return');
case 34:
isSafari = (opts.browserName || '').toLowerCase() === 'safari';
context$1$0.prev = 35;
if (!isSafari) {
context$1$0.next = 43;
break;
}
context$1$0.next = 39;
return _regeneratorRuntime.awrap(prepareSafariForCleanup());
case 39:
context$1$0.next = 41;
return _regeneratorRuntime.awrap(device.cleanSafari());
case 41:
context$1$0.next = 45;
break;
case 43:
context$1$0.next = 45;
return _regeneratorRuntime.awrap(device.scrubCustomApp(_path2['default'].basename(opts.app), opts.bundleId));
case 45:
context$1$0.next = 51;
break;
case 47:
context$1$0.prev = 47;
context$1$0.t1 = context$1$0['catch'](35);
_logger2['default'].warn(context$1$0.t1.message);
_logger2['default'].warn('Reset: could not scrub ' + (isSafari ? 'Safari browser' : 'application with id "' + opts.bundleId + '"') + '. Leaving as is.');
case 51:
case 'end':
return context$1$0.stop();
}
}, null, this, [[19, 24], [35, 47]]);
}
function fullResetSimulator(device) {
return _regeneratorRuntime.async(function fullResetSimulator$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
if (device) {
context$1$0.next = 2;
break;
}
return context$1$0.abrupt('return');
case 2:
context$1$0.next = 4;
return _regeneratorRuntime.awrap(device.clean());
case 4:
case 'end':
return context$1$0.stop();
}
}, null, this);
}
function endSimulator(device) {
return _regeneratorRuntime.async(function endSimulator$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
if (device) {
context$1$0.next = 2;
break;
}
return context$1$0.abrupt('return');
case 2:
_logger2['default'].debug('Reset: shutting down simulator');
context$1$0.next = 5;
return _regeneratorRuntime.awrap(device.shutdown());
case 5:
case 'end':
return context$1$0.stop();
}
}, null, this);
}
function isolateSimulatorDevice(device) {
var isolateSimDevice = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1];
return _regeneratorRuntime.async(function isolateSimulatorDevice$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
if (!isolateSimDevice) {
context$1$0.next = 3;
break;
}
context$1$0.next = 3;
return _regeneratorRuntime.awrap(device.isolateSim());
case 3:
case 'end':
return context$1$0.stop();
}
}, null, this);
}
function installToSimulator(device, app, bundleId) {
var noReset = arguments.length <= 3 || arguments[3] === undefined ? true : arguments[3];
return _regeneratorRuntime.async(function installToSimulator$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
if (app) {
context$1$0.next = 3;
break;
}
_logger2['default'].debug('No app path is given. Nothing to install.');
return context$1$0.abrupt('return');
case 3:
if (!bundleId) {
context$1$0.next = 13;
break;
}
context$1$0.next = 6;
return _regeneratorRuntime.awrap(device.isAppInstalled(bundleId));
case 6:
if (!context$1$0.sent) {
context$1$0.next = 13;
break;
}
if (!noReset) {
context$1$0.next = 10;
break;
}
_logger2['default'].debug('App \'' + bundleId + '\' is already installed. No need to reinstall.');
return context$1$0.abrupt('return');
case 10:
_logger2['default'].debug('Reset requested. Removing app with id \'' + bundleId + '\' from the device');
context$1$0.next = 13;
return _regeneratorRuntime.awrap(device.removeApp(bundleId));
case 13:
_logger2['default'].debug('Installing ' + app + ' on Simulator with UUID \'' + device.udid + '\'...');
context$1$0.next = 16;
return _regeneratorRuntime.awrap(device.installApp(app));
case 16:
_logger2['default'].debug('The app has been installed successfully.');
case 17:
case 'end':
return context$1$0.stop();
}
}, null, this);
}
exports.simBooted = simBooted;
exports.createSim = createSim;
exports.getExistingSim = getExistingSim;
exports.runSimulatorReset = runSimulatorReset;
exports.isolateSimulatorDevice = isolateSimulatorDevice;
exports.installToSimulator = installToSimulator;
// Terminate the app under test if it is still running on Simulator
// Termination is not needed if Simulator is not running
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi9zaW11bGF0b3ItbWFuYWdlbWVudC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7b0JBQWlCLE1BQU07Ozs7a0NBQ00sc0JBQXNCOzswQkFDQyxhQUFhOzt3QkFDaEMsVUFBVTs7NEJBQ3RCLGNBQWM7O3NCQUNyQixRQUFROzs7O3NCQUNOLFVBQVU7Ozs7O0FBSTFCLFNBQWUsU0FBUyxDQUFFLEdBQUc7TUFDdkIsSUFBSTs7Ozs7eUNBQVMsR0FBRyxDQUFDLElBQUksRUFBRTs7O0FBQXZCLFlBQUk7NENBQ0QsSUFBSSxDQUFDLEtBQUssS0FBSyxRQUFROzs7Ozs7O0NBQy9COzs7QUFHRCxTQUFlLFNBQVMsQ0FBRSxJQUFJLEVBQUUsU0FBUztNQUNuQyxJQUFJLEVBQ0osSUFBSTs7OztBQURKLFlBQUksbUJBQWlCLFNBQVM7O3lDQUNqQiw4QkFBYSxJQUFJLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDOzs7QUFBdEUsWUFBSTs7eUNBQ0ssc0NBQWEsSUFBSSxDQUFDOzs7Ozs7Ozs7O0NBQ2hDOztBQUVELFNBQWUsY0FBYyxDQUFFLFVBQVUsRUFBRSxlQUFlO01BQ3BELE9BQU8sa0ZBQ0YsTUFBTTs7Ozs7O3lDQURLLDRCQUFXLGVBQWUsQ0FBQzs7O0FBQTNDLGVBQU87Ozs7O2lDQUNRLG9CQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUM7Ozs7Ozs7O0FBQTNCLGNBQU07O2NBQ1QsTUFBTSxDQUFDLElBQUksS0FBSyxVQUFVLENBQUE7Ozs7Ozt5Q0FDZixzQ0FBYSxNQUFNLENBQUMsSUFBSSxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7NENBR25DLElBQUk7Ozs7Ozs7Q0FDWjs7QUFFRCxTQUFlLHVCQUF1QjtNQUFFLE9BQU8seURBQUcsSUFBSTs7Ozs7Ozs7eUNBRTVDLGdDQUFpQjs7Ozs7O2lEQUViLHdCQUFLLE9BQU8sRUFBRSxDQUFDLElBQUksRUFB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Q0FFNUI7O0FBRUQsU0FBZSxrQkFBa0IsQ0FBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLFFBQVE7TUFBRSxPQUFPLHlEQUFHLElBQUk7Ozs7WUFDakUsR0FBRzs7Ozs7QUFDTiw0QkFBSSxLQUFLLENBQUMsMkNBQTJDLENBQUMsQ0FBQzs7OzthQUlyRCxRQUFROzs7Ozs7eUNBQ0EsTUFBTSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUM7Ozs7Ozs7O2FBQ25DLE9BQU87Ozs7O0FBQ1QsNEJBQUksS0FBSyxZQUFTLFFBQVEsb0RBQWdELENBQUM7Ozs7QUFHN0UsNEJBQUksS0FBSyw4Q0FBMkMsUUFBUSx3QkFBb0IsQ0FBQzs7eUNBQzNFLE1BQU0sQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDOzs7QUFHcEMsNEJBQUksS0FBSyxpQkFBZSxHQUFHLGtDQUE0QixNQUFNLENBQUMsSUFBSSxXQUFPLENBQUM7O3lDQUNwRSxNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQzs7O0FBQzVCLDRCQUFJLEtBQUssQ0FBQywwQ0FBMEMsQ0FBQyxDQUFDOzs7Ozs7O0NBQ3ZEOztRQUdRLFNBQVMsR0FBVCxTQUFTO1FBQUUsU0FBUyxHQUFULFNBQVM7UUFBRSxjQUFjLEdBQWQsY0FBYztRQUFFLGlCQUFpQixHQUFqQixpQkFBaUI7UUFDdkQsc0JBQXNCLEdBQXRCLHNCQUFzQjtRQUFFLGtCQUFrQixHQUFsQixrQkFBa0IiLCJmaWxlIjoibGliL3NpbXVsYXRvci1tYW5hZ2VtZW50LmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBnZXRTaW11bGF0b3IgfSBmcm9tICdhcHBpdW0taW9zLXNpbXVsYXRvcic7XG5pbXBvcnQgeyBjcmVhdGVEZXZpY2UsIGdldERldmljZXMsIHRlcm1pbmF0ZSB9IGZyb20gJ25vZGUtc2ltY3RsJztcbmltcG9ydCB7IHdhaXRGb3JDb25kaXRpb24gfSBmcm9tICdhc3luY2JveCc7XG5pbXBvcnQgeyBleGVjIH0gZnJvbSAndGVlbl9wcm9jZXNzJztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgbG9nIGZyb20gJy4vbG9nZ2VyJztcblxuXG4vLyByZXR1cm5zIHRydWUgaWYgc2ltIGlzIGJvb3RlZC4gZmFsc2UgaWYgbm90IGJvb3RlZCBvciBkb2VzbnQgZXhpc3RcbmFzeW5jIGZ1bmN0aW9uIHNpbUJvb3RlZCAoc2ltKSB7XG4gIGxldCBzdGF0ID0gYXdhaXQgc2ltLnN0YXQoKTtcbiAgcmV0dXJuIHN0YXQuc3RhdGUgPT09ICdCb290ZWQnO1xufVxuXG4vLyByZXR1cm5zIHNpbSBmb3IgZGVzaXJlZCBjYXBzXG5hc3luYyBmdW5jdGlvbiBjcmVhdGVTaW0gKGNhcHMsIHNlc3Npb25JZCkge1xuICBsZXQgbmFtZSA9IGBhcHBpdW1UZXN0LSR7c2Vzc2lvbklkfWA7XG4gIGxldCB1ZGlkID0gYXdhaXQgY3JlYXRlRGV2aWNlKG5hbWUsIGNhcHMuZGV2aWNlTmFtZSwgY2Fwcy5wbGF0Zm9ybVZlcnNpb24pO1xuICByZXR1cm4gYXdhaXQgZ2V0U2ltdWxhdG9yKHVkaWQpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRFeGlzdGluZ1NpbSAoZGV2aWNlTmFtZSwgcGxhdGZvcm1WZXJzaW9uKSB7XG4gIGxldCBkZXZpY2VzID0gYXdhaXQgZ2V0RGV2aWNlcyhwbGF0Zm9ybVZlcnNpb24pO1xuICBmb3IgKGxldCBkZXZpY2Ugb2YgXy52YWx1ZXMoZGV2aWNlcykpIHtcbiAgICBpZiAoZGV2aWNlLm5hbWUgPT09IGRldmljZU5hbWUpIHtcbiAgICAgIHJldHVybiBhd2FpdCBnZXRTaW11bGF0b3IoZGV2aWNlLnVkaWQpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gbnVsbDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcHJlcGFyZVNhZmFyaUZvckNsZWFudXAgKHRpbWVvdXQgPSA1MDAwKSB7XG4gIHRyeSB7XG4gICAgYXdhaXQgd2FpdEZvckNvbmRpdGlvbihhc3luYyAoKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBleGVjKCdwZ3JlcCcsIFsnLXgnLCAnTW9iaWxlU2FmYXJpJ10pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoZS5jb2RlID09PSAxKSB7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBleGVjKCdwa2lsbCcsIFsnLTknLCAnLXgnLCAnTW9iaWxlU2FmYXJpJ10pO1xuICAgICAgICB9IGNhdGNoIChlMSkge1xuICAgICAgICAgIGlmIChlMS5jb2RlID09PSAxKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgbG9nLndhcm4oZTEubWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LCB7XG4gICAgICB3YWl0TXM6IHRpbWVvdXQsXG4gICAgICBpbnRlcnZhbE1zOiAyMDBcbiAgICB9KTtcbiAgICBsb2cuZGVidWcoJ01vYmlsZSBTYWZhcmkgcHJvY2VzcyBpcyBub3QgcnVubmluZy4gQ29udGludWluZyB3aXRoIGNsZWFudXAnKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgbG9nLndhcm4oYE1vYmlsZSBTYWZhcmkgaXMgc3RpbGwgcnVubmluZyBhZnRlciAke3RpbWVvdXR9IG1zYCk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gcnVuU2ltdWxhdG9yUmVzZXQgKGRldmljZSwgb3B0cykge1xuICBpZiAob3B0cy5ub1Jlc2V0ICYmICFvcHRzLmZ1bGxSZXNldCkge1xuICAgIC8vIG5vUmVzZXQgPT09IHRydWUgJiYgZnVsbFJlc2V0ID09PSBmYWxzZVxuICAgIGxvZy5kZWJ1ZygnUmVzZXQ6IG5vUmVzZXQgaXMgb24uIExlYXZpbmcgc2ltdWxhdG9yIGFzIGlzJyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKCFkZXZpY2UpIHtcbiAgICBsb2cuZGVidWcoJ1Jlc2V0OiBubyBkZXZpY2UgYXZhaWxhYmxlLiBTa2lwcGluZycpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChvcHRzLmZ1bGxSZXNldCkge1xuICAgIGxvZy5kZWJ1ZygnUmVzZXQ6IGZ1bGxSZXNldCBpcyBvbi4gQ2xlYW5pbmcgc2ltdWxhdG9yJyk7XG4gICAgLy8gVGhlIHNpbXVsYXRvciBwcm9jZXNzIG11c3QgYmUgZW5kZWQgYmVmb3JlIHdlIGRlbGV0ZSBhcHBsaWNhdGlvbnMuXG4gICAgYXdhaXQgZW5kU2ltdWxhdG9yKGRldmljZSk7XG4gICAgYXdhaXQgZnVsbFJlc2V0U2ltdWxhdG9yKGRldmljZSk7XG4gIH0gZWxzZSBpZiAob3B0cy5idW5kbGVJZCkge1xuICAgIC8vIFRlcm1pbmF0ZSB0aGUgYXBwIHVuZGVyIHRlc3QgaWYgaXQgaXMgc3RpbGwgcnVubmluZyBvbiBTaW11bGF0b3JcbiAgICAvLyBUZXJtaW5hdGlvbiBpcyBub3QgbmVlZGVkIGlmIFNpbXVsYXRvciBpcyBub3QgcnVubmluZ1xuICAgIGlmIChhd2FpdCBzaW1Cb290ZWQoZGV2aWNlKSkge1xuICAgICAgaWYgKGRldmljZS54Y29kZVZlcnNpb24ubWFqb3IgPj0gOCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHRlcm1pbmF0ZShkZXZpY2UudWRpZCwgb3B0cy5idW5kbGVJZCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGxvZy53YXJuKGBSZXNldDogZmFpbGVkIHRvIHRlcm1pbmF0ZSBTaW11bGF0b3IgYXBwbGljYXRpb24gd2l0aCBpZCBcIiR7b3B0cy5idW5kbGVJZH1cImApO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhd2FpdCBlbmRTaW11bGF0b3IoZGV2aWNlKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKG9wdHMuYXBwKSB7XG4gICAgICBsb2cuaW5mbygnTm90IHNjcnViYmluZyB0aGlyZCBwYXJ0eSBhcHAgaW4gYW50aWNpcGF0aW9uIG9mIHVuaW5zdGFsbCcpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBpc1NhZmFyaSA9IChvcHRzLmJyb3dzZXJOYW1lIHx8ICcnKS50b0xvd2VyQ2FzZSgpID09PSAnc2FmYXJpJztcbiAgICB0cnkge1xuICAgICAgaWYgKGlzU2FmYXJpKSB7XG4gICAgICAgIGF3YWl0IHByZXBhcmVTYWZhcmlGb3JDbGVhbnVwKCk7XG4gICAgICAgIGF3YWl0IGRldmljZS5jbGVhblNhZmFyaSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXdhaXQgZGV2aWNlLnNjcnViQ3VzdG9tQXBwKHBhdGguYmFzZW5hbWUob3B0cy5hcHApLCBvcHRzLmJ1bmRsZUlkKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGxvZy53YXJuKGVyci5tZXNzYWdlKTtcbiAgICAgIGxvZy53YXJuKGBSZXNldDogY291bGQgbm90IHNjcnViICR7aXNTYWZhcmkgPyAnU2FmYXJpIGJyb3dzZXInIDogJ2FwcGxpY2F0aW9uIHdpdGggaWQgXCInICsgb3B0cy5idW5kbGVJZCArICdcIid9LiBMZWF2aW5nIGFzIGlzLmApO1xuICAgIH1cbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBmdWxsUmVzZXRTaW11bGF0b3IgKGRldmljZSkge1xuICBpZiAoIWRldmljZSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGF3YWl0IGRldmljZS5jbGVhbigpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBlbmRTaW11bGF0b3IgKGRldmljZSkge1xuICBpZiAoIWRldmljZSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGxvZy5kZWJ1ZygnUmVzZXQ6IHNodXR0aW5nIGRvd24gc2ltdWxhdG9yJyk7XG4gIGF3YWl0IGRldmljZS5zaHV0ZG93bigpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBpc29sYXRlU2ltdWxhdG9yRGV2aWNlIChkZXZpY2UsIGlzb2xhdGVTaW1EZXZpY2UgPSB0cnVlKSB7XG4gIGlmIChpc29sYXRlU2ltRGV2aWNlKSB7XG4gICAgYXdhaXQgZGV2aWNlLmlzb2xhdGVTaW0oKTtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBpbnN0YWxsVG9TaW11bGF0b3IgKGRldmljZSwgYXBwLCBidW5kbGVJZCwgbm9SZXNldCA9IHRydWUpIHtcbiAgaWYgKCFhcHApIHtcbiAgICBsb2cuZGVidWcoJ05vIGFwcCBwYXRoIGlzIGdpdmVuLiBOb3RoaW5nIHRvIGluc3RhbGwuJyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKGJ1bmRsZUlkKSB7XG4gICAgaWYgKGF3YWl0IGRldmljZS5pc0FwcEluc3RhbGxlZChidW5kbGVJZCkpIHtcbiAgICAgIGlmIChub1Jlc2V0KSB7XG4gICAgICAgIGxvZy5kZWJ1ZyhgQXBwICcke2J1bmRsZUlkfScgaXMgYWxyZWFkeSBpbnN0YWxsZWQuIE5vIG5lZWQgdG8gcmVpbnN0YWxsLmApO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBsb2cuZGVidWcoYFJlc2V0IHJlcXVlc3RlZC4gUmVtb3ZpbmcgYXBwIHdpdGggaWQgJyR7YnVuZGxlSWR9JyBmcm9tIHRoZSBkZXZpY2VgKTtcbiAgICAgIGF3YWl0IGRldmljZS5yZW1vdmVBcHAoYnVuZGxlSWQpO1xuICAgIH1cbiAgfVxuICBsb2cuZGVidWcoYEluc3RhbGxpbmcgJHthcHB9IG9uIFNpbXVsYXRvciB3aXRoIFVVSUQgJyR7ZGV2aWNlLnVkaWR9Jy4uLmApO1xuICBhd2FpdCBkZXZpY2UuaW5zdGFsbEFwcChhcHApO1xuICBsb2cuZGVidWcoJ1RoZSBhcHAgaGFzIGJlZW4gaW5zdGFsbGVkIHN1Y2Nlc3NmdWxseS4nKTtcbn1cblxuXG5leHBvcnQgeyBzaW1Cb290ZWQsIGNyZWF0ZVNpbSwgZ2V0RXhpc3RpbmdTaW0sIHJ1blNpbXVsYXRvclJlc2V0LFxuICAgICAgICAgaXNvbGF0ZVNpbXVsYXRvckRldmljZSwgaW5zdGFsbFRvU2ltdWxhdG9yIH07XG4iXSwic291cmNlUm9vdCI6Ii4uLy4uIn0=