UNPKG

appium-adb-test

Version:

Android Debug Bridge interface

256 lines (211 loc) 28.3 kB
'use strict'; var _regeneratorRuntime = require('babel-runtime/regenerator')['default']; var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default']; var _interopRequireWildcard = require('babel-runtime/helpers/interop-require-wildcard')['default']; var _this = this; var _chai = require('chai'); var _chai2 = _interopRequireDefault(_chai); var _chaiAsPromised = require('chai-as-promised'); var _chaiAsPromised2 = _interopRequireDefault(_chaiAsPromised); var _ = require('../..'); var _2 = _interopRequireDefault(_); var _libHelpersJs = require('../../lib/helpers.js'); var helpers = _interopRequireWildcard(_libHelpersJs); var _path = require('path'); var _path2 = _interopRequireDefault(_path); var _teen_process = require('teen_process'); var teen_process = _interopRequireWildcard(_teen_process); var _appiumSupport = require('appium-support'); var appiumSupport = _interopRequireWildcard(_appiumSupport); var _appiumTestSupport = require('appium-test-support'); _chai2['default'].use(_chaiAsPromised2['default']); var selendroidTestApp = _path2['default'].resolve(helpers.rootDir, 'test', 'fixtures', 'selendroid-test-app.apk'), helperJarPath = _path2['default'].resolve(helpers.rootDir, 'jars'), keystorePath = _path2['default'].resolve(helpers.rootDir, 'test', 'fixtures', 'appiumtest.keystore'), keyAlias = 'appiumtest', password = 'android', selendroidTestAppPackage = 'io.selendroid.testapp', java_dummy_path = 'java_dummy_path', java_home = 'java_home', tempDir = appiumSupport.tempDir, fs = appiumSupport.fs; describe('signing', function () { var adb = new _2['default'](); adb.keystorePath = keystorePath; adb.keyAlias = keyAlias; adb.keystorePassword = password; adb.keyPassword = password; describe('signWithDefaultCert', (0, _appiumTestSupport.withMocks)({ teen_process: teen_process, helpers: helpers }, function (mocks) { it('should call exec with correct args', function callee$2$0() { var signPath; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: signPath = _path2['default'].resolve(helperJarPath, 'sign.jar'); mocks.helpers.expects("getJavaForOs").returns(java_dummy_path); mocks.teen_process.expects("exec").once().withExactArgs(java_dummy_path, ['-jar', signPath, selendroidTestApp, '--override']).returns(""); context$3$0.next = 5; return _regeneratorRuntime.awrap(adb.signWithDefaultCert(selendroidTestApp)); case 5: mocks.teen_process.verify(); case 6: case 'end': return context$3$0.stop(); } }, null, _this); }); it('should throw error for invalid file path', function callee$2$0() { var dummyPath; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: dummyPath = "dummyPath"; context$3$0.next = 3; return _regeneratorRuntime.awrap(adb.signWithDefaultCert(dummyPath).should.eventually.be.rejected); case 3: mocks.teen_process.verify(); mocks.helpers.verify(); case 5: case 'end': return context$3$0.stop(); } }, null, _this); }); })); describe('signWithCustomCert', (0, _appiumTestSupport.withMocks)({ teen_process: teen_process, helpers: helpers }, function (mocks) { it('should call exec with correct args', function callee$2$0() { var jarsigner; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: jarsigner = _path2['default'].resolve(java_home, 'bin', 'jarsigner'); if (appiumSupport.system.isWindows()) { jarsigner = jarsigner + '.exe'; } adb.useKeystore = true; mocks.helpers.expects("getJavaHome").returns(java_home); mocks.helpers.expects("getJavaForOs").returns(java_dummy_path); mocks.teen_process.expects("exec").withExactArgs(java_dummy_path, ['-jar', _path2['default'].resolve(helperJarPath, 'unsign.jar'), selendroidTestApp]).returns(""); mocks.teen_process.expects("exec").withExactArgs(jarsigner, ['-sigalg', 'MD5withRSA', '-digestalg', 'SHA1', '-keystore', keystorePath, '-storepass', password, '-keypass', password, selendroidTestApp, keyAlias]).returns(""); context$3$0.next = 9; return _regeneratorRuntime.awrap(adb.signWithCustomCert(selendroidTestApp)); case 9: mocks.teen_process.verify(); mocks.helpers.verify(); case 11: case 'end': return context$3$0.stop(); } }, null, _this); }); })); describe('getKeystoreMd5', (0, _appiumTestSupport.withMocks)({ teen_process: teen_process }, function (mocks) { it('should call exec with correct args', function callee$2$0() { var h, keytool, md5Str, md5; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: h = "a-fA-F0-9"; keytool = _path2['default'].resolve(java_home, 'bin', 'keytool'); md5Str = ['.*MD5.*((?:[', h, ']{2}:){15}[', h, ']{2})'].join(''); md5 = new RegExp(md5Str, 'mi'); adb.useKeystore = true; mocks.teen_process.expects("exec").once().withExactArgs(keytool, ['-v', '-list', '-alias', keyAlias, '-keystore', keystorePath, '-storepass', password]).returns(""); context$3$0.next = 8; return _regeneratorRuntime.awrap(adb.getKeystoreMd5(keytool, md5)); case 8: mocks.teen_process.verify(); case 9: case 'end': return context$3$0.stop(); } }, null, _this); }); })); // Skipping as unable to mock mkdirp, this case is covered in e2e tests for now. // TODO: find ways to mock mkdirp describe.skip('zipAlignApk', (0, _appiumTestSupport.withMocks)({ teen_process: teen_process, adb: adb, appiumSupport: appiumSupport, fs: fs, tempDir: tempDir }, function (mocks) { it('should call exec with correct args', function callee$2$0() { var alignedApk; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: alignedApk = "dummy_path"; mocks.tempDir.expects('path').once().withExactArgs({ prefix: 'appium', suffix: '.tmp' }).returns(alignedApk); mocks.adb.expects('initZipAlign').once().withExactArgs().returns(""); mocks.appiumSupport.expects('mkdirp').once().withExactArgs(_path2['default'].dirname(alignedApk)).returns(""); mocks.teen_process.expects("exec").once().withExactArgs(adb.binaries.zipalign, ['-f', '4', selendroidTestApp, alignedApk]); mocks.fs.expects("mv").once().withExactArgs(alignedApk, selendroidTestApp, { mkdirp: true }).returns(""); context$3$0.next = 8; return _regeneratorRuntime.awrap(adb.zipAlignApk(selendroidTestApp)); case 8: mocks.adb.verify(); mocks.appiumSupport.verify(); mocks.teen_process.verify(); mocks.tempDir.verify(); mocks.fs.verify(); case 13: case 'end': return context$3$0.stop(); } }, null, _this); }); })); describe('checkApkCert', (0, _appiumTestSupport.withMocks)({ teen_process: teen_process, helpers: helpers, adb: adb }, function (mocks) { it('should return false for apk not present', 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: mocks.helpers.expects("getJavaForOs").returns(java_dummy_path); context$3$0.next = 3; return _regeneratorRuntime.awrap(adb.checkApkCert('dummyPath', 'dummyPackage')); case 3: context$3$0.sent.should.be['false']; mocks.helpers.verify(); case 5: case 'end': return context$3$0.stop(); } }, null, _this); }); it('should call exec and zipAlign when not using keystore', 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: mocks.helpers.expects("getJavaForOs").returns(java_dummy_path); mocks.teen_process.expects("exec").once().withExactArgs(java_dummy_path, ['-jar', _path2['default'].resolve(helperJarPath, 'verify.jar'), selendroidTestApp]).returns(""); mocks.adb.expects('zipAlignApk').once().withExactArgs(selendroidTestApp).returns(""); adb.useKeystore = false; context$3$0.next = 6; return _regeneratorRuntime.awrap(adb.checkApkCert(selendroidTestApp, selendroidTestAppPackage)); case 6: mocks.adb.verify(); mocks.teen_process.verify(); mocks.helpers.verify(); case 9: case 'end': return context$3$0.stop(); } }, null, _this); }); it('should call checkCustomApkCert when using keystore', 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: mocks.helpers.expects("getJavaForOs").returns(java_dummy_path); mocks.adb.expects('checkCustomApkCert').once().withExactArgs(selendroidTestApp, selendroidTestAppPackage).returns(""); adb.useKeystore = true; context$3$0.next = 5; return _regeneratorRuntime.awrap(adb.checkApkCert(selendroidTestApp, selendroidTestAppPackage)); case 5: mocks.adb.verify(); mocks.helpers.verify(); case 7: case 'end': return context$3$0.stop(); } }, null, _this); }); })); }); //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvdW5pdC9hcGstc2lnbmluZy1zcGVjcy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O29CQUFpQixNQUFNOzs7OzhCQUNJLGtCQUFrQjs7OztnQkFDN0IsT0FBTzs7Ozs0QkFDRSxzQkFBc0I7O0lBQW5DLE9BQU87O29CQUNGLE1BQU07Ozs7NEJBQ08sY0FBYzs7SUFBaEMsWUFBWTs7NkJBQ08sZ0JBQWdCOztJQUFuQyxhQUFhOztpQ0FDQyxxQkFBcUI7O0FBRy9DLGtCQUFLLEdBQUcsNkJBQWdCLENBQUM7O0FBRXpCLElBQU0saUJBQWlCLEdBQUcsa0JBQUssT0FBTyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFDbkMseUJBQXlCLENBQUM7SUFDM0QsYUFBYSxHQUFHLGtCQUFLLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQztJQUNyRCxZQUFZLEdBQUcsa0JBQUssT0FBTyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFDbkMscUJBQXFCLENBQUM7SUFDbEQsUUFBUSxHQUFHLFlBQVk7SUFDdkIsUUFBUSxHQUFHLFNBQVM7SUFDcEIsd0JBQXdCLEdBQUcsdUJBQXVCO0lBQ2xELGVBQWUsR0FBRyxpQkFBaUI7SUFDbkMsU0FBUyxHQUFHLFdBQVc7SUFDdkIsT0FBTyxHQUFHLGFBQWEsQ0FBQyxPQUFPO0lBQy9CLEVBQUUsR0FBRyxhQUFhLENBQUMsRUFBRSxDQUFDOztBQUU1QixRQUFRLENBQUMsU0FBUyxFQUFFLFlBQU07QUFDeEIsTUFBSSxHQUFHLEdBQUcsbUJBQVMsQ0FBQztBQUNwQixLQUFHLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQztBQUNoQyxLQUFHLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztBQUN4QixLQUFHLENBQUMsZ0JBQWdCLEdBQUcsUUFBUSxDQUFDO0FBQ2hDLEtBQUcsQ0FBQyxXQUFXLEdBQUcsUUFBUSxDQUFDOztB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LCJmaWxlIjoidGVzdC91bml0L2Fway1zaWduaW5nLXNwZWNzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNoYWkgZnJvbSAnY2hhaSc7XHJcbmltcG9ydCBjaGFpQXNQcm9taXNlZCBmcm9tICdjaGFpLWFzLXByb21pc2VkJztcclxuaW1wb3J0IEFEQiBmcm9tICcuLi8uLic7XHJcbmltcG9ydCAqIGFzIGhlbHBlcnMgZnJvbSAnLi4vLi4vbGliL2hlbHBlcnMuanMnO1xyXG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcclxuaW1wb3J0ICogYXMgdGVlbl9wcm9jZXNzIGZyb20gJ3RlZW5fcHJvY2Vzcyc7XHJcbmltcG9ydCAqIGFzIGFwcGl1bVN1cHBvcnQgZnJvbSAnYXBwaXVtLXN1cHBvcnQnO1xyXG5pbXBvcnQgeyB3aXRoTW9ja3MgfSBmcm9tICdhcHBpdW0tdGVzdC1zdXBwb3J0JztcclxuXHJcblxyXG5jaGFpLnVzZShjaGFpQXNQcm9taXNlZCk7XHJcblxyXG5jb25zdCBzZWxlbmRyb2lkVGVzdEFwcCA9IHBhdGgucmVzb2x2ZShoZWxwZXJzLnJvb3REaXIsICd0ZXN0JywgJ2ZpeHR1cmVzJyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3NlbGVuZHJvaWQtdGVzdC1hcHAuYXBrJyksXHJcbiAgICAgIGhlbHBlckphclBhdGggPSBwYXRoLnJlc29sdmUoaGVscGVycy5yb290RGlyLCAnamFycycpLFxyXG4gICAgICBrZXlzdG9yZVBhdGggPSBwYXRoLnJlc29sdmUoaGVscGVycy5yb290RGlyLCAndGVzdCcsICdmaXh0dXJlcycsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnYXBwaXVtdGVzdC5rZXlzdG9yZScpLFxyXG4gICAgICBrZXlBbGlhcyA9ICdhcHBpdW10ZXN0JyxcclxuICAgICAgcGFzc3dvcmQgPSAnYW5kcm9pZCcsXHJcbiAgICAgIHNlbGVuZHJvaWRUZXN0QXBwUGFja2FnZSA9ICdpby5zZWxlbmRyb2lkLnRlc3RhcHAnLFxyXG4gICAgICBqYXZhX2R1bW15X3BhdGggPSAnamF2YV9kdW1teV9wYXRoJyxcclxuICAgICAgamF2YV9ob21lID0gJ2phdmFfaG9tZScsXHJcbiAgICAgIHRlbXBEaXIgPSBhcHBpdW1TdXBwb3J0LnRlbXBEaXIsXHJcbiAgICAgIGZzID0gYXBwaXVtU3VwcG9ydC5mcztcclxuXHJcbmRlc2NyaWJlKCdzaWduaW5nJywgKCkgPT4ge1xyXG4gIGxldCBhZGIgPSBuZXcgQURCKCk7XHJcbiAgYWRiLmtleXN0b3JlUGF0aCA9IGtleXN0b3JlUGF0aDtcclxuICBhZGIua2V5QWxpYXMgPSBrZXlBbGlhcztcclxuICBhZGIua2V5c3RvcmVQYXNzd29yZCA9IHBhc3N3b3JkO1xyXG4gIGFkYi5rZXlQYXNzd29yZCA9IHBhc3N3b3JkO1xyXG5cclxuICBkZXNjcmliZSgnc2lnbldpdGhEZWZhdWx0Q2VydCcsIHdpdGhNb2Nrcyh7dGVlbl9wcm9jZXNzLCBoZWxwZXJzfSwgKG1vY2tzKSA9PiB7XHJcbiAgICBpdCgnc2hvdWxkIGNhbGwgZXhlYyB3aXRoIGNvcnJlY3QgYXJncycsIGFzeW5jICgpID0+IHtcclxuICAgICAgbGV0IHNpZ25QYXRoID0gcGF0aC5yZXNvbHZlKGhlbHBlckphclBhdGgsICdzaWduLmphcicpO1xyXG4gICAgICBtb2Nrcy5oZWxwZXJzLmV4cGVjdHMoXCJnZXRKYXZhRm9yT3NcIilcclxuICAgICAgICAucmV0dXJucyhqYXZhX2R1bW15X3BhdGgpO1xyXG4gICAgICBtb2Nrcy50ZWVuX3Byb2Nlc3MuZXhwZWN0cyhcImV4ZWNcIilcclxuICAgICAgICAub25jZSgpLndpdGhFeGFjdEFyZ3MoamF2YV9kdW1teV9wYXRoLCBbJy1qYXInLCBzaWduUGF0aCwgc2VsZW5kcm9pZFRlc3RBcHAsICctLW92ZXJyaWRlJ10pXHJcbiAgICAgICAgLnJldHVybnMoXCJcIik7XHJcbiAgICAgIChhd2FpdCBhZGIuc2lnbldpdGhEZWZhdWx0Q2VydChzZWxlbmRyb2lkVGVzdEFwcCkpO1xyXG4gICAgICBtb2Nrcy50ZWVuX3Byb2Nlc3MudmVyaWZ5KCk7XHJcbiAgICB9KTtcclxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgZm9yIGludmFsaWQgZmlsZSBwYXRoJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBsZXQgZHVtbXlQYXRoID0gXCJkdW1teVBhdGhcIjtcclxuICAgICAgYXdhaXQgYWRiLnNpZ25XaXRoRGVmYXVsdENlcnQoZHVtbXlQYXRoKS5zaG91bGQuZXZlbnR1YWxseS5iZS5yZWplY3RlZDtcclxuICAgICAgbW9ja3MudGVlbl9wcm9jZXNzLnZlcmlmeSgpO1xyXG4gICAgICBtb2Nrcy5oZWxwZXJzLnZlcmlmeSgpO1xyXG4gICAgfSk7XHJcbiAgfSkpO1xyXG4gIGRlc2NyaWJlKCdzaWduV2l0aEN1c3RvbUNlcnQnLCB3aXRoTW9ja3Moe3RlZW5fcHJvY2VzcywgaGVscGVyc30sIChtb2NrcykgPT4ge1xyXG4gICAgaXQoJ3Nob3VsZCBjYWxsIGV4ZWMgd2l0aCBjb3JyZWN0IGFyZ3MnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGxldCBqYXJzaWduZXIgPSBwYXRoLnJlc29sdmUoamF2YV9ob21lLCAnYmluJywgJ2phcnNpZ25lcicpO1xyXG4gICAgICBpZiAoYXBwaXVtU3VwcG9ydC5zeXN0ZW0uaXNXaW5kb3dzKCkpIHtcclxuICAgICAgICBqYXJzaWduZXIgPSBqYXJzaWduZXIgKyAnLmV4ZSc7XHJcbiAgICAgIH1cclxuICAgICAgYWRiLnVzZUtleXN0b3JlID0gdHJ1ZTtcclxuICAgICAgbW9ja3MuaGVscGVycy5leHBlY3RzKFwiZ2V0SmF2YUhvbWVcIilcclxuICAgICAgICAucmV0dXJucyhqYXZhX2hvbWUpO1xyXG4gICAgICBtb2Nrcy5oZWxwZXJzLmV4cGVjdHMoXCJnZXRKYXZhRm9yT3NcIilcclxuICAgICAgICAucmV0dXJucyhqYXZhX2R1bW15X3BhdGgpO1xyXG4gICAgICBtb2Nrcy50ZWVuX3Byb2Nlc3MuZXhwZWN0cyhcImV4ZWNcIilcclxuICAgICAgICAud2l0aEV4YWN0QXJncyhqYXZhX2R1bW15X3BhdGgsIFsnLWphcicsIHBhdGgucmVzb2x2ZShoZWxwZXJKYXJQYXRoLCAndW5zaWduLmphcicpLCBzZWxlbmRyb2lkVGVzdEFwcF0pXHJcbiAgICAgICAgLnJldHVybnMoXCJcIik7XHJcbiAgICAgIG1vY2tzLnRlZW5fcHJvY2Vzcy5leHBlY3RzKFwiZXhlY1wiKVxyXG4gICAgICAgIC53aXRoRXhhY3RBcmdzKGphcnNpZ25lciwgWyctc2lnYWxnJywgJ01ENXdpdGhSU0EnLCAnLWRpZ2VzdGFsZycsICdTSEExJyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLWtleXN0b3JlJywga2V5c3RvcmVQYXRoLCAnLXN0b3JlcGFzcycsIHBhc3N3b3JkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcta2V5cGFzcycsIHBhc3N3b3JkLCBzZWxlbmRyb2lkVGVzdEFwcCwga2V5QWxpYXNdKVxyXG4gICAgICAgIC5yZXR1cm5zKFwiXCIpO1xyXG4gICAgICAoYXdhaXQgYWRiLnNpZ25XaXRoQ3VzdG9tQ2VydChzZWxlbmRyb2lkVGVzdEFwcCkpO1xyXG4gICAgICBtb2Nrcy50ZWVuX3Byb2Nlc3MudmVyaWZ5KCk7XHJcbiAgICAgIG1vY2tzLmhlbHBlcnMudmVyaWZ5KCk7XHJcbiAgICB9KTtcclxuICB9KSk7XHJcbiAgZGVzY3JpYmUoJ2dldEtleXN0b3JlTWQ1Jywgd2l0aE1vY2tzKHt0ZWVuX3Byb2Nlc3N9LCAobW9ja3MpID0+IHtcclxuICAgIGl0KCdzaG91bGQgY2FsbCBleGVjIHdpdGggY29ycmVjdCBhcmdzJywgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBsZXQgaCA9IFwiYS1mQS1GMC05XCI7XHJcbiAgICAgIGxldCBrZXl0b29sID0gcGF0aC5yZXNvbHZlKGphdmFfaG9tZSwgJ2JpbicsICdrZXl0b29sJyk7XHJcbiAgICAgIGxldCBtZDVTdHIgPSBbJy4qTUQ1LiooKD86WycsIGgsICddezJ9Oil7MTV9WycsIGgsICddezJ9KSddLmpvaW4oJycpO1xyXG4gICAgICBsZXQgbWQ1ID0gbmV3IFJlZ0V4cChtZDVTdHIsICdtaScpO1xyXG4gICAgICBhZGIudXNlS2V5c3RvcmUgPSB0cnVlO1xyXG4gICAgICBtb2Nrcy50ZWVuX3Byb2Nlc3MuZXhwZWN0cyhcImV4ZWNcIilcclxuICAgICAgICAub25jZSgpLndpdGhFeGFjdEFyZ3Moa2V5dG9vbCwgWyctdicsICctbGlzdCcsICctYWxpYXMnLCBrZXlBbGlhcyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcta2V5c3RvcmUnLCBrZXlzdG9yZVBhdGgsICctc3RvcmVwYXNzJyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhc3N3b3JkXSlcclxuICAgICAgICAucmV0dXJucyhcIlwiKTtcclxuICAgICAgKGF3YWl0IGFkYi5nZXRLZXlzdG9yZU1kNShrZXl0b29sLCBtZDUpKTtcclxuICAgICAgbW9ja3MudGVlbl9wcm9jZXNzLnZlcmlmeSgpO1xyXG4gICAgfSk7XHJcbiAgfSkpO1xyXG4gIC8vIFNraXBwaW5nIGFzIHVuYWJsZSB0byBtb2NrIG1rZGlycCwgdGhpcyBjYXNlIGlzIGNvdmVyZWQgaW4gZTJlIHRlc3RzIGZvciBub3cuXHJcbiAgLy8gVE9ETzogZmluZCB3YXlzIHRvIG1vY2sgbWtkaXJwXHJcbiAgZGVzY3JpYmUuc2tpcCgnemlwQWxpZ25BcGsnLCB3aXRoTW9ja3Moe3RlZW5fcHJvY2VzcywgYWRiLCBhcHBpdW1TdXBwb3J0LCBmcywgdGVtcERpcn0sIChtb2NrcykgPT4ge1xyXG4gICAgaXQoJ3Nob3VsZCBjYWxsIGV4ZWMgd2l0aCBjb3JyZWN0IGFyZ3MnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIGxldCBhbGlnbmVkQXBrID0gXCJkdW1teV9wYXRoXCI7XHJcbiAgICAgIG1vY2tzLnRlbXBEaXIuZXhwZWN0cygncGF0aCcpXHJcbiAgICAgICAgLm9uY2UoKS53aXRoRXhhY3RBcmdzKHtwcmVmaXg6ICdhcHBpdW0nLCBzdWZmaXg6ICcudG1wJ30pXHJcbiAgICAgICAgLnJldHVybnMoYWxpZ25lZEFwayk7XHJcbiAgICAgIG1vY2tzLmFkYi5leHBlY3RzKCdpbml0WmlwQWxpZ24nKVxyXG4gICAgICAgIC5vbmNlKCkud2l0aEV4YWN0QXJncygpXHJcbiAgICAgICAgLnJldHVybnMoXCJcIik7XHJcbiAgICAgIG1vY2tzLmFwcGl1bVN1cHBvcnQuZXhwZWN0cygnbWtkaXJwJylcclxuICAgICAgICAub25jZSgpLndpdGhFeGFjdEFyZ3MocGF0aC5kaXJuYW1lKGFsaWduZWRBcGspKVxyXG4gICAgICAgIC5yZXR1cm5zKFwiXCIpO1xyXG4gICAgICBtb2Nrcy50ZWVuX3Byb2Nlc3MuZXhwZWN0cyhcImV4ZWNcIilcclxuICAgICAgICAub25jZSgpLndpdGhFeGFjdEFyZ3MoYWRiLmJpbmFyaWVzLnppcGFsaWduLCBbJy1mJywgJzQnLCBzZWxlbmRyb2lkVGVzdEFwcCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxpZ25lZEFwa10pO1xyXG4gICAgICBtb2Nrcy5mcy5leHBlY3RzKFwibXZcIilcclxuICAgICAgICAub25jZSgpLndpdGhFeGFjdEFyZ3MoYWxpZ25lZEFwaywgc2VsZW5kcm9pZFRlc3RBcHAsIHsgbWtkaXJwOiB0cnVlIH0pXHJcbiAgICAgICAgLnJldHVybnMoXCJcIik7XHJcbiAgICAgIGF3YWl0IGFkYi56aXBBbGlnbkFwayhzZWxlbmRyb2lkVGVzdEFwcCk7XHJcbiAgICAgIG1vY2tzLmFkYi52ZXJpZnkoKTtcclxuICAgICAgbW9ja3MuYXBwaXVtU3VwcG9ydC52ZXJpZnkoKTtcclxuICAgICAgbW9ja3MudGVlbl9wcm9jZXNzLnZlcmlmeSgpO1xyXG4gICAgICBtb2Nrcy50ZW1wRGlyLnZlcmlmeSgpO1xyXG4gICAgICBtb2Nrcy5mcy52ZXJpZnkoKTtcclxuICAgIH0pO1xyXG4gIH0pKTtcclxuICBkZXNjcmliZSgnY2hlY2tBcGtDZXJ0Jywgd2l0aE1vY2tzKHt0ZWVuX3Byb2Nlc3MsIGhlbHBlcnMsIGFkYn0sIChtb2NrcykgPT4ge1xyXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZmFsc2UgZm9yIGFwayBub3QgcHJlc2VudCcsIGFzeW5jICgpID0+IHtcclxuICAgICAgbW9ja3MuaGVscGVycy5leHBlY3RzKFwiZ2V0SmF2YUZvck9zXCIpXHJcbiAgICAgICAgLnJldHVybnMoamF2YV9kdW1teV9wYXRoKTtcclxuICAgICAgKGF3YWl0IGFkYi5jaGVja0Fwa0NlcnQoJ2R1bW15UGF0aCcsICdkdW1teVBhY2thZ2UnKSkuc2hvdWxkLmJlLmZhbHNlO1xyXG4gICAgICBtb2Nrcy5oZWxwZXJzLnZlcmlmeSgpO1xyXG4gICAgfSk7XHJcbiAgICBpdCgnc2hvdWxkIGNhbGwgZXhlYyBhbmQgemlwQWxpZ24gd2hlbiBub3QgdXNpbmcga2V5c3RvcmUnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIG1vY2tzLmhlbHBlcnMuZXhwZWN0cyhcImdldEphdmFGb3JPc1wiKVxyXG4gICAgICAgICAgIC5yZXR1cm5zKGphdmFfZHVtbXlfcGF0aCk7XHJcbiAgICAgIG1vY2tzLnRlZW5fcHJvY2Vzcy5leHBlY3RzKFwiZXhlY1wiKVxyXG4gICAgICAgICAgIC5vbmNlKCkud2l0aEV4YWN0QXJncyhqYXZhX2R1bW15X3BhdGgsIFsnLWphcicsIHBhdGgucmVzb2x2ZShoZWxwZXJKYXJQYXRoLCAndmVyaWZ5LmphcicpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZW5kcm9pZFRlc3RBcHBdKVxyXG4gICAgICAgICAgIC5yZXR1cm5zKFwiXCIpO1xyXG4gICAgICBtb2Nrcy5hZGIuZXhwZWN0cygnemlwQWxpZ25BcGsnKVxyXG4gICAgICAgICAgIC5vbmNlKCkud2l0aEV4YWN0QXJncyhzZWxlbmRyb2lkVGVzdEFwcClcclxuICAgICAgICAgICAucmV0dXJucyhcIlwiKTtcclxuICAgICAgYWRiLnVzZUtleXN0b3JlID0gZmFsc2U7XHJcbiAgICAgIGF3YWl0IGFkYi5jaGVja0Fwa0NlcnQoc2VsZW5kcm9pZFRlc3RBcHAsIHNlbGVuZHJvaWRUZXN0QXBwUGFja2FnZSk7XHJcbiAgICAgIG1vY2tzLmFkYi52ZXJpZnkoKTtcclxuICAgICAgbW9ja3MudGVlbl9wcm9jZXNzLnZlcmlmeSgpO1xyXG4gICAgICBtb2Nrcy5oZWxwZXJzLnZlcmlmeSgpO1xyXG4gICAgfSk7XHJcbiAgICBpdCgnc2hvdWxkIGNhbGwgY2hlY2tDdXN0b21BcGtDZXJ0IHdoZW4gdXNpbmcga2V5c3RvcmUnLCBhc3luYyAoKSA9PiB7XHJcbiAgICAgIG1vY2tzLmhlbHBlcnMuZXhwZWN0cyhcImdldEphdmFGb3JPc1wiKVxyXG4gICAgICAgICAgIC5yZXR1cm5zKGphdmFfZHVtbXlfcGF0aCk7XHJcbiAgICAgIG1vY2tzLmFkYi5leHBlY3RzKCdjaGVja0N1c3RvbUFwa0NlcnQnKVxyXG4gICAgICAgICAgIC5vbmNlKCkud2l0aEV4YWN0QXJncyhzZWxlbmRyb2lkVGVzdEFwcCwgc2VsZW5kcm9pZFRlc3RBcHBQYWNrYWdlKVxyXG4gICAgICAgICAgIC5yZXR1cm5zKFwiXCIpO1xyXG4gICAgICBhZGIudXNlS2V5c3RvcmUgPSB0cnVlO1xyXG4gICAgICBhd2FpdCBhZGIuY2hlY2tBcGtDZXJ0KHNlbGVuZHJvaWRUZXN0QXBwLCBzZWxlbmRyb2lkVGVzdEFwcFBhY2thZ2UpO1xyXG4gICAgICBtb2Nrcy5hZGIudmVyaWZ5KCk7XHJcbiAgICAgIG1vY2tzLmhlbHBlcnMudmVyaWZ5KCk7XHJcbiAgICB9KTtcclxuICB9KSk7XHJcbn0pO1xyXG4iXSwic291cmNlUm9vdCI6Ii4uXFwuLlxcLi4ifQ==