UNPKG

appium-ios-simulator

Version:
749 lines (590 loc) 42.7 kB
require('source-map-support').install(); 'use strict'; var _regeneratorRuntime = require('babel-runtime/regenerator')['default']; var _getIterator = require('babel-runtime/core-js/get-iterator')['default']; var _interopRequireWildcard = require('babel-runtime/helpers/interop-require-wildcard')['default']; var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default']; var _ = require('../..'); var _nodeSimctl = require('node-simctl'); var simctl = _interopRequireWildcard(_nodeSimctl); var _chai = require('chai'); var _chai2 = _interopRequireDefault(_chai); var _chaiAsPromised = require('chai-as-promised'); var _chaiAsPromised2 = _interopRequireDefault(_chaiAsPromised); var _appiumSupport = require('appium-support'); var _bluebird = require('bluebird'); var _bluebird2 = _interopRequireDefault(_bluebird); var _sampleApps = require('sample-apps'); var _sampleApps2 = _interopRequireDefault(_sampleApps); var LONG_TIMEOUT = 120 * 1000; _chai2['default'].should(); _chai2['default'].use(_chaiAsPromised2['default']); function runTests(deviceType) { describe('simulator ' + deviceType.version, function () { this.timeout(LONG_TIMEOUT); var udid = undefined; before(function callee$2$0() { return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap((0, _.killAllSimulators)()); case 2: case 'end': return context$3$0.stop(); } }, null, this); }); beforeEach(function callee$2$0() { return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap(simctl.createDevice('ios-simulator testing', deviceType.device, deviceType.version)); case 2: udid = context$3$0.sent; case 3: case 'end': return context$3$0.stop(); } }, null, this); }); afterEach(function callee$2$0() { var devicePresent; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap(simctl.getDevices()); case 2: context$3$0.t0 = deviceType.version; context$3$0.t1 = function (device) { return device.udid === udid; }; context$3$0.t2 = context$3$0.sent[context$3$0.t0].filter(context$3$0.t1).length; devicePresent = context$3$0.t2 > 0; if (!devicePresent) { context$3$0.next = 11; break; } context$3$0.next = 9; return _regeneratorRuntime.awrap((0, _.killAllSimulators)()); case 9: context$3$0.next = 11; return _regeneratorRuntime.awrap(simctl.deleteDevice(udid)); case 11: case 'end': return context$3$0.stop(); } }, null, this); }); it('should detect whether a simulator has been run before', function callee$2$0() { var sim; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap((0, _.getSimulator)(udid)); case 2: sim = context$3$0.sent; context$3$0.next = 5; return _regeneratorRuntime.awrap(sim.isFresh().should.eventually.equal(true)); case 5: context$3$0.next = 7; return _regeneratorRuntime.awrap(sim.launchAndQuit()); case 7: context$3$0.next = 9; return _regeneratorRuntime.awrap(sim.isFresh().should.eventually.equal(false)); case 9: case 'end': return context$3$0.stop(); } }, null, this); }); it('should launch and shutdown a sim', function callee$2$0() { var sim; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap((0, _.getSimulator)(udid)); case 2: sim = context$3$0.sent; context$3$0.next = 5; return _regeneratorRuntime.awrap(sim.launchAndQuit()); case 5: context$3$0.next = 7; return _regeneratorRuntime.awrap(sim.stat()); case 7: context$3$0.sent.state.should.equal('Shutdown'); case 8: case 'end': return context$3$0.stop(); } }, null, this); }); it('should launch and shutdown a sim, also starting safari', function callee$2$0() { var sim; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap((0, _.getSimulator)(udid)); case 2: sim = context$3$0.sent; context$3$0.next = 5; return _regeneratorRuntime.awrap(sim.launchAndQuit(true)); case 5: context$3$0.next = 7; return _regeneratorRuntime.awrap(sim.stat()); case 7: context$3$0.sent.state.should.equal('Shutdown'); case 8: case 'end': return context$3$0.stop(); } }, null, this); }); it('should clean a sim', function callee$2$0() { var sim; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap((0, _.getSimulator)(udid)); case 2: sim = context$3$0.sent; context$3$0.next = 5; return _regeneratorRuntime.awrap(sim.isFresh().should.eventually.equal(true)); case 5: context$3$0.next = 7; return _regeneratorRuntime.awrap(sim.launchAndQuit()); case 7: context$3$0.next = 9; return _regeneratorRuntime.awrap(sim.isFresh().should.eventually.equal(false)); case 9: context$3$0.next = 11; return _regeneratorRuntime.awrap(sim.clean()); case 11: context$3$0.next = 13; return _regeneratorRuntime.awrap(sim.isFresh().should.eventually.equal(true)); case 13: case 'end': return context$3$0.stop(); } }, null, this); }); it('should not find any TestApp data or bundle directories on a fresh simulator', function callee$2$0() { var sim, dirs; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap((0, _.getSimulator)(udid)); case 2: sim = context$3$0.sent; context$3$0.next = 5; return _regeneratorRuntime.awrap(sim.getAppDirs('TestApp', 'io.appium.TestApp')); case 5: dirs = context$3$0.sent; dirs.should.have.length(0); case 7: case 'end': return context$3$0.stop(); } }, null, this); }); it('should find both a data and bundle directory for TestApp', function callee$2$0() { var sim, dirs; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap((0, _.getSimulator)(udid)); case 2: sim = context$3$0.sent; context$3$0.next = 5; return _regeneratorRuntime.awrap(sim.run()); case 5: context$3$0.next = 7; return _regeneratorRuntime.awrap(simctl.installApp(udid, (0, _sampleApps2['default'])('TestApp'))); case 7: context$3$0.next = 9; return _regeneratorRuntime.awrap(simctl.launch(udid, 'io.appium.TestApp')); case 9: context$3$0.next = 11; return _regeneratorRuntime.awrap(sim.getAppDirs('TestApp', 'io.appium.TestApp')); case 11: dirs = context$3$0.sent; dirs.should.have.length(2); dirs[0].should.contain('/Data/'); dirs[1].should.contain('/Bundle/'); case 15: case 'end': return context$3$0.stop(); } }, null, this); }); it('should delete custom app data', function callee$2$0() { var sim, dirs; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap((0, _.getSimulator)(udid)); case 2: sim = context$3$0.sent; context$3$0.next = 5; return _regeneratorRuntime.awrap(sim.run()); case 5: context$3$0.next = 7; return _regeneratorRuntime.awrap(simctl.installApp(udid, (0, _sampleApps2['default'])('TestApp'))); case 7: context$3$0.next = 9; return _regeneratorRuntime.awrap(simctl.launch(udid, 'io.appium.TestApp')); case 9: context$3$0.next = 11; return _regeneratorRuntime.awrap(sim.cleanCustomApp('TestApp', 'io.appium.TestApp')); case 11: // clear paths to force the simulator to get a new list of directories sim.appDataBundlePaths = {}; context$3$0.next = 14; return _regeneratorRuntime.awrap(sim.getAppDirs('TestApp', 'io.appium.TestApp')); case 14: dirs = context$3$0.sent; dirs.should.have.length(0); case 16: case 'end': return context$3$0.stop(); } }, null, this); }); it('should delete a sim', function callee$2$0() { var numDevices, sim, numDevicesAfter; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap(simctl.getDevices()); case 2: context$3$0.t0 = deviceType.version; numDevices = context$3$0.sent[context$3$0.t0].length; numDevices.should.be.above(0); context$3$0.next = 7; return _regeneratorRuntime.awrap((0, _.getSimulator)(udid)); case 7: sim = context$3$0.sent; context$3$0.next = 10; return _regeneratorRuntime.awrap(sim['delete']()); case 10: context$3$0.next = 12; return _regeneratorRuntime.awrap(simctl.getDevices()); case 12: context$3$0.t1 = deviceType.version; numDevicesAfter = context$3$0.sent[context$3$0.t1].length; numDevicesAfter.should.equal(numDevices - 1); case 15: case 'end': return context$3$0.stop(); } }, null, this); }); var itText = 'should match a bundleId to its app directory on a used sim'; var bundleId = 'com.apple.mobilesafari'; if (deviceType.version === '7.1') { itText = 'should match an app to its app directory on a used sim'; bundleId = 'MobileSafari'; } it(itText, function callee$2$0() { var sim, path; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap((0, _.getSimulator)(udid)); case 2: sim = context$3$0.sent; context$3$0.next = 5; return _regeneratorRuntime.awrap(sim.launchAndQuit()); case 5: context$3$0.next = 7; return _regeneratorRuntime.awrap(sim.getAppDir(bundleId)); case 7: path = context$3$0.sent; context$3$0.next = 10; return _regeneratorRuntime.awrap(_appiumSupport.fs.hasAccess(path).should.eventually.be['true']); case 10: case 'end': return context$3$0.stop(); } }, null, this); }); itText = 'should match a bundleId to its app directory on a fresh sim'; bundleId = 'com.apple.mobilesafari'; if (deviceType.version === '7.1') { itText = 'should match an app to its app directory on a fresh sim'; bundleId = 'MobileSafari'; } it(itText, function callee$2$0() { var sim, path; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap((0, _.getSimulator)(udid)); case 2: sim = context$3$0.sent; context$3$0.next = 5; return _regeneratorRuntime.awrap(sim.getAppDir(bundleId)); case 5: path = context$3$0.sent; context$3$0.next = 8; return _regeneratorRuntime.awrap(_appiumSupport.fs.hasAccess(path).should.eventually.be['true']); case 8: case 'end': return context$3$0.stop(); } }, null, this); }); it('should start a sim using the "run" method', function callee$2$0() { var sim, stat; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap((0, _.getSimulator)(udid)); case 2: sim = context$3$0.sent; context$3$0.next = 5; return _regeneratorRuntime.awrap(sim.run()); case 5: context$3$0.next = 7; return _regeneratorRuntime.awrap(sim.stat()); case 7: stat = context$3$0.sent; stat.state.should.equal('Booted'); context$3$0.next = 11; return _regeneratorRuntime.awrap(sim.shutdown()); case 11: context$3$0.next = 13; return _regeneratorRuntime.awrap(sim.stat()); case 13: stat = context$3$0.sent; stat.state.should.equal('Shutdown'); case 15: case 'end': return context$3$0.stop(); } }, null, this); }); it('should be able to start safari', function callee$2$0() { var sim; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap((0, _.getSimulator)(udid)); case 2: sim = context$3$0.sent; context$3$0.next = 5; return _regeneratorRuntime.awrap(sim.run()); case 5: context$3$0.next = 7; return _regeneratorRuntime.awrap(sim.openUrl('http://apple.com')); case 7: context$3$0.next = 9; return _regeneratorRuntime.awrap(sim.shutdown()); case 9: case 'end': return context$3$0.stop(); } }, null, this); }); // this test to catch errors in openUrl, that arise from bad sims or certain versions of xcode it('should detect if a sim is running', function callee$2$0() { var sim, running; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap((0, _.getSimulator)(udid)); case 2: sim = context$3$0.sent; context$3$0.next = 5; return _regeneratorRuntime.awrap(sim.isRunning()); case 5: running = context$3$0.sent; running.should.be['false']; context$3$0.next = 9; return _regeneratorRuntime.awrap(sim.run()); case 9: context$3$0.next = 11; return _regeneratorRuntime.awrap(sim.isRunning()); case 11: running = context$3$0.sent; running.should.be['true']; context$3$0.next = 15; return _regeneratorRuntime.awrap(sim.shutdown()); case 15: context$3$0.next = 17; return _regeneratorRuntime.awrap(sim.isRunning()); case 17: running = context$3$0.sent; running.should.be['false']; case 19: case 'end': return context$3$0.stop(); } }, null, this); }); it('should isolate sim', function callee$2$0() { var sim, numDevices; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap((0, _.getSimulator)(udid)); case 2: sim = context$3$0.sent; context$3$0.next = 5; return _regeneratorRuntime.awrap(sim.isolateSim()); case 5: context$3$0.next = 7; return _regeneratorRuntime.awrap(simctl.getDevices()); case 7: context$3$0.t0 = deviceType.version; numDevices = context$3$0.sent[context$3$0.t0].length; numDevices.should.equal(1); case 10: case 'end': return context$3$0.stop(); } }, null, this); }); }); describe('reuse an already-created already-run simulator ' + deviceType.version, function () { this.timeout(LONG_TIMEOUT); var sim = undefined; before(function callee$2$0() { var udid; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap((0, _.killAllSimulators)()); case 2: context$3$0.next = 4; return _regeneratorRuntime.awrap(simctl.createDevice('ios-simulator testing', deviceType.device, deviceType.version)); case 4: udid = context$3$0.sent; context$3$0.next = 7; return _regeneratorRuntime.awrap((0, _.getSimulator)(udid)); case 7: sim = context$3$0.sent; context$3$0.next = 10; return _regeneratorRuntime.awrap(sim.run()); case 10: context$3$0.next = 12; return _regeneratorRuntime.awrap(sim.shutdown()); case 12: context$3$0.next = 14; return _regeneratorRuntime.awrap(_bluebird2['default'].delay(4000)); case 14: case 'end': return context$3$0.stop(); } }, null, this); }); after(function callee$2$0() { var devicePresent; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap(simctl.getDevices()); case 2: context$3$0.t0 = deviceType.version; context$3$0.t1 = function (device) { return device.udid === sim.udid; }; context$3$0.t2 = context$3$0.sent[context$3$0.t0].filter(context$3$0.t1).length; devicePresent = context$3$0.t2 > 0; if (!devicePresent) { context$3$0.next = 9; break; } context$3$0.next = 9; return _regeneratorRuntime.awrap(simctl.deleteDevice(sim.udid)); case 9: case 'end': return context$3$0.stop(); } }, null, this); }); it('should start a sim using the "run" method', function callee$2$0() { var stat; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap(sim.run()); case 2: context$3$0.next = 4; return _regeneratorRuntime.awrap(sim.stat()); case 4: stat = context$3$0.sent; stat.state.should.equal('Booted'); context$3$0.next = 8; return _regeneratorRuntime.awrap(sim.shutdown()); case 8: context$3$0.next = 10; return _regeneratorRuntime.awrap(sim.stat()); case 10: stat = context$3$0.sent; stat.state.should.equal('Shutdown'); case 12: case 'end': return context$3$0.stop(); } }, null, this); }); }); } var deviceTypes = [{ version: '8.4', device: 'iPhone 6' }, { version: '9.0', device: 'iPhone 6s' }, { version: '9.1', device: 'iPhone 6s' }]; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = _getIterator(deviceTypes), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var deviceType = _step.value; runTests(deviceType); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator['return']) { _iterator['return'](); } } finally { if (_didIteratorError) { throw _iteratorError; } } } // only want to get rid of the device if it is present // install & launch test app // install & launch test app // delete app directories // only want to get rid of the device if it is present //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3Qvc2ltdWxhdG9yLWUyZS1zcGVjcy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Z0JBRWdELE9BQU87OzBCQUMvQixhQUFhOztJQUF6QixNQUFNOztvQkFDRCxNQUFNOzs7OzhCQUNJLGtCQUFrQjs7Ozs2QkFDMUIsZ0JBQWdCOzt3QkFDckIsVUFBVTs7OzswQkFDRCxhQUFhOzs7O0FBR3BDLElBQU0sWUFBWSxHQUFHLEdBQUcsR0FBQyxJQUFJLENBQUM7O0FBRTlCLGtCQUFLLE1BQU0sRUFBRSxDQUFDO0FBQ2Qsa0JBQUssR0FBRyw2QkFBZ0IsQ0FBQzs7QUFFekIsU0FBUyxRQUFRLENBQUUsVUFBVSxFQUFFO0FBQzdCLFVBQVEsZ0JBQWMsVUFBVSxDQUFDLE9BQU8sRUFBSSxZQUFZO0FBQ3RELFFBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7QUFDM0IsUUFBSSxJQUFJLFlBQUEsQ0FBQztBQUNULFVBQU0sQ0FBQzs7Ozs7NkNBQ0MsMEJBQW1COzs7Ozs7O0tBQzFCLENBQUMsQ0FBQzs7QUFFSCxjQUFVLENBQUM7Ozs7OzZDQUNJLE1BQU0sQ0FBQyxZQUFZLENBQUMsdUJBQXVCLEVBQ3ZCLFVBQVUsQ0FBQyxNQUFNLEVBQ2pCLFVBQVUsQ0FBQyxPQUFPLENBQUM7OztBQUZwRCxnQkFBSTs7Ozs7OztLQUdMLENBQUMsQ0FBQztBQUNILGFBQVMsQ0FBQztVQUVKLGFBQWE7Ozs7OzZDQUFVLE1BQU0sQ0FBQyxVQUFVLEVBQUU7Ozs2QkFBRSxVQUFVLENBQUMsT0FBTzs7NkJBQ3hELFVBQUMsTUFBTSxFQUFLO0FBQ2xCLHFCQUFPLE1BQU0sQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDO2FBQzdCOzs4REFGQSxNQUFNLGlCQUVKLE1BQU07QUFIUCx5QkFBYSxvQkFHSCxDQUFDOztpQkFDWCxhQUFhOzs7Ozs7NkNBQ1QsMEJBQW1COzs7OzZDQUNuQixNQUFNLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQzs7Ozs7OztL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aUJBQ1gsYUFBYTs7Ozs7OzZDQUNULE1BQU0sQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQzs7Ozs7OztLQUV0QyxDQUFDLENBQUM7O0FBRUgsTUFBRSxDQUFDLDJDQUEyQyxFQUFFO1VBRzFDLElBQUk7Ozs7OzZDQUZGLEdBQUcsQ0FBQyxHQUFHLEVBQUU7Ozs7NkNBRUUsR0FBRyxDQUFDLElBQUksRUFBRTs7O0FBQXZCLGdCQUFJOztBQUNSLGdCQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7Ozs2Q0FFNUIsR0FBRyxDQUFDLFFBQVEsRUFBRTs7Ozs2Q0FDUCxHQUFHLENBQUMsSUFBSSxFQUFFOzs7QUFBdkIsZ0JBQUk7O0FBQ0osZ0JBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQzs7Ozs7OztLQUNyQyxDQUFDLENBQUM7R0FDSixDQUFDLENBQUM7Q0FDSjs7QUFFRCxJQUFNLFdBQVcsR0FBRyxDQUNsQjtBQUNFLFNBQU8sRUFBRSxLQUFLO0FBQ2QsUUFBTSxFQUFFLFVBQVU7Q0FDbkIsRUFDRDtBQUNFLFNBQU8sRUFBRSxLQUFLO0FBQ2QsUUFBTSxFQUFFLFdBQVc7Q0FDcEIsRUFDRDtBQUNFLFNBQU8sRUFBRSxLQUFLO0FBQ2QsUUFBTSxFQUFFLFdBQVc7Q0FDcEIsQ0FDRixDQUFDOzs7Ozs7QUFDRixvQ0FBdUIsV0FBVyw0R0FBRTtRQUEzQixVQUFVOztBQUNqQixZQUFRLENBQUMsVUFBVSxDQUFDLENBQUM7R0FDdEIiLCJmaWxlIjoidGVzdC9zaW11bGF0b3ItZTJlLXNwZWNzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gdHJhbnNwaWxlOm1vY2hhXG5cbmltcG9ydCB7IGdldFNpbXVsYXRvciwga2lsbEFsbFNpbXVsYXRvcnMgfSBmcm9tICcuLi8uLic7XG5pbXBvcnQgKiBhcyBzaW1jdGwgZnJvbSAnbm9kZS1zaW1jdGwnO1xuaW1wb3J0IGNoYWkgZnJvbSAnY2hhaSc7XG5pbXBvcnQgY2hhaUFzUHJvbWlzZWQgZnJvbSAnY2hhaS1hcy1wcm9taXNlZCc7XG5pbXBvcnQgeyBmcyB9IGZyb20gJ2FwcGl1bS1zdXBwb3J0JztcbmltcG9ydCBCIGZyb20gJ2JsdWViaXJkJztcbmltcG9ydCBnZXRBcHBQYXRoIGZyb20gJ3NhbXBsZS1hcHBzJztcblxuXG5jb25zdCBMT05HX1RJTUVPVVQgPSAxMjAqMTAwMDtcblxuY2hhaS5zaG91bGQoKTtcbmNoYWkudXNlKGNoYWlBc1Byb21pc2VkKTtcblxuZnVuY3Rpb24gcnVuVGVzdHMgKGRldmljZVR5cGUpIHtcbiAgZGVzY3JpYmUoYHNpbXVsYXRvciAke2RldmljZVR5cGUudmVyc2lvbn1gLCBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy50aW1lb3V0KExPTkdfVElNRU9VVCk7XG4gICAgbGV0IHVkaWQ7XG4gICAgYmVmb3JlKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IGtpbGxBbGxTaW11bGF0b3JzKCk7XG4gICAgfSk7XG5cbiAgICBiZWZvcmVFYWNoKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIHVkaWQgPSBhd2FpdCBzaW1jdGwuY3JlYXRlRGV2aWNlKCdpb3Mtc2ltdWxhdG9yIHRlc3RpbmcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV2aWNlVHlwZS5kZXZpY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXZpY2VUeXBlLnZlcnNpb24pO1xuICAgIH0pO1xuICAgIGFmdGVyRWFjaChhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBvbmx5IHdhbnQgdG8gZ2V0IHJpZCBvZiB0aGUgZGV2aWNlIGlmIGl0IGlzIHByZXNlbnRcbiAgICAgIGxldCBkZXZpY2VQcmVzZW50ID0gKGF3YWl0IHNpbWN0bC5nZXREZXZpY2VzKCkpW2RldmljZVR5cGUudmVyc2lvbl1cbiAgICAgICAgLmZpbHRlcigoZGV2aWNlKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGRldmljZS51ZGlkID09PSB1ZGlkO1xuICAgICAgICB9KS5sZW5ndGggPiAwO1xuICAgICAgaWYgKGRldmljZVByZXNlbnQpIHtcbiAgICAgICAgYXdhaXQga2lsbEFsbFNpbXVsYXRvcnMoKTtcbiAgICAgICAgYXdhaXQgc2ltY3RsLmRlbGV0ZURldmljZSh1ZGlkKTtcbiAgICAgIH1cbiAgICB9KTtcblxuXG4gICAgaXQoJ3Nob3VsZCBkZXRlY3Qgd2hldGhlciBhIHNpbXVsYXRvciBoYXMgYmVlbiBydW4gYmVmb3JlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IHNpbSA9IGF3YWl0IGdldFNpbXVsYXRvcih1ZGlkKTtcbiAgICAgIGF3YWl0IHNpbS5pc0ZyZXNoKCkuc2hvdWxkLmV2ZW50dWFsbHkuZXF1YWwodHJ1ZSk7XG4gICAgICBhd2FpdCBzaW0ubGF1bmNoQW5kUXVpdCgpO1xuICAgICAgYXdhaXQgc2ltLmlzRnJlc2goKS5zaG91bGQuZXZlbnR1YWxseS5lcXVhbChmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGxhdW5jaCBhbmQgc2h1dGRvd24gYSBzaW0nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBsZXQgc2ltID0gYXdhaXQgZ2V0U2ltdWxhdG9yKHVkaWQpO1xuICAgICAgYXdhaXQgc2ltLmxhdW5jaEFuZFF1aXQoKTtcbiAgICAgIChhd2FpdCBzaW0uc3RhdCgpKS5zdGF0ZS5zaG91bGQuZXF1YWwoJ1NodXRkb3duJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGxhdW5jaCBhbmQgc2h1dGRvd24gYSBzaW0sIGFsc28gc3RhcnRpbmcgc2FmYXJpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IHNpbSA9IGF3YWl0IGdldFNpbXVsYXRvcih1ZGlkKTtcbiAgICAgIGF3YWl0IHNpbS5sYXVuY2hBbmRRdWl0KHRydWUpO1xuICAgICAgKGF3YWl0IHNpbS5zdGF0KCkpLnN0YXRlLnNob3VsZC5lcXVhbCgnU2h1dGRvd24nKTtcbiAgICB9KTtcblxuXG4gICAgaXQoJ3Nob3VsZCBjbGVhbiBhIHNpbScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGxldCBzaW0gPSBhd2FpdCBnZXRTaW11bGF0b3IodWRpZCk7XG4gICAgICBhd2FpdCBzaW0uaXNGcmVzaCgpLnNob3VsZC5ldmVudHVhbGx5LmVxdWFsKHRydWUpO1xuICAgICAgYXdhaXQgc2ltLmxhdW5jaEFuZFF1aXQoKTtcbiAgICAgIGF3YWl0IHNpbS5pc0ZyZXNoKCkuc2hvdWxkLmV2ZW50dWFsbHkuZXF1YWwoZmFsc2UpO1xuICAgICAgYXdhaXQgc2ltLmNsZWFuKCk7XG4gICAgICBhd2FpdCBzaW0uaXNGcmVzaCgpLnNob3VsZC5ldmVudHVhbGx5LmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBub3QgZmluZCBhbnkgVGVzdEFwcCBkYXRhIG9yIGJ1bmRsZSBkaXJlY3RvcmllcyBvbiBhIGZyZXNoIHNpbXVsYXRvcicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGxldCBzaW0gPSBhd2FpdCBnZXRTaW11bGF0b3IodWRpZCk7XG4gICAgICBsZXQgZGlycyA9IGF3YWl0IHNpbS5nZXRBcHBEaXJzKCdUZXN0QXBwJywgJ2lvLmFwcGl1bS5UZXN0QXBwJyk7XG4gICAgICBkaXJzLnNob3VsZC5oYXZlLmxlbmd0aCgwKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmluZCBib3RoIGEgZGF0YSBhbmQgYnVuZGxlIGRpcmVjdG9yeSBmb3IgVGVzdEFwcCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGxldCBzaW0gPSBhd2FpdCBnZXRTaW11bGF0b3IodWRpZCk7XG4gICAgICBhd2FpdCBzaW0ucnVuKCk7XG5cbiAgICAgIC8vIGluc3RhbGwgJiBsYXVuY2ggdGVzdCBhcHBcbiAgICAgIGF3YWl0IHNpbWN0bC5pbnN0YWxsQXBwKHVkaWQsIGdldEFwcFBhdGgoJ1Rlc3RBcHAnKSk7XG4gICAgICBhd2FpdCBzaW1jdGwubGF1bmNoKHVkaWQsICdpby5hcHBpdW0uVGVzdEFwcCcpO1xuXG4gICAgICBsZXQgZGlycyA9IGF3YWl0IHNpbS5nZXRBcHBEaXJzKCdUZXN0QXBwJywgJ2lvLmFwcGl1bS5UZXN0QXBwJyk7XG4gICAgICBkaXJzLnNob3VsZC5oYXZlLmxlbmd0aCgyKTtcbiAgICAgIGRpcnNbMF0uc2hvdWxkLmNvbnRhaW4oJy9EYXRhLycpO1xuICAgICAgZGlyc1sxXS5zaG91bGQuY29udGFpbignL0J1bmRsZS8nKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZGVsZXRlIGN1c3RvbSBhcHAgZGF0YScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGxldCBzaW0gPSBhd2FpdCBnZXRTaW11bGF0b3IodWRpZCk7XG4gICAgICBhd2FpdCBzaW0ucnVuKCk7XG5cbiAgICAgIC8vIGluc3RhbGwgJiBsYXVuY2ggdGVzdCBhcHBcbiAgICAgIGF3YWl0IHNpbWN0bC5pbnN0YWxsQXBwKHVkaWQsIGdldEFwcFBhdGgoJ1Rlc3RBcHAnKSk7XG4gICAgICBhd2FpdCBzaW1jdGwubGF1bmNoKHVkaWQsICdpby5hcHBpdW0uVGVzdEFwcCcpO1xuXG4gICAgICAvLyBkZWxldGUgYXBwIGRpcmVjdG9yaWVzXG4gICAgICBhd2FpdCBzaW0uY2xlYW5DdXN0b21BcHAoJ1Rlc3RBcHAnLCAnaW8uYXBwaXVtLlRlc3RBcHAnKTtcblxuICAgICAgLy8gY2xlYXIgcGF0aHMgdG8gZm9yY2UgdGhlIHNpbXVsYXRvciB0byBnZXQgYSBuZXcgbGlzdCBvZiBkaXJlY3Rvcmllc1xuICAgICAgc2ltLmFwcERhdGFCdW5kbGVQYXRocyA9IHt9O1xuXG4gICAgICBsZXQgZGlycyA9IGF3YWl0IHNpbS5nZXRBcHBEaXJzKCdUZXN0QXBwJywgJ2lvLmFwcGl1bS5UZXN0QXBwJyk7XG4gICAgICBkaXJzLnNob3VsZC5oYXZlLmxlbmd0aCgwKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZGVsZXRlIGEgc2ltJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IG51bURldmljZXMgPSAoYXdhaXQgc2ltY3RsLmdldERldmljZXMoKSlbZGV2aWNlVHlwZS52ZXJzaW9uXS5sZW5ndGg7XG4gICAgICBudW1EZXZpY2VzLnNob3VsZC5iZS5hYm92ZSgwKTtcblxuICAgICAgbGV0IHNpbSA9IGF3YWl0IGdldFNpbXVsYXRvcih1ZGlkKTtcbiAgICAgIGF3YWl0IHNpbS5kZWxldGUoKTtcbiAgICAgIGxldCBudW1EZXZpY2VzQWZ0ZXIgPSAoYXdhaXQgc2ltY3RsLmdldERldmljZXMoKSlbZGV2aWNlVHlwZS52ZXJzaW9uXS5sZW5ndGg7XG4gICAgICBudW1EZXZpY2VzQWZ0ZXIuc2hvdWxkLmVxdWFsKG51bURldmljZXMtMSk7XG4gICAgfSk7XG5cbiAgICBsZXQgaXRUZXh0ID0gJ3Nob3VsZCBtYXRjaCBhIGJ1bmRsZUlkIHRvIGl0cyBhcHAgZGlyZWN0b3J5IG9uIGEgdXNlZCBzaW0nO1xuICAgIGxldCBidW5kbGVJZCA9ICdjb20uYXBwbGUubW9iaWxlc2FmYXJpJztcbiAgICBpZiAoZGV2aWNlVHlwZS52ZXJzaW9uID09PSAnNy4xJykge1xuICAgICAgaXRUZXh0ID0gJ3Nob3VsZCBtYXRjaCBhbiBhcHAgdG8gaXRzIGFwcCBkaXJlY3Rvcnkgb24gYSB1c2VkIHNpbSc7XG4gICAgICBidW5kbGVJZCA9ICdNb2JpbGVTYWZhcmknO1xuICAgIH1cbiAgICBpdChpdFRleHQsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGxldCBzaW0gPSBhd2FpdCBnZXRTaW11bGF0b3IodWRpZCk7XG4gICAgICBhd2FpdCBzaW0ubGF1bmNoQW5kUXVpdCgpO1xuXG4gICAgICBsZXQgcGF0aCA9IGF3YWl0IHNpbS5nZXRBcHBEaXIoYnVuZGxlSWQpO1xuICAgICAgYXdhaXQgZnMuaGFzQWNjZXNzKHBhdGgpLnNob3VsZC5ldmVudHVhbGx5LmJlLnRydWU7XG4gICAgfSk7XG5cbiAgICBpdFRleHQgPSAnc2hvdWxkIG1hdGNoIGEgYnVuZGxlSWQgdG8gaXRzIGFwcCBkaXJlY3Rvcnkgb24gYSBmcmVzaCBzaW0nO1xuICAgIGJ1bmRsZUlkID0gJ2NvbS5hcHBsZS5tb2JpbGVzYWZhcmknO1xuICAgIGlmIChkZXZpY2VUeXBlLnZlcnNpb24gPT09ICc3LjEnKSB7XG4gICAgICBpdFRleHQgPSAnc2hvdWxkIG1hdGNoIGFuIGFwcCB0byBpdHMgYXBwIGRpcmVjdG9yeSBvbiBhIGZyZXNoIHNpbSc7XG4gICAgICBidW5kbGVJZCA9ICdNb2JpbGVTYWZhcmknO1xuICAgIH1cbiAgICBpdChpdFRleHQsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGxldCBzaW0gPSBhd2FpdCBnZXRTaW11bGF0b3IodWRpZCk7XG4gICAgICBsZXQgcGF0aCA9IGF3YWl0IHNpbS5nZXRBcHBEaXIoYnVuZGxlSWQpO1xuICAgICAgYXdhaXQgZnMuaGFzQWNjZXNzKHBhdGgpLnNob3VsZC5ldmVudHVhbGx5LmJlLnRydWU7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHN0YXJ0IGEgc2ltIHVzaW5nIHRoZSBcInJ1blwiIG1ldGhvZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGxldCBzaW0gPSBhd2FpdCBnZXRTaW11bGF0b3IodWRpZCk7XG5cbiAgICAgIGF3YWl0IHNpbS5ydW4oKTtcblxuICAgICAgbGV0IHN0YXQgPSBhd2FpdCBzaW0uc3RhdCgpO1xuICAgICAgc3RhdC5zdGF0ZS5zaG91bGQuZXF1YWwoJ0Jvb3RlZCcpO1xuXG4gICAgICBhd2FpdCBzaW0uc2h1dGRvd24oKTtcbiAgICAgIHN0YXQgPSBhd2FpdCBzaW0uc3RhdCgpO1xuICAgICAgc3RhdC5zdGF0ZS5zaG91bGQuZXF1YWwoJ1NodXRkb3duJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJlIGFibGUgdG8gc3RhcnQgc2FmYXJpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IHNpbSA9IGF3YWl0IGdldFNpbXVsYXRvcih1ZGlkKTtcblxuICAgICAgYXdhaXQgc2ltLnJ1bigpO1xuICAgICAgYXdhaXQgc2ltLm9wZW5VcmwoJ2h0dHA6Ly9hcHBsZS5jb20nKTtcbiAgICAgIGF3YWl0IHNpbS5zaHV0ZG93bigpO1xuXG4gICAgICAvLyB0aGlzIHRlc3QgdG8gY2F0Y2ggZXJyb3JzIGluIG9wZW5VcmwsIHRoYXQgYXJpc2UgZnJvbSBiYWQgc2ltcyBvciBjZXJ0YWluIHZlcnNpb25zIG9mIHhjb2RlXG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGRldGVjdCBpZiBhIHNpbSBpcyBydW5uaW5nJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IHNpbSA9IGF3YWl0IGdldFNpbXVsYXRvcih1ZGlkKTtcbiAgICAgIGxldCBydW5uaW5nID0gYXdhaXQgc2ltLmlzUnVubmluZygpO1xuICAgICAgcnVubmluZy5zaG91bGQuYmUuZmFsc2U7XG5cbiAgICAgIGF3YWl0IHNpbS5ydW4oKTtcbiAgICAgIHJ1bm5pbmcgPSBhd2FpdCBzaW0uaXNSdW5uaW5nKCk7XG4gICAgICBydW5uaW5nLnNob3VsZC5iZS50cnVlO1xuXG4gICAgICBhd2FpdCBzaW0uc2h1dGRvd24oKTtcbiAgICAgIHJ1bm5pbmcgPSBhd2FpdCBzaW0uaXNSdW5uaW5nKCk7XG4gICAgICBydW5uaW5nLnNob3VsZC5iZS5mYWxzZTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgaXNvbGF0ZSBzaW0nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBsZXQgc2ltID0gYXdhaXQgZ2V0U2ltdWxhdG9yKHVkaWQpO1xuICAgICAgYXdhaXQgc2ltLmlzb2xhdGVTaW0oKTtcblxuICAgICAgbGV0IG51bURldmljZXMgPSAoYXdhaXQgc2ltY3RsLmdldERldmljZXMoKSlbZGV2aWNlVHlwZS52ZXJzaW9uXS5sZW5ndGg7XG5cbiAgICAgIG51bURldmljZXMuc2hvdWxkLmVxdWFsKDEpO1xuICAgIH0pO1xuXG4gIH0pO1xuXG4gIGRlc2NyaWJlKGByZXVzZSBhbiBhbHJlYWR5LWNyZWF0ZWQgYWxyZWFkeS1ydW4gc2ltdWxhdG9yICR7ZGV2aWNlVHlwZS52ZXJzaW9ufWAsIGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLnRpbWVvdXQoTE9OR19USU1FT1VUKTtcbiAgICBsZXQgc2ltO1xuICAgIGJlZm9yZShhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhd2FpdCBraWxsQWxsU2ltdWxhdG9ycygpO1xuICAgICAgbGV0IHVkaWQgPSBhd2FpdCBzaW1jdGwuY3JlYXRlRGV2aWNlKCdpb3Mtc2ltdWxhdG9yIHRlc3RpbmcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV2aWNlVHlwZS5kZXZpY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXZpY2VUeXBlLnZlcnNpb24pO1xuICAgICAgc2ltID0gYXdhaXQgZ2V0U2ltdWxhdG9yKHVkaWQpO1xuICAgICAgYXdhaXQgc2ltLnJ1bigpO1xuICAgICAgYXdhaXQgc2ltLnNodXRkb3duKCk7XG4gICAgICBhd2FpdCBCLmRlbGF5KDQwMDApO1xuICAgIH0pO1xuICAgIGFmdGVyKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIG9ubHkgd2FudCB0byBnZXQgcmlkIG9mIHRoZSBkZXZpY2UgaWYgaXQgaXMgcHJlc2VudFxuICAgICAgbGV0IGRldmljZVByZXNlbnQgPSAoYXdhaXQgc2ltY3RsLmdldERldmljZXMoKSlbZGV2aWNlVHlwZS52ZXJzaW9uXVxuICAgICAgICAuZmlsdGVyKChkZXZpY2UpID0+IHtcbiAgICAgICAgICByZXR1cm4gZGV2aWNlLnVkaWQgPT09IHNpbS51ZGlkO1xuICAgICAgICB9KS5sZW5ndGggPiAwO1xuICAgICAgaWYgKGRldmljZVByZXNlbnQpIHtcbiAgICAgICAgYXdhaXQgc2ltY3RsLmRlbGV0ZURldmljZShzaW0udWRpZCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHN0YXJ0IGEgc2ltIHVzaW5nIHRoZSBcInJ1blwiIG1ldGhvZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IHNpbS5ydW4oKTtcblxuICAgICAgbGV0IHN0YXQgPSBhd2FpdCBzaW0uc3RhdCgpO1xuICAgICAgc3RhdC5zdGF0ZS5zaG91bGQuZXF1YWwoJ0Jvb3RlZCcpO1xuXG4gICAgICBhd2FpdCBzaW0uc2h1dGRvd24oKTtcbiAgICAgIHN0YXQgPSBhd2FpdCBzaW0uc3RhdCgpO1xuICAgICAgc3RhdC5zdGF0ZS5zaG91bGQuZXF1YWwoJ1NodXRkb3duJyk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5jb25zdCBkZXZpY2VUeXBlcyA9IFtcbiAge1xuICAgIHZlcnNpb246ICc4LjQnLFxuICAgIGRldmljZTogJ2lQaG9uZSA2J1xuICB9LFxuICB7XG4gICAgdmVyc2lvbjogJzkuMCcsXG4gICAgZGV2aWNlOiAnaVBob25lIDZzJ1xuICB9LFxuICB7XG4gICAgdmVyc2lvbjogJzkuMScsXG4gICAgZGV2aWNlOiAnaVBob25lIDZzJ1xuICB9XG5dO1xuZm9yIChsZXQgZGV2aWNlVHlwZSBvZiBkZXZpY2VUeXBlcykge1xuICBydW5UZXN0cyhkZXZpY2VUeXBlKTtcbn1cbiJdfQ==