UNPKG

@testim/testim-cli

Version:

Command line interface for running Testing on you CI

473 lines (374 loc) 44 kB
'use strict'; var _Object$create = require('babel-runtime/core-js/object/create')['default']; var _Object$keys = require('babel-runtime/core-js/object/keys')['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 _q = require('q'); var _q2 = _interopRequireDefault(_q); var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs); var _path = require('path'); var _path2 = _interopRequireDefault(_path); var _deepmerge = require('deepmerge'); var _deepmerge2 = _interopRequireDefault(_deepmerge); var _events = require('events'); var _events2 = _interopRequireDefault(_events); var _utilsRequestHandler = require('./utils/RequestHandler'); var _utilsRequestHandler2 = _interopRequireDefault(_utilsRequestHandler); var _utilsErrorHandler = require('./utils/ErrorHandler'); var _utilsLogger = require('./utils/Logger'); var _utilsLogger2 = _interopRequireDefault(_utilsLogger); var _helpersSafeExecute = require('./helpers/safeExecute'); var _helpersSafeExecute2 = _interopRequireDefault(_helpersSafeExecute); var _helpersSanitize = require('./helpers/sanitize'); var _helpersSanitize2 = _interopRequireDefault(_helpersSanitize); var _helpersIsMobile = require('./helpers/isMobile'); var _helpersIsMobile2 = _interopRequireDefault(_helpersIsMobile); var _helpersDetectSeleniumBackend = require('./helpers/detectSeleniumBackend'); var _helpersDetectSeleniumBackend2 = _interopRequireDefault(_helpersDetectSeleniumBackend); var INTERNAL_EVENTS = ['init', 'command', 'error', 'result', 'end']; var PROMISE_FUNCTIONS = ['then', 'catch', 'finally']; var EventEmitter = _events2['default'].EventEmitter; /** * WebdriverIO v4 */ var WebdriverIO = function WebdriverIO(args, modifier) { var prototype = _Object$create(Object.prototype); var eventHandler = new EventEmitter(); var fulFilledPromise = (0, _q2['default'])(); var stacktrace = []; var commandList = []; var EVENTHANDLER_FUNCIONS = Object.getPrototypeOf(eventHandler); /** * merge default options with given user options */ var options = (0, _deepmerge2['default'])({ protocol: 'http', waitforTimeout: 500, coloredLogs: true, logLevel: 'silent', baseUrl: null }, typeof args !== 'string' ? args : {}); /** * define Selenium backend given on user options */ options = (0, _deepmerge2['default'])((0, _helpersDetectSeleniumBackend2['default'])(args), options); /** * only set globals we wouldn't get otherwise */ if (!process.env.WEBDRIVERIO_COLORED_LOGS) { process.env.WEBDRIVERIO_COLORED_LOGS = options.coloredLogs; } var logger = new _utilsLogger2['default'](options, eventHandler); var requestHandler = new _utilsRequestHandler2['default'](options, eventHandler, logger); /** * assign instance to existing session */ if (typeof args === 'string') { requestHandler.sessionID = args; } var desiredCapabilities = (0, _deepmerge2['default'])({ browserName: 'firefox', version: '', javascriptEnabled: true, locationContextEnabled: true, handlesAlerts: true, rotatable: true, platform: 'ANY' }, options.desiredCapabilities || {}); /** * set default logging prefs to enable log commands (mainly for chromedriver) */ if (typeof desiredCapabilities.loggingPrefs === 'undefined') { desiredCapabilities.loggingPrefs = { browser: 'ALL', driver: 'ALL' }; } var isMobile = (0, _helpersIsMobile2['default'])(desiredCapabilities); var resolve = function resolve(result, isErrorHandled) { if (typeof result === 'function') { this.isExecuted = true; result = result.call(this); } var resolveMethod = result instanceof Error ? 'reject' : 'resolve'; this.defer[resolveMethod](result); /** * By using finally in our next method we omit the duty to throw an exception an some * point. To avoid propagating rejected promises until everything crashes silently we * check if the last and current promise got rejected. If so we can throw the error. */ if (this.promise.isRejected() && !isErrorHandled) { /** * take screenshot only if screenshotPath is given */ if (typeof options.screenshotPath !== 'string') { return throwException(result, stacktrace); } var screenshotPath = _path2['default'].join(process.cwd(), options.screenshotPath); /** * take screenshot only if directory exists */ if (!_fs2['default'].existsSync(screenshotPath)) { return throwException(result, stacktrace); } var client = unit(); client.next(prototype.saveScreenshot, [_path2['default'].join(screenshotPath, 'ERROR_' + _helpersSanitize2['default'].caps(desiredCapabilities) + '_' + new Date().toJSON() + '.png')], 'saveScreenshot'); var stack = stacktrace.slice(); return throwException.bind(null, result, stack); } return this.promise; }; function throwException(e, stack) { stack = stack.slice(0, -1).map(function (trace) { return ' at ' + trace; }); e.stack = e.type + ': ' + e.message + '\n' + stack.reverse().join('\n'); throw e; } /** * WebdriverIO Monad */ function unit(lastPromise) { var client = _Object$create(prototype); var defer = _q2['default'].defer(); var promise = defer.promise; client.defer = defer; client.promise = promise; client.lastPromise = lastPromise || fulFilledPromise; client.desiredCapabilities = desiredCapabilities; client.requestHandler = requestHandler; client.logger = logger; client.options = options; client.isMobile = isMobile; client.commandList = commandList; /** * actual bind function */ client.next = function (func, args, name) { var _this = this; /** * use finally to propagate rejected promises up the chain */ return this.lastPromise.then(function () { /** * store command into command list so `getHistory` can return it */ commandList.push({ name: name, args: args }); return resolve.call(_this, (0, _helpersSafeExecute2['default'])(func, args)); }, function (e) { /** * reject pending commands in chain */ if (e.isPropagatedError) { return _this.defer.reject(e); } _this.emit('error', { message: e.message, type: e.type, stack: stacktrace }); /** * mark error as propagated so that error messages get only printed once */ e.isPropagatedError = true; logger.printException(e.type || 'Error', e.message, stacktrace); _this.defer.reject(e); }); }; client['finally'] = function (fn) { var _this2 = this; var client = unit(this.promise['finally'](function () { return resolve.call(client, (0, _helpersSafeExecute2['default'])(fn, []).bind(_this2)); })); return client; }; client.call = function (fn) { var _this3 = this; var client = unit(this.promise.done(function () { return resolve.call(client, (0, _helpersSafeExecute2['default'])(fn, []).bind(_this3)); })); return client; }; client.then = function (onFulfilled, onRejected) { var _this4 = this; if (typeof onFulfilled !== 'function' && typeof onRejected !== 'function') { return this; } /** * execute then function in context of the new instance * but resolve result with this */ var client = unit(this.promise.then(function () { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return resolve.call(client, (0, _helpersSafeExecute2['default'])(onFulfilled, args).bind(_this4)); }, function () { for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } return resolve.call(client, (0, _helpersSafeExecute2['default'])(onRejected, args).bind(_this4), typeof onRejected === 'function'); })); return client; }; client['catch'] = function (onRejected) { return this.then(undefined, onRejected); }; client.inspect = function () { return this.promise.inspect(); }; /** * internal helper method to handle command results * * @param {Promise[]} promises list of promises * @param {Boolean} option if true extract value property from selenium result */ client.unify = function (promises, option) { option = option || {}; promises = Array.isArray(promises) ? promises : [promises]; return _q2['default'].all(promises) /** * extract value property from result if desired */ .then(function (result) { if (!option.extractValue || !Array.isArray(result)) { return result; } return result.map(function (res) { return res.value && typeof res.value === 'string' ? res.value.trim() : res.value; }); /** * sanitize result for better assertion */ }).then(function (result) { if (Array.isArray(result) && result.length === 1) { result = result[0]; } if (option.lowercase && typeof result === 'string') { result = result.toLowerCase(); } return result; }); }; client.addCommand = function (fnName, fn, forceOverwrite) { if (client[fnName] && !forceOverwrite) { throw new _utilsErrorHandler.RuntimeError('Command "' + fnName + '" is already defined!'); } return unit.lift(fnName, fn); }; client.transferPromiseness = function (target, promise) { /** * transfer WebdriverIO commands */ var clientFunctions = _Object$keys(prototype); var functionsToTranfer = clientFunctions.concat(PROMISE_FUNCTIONS); var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = _getIterator(functionsToTranfer), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var fnName = _step.value; if (typeof promise[fnName] === 'function') { target[fnName] = promise[fnName].bind(promise); } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator['return']) { _iterator['return'](); } } finally { if (_didIteratorError) { throw _iteratorError; } } } }; if (typeof modifier === 'function') { client = modifier(client, options); } return client; } /** * enhance base monad prototype with methods */ unit.lift = function (name, func) { prototype[name] = function () { var nextPromise = this.promise; /** * commands executed inside commands don't have to wait * on any promise */ if (this.isExecuted) { nextPromise = this.lastPromise; } var client = unit(nextPromise); /** * catch stack to find information about where the command that causes * the error was used (stack line 2) and only save it when it was not * within WebdriverIO context */ var stack = new Error().stack; var lineInTest = stack.split('\n').slice(2, 3).join('\n'); var fileAndPosition = lineInTest.slice(lineInTest.indexOf('(') + 1, lineInTest.indexOf(')')); var atCommand = lineInTest.trim().slice(3).split(' ')[0]; atCommand = atCommand.slice(atCommand.lastIndexOf('.') + 1); for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } var trace = name + '(' + _helpersSanitize2['default'].args(args) + ') - ' + fileAndPosition.slice(fileAndPosition.lastIndexOf('/') + 1); if (_Object$keys(prototype).indexOf(atCommand) === -1 && atCommand !== 'exports') { stacktrace = [trace]; } else { /** * save trace for nested commands */ stacktrace.push(trace); } /** * queue command */ client.next(func, args, name); return client; }; return unit; }; /** * register event emitter */ var _loop = function (eventCommand) { prototype[eventCommand] = function () { for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { args[_key4] = arguments[_key4]; } /** * custom commands needs to get emitted and registered in order * to prevent race conditions */ if (INTERNAL_EVENTS.indexOf(args[0]) === -1) { return this['finally'](function () { return eventHandler[eventCommand].apply(eventHandler, args); }); } eventHandler[eventCommand].apply(eventHandler, args); return this; }; }; for (var eventCommand in EVENTHANDLER_FUNCIONS) { _loop(eventCommand); } return unit; }; exports['default'] = WebdriverIO; module.exports = exports['default']; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi93ZWJkcml2ZXJpby5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZLENBQUE7Ozs7Ozs7Ozs7Ozs7O2lCQUVFLEdBQUc7Ozs7a0JBQ0YsSUFBSTs7OztvQkFDRixNQUFNOzs7O3lCQUNMLFdBQVc7Ozs7c0JBQ1YsUUFBUTs7OzttQ0FFQSx3QkFBd0I7Ozs7aUNBQ3RCLHNCQUFzQjs7MkJBQ2hDLGdCQUFnQjs7OztrQ0FFWCx1QkFBdUI7Ozs7K0JBQzFCLG9CQUFvQjs7OzsrQkFDZCxvQkFBb0I7Ozs7NENBQ2IsaUNBQWlDOzs7O0FBRW5FLElBQU0sZUFBZSxHQUFHLENBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFBO0FBQ3JFLElBQU0saUJBQWlCLEdBQUcsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLFNBQVMsQ0FBQyxDQUFBOztBQUV0RCxJQUFJLFlBQVksR0FBRyxvQkFBTyxZQUFZLENBQUE7Ozs7O0FBS3RDLElBQUksV0FBVyxHQUFHLFNBQWQsV0FBVyxDQUFhLElBQUksRUFBRSxRQUFRLEVBQUU7QUFDeEMsUUFBSSxTQUFTLEdBQUcsZUFBYyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUE7QUFDL0MsUUFBSSxZQUFZLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQTtBQUNyQyxRQUFJLGdCQUFnQixHQUFHLHFCQUFHLENBQUE7QUFDMUIsUUFBSSxVQUFVLEdBQUcsRUFBRSxDQUFBO0FBQ25CLFFBQUksV0FBVyxHQUFHLEVBQUUsQ0FBQTs7QUFFcEIsUUFBTSxxQkFBcUIsR0FBRyxNQUFNLENBQUMsY0FBYyxDQUFDLFlBQVksQ0FBQyxDQUFBOzs7OztBQUtqRSxRQUFJLE9BQU8sR0FBRyw0QkFBTTtBQUNoQixnQkFBUSxFQUFFLE1BQU07QUFDaEIsc0JBQWMsRUFBRSxHQUFHO0FBQ25CLG1CQUFXLEVBQUUsSUFBSTtBQUNqQixnQkFBUSxFQUFFLFFBQVE7QUFDbEIs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QyxXQUFXLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7QUFDbkgsZ0JBQUksYUFBWSxTQUFTLENBQUMsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksU0FBUyxLQUFLLFNBQVMsRUFBRTtBQUM3RSwwQkFBVSxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUE7YUFDdkIsTUFBTTs7OztBQUlILDBCQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFBO2FBQ3pCOzs7OztBQUtELGtCQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUE7QUFDN0IsbUJBQU8sTUFBTSxDQUFBO1NBQ2hCLENBQUE7O0FBRUQsZUFBTyxJQUFJLENBQUE7S0FDZCxDQUFBOzs7Ozs7MEJBS1EsWUFBWTtBQUNqQixpQkFBUyxDQUFDLFlBQVksQ0FBQyxHQUFHLFlBQW1COytDQUFOLElBQUk7QUFBSixvQkFBSTs7Ozs7OztBQUt2QyxnQkFBSSxlQUFlLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFO0FBQ3pDLHVCQUFPLElBQUksV0FBUSxDQUFDOzJCQUFNLFlBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQztpQkFBQSxDQUFDLENBQUE7YUFDbEY7O0FBRUQsd0JBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxDQUFBO0FBQ3BELG1CQUFPLElBQUksQ0FBQTtTQUNkLENBQUE7OztBQVpMLFNBQUssSUFBSSxZQUFZLElBQUkscUJBQXFCLEVBQUU7Y0FBdkMsWUFBWTtLQWFwQjs7QUFFRCxXQUFPLElBQUksQ0FBQTtDQUNkLENBQUE7O3FCQUVjLFdBQVciLCJmaWxlIjoid2ViZHJpdmVyaW8uanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCdcblxuaW1wb3J0IHEgZnJvbSAncSdcbmltcG9ydCBmcyBmcm9tICdmcydcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnXG5pbXBvcnQgbWVyZ2UgZnJvbSAnZGVlcG1lcmdlJ1xuaW1wb3J0IGV2ZW50cyBmcm9tICdldmVudHMnXG5cbmltcG9ydCBSZXF1ZXN0SGFuZGxlciBmcm9tICcuL3V0aWxzL1JlcXVlc3RIYW5kbGVyJ1xuaW1wb3J0IHsgUnVudGltZUVycm9yIH0gZnJvbSAnLi91dGlscy9FcnJvckhhbmRsZXInXG5pbXBvcnQgTG9nZ2VyIGZyb20gJy4vdXRpbHMvTG9nZ2VyJ1xuXG5pbXBvcnQgc2FmZUV4ZWN1dGUgZnJvbSAnLi9oZWxwZXJzL3NhZmVFeGVjdXRlJ1xuaW1wb3J0IHNhbml0aXplIGZyb20gJy4vaGVscGVycy9zYW5pdGl6ZSdcbmltcG9ydCBpc01vYmlsZUhlbHBlciBmcm9tICcuL2hlbHBlcnMvaXNNb2JpbGUnXG5pbXBvcnQgZGV0ZWN0U2VsZW5pdW1CYWNrZW5kIGZyb20gJy4vaGVscGVycy9kZXRlY3RTZWxlbml1bUJhY2tlbmQnXG5cbmNvbnN0IElOVEVSTkFMX0VWRU5UUyA9IFsnaW5pdCcsICdjb21tYW5kJywgJ2Vycm9yJywgJ3Jlc3VsdCcsICdlbmQnXVxuY29uc3QgUFJPTUlTRV9GVU5DVElPTlMgPSBbJ3RoZW4nLCAnY2F0Y2gnLCAnZmluYWxseSddXG5cbmxldCBFdmVudEVtaXR0ZXIgPSBldmVudHMuRXZlbnRFbWl0dGVyXG5cbi8qKlxuICogV2ViZHJpdmVySU8gdjRcbiAqL1xubGV0IFdlYmRyaXZlcklPID0gZnVuY3Rpb24gKGFyZ3MsIG1vZGlmaWVyKSB7XG4gICAgbGV0IHByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoT2JqZWN0LnByb3RvdHlwZSlcbiAgICBsZXQgZXZlbnRIYW5kbGVyID0gbmV3IEV2ZW50RW1pdHRlcigpXG4gICAgbGV0IGZ1bEZpbGxlZFByb21pc2UgPSBxKClcbiAgICBsZXQgc3RhY2t0cmFjZSA9IFtdXG4gICAgbGV0IGNvbW1hbmRMaXN0ID0gW11cblxuICAgIGNvbnN0IEVWRU5USEFORExFUl9GVU5DSU9OUyA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihldmVudEhhbmRsZXIpXG5cbiAgICAvKipcbiAgICAgKiBtZXJnZSBkZWZhdWx0IG9wdGlvbnMgd2l0aCBnaXZlbiB1c2VyIG9wdGlvbnNcbiAgICAgKi9cbiAgICBsZXQgb3B0aW9ucyA9IG1lcmdlKHtcbiAgICAgICAgcHJvdG9jb2w6ICdodHRwJyxcbiAgICAgICAgd2FpdGZvclRpbWVvdXQ6IDUwMCxcbiAgICAgICAgY29sb3JlZExvZ3M6IHRydWUsXG4gICAgICAgIGxvZ0xldmVsOiAnc2lsZW50JyxcbiAgICAgICAgYmFzZVVybDogbnVsbFxuICAgIH0sIHR5cGVvZiBhcmdzICE9PSAnc3RyaW5nJyA/IGFyZ3MgOiB7fSlcblxuICAgIC8qKlxuICAgICAqIGRlZmluZSBTZWxlbml1bSBiYWNrZW5kIGdpdmVuIG9uIHVzZXIgb3B0aW9uc1xuICAgICAqL1xuICAgIG9wdGlvbnMgPSBtZXJnZShkZXRlY3RTZWxlbml1bUJhY2tlbmQoYXJncyksIG9wdGlvbnMpXG5cbiAgICAvKipcbiAgICAgKiBvbmx5IHNldCBnbG9iYWxzIHdlIHdvdWxkbid0IGdldCBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBpZiAoIXByb2Nlc3MuZW52LldFQkRSSVZFUklPX0NPTE9SRURfTE9HUykge1xuICAgICAgICBwcm9jZXNzLmVudi5XRUJEUklWRVJJT19DT0xPUkVEX0xPR1MgPSBvcHRpb25zLmNvbG9yZWRMb2dzXG4gICAgfVxuXG4gICAgbGV0IGxvZ2dlciA9IG5ldyBMb2dnZXIob3B0aW9ucywgZXZlbnRIYW5kbGVyKVxuICAgIGxldCByZXF1ZXN0SGFuZGxlciA9IG5ldyBSZXF1ZXN0SGFuZGxlcihvcHRpb25zLCBldmVudEhhbmRsZXIsIGxvZ2dlcilcblxuICAgIC8qKlxuICAgICAqIGFzc2lnbiBpbnN0YW5jZSB0byBleGlzdGluZyBzZXNzaW9uXG4gICAgICovXG4gICAgaWYgKHR5cGVvZiBhcmdzID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXF1ZXN0SGFuZGxlci5zZXNzaW9uSUQgPSBhcmdzXG4gICAgfVxuXG4gICAgbGV0IGRlc2lyZWRDYXBhYmlsaXRpZXMgPSBtZXJnZSh7XG4gICAgICAgIGJyb3dzZXJOYW1lOiAnZmlyZWZveCcsXG4gICAgICAgIHZlcnNpb246ICcnLFxuICAgICAgICBqYXZhc2NyaXB0RW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgbG9jYXRpb25Db250ZXh0RW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgaGFuZGxlc0FsZXJ0czogdHJ1ZSxcbiAgICAgICAgcm90YXRhYmxlOiB0cnVlLFxuICAgICAgICBwbGF0Zm9ybTogJ0FOWSdcbiAgICB9LCBvcHRpb25zLmRlc2lyZWRDYXBhYmlsaXRpZXMgfHwge30pXG5cbiAgICAvKipcbiAgICAgKiBzZXQgZGVmYXVsdCBsb2dnaW5nIHByZWZzIHRvIGVuYWJsZSBsb2cgY29tbWFuZHMgKG1haW5seSBmb3IgY2hyb21lZHJpdmVyKVxuICAgICAqL1xuICAgIGlmICh0eXBlb2YgZGVzaXJlZENhcGFiaWxpdGllcy5sb2dnaW5nUHJlZnMgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGRlc2lyZWRDYXBhYmlsaXRpZXMubG9nZ2luZ1ByZWZzID0ge1xuICAgICAgICAgICAgYnJvd3NlcjogJ0FMTCcsXG4gICAgICAgICAgICBkcml2ZXI6ICdBTEwnXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgaXNNb2JpbGUgPSBpc01vYmlsZUhlbHBlcihkZXNpcmVkQ2FwYWJpbGl0aWVzKVxuXG4gICAgbGV0IHJlc29sdmUgPSBmdW5jdGlvbiAocmVzdWx0LCBpc0Vycm9ySGFuZGxlZCkge1xuICAgICAgICBpZiAodHlwZW9mIHJlc3VsdCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgdGhpcy5pc0V4ZWN1dGVkID0gdHJ1ZVxuICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LmNhbGwodGhpcylcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXNvbHZlTWV0aG9kID0gcmVzdWx0IGluc3RhbmNlb2YgRXJyb3IgPyAncmVqZWN0JyA6ICdyZXNvbHZlJ1xuICAgICAgICB0aGlzLmRlZmVyW3Jlc29sdmVNZXRob2RdKHJlc3VsdClcblxuICAgICAgICAvKipcbiAgICAgICAgICogQnkgdXNpbmcgZmluYWxseSBpbiBvdXIgbmV4dCBtZXRob2Qgd2Ugb21pdCB0aGUgZHV0eSB0byB0aHJvdyBhbiBleGNlcHRpb24gYW4gc29tZVxuICAgICAgICAgKiBwb2ludC4gVG8gYXZvaWQgcHJvcGFnYXRpbmcgcmVqZWN0ZWQgcHJvbWlzZXMgdW50aWwgZXZlcnl0aGluZyBjcmFzaGVzIHNpbGVudGx5IHdlXG4gICAgICAgICAqIGNoZWNrIGlmIHRoZSBsYXN0IGFuZCBjdXJyZW50IHByb21pc2UgZ290IHJlamVjdGVkLiBJZiBzbyB3ZSBjYW4gdGhyb3cgdGhlIGVycm9yLlxuICAgICAgICAgKi9cbiAgICAgICAgaWYgKHRoaXMucHJvbWlzZS5pc1JlamVjdGVkKCkgJiYgIWlzRXJyb3JIYW5kbGVkKSB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIHRha2Ugc2NyZWVuc2hvdCBvbmx5IGlmIHNjcmVlbnNob3RQYXRoIGlzIGdpdmVuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5zY3JlZW5zaG90UGF0aCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhyb3dFeGNlcHRpb24ocmVzdWx0LCBzdGFja3RyYWNlKVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgc2NyZWVuc2hvdFBhdGggPSBwYXRoLmpvaW4ocHJvY2Vzcy5jd2QoKSwgb3B0aW9ucy5zY3JlZW5zaG90UGF0aClcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiB0YWtlIHNjcmVlbnNob3Qgb25seSBpZiBkaXJlY3RvcnkgZXhpc3RzXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGlmICghZnMuZXhpc3RzU3luYyhzY3JlZW5zaG90UGF0aCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhyb3dFeGNlcHRpb24ocmVzdWx0LCBzdGFja3RyYWNlKVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgY2xpZW50ID0gdW5pdCgpXG4gICAgICAgICAgICBjbGllbnQubmV4dChwcm90b3R5cGUuc2F2ZVNjcmVlbnNob3QsIFtcbiAgICAgICAgICAgICAgICBwYXRoLmpvaW4oc2NyZWVuc2hvdFBhdGgsICdFUlJPUl8nICsgc2FuaXRpemUuY2FwcyhkZXNpcmVkQ2FwYWJpbGl0aWVzKSArICdfJyArIG5ldyBEYXRlKCkudG9KU09OKCkgKyAnLnBuZycpXG4gICAgICAgICAgICBdLCAnc2F2ZVNjcmVlbnNob3QnKVxuXG4gICAgICAgICAgICBsZXQgc3RhY2sgPSBzdGFja3RyYWNlLnNsaWNlKClcbiAgICAgICAgICAgIHJldHVybiB0aHJvd0V4Y2VwdGlvbi5iaW5kKG51bGwsIHJlc3VsdCwgc3RhY2spXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5wcm9taXNlXG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdGhyb3dFeGNlcHRpb24gKGUsIHN0YWNrKSB7XG4gICAgICAgIHN0YWNrID0gc3RhY2suc2xpY2UoMCwgLTEpLm1hcCh0cmFjZSA9PiAnICAgIGF0ICcgKyB0cmFjZSlcbiAgICAgICAgZS5zdGFjayA9IGUudHlwZSArICc6ICcgKyBlLm1lc3NhZ2UgKyAnXFxuJyArIHN0YWNrLnJldmVyc2UoKS5qb2luKCdcXG4nKVxuICAgICAgICB0aHJvdyBlXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV2ViZHJpdmVySU8gTW9uYWRcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1bml0IChsYXN0UHJvbWlzZSkge1xuICAgICAgICBsZXQgY2xpZW50ID0gT2JqZWN0LmNyZWF0ZShwcm90b3R5cGUpXG4gICAgICAgIGxldCBkZWZlciA9IHEuZGVmZXIoKVxuICAgICAgICBsZXQgcHJvbWlzZSA9IGRlZmVyLnByb21pc2VcblxuICAgICAgICBjbGllbnQuZGVmZXIgPSBkZWZlclxuICAgICAgICBjbGllbnQucHJvbWlzZSA9IHByb21pc2VcbiAgICAgICAgY2xpZW50Lmxhc3RQcm9taXNlID0gbGFzdFByb21pc2UgfHwgZnVsRmlsbGVkUHJvbWlzZVxuXG4gICAgICAgIGNsaWVudC5kZXNpcmVkQ2FwYWJpbGl0aWVzID0gZGVzaXJlZENhcGFiaWxpdGllc1xuICAgICAgICBjbGllbnQucmVxdWVzdEhhbmRsZXIgPSByZXF1ZXN0SGFuZGxlclxuICAgICAgICBjbGllbnQubG9nZ2VyID0gbG9nZ2VyXG4gICAgICAgIGNsaWVudC5vcHRpb25zID0gb3B0aW9uc1xuICAgICAgICBjbGllbnQuaXNNb2JpbGUgPSBpc01vYmlsZVxuICAgICAgICBjbGllbnQuY29tbWFuZExpc3QgPSBjb21tYW5kTGlzdFxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBhY3R1YWwgYmluZCBmdW5jdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgY2xpZW50Lm5leHQgPSBmdW5jdGlvbiAoZnVuYywgYXJncywgbmFtZSkge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiB1c2UgZmluYWxseSB0byBwcm9wYWdhdGUgcmVqZWN0ZWQgcHJvbWlzZXMgdXAgdGhlIGNoYWluXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxhc3RQcm9taXNlLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAqIHN0b3JlIGNvbW1hbmQgaW50byBjb21tYW5kIGxpc3Qgc28gYGdldEhpc3RvcnlgIGNhbiByZXR1cm4gaXRcbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBjb21tYW5kTGlzdC5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgICAgICAgICAgICAgYXJnczogYXJnc1xuICAgICAgICAgICAgICAgIH0pXG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZS5jYWxsKHRoaXMsIHNhZmVFeGVjdXRlKGZ1bmMsIGFyZ3MpKVxuICAgICAgICAgICAgfSwgKGUpID0+IHtcbiAgICAgICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAgICAgKiByZWplY3QgcGVuZGluZyBjb21tYW5kcyBpbiBjaGFpblxuICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgIGlmIChlLmlzUHJvcGFnYXRlZEVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmRlZmVyLnJlamVjdChlKVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuZW1pdCgnZXJyb3InLCB7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGUubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogZS50eXBlLFxuICAgICAgICAgICAgICAgICAgICBzdGFjazogc3RhY2t0cmFjZVxuICAgICAgICAgICAgICAgIH0pXG5cbiAgICAgICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAgICAgKiBtYXJrIGVycm9yIGFzIHByb3BhZ2F0ZWQgc28gdGhhdCBlcnJvciBtZXNzYWdlcyBnZXQgb25seSBwcmludGVkIG9uY2VcbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBlLmlzUHJvcGFnYXRlZEVycm9yID0gdHJ1ZVxuICAgICAgICAgICAgICAgIGxvZ2dlci5wcmludEV4Y2VwdGlvbihlLnR5cGUgfHwgJ0Vycm9yJywgZS5tZXNzYWdlLCBzdGFja3RyYWNlKVxuICAgICAgICAgICAgICAgIHRoaXMuZGVmZXIucmVqZWN0KGUpXG4gICAgICAgICAgICB9KVxuICAgICAgICB9XG5cbiAgICAgICAgY2xpZW50LmZpbmFsbHkgPSBmdW5jdGlvbiAoZm4pIHtcbiAgICAgICAgICAgIGxldCBjbGllbnQgPSB1bml0KHRoaXMucHJvbWlzZS5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZS5jYWxsKGNsaWVudCwgc2FmZUV4ZWN1dGUoZm4sIFtdKS5iaW5kKHRoaXMpKVxuICAgICAgICAgICAgfSkpXG4gICAgICAgICAgICByZXR1cm4gY2xpZW50XG4gICAgICAgIH1cblxuICAgICAgICBjbGllbnQuY2FsbCA9IGZ1bmN0aW9uIChmbikge1xuICAgICAgICAgICAgbGV0IGNsaWVudCA9IHVuaXQodGhpcy5wcm9taXNlLmRvbmUoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlLmNhbGwoY2xpZW50LCBzYWZlRXhlY3V0ZShmbiwgW10pLmJpbmQodGhpcykpXG4gICAgICAgICAgICB9KSlcbiAgICAgICAgICAgIHJldHVybiBjbGllbnRcbiAgICAgICAgfVxuXG4gICAgICAgIGNsaWVudC50aGVuID0gZnVuY3Rpb24gKG9uRnVsZmlsbGVkLCBvblJlamVjdGVkKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG9uRnVsZmlsbGVkICE9PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBvblJlamVjdGVkICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXNcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBleGVjdXRlIHRoZW4gZnVuY3Rpb24gaW4gY29udGV4dCBvZiB0aGUgbmV3IGluc3RhbmNlXG4gICAgICAgICAgICAgKiBidXQgcmVzb2x2ZSByZXN1bHQgd2l0aCB0aGlzXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGxldCBjbGllbnQgPSB1bml0KHRoaXMucHJvbWlzZS50aGVuKCguLi5hcmdzKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUuY2FsbChjbGllbnQsIHNhZmVFeGVjdXRlKG9uRnVsZmlsbGVkLCBhcmdzKS5iaW5kKHRoaXMpKVxuICAgICAgICAgICAgfSwgKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZS5jYWxsKGNsaWVudCwgc2FmZUV4ZWN1dGUob25SZWplY3RlZCwgYXJncykuYmluZCh0aGlzKSwgdHlwZW9mIG9uUmVqZWN0ZWQgPT09ICdmdW5jdGlvbicpXG4gICAgICAgICAgICB9KSlcblxuICAgICAgICAgICAgcmV0dXJuIGNsaWVudFxuICAgICAgICB9XG5cbiAgICAgICAgY2xpZW50LmNhdGNoID0gZnVuY3Rpb24gKG9uUmVqZWN0ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRoZW4odW5kZWZpbmVkLCBvblJlamVjdGVkKVxuICAgICAgICB9XG5cbiAgICAgICAgY2xpZW50Lmluc3BlY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wcm9taXNlLmluc3BlY3QoKVxuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIGludGVybmFsIGhlbHBlciBtZXRob2QgdG8gaGFuZGxlIGNvbW1hbmQgcmVzdWx0c1xuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gIHtQcm9taXNlW119IHByb21pc2VzICBsaXN0IG9mIHByb21pc2VzXG4gICAgICAgICAqIEBwYXJhbSAge0Jvb2xlYW59ICAgb3B0aW9uICAgIGlmIHRydWUgZXh0cmFjdCB2YWx1ZSBwcm9wZXJ0eSBmcm9tIHNlbGVuaXVtIHJlc3VsdFxuICAgICAgICAgKi9cbiAgICAgICAgY2xpZW50LnVuaWZ5ID0gZnVuY3Rpb24gKHByb21pc2VzLCBvcHRpb24pIHtcbiAgICAgICAgICAgIG9wdGlvbiA9IG9wdGlvbiB8fCB7fVxuICAgICAgICAgICAgcHJvbWlzZXMgPSBBcnJheS5pc0FycmF5KHByb21pc2VzKSA/IHByb21pc2VzIDogW3Byb21pc2VzXVxuXG4gICAgICAgICAgICByZXR1cm4gcS5hbGwocHJvbWlzZXMpXG4gICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICogZXh0cmFjdCB2YWx1ZSBwcm9wZXJ0eSBmcm9tIHJlc3VsdCBpZiBkZXNpcmVkXG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgLnRoZW4oKHJlc3VsdCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIW9wdGlvbi5leHRyYWN0VmFsdWUgfHwgIUFycmF5LmlzQXJyYXkocmVzdWx0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdFxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC5tYXAocmVzID0+XG4gICAgICAgICAgICAgICAgICAgICAgICByZXMudmFsdWUgJiYgdHlwZW9mIHJlcy52YWx1ZSA9PT0gJ3N0cmluZycgPyByZXMudmFsdWUudHJpbSgpIDogcmVzLnZhbHVlKVxuXG4gICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICogc2FuaXRpemUgcmVzdWx0IGZvciBiZXR0ZXIgYXNzZXJ0aW9uXG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgfSkudGhlbigocmVzdWx0KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHJlc3VsdCkgJiYgcmVzdWx0Lmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0WzBdXG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9uLmxvd2VyY2FzZSAmJiB0eXBlb2YgcmVzdWx0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LnRvTG93ZXJDYXNlKClcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHRcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICB9XG5cbiAgICAgICAgY2xpZW50LmFkZENvbW1hbmQgPSBmdW5jdGlvbiAoZm5OYW1lLCBmbiwgZm9yY2VPdmVyd3JpdGUpIHtcbiAgICAgICAgICAgIGlmIChjbGllbnRbZm5OYW1lXSAmJiAhZm9yY2VPdmVyd3JpdGUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUnVudGltZUVycm9yKGBDb21tYW5kIFwiJHtmbk5hbWV9XCIgaXMgYWxyZWFkeSBkZWZpbmVkIWApXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdW5pdC5saWZ0KGZuTmFtZSwgZm4pXG4gICAgICAgIH1cblxuICAgICAgICBjbGllbnQudHJhbnNmZXJQcm9taXNlbmVzcyA9IGZ1bmN0aW9uICh0YXJnZXQsIHByb21pc2UpIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogdHJhbnNmZXIgV2ViZHJpdmVySU8gY29tbWFuZHNcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbGV0IGNsaWVudEZ1bmN0aW9ucyA9IE9iamVjdC5rZXlzKHByb3RvdHlwZSlcbiAgICAgICAgICAgIGxldCBmdW5jdGlvbnNUb1RyYW5mZXIgPSBjbGllbnRGdW5jdGlvbnMuY29uY2F0KFBST01JU0VfRlVOQ1RJT05TKVxuXG4gICAgICAgICAgICBmb3IgKGxldCBmbk5hbWUgb2YgZnVuY3Rpb25zVG9UcmFuZmVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBwcm9taXNlW2ZuTmFtZV0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0W2ZuTmFtZV0gPSBwcm9taXNlW2ZuTmFtZV0uYmluZChwcm9taXNlKVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgbW9kaWZpZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGNsaWVudCA9IG1vZGlmaWVyKGNsaWVudCwgb3B0aW9ucylcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjbGllbnRcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBlbmhhbmNlIGJhc2UgbW9uYWQgcHJvdG90eXBlIHdpdGggbWV0aG9kc1xuICAgICAqL1xuICAgIHVuaXQubGlmdCA9IGZ1bmN0aW9uIChuYW1lLCBmdW5jKSB7XG4gICAgICAgIHByb3RvdHlwZVtuYW1lXSA9IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgICAgICBsZXQgbmV4dFByb21pc2UgPSB0aGlzLnByb21pc2VcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBjb21tYW5kcyBleGVjdXRlZCBpbnNpZGUgY29tbWFuZHMgZG9uJ3QgaGF2ZSB0byB3YWl0XG4gICAgICAgICAgICAgKiBvbiBhbnkgcHJvbWlzZVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBpZiAodGhpcy5pc0V4ZWN1dGVkKSB7XG4gICAgICAgICAgICAgICAgbmV4dFByb21pc2UgPSB0aGlzLmxhc3RQcm9taXNlXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBjbGllbnQgPSB1bml0KG5leHRQcm9taXNlKVxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIGNhdGNoIHN0YWNrIHRvIGZpbmQgaW5mb3JtYXRpb24gYWJvdXQgd2hlcmUgdGhlIGNvbW1hbmQgdGhhdCBjYXVzZXNcbiAgICAgICAgICAgICAqIHRoZSBlcnJvciB3YXMgdXNlZCAoc3RhY2sgbGluZSAyKSBhbmQgb25seSBzYXZlIGl0IHdoZW4gaXQgd2FzIG5vdFxuICAgICAgICAgICAgICogd2l0aGluIFdlYmRyaXZlcklPIGNvbnRleHRcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbGV0IHN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2tcbiAgICAgICAgICAgIGxldCBsaW5lSW5UZXN0ID0gc3RhY2suc3BsaXQoJ1xcbicpLnNsaWNlKDIsIDMpLmpvaW4oJ1xcbicpXG4gICAgICAgICAgICBsZXQgZmlsZUFuZFBvc2l0aW9uID0gbGluZUluVGVzdC5zbGljZShsaW5lSW5UZXN0LmluZGV4T2YoJygnKSArIDEsIGxpbmVJblRlc3QuaW5kZXhPZignKScpKVxuICAgICAgICAgICAgbGV0IGF0Q29tbWFuZCA9IGxpbmVJblRlc3QudHJpbSgpLnNsaWNlKDMpLnNwbGl0KCcgJylbMF1cblxuICAgICAgICAgICAgYXRDb21tYW5kID0gYXRDb21tYW5kLnNsaWNlKGF0Q29tbWFuZC5sYXN0SW5kZXhPZignLicpICsgMSlcblxuICAgICAgICAgICAgbGV0IHRyYWNlID0gbmFtZSArICcoJyArIHNhbml0aXplLmFyZ3MoYXJncykgKyAnKSAtICcgKyBmaWxlQW5kUG9zaXRpb24uc2xpY2UoZmlsZUFuZFBvc2l0aW9uLmxhc3RJbmRleE9mKCcvJykgKyAxKVxuICAgICAgICAgICAgaWYgKE9iamVjdC5rZXlzKHByb3RvdHlwZSkuaW5kZXhPZihhdENvbW1hbmQpID09PSAtMSAmJiBhdENvbW1hbmQgIT09ICdleHBvcnRzJykge1xuICAgICAgICAgICAgICAgIHN0YWNrdHJhY2UgPSBbdHJhY2VdXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAqIHNhdmUgdHJhY2UgZm9yIG5lc3RlZCBjb21tYW5kc1xuICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgIHN0YWNrdHJhY2UucHVzaCh0cmFjZSlcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBxdWV1ZSBjb21tYW5kXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGNsaWVudC5uZXh0KGZ1bmMsIGFyZ3MsIG5hbWUpXG4gICAgICAgICAgICByZXR1cm4gY2xpZW50XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdW5pdFxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIHJlZ2lzdGVyIGV2ZW50IGVtaXR0ZXJcbiAgICAgKi9cbiAgICBmb3IgKGxldCBldmVudENvbW1hbmQgaW4gRVZFTlRIQU5ETEVSX0ZVTkNJT05TKSB7XG4gICAgICAgIHByb3RvdHlwZVtldmVudENvbW1hbmRdID0gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogY3VzdG9tIGNvbW1hbmRzIG5lZWRzIHRvIGdldCBlbWl0dGVkIGFuZCByZWdpc3RlcmVkIGluIG9yZGVyXG4gICAgICAgICAgICAgKiB0byBwcmV2ZW50IHJhY2UgY29uZGl0aW9uc1xuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBpZiAoSU5URVJOQUxfRVZFTlRTLmluZGV4T2YoYXJnc1swXSkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmluYWxseSgoKSA9PiBldmVudEhhbmRsZXJbZXZlbnRDb21tYW5kXS5hcHBseShldmVudEhhbmRsZXIsIGFyZ3MpKVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBldmVudEhhbmRsZXJbZXZlbnRDb21tYW5kXS5hcHBseShldmVudEhhbmRsZXIsIGFyZ3MpXG4gICAgICAgICAgICByZXR1cm4gdGhpc1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHVuaXRcbn1cblxuZXhwb3J0IGRlZmF1bHQgV2ViZHJpdmVySU9cbiJdfQ==