@testim/testim-cli
Version:
Command line interface for running Testing on you CI
473 lines (374 loc) • 44 kB
JavaScript
;
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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi93ZWJkcml2ZXJpby5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZLENBQUE7Ozs7Ozs7Ozs7Ozs7O2lCQUVFLEdBQUc7Ozs7a0JBQ0YsSUFBSTs7OztvQkFDRixNQUFNOzs7O3lCQUNMLFdBQVc7Ozs7c0JBQ1YsUUFBUTs7OzttQ0FFQSx3QkFBd0I7Ozs7aUNBQ3RCLHNCQUFzQjs7MkJBQ2hDLGdCQUFnQjs7OztrQ0FFWCx1QkFBdUI7Ozs7K0JBQzFCLG9CQUFvQjs7OzsrQkFDZCxvQkFBb0I7Ozs7NENBQ2IsaUNBQWlDOzs7O0FBRW5FLElBQU0sZUFBZSxHQUFHLENBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFBO0FBQ3JFLElBQU0saUJBQWlCLEdBQUcsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLFNBQVMsQ0FBQyxDQUFBOztBQUV0RCxJQUFJLFlBQVksR0FBRyxvQkFBTyxZQUFZLENBQUE7Ozs7O0FBS3RDLElBQUksV0FBVyxHQUFHLFNBQWQsV0FBVyxDQUFhLElBQUksRUFBRSxRQUFRLEVBQUU7QUFDeEMsUUFBSSxTQUFTLEdBQUcsZUFBYyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUE7QUFDL0MsUUFBSSxZQUFZLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQTtBQUNyQyxRQUFJLGdCQUFnQixHQUFHLHFCQUFHLENBQUE7QUFDMUIsUUFBSSxVQUFVLEdBQUcsRUFBRSxDQUFBO0FBQ25CLFFBQUksV0FBVyxHQUFHLEVBQUUsQ0FBQTs7QUFFcEIsUUFBTSxxQkFBcUIsR0FBRyxNQUFNLENBQUMsY0FBYyxDQUFDLFlBQVksQ0FBQyxDQUFBOzs7OztBQUtqRSxRQUFJLE9BQU8sR0FBRyw0QkFBTTtBQUNoQixnQkFBUSxFQUFFLE1BQU07QUFDaEIsc0JBQWMsRUFBRSxHQUFHO0FBQ25CLG1CQUFXLEVBQUUsSUFBSTtBQUNqQixnQkFBUSxFQUFFLFFBQVE7QUFDbEIsZUFBTyxFQUFFLElBQUk7S0FDaEIsRUFBRSxPQUFPLElBQUksS0FBSyxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQyxDQUFBOzs7OztBQUt4QyxXQUFPLEdBQUcsNEJBQU0sK0NBQXNCLElBQUksQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFBOzs7OztBQUtyRCxRQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsRUFBRTtBQUN2QyxlQUFPLENBQUMsR0FBRyxDQUFDLHdCQUF3QixHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUE7S0FDN0Q7O0FBRUQsUUFBSSxNQUFNLEdBQUcsNkJBQVcsT0FBTyxFQUFFLFlBQVksQ0FBQyxDQUFBO0FBQzlDLFFBQUksY0FBYyxHQUFHLHFDQUFtQixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sQ0FBQyxDQUFBOzs7OztBQUt0RSxRQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVEsRUFBRTtBQUMxQixzQkFBYyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUE7S0FDbEM7O0FBRUQsUUFBSSxtQkFBbUIsR0FBRyw0QkFBTTtBQUM1QixtQkFBVyxFQUFFLFNBQVM7QUFDdEIsZUFBTyxFQUFFLEVBQUU7QUFDWCx5QkFBaUIsRUFBRSxJQUFJO0FBQ3ZCLDhCQUFzQixFQUFFLElBQUk7QUFDNUIscUJBQWEsRUFBRSxJQUFJO0FBQ25CLGlCQUFTLEVBQUUsSUFBSTtBQUNmLGdCQUFRLEVBQUUsS0FBSztLQUNsQixFQUFFLE9BQU8sQ0FBQyxtQkFBbUIsSUFBSSxFQUFFLENBQUMsQ0FBQTs7Ozs7QUFLckMsUUFBSSxPQUFPLG1CQUFtQixDQUFDLFlBQVksS0FBSyxXQUFXLEVBQUU7QUFDekQsMkJBQW1CLENBQUMsWUFBWSxHQUFHO0FBQy9CLG1CQUFPLEVBQUUsS0FBSztBQUNkLGtCQUFNLEVBQUUsS0FBSztTQUNoQixDQUFBO0tBQ0o7O0FBRUQsUUFBSSxRQUFRLEdBQUcsa0NBQWUsbUJBQW1CLENBQUMsQ0FBQTs7QUFFbEQsUUFBSSxPQUFPLEdBQUcsU0FBVixPQUFPLENBQWEsTUFBTSxFQUFFLGNBQWMsRUFBRTtBQUM1QyxZQUFJLE9BQU8sTUFBTSxLQUFLLFVBQVUsRUFBRTtBQUM5QixnQkFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUE7QUFDdEIsa0JBQU0sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFBO1NBQzdCOztBQUVELFlBQUksYUFBYSxHQUFHLE1BQU0sWUFBWSxLQUFLLEdBQUcsUUFBUSxHQUFHLFNBQVMsQ0FBQTtBQUNsRSxZQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFBOzs7Ozs7O0FBT2pDLFlBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLGNBQWMsRUFBRTs7OztBQUk5QyxnQkFBSSxPQUFPLE9BQU8sQ0FBQyxjQUFjLEtBQUssUUFBUSxFQUFFO0FBQzVDLHVCQUFPLGNBQWMsQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLENBQUE7YUFDNUM7O0FBRUQsZ0JBQUksY0FBYyxHQUFHLGtCQUFLLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQUUsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFBOzs7OztBQUtyRSxnQkFBSSxDQUFDLGdCQUFHLFVBQVUsQ0FBQyxjQUFjLENBQUMsRUFBRTtBQUNoQyx1QkFBTyxjQUFjLENBQUMsTUFBTSxFQUFFLFVBQVUsQ0FBQyxDQUFBO2FBQzVDOztBQUVELGdCQUFJLE1BQU0sR0FBRyxJQUFJLEVBQUUsQ0FBQTtBQUNuQixrQkFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFLENBQ2xDLGtCQUFLLElBQUksQ0FBQyxjQUFjLEVBQUUsUUFBUSxHQUFHLDZCQUFTLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLEdBQUcsR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxDQUNoSCxFQUFFLGdCQUFnQixDQUFDLENBQUE7O0FBRXBCLGdCQUFJLEtBQUssR0FBRyxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUE7QUFDOUIsbUJBQU8sY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFBO1NBQ2xEOztBQUVELGVBQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQTtLQUN0QixDQUFBOztBQUVELGFBQVMsY0FBYyxDQUFFLENBQUMsRUFBRSxLQUFLLEVBQUU7QUFDL0IsYUFBSyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLFVBQUEsS0FBSzttQkFBSSxTQUFTLEdBQUcsS0FBSztTQUFBLENBQUMsQ0FBQTtBQUMxRCxTQUFDLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxJQUFJLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxPQUFPLEdBQUcsSUFBSSxHQUFHLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUE7QUFDdkUsY0FBTSxDQUFDLENBQUE7S0FDVjs7Ozs7QUFLRCxhQUFTLElBQUksQ0FBRSxXQUFXLEVBQUU7QUFDeEIsWUFBSSxNQUFNLEdBQUcsZUFBYyxTQUFTLENBQUMsQ0FBQTtBQUNyQyxZQUFJLEtBQUssR0FBRyxlQUFFLEtBQUssRUFBRSxDQUFBO0FBQ3JCLFlBQUksT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUE7O0FBRTNCLGNBQU0sQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFBO0FBQ3BCLGNBQU0sQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFBO0FBQ3hCLGNBQU0sQ0FBQyxXQUFXLEdBQUcsV0FBVyxJQUFJLGdCQUFnQixDQUFBOztBQUVwRCxjQUFNLENBQUMsbUJBQW1CLEdBQUcsbUJBQW1CLENBQUE7QUFDaEQsY0FBTSxDQUFDLGNBQWMsR0FBRyxjQUFjLENBQUE7QUFDdEMsY0FBTSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUE7QUFDdEIsY0FBTSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUE7QUFDeEIsY0FBTSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUE7QUFDMUIsY0FBTSxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUE7Ozs7O0FBS2hDLGNBQU0sQ0FBQyxJQUFJLEdBQUcsVUFBVSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRTs7Ozs7O0FBSXRDLG1CQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFlBQU07Ozs7QUFJL0IsMkJBQVcsQ0FBQyxJQUFJLENBQUM7QUFDYix3QkFBSSxFQUFFLElBQUk7QUFDVix3QkFBSSxFQUFFLElBQUk7aUJBQ2IsQ0FBQyxDQUFBOztBQUVGLHVCQUFPLE9BQU8sQ0FBQyxJQUFJLFFBQU8scUNBQVksSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUE7YUFDckQsRUFBRSxVQUFDLENBQUMsRUFBSzs7OztBQUlOLG9CQUFJLENBQUMsQ0FBQyxpQkFBaUIsRUFBRTtBQUNyQiwyQkFBTyxNQUFLLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUE7aUJBQzlCOztBQUVELHNCQUFLLElBQUksQ0FBQyxPQUFPLEVBQUU7QUFDZiwyQkFBTyxFQUFFLENBQUMsQ0FBQyxPQUFPO0FBQ2xCLHdCQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUk7QUFDWix5QkFBSyxFQUFFLFVBQVU7aUJBQ3BCLENBQUMsQ0FBQTs7Ozs7QUFLRixpQkFBQyxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQTtBQUMxQixzQkFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLE9BQU8sRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFBO0FBQy9ELHNCQUFLLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUE7YUFDdkIsQ0FBQyxDQUFBO1NBQ0wsQ0FBQTs7QUFFRCxjQUFNLFdBQVEsR0FBRyxVQUFVLEVBQUUsRUFBRTs7O0FBQzNCLGdCQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sV0FBUSxDQUFDLFlBQU07QUFDekMsdUJBQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUscUNBQVksRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksUUFBTSxDQUFDLENBQUE7YUFDOUQsQ0FBQyxDQUFDLENBQUE7QUFDSCxtQkFBTyxNQUFNLENBQUE7U0FDaEIsQ0FBQTs7QUFFRCxjQUFNLENBQUMsSUFBSSxHQUFHLFVBQVUsRUFBRSxFQUFFOzs7QUFDeEIsZ0JBQUksTUFBTSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxZQUFNO0FBQ3RDLHVCQUFPLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLHFDQUFZLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLFFBQU0sQ0FBQyxDQUFBO2FBQzlELENBQUMsQ0FBQyxDQUFBO0FBQ0gsbUJBQU8sTUFBTSxDQUFBO1NBQ2hCLENBQUE7O0FBRUQsY0FBTSxDQUFDLElBQUksR0FBRyxVQUFVLFdBQVcsRUFBRSxVQUFVLEVBQUU7OztBQUM3QyxnQkFBSSxPQUFPLFdBQVcsS0FBSyxVQUFVLElBQUksT0FBTyxVQUFVLEtBQUssVUFBVSxFQUFFO0FBQ3ZFLHVCQUFPLElBQUksQ0FBQTthQUNkOzs7Ozs7QUFNRCxnQkFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFlBQWE7a0RBQVQsSUFBSTtBQUFKLHdCQUFJOzs7QUFDeEMsdUJBQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUscUNBQVksV0FBVyxFQUFFLElBQUksQ0FBQyxDQUFDLElBQUksUUFBTSxDQUFDLENBQUE7YUFDekUsRUFBRSxZQUFhO21EQUFULElBQUk7QUFBSix3QkFBSTs7O0FBQ1AsdUJBQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUscUNBQVksVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDLElBQUksUUFBTSxFQUFFLE9BQU8sVUFBVSxLQUFLLFVBQVUsQ0FBQyxDQUFBO2FBQzFHLENBQUMsQ0FBQyxDQUFBOztBQUVILG1CQUFPLE1BQU0sQ0FBQTtTQUNoQixDQUFBOztBQUVELGNBQU0sU0FBTSxHQUFHLFVBQVUsVUFBVSxFQUFFO0FBQ2pDLG1CQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFVBQVUsQ0FBQyxDQUFBO1NBQzFDLENBQUE7O0FBRUQsY0FBTSxDQUFDLE9BQU8sR0FBRyxZQUFZO0FBQ3pCLG1CQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUE7U0FDaEMsQ0FBQTs7Ozs7Ozs7QUFRRCxjQUFNLENBQUMsS0FBSyxHQUFHLFVBQVUsUUFBUSxFQUFFLE1BQU0sRUFBRTtBQUN2QyxrQkFBTSxHQUFHLE1BQU0sSUFBSSxFQUFFLENBQUE7QUFDckIsb0JBQVEsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHLFFBQVEsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFBOztBQUUxRCxtQkFBTyxlQUFFLEdBQUcsQ0FBQyxRQUFRLENBQUM7Ozs7YUFJakIsSUFBSSxDQUFDLFVBQUMsTUFBTSxFQUFLO0FBQ2Qsb0JBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRTtBQUNoRCwyQkFBTyxNQUFNLENBQUE7aUJBQ2hCOztBQUVELHVCQUFPLE1BQU0sQ0FBQyxHQUFHLENBQUMsVUFBQSxHQUFHOzJCQUNqQixHQUFHLENBQUMsS0FBSyxJQUFJLE9BQU8sR0FBRyxDQUFDLEtBQUssS0FBSyxRQUFRLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsR0FBRyxHQUFHLENBQUMsS0FBSztpQkFBQSxDQUFDLENBQUE7Ozs7O2FBS2pGLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBQyxNQUFNLEVBQUs7QUFDaEIsb0JBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtBQUM5QywwQkFBTSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQTtpQkFDckI7O0FBRUQsb0JBQUksTUFBTSxDQUFDLFNBQVMsSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRLEVBQUU7QUFDaEQsMEJBQU0sR0FBRyxNQUFNLENBQUMsV0FBVyxFQUFFLENBQUE7aUJBQ2hDOztBQUVELHVCQUFPLE1BQU0sQ0FBQTthQUNoQixDQUFDLENBQUE7U0FDVCxDQUFBOztBQUVELGNBQU0sQ0FBQyxVQUFVLEdBQUcsVUFBVSxNQUFNLEVBQUUsRUFBRSxFQUFFLGNBQWMsRUFBRTtBQUN0RCxnQkFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUU7QUFDbkMsc0JBQU0sa0RBQTZCLE1BQU0sMkJBQXdCLENBQUE7YUFDcEU7QUFDRCxtQkFBTyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQTtTQUMvQixDQUFBOztBQUVELGNBQU0sQ0FBQyxtQkFBbUIsR0FBRyxVQUFVLE1BQU0sRUFBRSxPQUFPLEVBQUU7Ozs7QUFJcEQsZ0JBQUksZUFBZSxHQUFHLGFBQVksU0FBUyxDQUFDLENBQUE7QUFDNUMsZ0JBQUksa0JBQWtCLEdBQUcsZUFBZSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFBOzs7Ozs7O0FBRWxFLGtEQUFtQixrQkFBa0IsNEdBQUU7d0JBQTlCLE1BQU07O0FBQ1gsd0JBQUksT0FBTyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssVUFBVSxFQUFFO0FBQ3ZDLDhCQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQTtxQkFDakQ7aUJBQ0o7Ozs7Ozs7Ozs7Ozs7OztTQUNKLENBQUE7O0FBRUQsWUFBSSxPQUFPLFFBQVEsS0FBSyxVQUFVLEVBQUU7QUFDaEMsa0JBQU0sR0FBRyxRQUFRLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFBO1NBQ3JDOztBQUVELGVBQU8sTUFBTSxDQUFBO0tBQ2hCOzs7OztBQUtELFFBQUksQ0FBQyxJQUFJLEdBQUcsVUFBVSxJQUFJLEVBQUUsSUFBSSxFQUFFO0FBQzlCLGlCQUFTLENBQUMsSUFBSSxDQUFDLEdBQUcsWUFBbUI7QUFDakMsZ0JBQUksV0FBVyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUE7Ozs7OztBQU05QixnQkFBSSxJQUFJLENBQUMsVUFBVSxFQUFFO0FBQ2pCLDJCQUFXLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQTthQUNqQzs7QUFFRCxnQkFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFBOzs7Ozs7O0FBTzlCLGdCQUFJLEtBQUssR0FBRyxJQUFJLEtBQUssRUFBRSxDQUFDLEtBQUssQ0FBQTtBQUM3QixnQkFBSSxVQUFVLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtBQUN6RCxnQkFBSSxlQUFlLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxVQUFVLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7QUFDNUYsZ0JBQUksU0FBUyxHQUFHLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBOztBQUV4RCxxQkFBUyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQTs7K0NBdkJoQyxJQUFJO0FBQUosb0JBQUk7OztBQXlCL0IsZ0JBQUksS0FBSyxHQUFHLElBQUksR0FBRyxHQUFHLEdBQUcsNkJBQVMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLE1BQU0sR0FBRyxlQUFlLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7QUFDbkgsZ0JBQUksYUFBWSxTQUFTLENBQUMsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksU0FBUyxLQUFLLFNBQVMsRUFBRTtBQUM3RSwwQkFBVSxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUE7YUFDdkIsTUFBTTs7OztBQUlILDBCQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFBO2FBQ3pCOzs7OztBQUtELGtCQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUE7QUFDN0IsbUJBQU8sTUFBTSxDQUFBO1NBQ2hCLENBQUE7O0FBRUQsZUFBTyxJQUFJLENBQUE7S0FDZCxDQUFBOzs7Ozs7MEJBS1EsWUFBWTtBQUNqQixpQkFBUyxDQUFDLFlBQVksQ0FBQyxHQUFHLFlBQW1COytDQUFOLElBQUk7QUFBSixvQkFBSTs7Ozs7OztBQUt2QyxnQkFBSSxlQUFlLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFO0FBQ3pDLHVCQUFPLElBQUksV0FBUSxDQUFDOzJCQUFNLFlBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQztpQkFBQSxDQUFDLENBQUE7YUFDbEY7O0FBRUQsd0JBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxDQUFBO0FBQ3BELG1CQUFPLElBQUksQ0FBQTtTQUNkLENBQUE7OztBQVpMLFNBQUssSUFBSSxZQUFZLElBQUkscUJBQXFCLEVBQUU7Y0FBdkMsWUFBWTtLQWFwQjs7QUFFRCxXQUFPLElBQUksQ0FBQTtDQUNkLENBQUE7O3FCQUVjLFdBQVciLCJmaWxlIjoid2ViZHJpdmVyaW8uanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCdcblxuaW1wb3J0IHEgZnJvbSAncSdcbmltcG9ydCBmcyBmcm9tICdmcydcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnXG5pbXBvcnQgbWVyZ2UgZnJvbSAnZGVlcG1lcmdlJ1xuaW1wb3J0IGV2ZW50cyBmcm9tICdldmVudHMnXG5cbmltcG9ydCBSZXF1ZXN0SGFuZGxlciBmcm9tICcuL3V0aWxzL1JlcXVlc3RIYW5kbGVyJ1xuaW1wb3J0IHsgUnVudGltZUVycm9yIH0gZnJvbSAnLi91dGlscy9FcnJvckhhbmRsZXInXG5pbXBvcnQgTG9nZ2VyIGZyb20gJy4vdXRpbHMvTG9nZ2VyJ1xuXG5pbXBvcnQgc2FmZUV4ZWN1dGUgZnJvbSAnLi9oZWxwZXJzL3NhZmVFeGVjdXRlJ1xuaW1wb3J0IHNhbml0aXplIGZyb20gJy4vaGVscGVycy9zYW5pdGl6ZSdcbmltcG9ydCBpc01vYmlsZUhlbHBlciBmcm9tICcuL2hlbHBlcnMvaXNNb2JpbGUnXG5pbXBvcnQgZGV0ZWN0U2VsZW5pdW1CYWNrZW5kIGZyb20gJy4vaGVscGVycy9kZXRlY3RTZWxlbml1bUJhY2tlbmQnXG5cbmNvbnN0IElOVEVSTkFMX0VWRU5UUyA9IFsnaW5pdCcsICdjb21tYW5kJywgJ2Vycm9yJywgJ3Jlc3VsdCcsICdlbmQnXVxuY29uc3QgUFJPTUlTRV9GVU5DVElPTlMgPSBbJ3RoZW4nLCAnY2F0Y2gnLCAnZmluYWxseSddXG5cbmxldCBFdmVudEVtaXR0ZXIgPSBldmVudHMuRXZlbnRFbWl0dGVyXG5cbi8qKlxuICogV2ViZHJpdmVySU8gdjRcbiAqL1xubGV0IFdlYmRyaXZlcklPID0gZnVuY3Rpb24gKGFyZ3MsIG1vZGlmaWVyKSB7XG4gICAgbGV0IHByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoT2JqZWN0LnByb3RvdHlwZSlcbiAgICBsZXQgZXZlbnRIYW5kbGVyID0gbmV3IEV2ZW50RW1pdHRlcigpXG4gICAgbGV0IGZ1bEZpbGxlZFByb21pc2UgPSBxKClcbiAgICBsZXQgc3RhY2t0cmFjZSA9IFtdXG4gICAgbGV0IGNvbW1hbmRMaXN0ID0gW11cblxuICAgIGNvbnN0IEVWRU5USEFORExFUl9GVU5DSU9OUyA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihldmVudEhhbmRsZXIpXG5cbiAgICAvKipcbiAgICAgKiBtZXJnZSBkZWZhdWx0IG9wdGlvbnMgd2l0aCBnaXZlbiB1c2VyIG9wdGlvbnNcbiAgICAgKi9cbiAgICBsZXQgb3B0aW9ucyA9IG1lcmdlKHtcbiAgICAgICAgcHJvdG9jb2w6ICdodHRwJyxcbiAgICAgICAgd2FpdGZvclRpbWVvdXQ6IDUwMCxcbiAgICAgICAgY29sb3JlZExvZ3M6IHRydWUsXG4gICAgICAgIGxvZ0xldmVsOiAnc2lsZW50JyxcbiAgICAgICAgYmFzZVVybDogbnVsbFxuICAgIH0sIHR5cGVvZiBhcmdzICE9PSAnc3RyaW5nJyA/IGFyZ3MgOiB7fSlcblxuICAgIC8qKlxuICAgICAqIGRlZmluZSBTZWxlbml1bSBiYWNrZW5kIGdpdmVuIG9uIHVzZXIgb3B0aW9uc1xuICAgICAqL1xuICAgIG9wdGlvbnMgPSBtZXJnZShkZXRlY3RTZWxlbml1bUJhY2tlbmQoYXJncyksIG9wdGlvbnMpXG5cbiAgICAvKipcbiAgICAgKiBvbmx5IHNldCBnbG9iYWxzIHdlIHdvdWxkbid0IGdldCBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBpZiAoIXByb2Nlc3MuZW52LldFQkRSSVZFUklPX0NPTE9SRURfTE9HUykge1xuICAgICAgICBwcm9jZXNzLmVudi5XRUJEUklWRVJJT19DT0xPUkVEX0xPR1MgPSBvcHRpb25zLmNvbG9yZWRMb2dzXG4gICAgfVxuXG4gICAgbGV0IGxvZ2dlciA9IG5ldyBMb2dnZXIob3B0aW9ucywgZXZlbnRIYW5kbGVyKVxuICAgIGxldCByZXF1ZXN0SGFuZGxlciA9IG5ldyBSZXF1ZXN0SGFuZGxlcihvcHRpb25zLCBldmVudEhhbmRsZXIsIGxvZ2dlcilcblxuICAgIC8qKlxuICAgICAqIGFzc2lnbiBpbnN0YW5jZSB0byBleGlzdGluZyBzZXNzaW9uXG4gICAgICovXG4gICAgaWYgKHR5cGVvZiBhcmdzID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXF1ZXN0SGFuZGxlci5zZXNzaW9uSUQgPSBhcmdzXG4gICAgfVxuXG4gICAgbGV0IGRlc2lyZWRDYXBhYmlsaXRpZXMgPSBtZXJnZSh7XG4gICAgICAgIGJyb3dzZXJOYW1lOiAnZmlyZWZveCcsXG4gICAgICAgIHZlcnNpb246ICcnLFxuICAgICAgICBqYXZhc2NyaXB0RW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgbG9jYXRpb25Db250ZXh0RW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgaGFuZGxlc0FsZXJ0czogdHJ1ZSxcbiAgICAgICAgcm90YXRhYmxlOiB0cnVlLFxuICAgICAgICBwbGF0Zm9ybTogJ0FOWSdcbiAgICB9LCBvcHRpb25zLmRlc2lyZWRDYXBhYmlsaXRpZXMgfHwge30pXG5cbiAgICAvKipcbiAgICAgKiBzZXQgZGVmYXVsdCBsb2dnaW5nIHByZWZzIHRvIGVuYWJsZSBsb2cgY29tbWFuZHMgKG1haW5seSBmb3IgY2hyb21lZHJpdmVyKVxuICAgICAqL1xuICAgIGlmICh0eXBlb2YgZGVzaXJlZENhcGFiaWxpdGllcy5sb2dnaW5nUHJlZnMgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGRlc2lyZWRDYXBhYmlsaXRpZXMubG9nZ2luZ1ByZWZzID0ge1xuICAgICAgICAgICAgYnJvd3NlcjogJ0FMTCcsXG4gICAgICAgICAgICBkcml2ZXI6ICdBTEwnXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgaXNNb2JpbGUgPSBpc01vYmlsZUhlbHBlcihkZXNpcmVkQ2FwYWJpbGl0aWVzKVxuXG4gICAgbGV0IHJlc29sdmUgPSBmdW5jdGlvbiAocmVzdWx0LCBpc0Vycm9ySGFuZGxlZCkge1xuICAgICAgICBpZiAodHlwZW9mIHJlc3VsdCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgdGhpcy5pc0V4ZWN1dGVkID0gdHJ1ZVxuICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LmNhbGwodGhpcylcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXNvbHZlTWV0aG9kID0gcmVzdWx0IGluc3RhbmNlb2YgRXJyb3IgPyAncmVqZWN0JyA6ICdyZXNvbHZlJ1xuICAgICAgICB0aGlzLmRlZmVyW3Jlc29sdmVNZXRob2RdKHJlc3VsdClcblxuICAgICAgICAvKipcbiAgICAgICAgICogQnkgdXNpbmcgZmluYWxseSBpbiBvdXIgbmV4dCBtZXRob2Qgd2Ugb21pdCB0aGUgZHV0eSB0byB0aHJvdyBhbiBleGNlcHRpb24gYW4gc29tZVxuICAgICAgICAgKiBwb2ludC4gVG8gYXZvaWQgcHJvcGFnYXRpbmcgcmVqZWN0ZWQgcHJvbWlzZXMgdW50aWwgZXZlcnl0aGluZyBjcmFzaGVzIHNpbGVudGx5IHdlXG4gICAgICAgICAqIGNoZWNrIGlmIHRoZSBsYXN0IGFuZCBjdXJyZW50IHByb21pc2UgZ290IHJlamVjdGVkLiBJZiBzbyB3ZSBjYW4gdGhyb3cgdGhlIGVycm9yLlxuICAgICAgICAgKi9cbiAgICAgICAgaWYgKHRoaXMucHJvbWlzZS5pc1JlamVjdGVkKCkgJiYgIWlzRXJyb3JIYW5kbGVkKSB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIHRha2Ugc2NyZWVuc2hvdCBvbmx5IGlmIHNjcmVlbnNob3RQYXRoIGlzIGdpdmVuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5zY3JlZW5zaG90UGF0aCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhyb3dFeGNlcHRpb24ocmVzdWx0LCBzdGFja3RyYWNlKVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgc2NyZWVuc2hvdFBhdGggPSBwYXRoLmpvaW4ocHJvY2Vzcy5jd2QoKSwgb3B0aW9ucy5zY3JlZW5zaG90UGF0aClcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiB0YWtlIHNjcmVlbnNob3Qgb25seSBpZiBkaXJlY3RvcnkgZXhpc3RzXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGlmICghZnMuZXhpc3RzU3luYyhzY3JlZW5zaG90UGF0aCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhyb3dFeGNlcHRpb24ocmVzdWx0LCBzdGFja3RyYWNlKVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgY2xpZW50ID0gdW5pdCgpXG4gICAgICAgICAgICBjbGllbnQubmV4dChwcm90b3R5cGUuc2F2ZVNjcmVlbnNob3QsIFtcbiAgICAgICAgICAgICAgICBwYXRoLmpvaW4oc2NyZWVuc2hvdFBhdGgsICdFUlJPUl8nICsgc2FuaXRpemUuY2FwcyhkZXNpcmVkQ2FwYWJpbGl0aWVzKSArICdfJyArIG5ldyBEYXRlKCkudG9KU09OKCkgKyAnLnBuZycpXG4gICAgICAgICAgICBdLCAnc2F2ZVNjcmVlbnNob3QnKVxuXG4gICAgICAgICAgICBsZXQgc3RhY2sgPSBzdGFja3RyYWNlLnNsaWNlKClcbiAgICAgICAgICAgIHJldHVybiB0aHJvd0V4Y2VwdGlvbi5iaW5kKG51bGwsIHJlc3VsdCwgc3RhY2spXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5wcm9taXNlXG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdGhyb3dFeGNlcHRpb24gKGUsIHN0YWNrKSB7XG4gICAgICAgIHN0YWNrID0gc3RhY2suc2xpY2UoMCwgLTEpLm1hcCh0cmFjZSA9PiAnICAgIGF0ICcgKyB0cmFjZSlcbiAgICAgICAgZS5zdGFjayA9IGUudHlwZSArICc6ICcgKyBlLm1lc3NhZ2UgKyAnXFxuJyArIHN0YWNrLnJldmVyc2UoKS5qb2luKCdcXG4nKVxuICAgICAgICB0aHJvdyBlXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV2ViZHJpdmVySU8gTW9uYWRcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1bml0IChsYXN0UHJvbWlzZSkge1xuICAgICAgICBsZXQgY2xpZW50ID0gT2JqZWN0LmNyZWF0ZShwcm90b3R5cGUpXG4gICAgICAgIGxldCBkZWZlciA9IHEuZGVmZXIoKVxuICAgICAgICBsZXQgcHJvbWlzZSA9IGRlZmVyLnByb21pc2VcblxuICAgICAgICBjbGllbnQuZGVmZXIgPSBkZWZlclxuICAgICAgICBjbGllbnQucHJvbWlzZSA9IHByb21pc2VcbiAgICAgICAgY2xpZW50Lmxhc3RQcm9taXNlID0gbGFzdFByb21pc2UgfHwgZnVsRmlsbGVkUHJvbWlzZVxuXG4gICAgICAgIGNsaWVudC5kZXNpcmVkQ2FwYWJpbGl0aWVzID0gZGVzaXJlZENhcGFiaWxpdGllc1xuICAgICAgICBjbGllbnQucmVxdWVzdEhhbmRsZXIgPSByZXF1ZXN0SGFuZGxlclxuICAgICAgICBjbGllbnQubG9nZ2VyID0gbG9nZ2VyXG4gICAgICAgIGNsaWVudC5vcHRpb25zID0gb3B0aW9uc1xuICAgICAgICBjbGllbnQuaXNNb2JpbGUgPSBpc01vYmlsZVxuICAgICAgICBjbGllbnQuY29tbWFuZExpc3QgPSBjb21tYW5kTGlzdFxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBhY3R1YWwgYmluZCBmdW5jdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgY2xpZW50Lm5leHQgPSBmdW5jdGlvbiAoZnVuYywgYXJncywgbmFtZSkge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiB1c2UgZmluYWxseSB0byBwcm9wYWdhdGUgcmVqZWN0ZWQgcHJvbWlzZXMgdXAgdGhlIGNoYWluXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxhc3RQcm9taXNlLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAqIHN0b3JlIGNvbW1hbmQgaW50byBjb21tYW5kIGxpc3Qgc28gYGdldEhpc3RvcnlgIGNhbiByZXR1cm4gaXRcbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBjb21tYW5kTGlzdC5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgICAgICAgICAgICAgYXJnczogYXJnc1xuICAgICAgICAgICAgICAgIH0pXG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZS5jYWxsKHRoaXMsIHNhZmVFeGVjdXRlKGZ1bmMsIGFyZ3MpKVxuICAgICAgICAgICAgfSwgKGUpID0+IHtcbiAgICAgICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAgICAgKiByZWplY3QgcGVuZGluZyBjb21tYW5kcyBpbiBjaGFpblxuICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgIGlmIChlLmlzUHJvcGFnYXRlZEVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmRlZmVyLnJlamVjdChlKVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuZW1pdCgnZXJyb3InLCB7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGUubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogZS50eXBlLFxuICAgICAgICAgICAgICAgICAgICBzdGFjazogc3RhY2t0cmFjZVxuICAgICAgICAgICAgICAgIH0pXG5cbiAgICAgICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAgICAgKiBtYXJrIGVycm9yIGFzIHByb3BhZ2F0ZWQgc28gdGhhdCBlcnJvciBtZXNzYWdlcyBnZXQgb25seSBwcmludGVkIG9uY2VcbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBlLmlzUHJvcGFnYXRlZEVycm9yID0gdHJ1ZVxuICAgICAgICAgICAgICAgIGxvZ2dlci5wcmludEV4Y2VwdGlvbihlLnR5cGUgfHwgJ0Vycm9yJywgZS5tZXNzYWdlLCBzdGFja3RyYWNlKVxuICAgICAgICAgICAgICAgIHRoaXMuZGVmZXIucmVqZWN0KGUpXG4gICAgICAgICAgICB9KVxuICAgICAgICB9XG5cbiAgICAgICAgY2xpZW50LmZpbmFsbHkgPSBmdW5jdGlvbiAoZm4pIHtcbiAgICAgICAgICAgIGxldCBjbGllbnQgPSB1bml0KHRoaXMucHJvbWlzZS5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZS5jYWxsKGNsaWVudCwgc2FmZUV4ZWN1dGUoZm4sIFtdKS5iaW5kKHRoaXMpKVxuICAgICAgICAgICAgfSkpXG4gICAgICAgICAgICByZXR1cm4gY2xpZW50XG4gICAgICAgIH1cblxuICAgICAgICBjbGllbnQuY2FsbCA9IGZ1bmN0aW9uIChmbikge1xuICAgICAgICAgICAgbGV0IGNsaWVudCA9IHVuaXQodGhpcy5wcm9taXNlLmRvbmUoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlLmNhbGwoY2xpZW50LCBzYWZlRXhlY3V0ZShmbiwgW10pLmJpbmQodGhpcykpXG4gICAgICAgICAgICB9KSlcbiAgICAgICAgICAgIHJldHVybiBjbGllbnRcbiAgICAgICAgfVxuXG4gICAgICAgIGNsaWVudC50aGVuID0gZnVuY3Rpb24gKG9uRnVsZmlsbGVkLCBvblJlamVjdGVkKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG9uRnVsZmlsbGVkICE9PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBvblJlamVjdGVkICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXNcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBleGVjdXRlIHRoZW4gZnVuY3Rpb24gaW4gY29udGV4dCBvZiB0aGUgbmV3IGluc3RhbmNlXG4gICAgICAgICAgICAgKiBidXQgcmVzb2x2ZSByZXN1bHQgd2l0aCB0aGlzXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGxldCBjbGllbnQgPSB1bml0KHRoaXMucHJvbWlzZS50aGVuKCguLi5hcmdzKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUuY2FsbChjbGllbnQsIHNhZmVFeGVjdXRlKG9uRnVsZmlsbGVkLCBhcmdzKS5iaW5kKHRoaXMpKVxuICAgICAgICAgICAgfSwgKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZS5jYWxsKGNsaWVudCwgc2FmZUV4ZWN1dGUob25SZWplY3RlZCwgYXJncykuYmluZCh0aGlzKSwgdHlwZW9mIG9uUmVqZWN0ZWQgPT09ICdmdW5jdGlvbicpXG4gICAgICAgICAgICB9KSlcblxuICAgICAgICAgICAgcmV0dXJuIGNsaWVudFxuICAgICAgICB9XG5cbiAgICAgICAgY2xpZW50LmNhdGNoID0gZnVuY3Rpb24gKG9uUmVqZWN0ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRoZW4odW5kZWZpbmVkLCBvblJlamVjdGVkKVxuICAgICAgICB9XG5cbiAgICAgICAgY2xpZW50Lmluc3BlY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wcm9taXNlLmluc3BlY3QoKVxuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIGludGVybmFsIGhlbHBlciBtZXRob2QgdG8gaGFuZGxlIGNvbW1hbmQgcmVzdWx0c1xuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gIHtQcm9taXNlW119IHByb21pc2VzICBsaXN0IG9mIHByb21pc2VzXG4gICAgICAgICAqIEBwYXJhbSAge0Jvb2xlYW59ICAgb3B0aW9uICAgIGlmIHRydWUgZXh0cmFjdCB2YWx1ZSBwcm9wZXJ0eSBmcm9tIHNlbGVuaXVtIHJlc3VsdFxuICAgICAgICAgKi9cbiAgICAgICAgY2xpZW50LnVuaWZ5ID0gZnVuY3Rpb24gKHByb21pc2VzLCBvcHRpb24pIHtcbiAgICAgICAgICAgIG9wdGlvbiA9IG9wdGlvbiB8fCB7fVxuICAgICAgICAgICAgcHJvbWlzZXMgPSBBcnJheS5pc0FycmF5KHByb21pc2VzKSA/IHByb21pc2VzIDogW3Byb21pc2VzXVxuXG4gICAgICAgICAgICByZXR1cm4gcS5hbGwocHJvbWlzZXMpXG4gICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICogZXh0cmFjdCB2YWx1ZSBwcm9wZXJ0eSBmcm9tIHJlc3VsdCBpZiBkZXNpcmVkXG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgLnRoZW4oKHJlc3VsdCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIW9wdGlvbi5leHRyYWN0VmFsdWUgfHwgIUFycmF5LmlzQXJyYXkocmVzdWx0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdFxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC5tYXAocmVzID0+XG4gICAgICAgICAgICAgICAgICAgICAgICByZXMudmFsdWUgJiYgdHlwZW9mIHJlcy52YWx1ZSA9PT0gJ3N0cmluZycgPyByZXMudmFsdWUudHJpbSgpIDogcmVzLnZhbHVlKVxuXG4gICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICogc2FuaXRpemUgcmVzdWx0IGZvciBiZXR0ZXIgYXNzZXJ0aW9uXG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgfSkudGhlbigocmVzdWx0KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHJlc3VsdCkgJiYgcmVzdWx0Lmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0WzBdXG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9uLmxvd2VyY2FzZSAmJiB0eXBlb2YgcmVzdWx0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LnRvTG93ZXJDYXNlKClcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHRcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICB9XG5cbiAgICAgICAgY2xpZW50LmFkZENvbW1hbmQgPSBmdW5jdGlvbiAoZm5OYW1lLCBmbiwgZm9yY2VPdmVyd3JpdGUpIHtcbiAgICAgICAgICAgIGlmIChjbGllbnRbZm5OYW1lXSAmJiAhZm9yY2VPdmVyd3JpdGUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUnVudGltZUVycm9yKGBDb21tYW5kIFwiJHtmbk5hbWV9XCIgaXMgYWxyZWFkeSBkZWZpbmVkIWApXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdW5pdC5saWZ0KGZuTmFtZSwgZm4pXG4gICAgICAgIH1cblxuICAgICAgICBjbGllbnQudHJhbnNmZXJQcm9taXNlbmVzcyA9IGZ1bmN0aW9uICh0YXJnZXQsIHByb21pc2UpIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogdHJhbnNmZXIgV2ViZHJpdmVySU8gY29tbWFuZHNcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbGV0IGNsaWVudEZ1bmN0aW9ucyA9IE9iamVjdC5rZXlzKHByb3RvdHlwZSlcbiAgICAgICAgICAgIGxldCBmdW5jdGlvbnNUb1RyYW5mZXIgPSBjbGllbnRGdW5jdGlvbnMuY29uY2F0KFBST01JU0VfRlVOQ1RJT05TKVxuXG4gICAgICAgICAgICBmb3IgKGxldCBmbk5hbWUgb2YgZnVuY3Rpb25zVG9UcmFuZmVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBwcm9taXNlW2ZuTmFtZV0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0W2ZuTmFtZV0gPSBwcm9taXNlW2ZuTmFtZV0uYmluZChwcm9taXNlKVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgbW9kaWZpZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGNsaWVudCA9IG1vZGlmaWVyKGNsaWVudCwgb3B0aW9ucylcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjbGllbnRcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBlbmhhbmNlIGJhc2UgbW9uYWQgcHJvdG90eXBlIHdpdGggbWV0aG9kc1xuICAgICAqL1xuICAgIHVuaXQubGlmdCA9IGZ1bmN0aW9uIChuYW1lLCBmdW5jKSB7XG4gICAgICAgIHByb3RvdHlwZVtuYW1lXSA9IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgICAgICBsZXQgbmV4dFByb21pc2UgPSB0aGlzLnByb21pc2VcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBjb21tYW5kcyBleGVjdXRlZCBpbnNpZGUgY29tbWFuZHMgZG9uJ3QgaGF2ZSB0byB3YWl0XG4gICAgICAgICAgICAgKiBvbiBhbnkgcHJvbWlzZVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBpZiAodGhpcy5pc0V4ZWN1dGVkKSB7XG4gICAgICAgICAgICAgICAgbmV4dFByb21pc2UgPSB0aGlzLmxhc3RQcm9taXNlXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBjbGllbnQgPSB1bml0KG5leHRQcm9taXNlKVxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIGNhdGNoIHN0YWNrIHRvIGZpbmQgaW5mb3JtYXRpb24gYWJvdXQgd2hlcmUgdGhlIGNvbW1hbmQgdGhhdCBjYXVzZXNcbiAgICAgICAgICAgICAqIHRoZSBlcnJvciB3YXMgdXNlZCAoc3RhY2sgbGluZSAyKSBhbmQgb25seSBzYXZlIGl0IHdoZW4gaXQgd2FzIG5vdFxuICAgICAgICAgICAgICogd2l0aGluIFdlYmRyaXZlcklPIGNvbnRleHRcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbGV0IHN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2tcbiAgICAgICAgICAgIGxldCBsaW5lSW5UZXN0ID0gc3RhY2suc3BsaXQoJ1xcbicpLnNsaWNlKDIsIDMpLmpvaW4oJ1xcbicpXG4gICAgICAgICAgICBsZXQgZmlsZUFuZFBvc2l0aW9uID0gbGluZUluVGVzdC5zbGljZShsaW5lSW5UZXN0LmluZGV4T2YoJygnKSArIDEsIGxpbmVJblRlc3QuaW5kZXhPZignKScpKVxuICAgICAgICAgICAgbGV0IGF0Q29tbWFuZCA9IGxpbmVJblRlc3QudHJpbSgpLnNsaWNlKDMpLnNwbGl0KCcgJylbMF1cblxuICAgICAgICAgICAgYXRDb21tYW5kID0gYXRDb21tYW5kLnNsaWNlKGF0Q29tbWFuZC5sYXN0SW5kZXhPZignLicpICsgMSlcblxuICAgICAgICAgICAgbGV0IHRyYWNlID0gbmFtZSArICcoJyArIHNhbml0aXplLmFyZ3MoYXJncykgKyAnKSAtICcgKyBmaWxlQW5kUG9zaXRpb24uc2xpY2UoZmlsZUFuZFBvc2l0aW9uLmxhc3RJbmRleE9mKCcvJykgKyAxKVxuICAgICAgICAgICAgaWYgKE9iamVjdC5rZXlzKHByb3RvdHlwZSkuaW5kZXhPZihhdENvbW1hbmQpID09PSAtMSAmJiBhdENvbW1hbmQgIT09ICdleHBvcnRzJykge1xuICAgICAgICAgICAgICAgIHN0YWNrdHJhY2UgPSBbdHJhY2VdXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAqIHNhdmUgdHJhY2UgZm9yIG5lc3RlZCBjb21tYW5kc1xuICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgIHN0YWNrdHJhY2UucHVzaCh0cmFjZSlcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBxdWV1ZSBjb21tYW5kXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGNsaWVudC5uZXh0KGZ1bmMsIGFyZ3MsIG5hbWUpXG4gICAgICAgICAgICByZXR1cm4gY2xpZW50XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdW5pdFxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIHJlZ2lzdGVyIGV2ZW50IGVtaXR0ZXJcbiAgICAgKi9cbiAgICBmb3IgKGxldCBldmVudENvbW1hbmQgaW4gRVZFTlRIQU5ETEVSX0ZVTkNJT05TKSB7XG4gICAgICAgIHByb3RvdHlwZVtldmVudENvbW1hbmRdID0gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogY3VzdG9tIGNvbW1hbmRzIG5lZWRzIHRvIGdldCBlbWl0dGVkIGFuZCByZWdpc3RlcmVkIGluIG9yZGVyXG4gICAgICAgICAgICAgKiB0byBwcmV2ZW50IHJhY2UgY29uZGl0aW9uc1xuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBpZiAoSU5URVJOQUxfRVZFTlRTLmluZGV4T2YoYXJnc1swXSkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmluYWxseSgoKSA9PiBldmVudEhhbmRsZXJbZXZlbnRDb21tYW5kXS5hcHBseShldmVudEhhbmRsZXIsIGFyZ3MpKVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBldmVudEhhbmRsZXJbZXZlbnRDb21tYW5kXS5hcHBseShldmVudEhhbmRsZXIsIGFyZ3MpXG4gICAgICAgICAgICByZXR1cm4gdGhpc1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHVuaXRcbn1cblxuZXhwb3J0IGRlZmF1bHQgV2ViZHJpdmVySU9cbiJdfQ==