Innovenergy_trunk/frontend/node_modules/testcafe/lib/browser/connection/index.js

420 lines
66 KiB
JavaScript

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const debug_1 = __importDefault(require("debug"));
const time_limit_promise_1 = __importDefault(require("time-limit-promise"));
const events_1 = require("events");
const mustache_1 = __importDefault(require("mustache"));
const lodash_1 = require("lodash");
const parse_user_agent_1 = require("../../utils/parse-user-agent");
const read_file_relative_1 = require("read-file-relative");
const promisify_event_1 = __importDefault(require("promisify-event"));
const nanoid_1 = require("nanoid");
const command_1 = __importDefault(require("./command"));
const status_1 = __importDefault(require("./status"));
const heartbeat_status_1 = __importDefault(require("./heartbeat-status"));
const runtime_1 = require("../../errors/runtime");
const types_1 = require("../../errors/types");
const warning_log_1 = __importDefault(require("../../notifications/warning-log"));
const service_routes_1 = __importDefault(require("./service-routes"));
const browser_connection_timeouts_1 = require("../../utils/browser-connection-timeouts");
const tracker_1 = __importDefault(require("./tracker"));
const getBrowserConnectionDebugScope = (id) => `testcafe:browser:connection:${id}`;
const IDLE_PAGE_TEMPLATE = (0, read_file_relative_1.readSync)('../../client/browser/idle-page/index.html.mustache');
class BrowserConnection extends events_1.EventEmitter {
constructor(gateway, browserInfo, permanent, disableMultipleWindows = false, proxyless = false, messageBus) {
super();
this._currentTestRun = null;
this.url = '';
this.idleUrl = '';
this.forcedIdleUrl = '';
this.initScriptUrl = '';
this.heartbeatUrl = '';
this.statusUrl = '';
this.activeWindowIdUrl = '';
this.closeWindowUrl = '';
this.statusDoneUrl = '';
this.heartbeatRelativeUrl = '';
this.statusRelativeUrl = '';
this.statusDoneRelativeUrl = '';
this.idleRelativeUrl = '';
this.openFileProtocolRelativeUrl = '';
this.openFileProtocolUrl = '';
this.dispatchProxylessEventRelativeUrl = '';
this.osInfo = null;
this.HEARTBEAT_TIMEOUT = browser_connection_timeouts_1.HEARTBEAT_TIMEOUT;
this.BROWSER_CLOSE_TIMEOUT = browser_connection_timeouts_1.BROWSER_CLOSE_TIMEOUT;
this.BROWSER_RESTART_TIMEOUT = browser_connection_timeouts_1.BROWSER_RESTART_TIMEOUT;
this.id = BrowserConnection._generateId();
this.jobQueue = [];
this.initScriptsQueue = [];
this.browserConnectionGateway = gateway;
this.disconnectionPromise = null;
this.testRunAborted = false;
this.warningLog = new warning_log_1.default(null, warning_log_1.default.createAddWarningCallback(messageBus));
this.debugLogger = (0, debug_1.default)(getBrowserConnectionDebugScope(this.id));
if (messageBus)
this.messageBus = messageBus;
this.browserInfo = browserInfo;
this.browserInfo.userAgentProviderMetaInfo = '';
this.provider = browserInfo.provider;
this.permanent = permanent;
this.status = status_1.default.uninitialized;
this.idle = true;
this.heartbeatTimeout = null;
this.pendingTestRunInfo = null;
this.disableMultipleWindows = disableMultipleWindows;
this.proxyless = proxyless;
this._buildCommunicationUrls(gateway.proxy);
this._setEventHandlers();
tracker_1.default.add(this);
this.previousActiveWindowId = null;
this.browserConnectionGateway.startServingConnection(this);
// NOTE: Give a caller time to assign event listeners
process.nextTick(() => this._runBrowser());
}
_buildCommunicationUrls(proxy) {
this.url = proxy.resolveRelativeServiceUrl(`${service_routes_1.default.connect}/${this.id}`);
this.forcedIdleUrl = proxy.resolveRelativeServiceUrl(`${service_routes_1.default.idleForced}/${this.id}`);
this.initScriptUrl = proxy.resolveRelativeServiceUrl(`${service_routes_1.default.initScript}/${this.id}`);
this.heartbeatRelativeUrl = `${service_routes_1.default.heartbeat}/${this.id}`;
this.statusRelativeUrl = `${service_routes_1.default.status}/${this.id}`;
this.statusDoneRelativeUrl = `${service_routes_1.default.statusDone}/${this.id}`;
this.idleRelativeUrl = `${service_routes_1.default.idle}/${this.id}`;
this.activeWindowIdUrl = `${service_routes_1.default.activeWindowId}/${this.id}`;
this.closeWindowUrl = `${service_routes_1.default.closeWindow}/${this.id}`;
this.openFileProtocolRelativeUrl = `${service_routes_1.default.openFileProtocol}/${this.id}`;
this.dispatchProxylessEventRelativeUrl = `${service_routes_1.default.dispatchProxylessEvent}/${this.id}`;
this.idleUrl = proxy.resolveRelativeServiceUrl(this.idleRelativeUrl);
this.heartbeatUrl = proxy.resolveRelativeServiceUrl(this.heartbeatRelativeUrl);
this.statusUrl = proxy.resolveRelativeServiceUrl(this.statusRelativeUrl);
this.statusDoneUrl = proxy.resolveRelativeServiceUrl(this.statusDoneRelativeUrl);
this.openFileProtocolUrl = proxy.resolveRelativeServiceUrl(this.openFileProtocolRelativeUrl);
}
set messageBus(messageBus) {
this._messageBus = messageBus;
this.warningLog.callback = warning_log_1.default.createAddWarningCallback(this._messageBus);
if (messageBus) {
messageBus.on('test-run-start', testRun => {
if (testRun.browserConnection.id === this.id)
this._currentTestRun = testRun;
});
}
this.emit('message-bus-initialized', messageBus);
}
get messageBus() {
return this._messageBus;
}
_setEventHandlers() {
this.on('error', e => {
this.debugLogger(e);
this._forceIdle();
this.close();
});
for (const name in status_1.default) {
const status = status_1.default[name];
this.on(status, () => {
this.debugLogger(`status changed to '${status}'`);
});
}
}
static _generateId() {
return (0, nanoid_1.nanoid)(7);
}
_getAdditionalBrowserOptions() {
const options = {
disableMultipleWindows: this.disableMultipleWindows,
};
if (this.proxyless) {
options.proxyless = {
serviceDomains: [
this.browserConnectionGateway.proxy.server1Info.domain,
this.browserConnectionGateway.proxy.server2Info.domain,
],
developmentMode: this.browserConnectionGateway.proxy.options.developmentMode,
};
}
return options;
}
async _runBrowser() {
try {
const additionalOptions = this._getAdditionalBrowserOptions();
await this.provider.openBrowser(this.id, this.url, this.browserInfo.browserOption, additionalOptions);
if (this.status !== status_1.default.ready)
await (0, promisify_event_1.default)(this, 'ready');
this.status = status_1.default.opened;
this.emit('opened');
}
catch (err) {
this.emit('error', new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.unableToOpenBrowser, this.browserInfo.providerName + ':' + this.browserInfo.browserName, err.stack));
}
}
async _closeBrowser(data = {}) {
if (!this.idle)
await (0, promisify_event_1.default)(this, 'idle');
try {
await this.provider.closeBrowser(this.id, data);
}
catch (err) {
// NOTE: A warning would be really nice here, but it can't be done while log is stored in a task.
this.debugLogger(err);
}
}
_forceIdle() {
if (!this.idle) {
this.idle = true;
this.emit('idle');
}
}
_createBrowserDisconnectedError() {
return new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.browserDisconnected, this.userAgent);
}
_waitForHeartbeat() {
this.heartbeatTimeout = setTimeout(() => {
const err = this._createBrowserDisconnectedError();
this.status = status_1.default.disconnected;
this.testRunAborted = true;
this.emit('disconnected', err);
this._restartBrowserOnDisconnect(err);
}, this.HEARTBEAT_TIMEOUT);
}
async _getTestRunInfo(needPopNext) {
if (needPopNext || !this.pendingTestRunInfo)
this.pendingTestRunInfo = await this._popNextTestRunInfo();
return this.pendingTestRunInfo;
}
async _popNextTestRunInfo() {
while (this.hasQueuedJobs && !this.currentJob.hasQueuedTestRuns)
this.jobQueue.shift();
return this.hasQueuedJobs ? await this.currentJob.popNextTestRunInfo(this) : null;
}
getCurrentTestRun() {
return this._currentTestRun;
}
static getById(id) {
return tracker_1.default.activeBrowserConnections[id] || null;
}
async _restartBrowser() {
this.status = status_1.default.uninitialized;
this._forceIdle();
let resolveTimeout = null;
let isTimeoutExpired = false;
let timeout = null;
const restartPromise = (0, time_limit_promise_1.default)(this._closeBrowser({ isRestarting: true }), this.BROWSER_CLOSE_TIMEOUT, { rejectWith: new runtime_1.TimeoutError() })
.catch(err => this.debugLogger(err))
.then(() => this._runBrowser());
const timeoutPromise = new Promise(resolve => {
resolveTimeout = resolve;
timeout = setTimeout(() => {
isTimeoutExpired = true;
resolve();
}, this.BROWSER_RESTART_TIMEOUT);
});
return Promise.race([restartPromise, timeoutPromise])
.then(() => {
clearTimeout(timeout);
if (isTimeoutExpired)
this.emit('error', this._createBrowserDisconnectedError());
else
resolveTimeout();
});
}
_restartBrowserOnDisconnect(err) {
let resolveFn = null;
let rejectFn = null;
this.disconnectionPromise = new Promise((resolve, reject) => {
resolveFn = resolve;
rejectFn = () => {
reject(err);
};
setTimeout(() => {
rejectFn();
});
})
.then(() => {
return this._restartBrowser();
})
.catch(e => {
this.emit('error', e);
});
this.disconnectionPromise.resolve = resolveFn;
this.disconnectionPromise.reject = rejectFn;
}
async getDefaultBrowserInitTimeout() {
const isLocalBrowser = await this.provider.isLocalBrowser(this.id, this.browserInfo.browserName);
return isLocalBrowser ? browser_connection_timeouts_1.LOCAL_BROWSER_INIT_TIMEOUT : browser_connection_timeouts_1.REMOTE_BROWSER_INIT_TIMEOUT;
}
async processDisconnection(disconnectionThresholdExceeded) {
const { resolve, reject } = this.disconnectionPromise;
if (disconnectionThresholdExceeded)
reject();
else
resolve();
}
addWarning(message, ...args) {
if (this.currentJob)
this.currentJob.warningLog.addWarning(message, ...args);
else
this.warningLog.addWarning(message, ...args);
}
_appendToPrettyUserAgent(str) {
this.browserInfo.parsedUserAgent.prettyUserAgent += ` (${str})`;
}
_moveWarningLogToJob(job) {
job.warningLog.copyFrom(this.warningLog);
this.warningLog.clear();
}
setProviderMetaInfo(str, options) {
const appendToUserAgent = options === null || options === void 0 ? void 0 : options.appendToUserAgent;
if (appendToUserAgent) {
// NOTE:
// change prettyUserAgent only when connection already was established
if (this.isReady())
this._appendToPrettyUserAgent(str);
else
this.on('ready', () => this._appendToPrettyUserAgent(str));
return;
}
this.browserInfo.userAgentProviderMetaInfo = str;
}
get userAgent() {
let userAgent = this.browserInfo.parsedUserAgent.prettyUserAgent;
if (this.browserInfo.userAgentProviderMetaInfo)
userAgent += ` (${this.browserInfo.userAgentProviderMetaInfo})`;
return userAgent;
}
get connectionInfo() {
if (!this.osInfo)
return this.userAgent;
const { name, version } = this.browserInfo.parsedUserAgent;
let connectionInfo = (0, parse_user_agent_1.calculatePrettyUserAgent)({ name, version }, this.osInfo);
const metaInfo = this.browserInfo.userAgentProviderMetaInfo || (0, parse_user_agent_1.extractMetaInfo)(this.browserInfo.parsedUserAgent.prettyUserAgent);
if (metaInfo)
connectionInfo += ` (${metaInfo})`;
return connectionInfo;
}
get retryTestPages() {
return this.browserConnectionGateway.retryTestPages;
}
get hasQueuedJobs() {
return !!this.jobQueue.length;
}
get currentJob() {
return this.jobQueue[0];
}
// API
runInitScript(code) {
return new Promise(resolve => this.initScriptsQueue.push({ code, resolve }));
}
addJob(job) {
this.jobQueue.push(job);
this._moveWarningLogToJob(job);
}
removeJob(job) {
(0, lodash_1.pull)(this.jobQueue, job);
}
async close() {
if (this.status === status_1.default.closing || this.status === status_1.default.closed)
return;
this.status = status_1.default.closing;
this.emit(status_1.default.closing);
await this._closeBrowser();
this.browserConnectionGateway.stopServingConnection(this);
if (this.heartbeatTimeout)
clearTimeout(this.heartbeatTimeout);
tracker_1.default.remove(this);
this.status = status_1.default.closed;
this.emit(status_1.default.closed);
}
async establish(userAgent) {
this.status = status_1.default.ready;
this.browserInfo.parsedUserAgent = (0, parse_user_agent_1.parseUserAgent)(userAgent);
this.osInfo = await this.provider.getOSInfo(this.id);
this._waitForHeartbeat();
this.emit('ready');
}
heartbeat() {
if (this.heartbeatTimeout)
clearTimeout(this.heartbeatTimeout);
this._waitForHeartbeat();
return {
code: this.status === status_1.default.closing ? heartbeat_status_1.default.closing : heartbeat_status_1.default.ok,
url: this.status === status_1.default.closing ? this.idleUrl : '',
};
}
renderIdlePage() {
return mustache_1.default.render(IDLE_PAGE_TEMPLATE, {
userAgent: this.connectionInfo,
statusUrl: this.statusUrl,
heartbeatUrl: this.heartbeatUrl,
initScriptUrl: this.initScriptUrl,
openFileProtocolUrl: this.openFileProtocolUrl,
retryTestPages: !!this.browserConnectionGateway.retryTestPages,
proxyless: this.proxyless,
});
}
getInitScript() {
const initScriptPromise = this.initScriptsQueue[0];
return { code: initScriptPromise ? initScriptPromise.code : null };
}
handleInitScriptResult(data) {
const initScriptPromise = this.initScriptsQueue.shift();
if (initScriptPromise)
initScriptPromise.resolve(JSON.parse(data));
}
isHeadlessBrowser() {
return this.provider.isHeadlessBrowser(this.id);
}
async reportJobResult(status, data) {
await this.provider.reportJobResult(this.id, status, data);
}
async getStatus(isTestDone) {
if (!this.idle && !isTestDone) {
this.idle = true;
this.emit('idle');
}
if (this.status === status_1.default.opened) {
const nextTestRunInfo = await this._getTestRunInfo(isTestDone || this.testRunAborted);
this.testRunAborted = false;
if (nextTestRunInfo) {
this.idle = false;
return {
cmd: command_1.default.run,
testRunId: nextTestRunInfo.testRunId,
url: nextTestRunInfo.url,
};
}
}
return {
cmd: command_1.default.idle,
url: this.idleUrl,
testRunId: null,
};
}
get activeWindowId() {
return this.provider.getActiveWindowId(this.id);
}
set activeWindowId(val) {
this.previousActiveWindowId = this.activeWindowId;
this.provider.setActiveWindowId(this.id, val);
}
async openFileProtocol(url) {
return this.provider.openFileProtocol(this.id, url);
}
async dispatchProxylessEvent(type, options) {
return this.provider.dispatchProxylessEvent(this.id, type, options);
}
async canUseDefaultWindowActions() {
return this.provider.canUseDefaultWindowActions(this.id);
}
isReady() {
return this.status === status_1.default.ready ||
this.status === status_1.default.opened ||
this.status === status_1.default.closing;
}
}
exports.default = BrowserConnection;
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYnJvd3Nlci9jb25uZWN0aW9uL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsa0RBQTBCO0FBQzFCLDRFQUEyQztBQUMzQyxtQ0FBc0M7QUFDdEMsd0RBQWdDO0FBQ2hDLG1DQUF3QztBQUN4QyxtRUFLc0M7QUFDdEMsMkRBQXNEO0FBQ3RELHNFQUE2QztBQUM3QyxtQ0FBZ0M7QUFDaEMsd0RBQWdDO0FBQ2hDLHNEQUErQztBQUMvQywwRUFBaUQ7QUFDakQsa0RBQWtFO0FBQ2xFLDhDQUFvRDtBQUdwRCxrRkFBeUQ7QUFHekQsc0VBQThDO0FBQzlDLHlGQU1pRDtBQUVqRCx3REFBaUQ7QUFRakQsTUFBTSw4QkFBOEIsR0FBRyxDQUFDLEVBQVUsRUFBVSxFQUFFLENBQUMsK0JBQStCLEVBQUUsRUFBRSxDQUFDO0FBRW5HLE1BQU0sa0JBQWtCLEdBQUcsSUFBQSw2QkFBSSxFQUFDLG9EQUFvRCxDQUFDLENBQUM7QUE2Q3RGLE1BQXFCLGlCQUFrQixTQUFRLHFCQUFZO0lBNkN2RCxZQUNJLE9BQWlDLEVBQ2pDLFdBQXdCLEVBQ3hCLFNBQWtCLEVBQ2xCLHNCQUFzQixHQUFHLEtBQUssRUFDOUIsU0FBUyxHQUFHLEtBQUssRUFDakIsVUFBdUI7UUFDdkIsS0FBSyxFQUFFLENBQUM7UUEzQ0osb0JBQWUsR0FBbUIsSUFBSSxDQUFDO1FBU3hDLFFBQUcsR0FBRyxFQUFFLENBQUM7UUFDVCxZQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ1osa0JBQWEsR0FBRyxFQUFFLENBQUM7UUFDbkIsa0JBQWEsR0FBRyxFQUFFLENBQUM7UUFDcEIsaUJBQVksR0FBRyxFQUFFLENBQUM7UUFDbEIsY0FBUyxHQUFHLEVBQUUsQ0FBQztRQUNmLHNCQUFpQixHQUFHLEVBQUUsQ0FBQztRQUN2QixtQkFBYyxHQUFHLEVBQUUsQ0FBQztRQUNwQixrQkFBYSxHQUFHLEVBQUUs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QUUsT0FBWTtRQUM5RCxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDeEUsQ0FBQztJQUVNLEtBQUssQ0FBQywwQkFBMEI7UUFDbkMsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLDBCQUEwQixDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM3RCxDQUFDO0lBRU0sT0FBTztRQUNWLE9BQU8sSUFBSSxDQUFDLE1BQU0sS0FBSyxnQkFBdUIsQ0FBQyxLQUFLO1lBQ2hELElBQUksQ0FBQyxNQUFNLEtBQUssZ0JBQXVCLENBQUMsTUFBTTtZQUM5QyxJQUFJLENBQUMsTUFBTSxLQUFLLGdCQUF1QixDQUFDLE9BQU8sQ0FBQztJQUN4RCxDQUFDO0NBQ0o7QUEvaEJELG9DQStoQkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZGVidWcgZnJvbSAnZGVidWcnO1xuaW1wb3J0IHRpbWVMaW1pdCBmcm9tICd0aW1lLWxpbWl0LXByb21pc2UnO1xuaW1wb3J0IHsgRXZlbnRFbWl0dGVyIH0gZnJvbSAnZXZlbnRzJztcbmltcG9ydCBNdXN0YWNoZSBmcm9tICdtdXN0YWNoZSc7XG5pbXBvcnQgeyBwdWxsIGFzIHJlbW92ZSB9IGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQge1xuICAgIGNhbGN1bGF0ZVByZXR0eVVzZXJBZ2VudCxcbiAgICBleHRyYWN0TWV0YUluZm8sXG4gICAgUGFyc2VkVXNlckFnZW50LFxuICAgIHBhcnNlVXNlckFnZW50LFxufSBmcm9tICcuLi8uLi91dGlscy9wYXJzZS11c2VyLWFnZW50JztcbmltcG9ydCB7IHJlYWRTeW5jIGFzIHJlYWQgfSBmcm9tICdyZWFkLWZpbGUtcmVsYXRpdmUnO1xuaW1wb3J0IHByb21pc2lmeUV2ZW50IGZyb20gJ3Byb21pc2lmeS1ldmVudCc7XG5pbXBvcnQgeyBuYW5vaWQgfSBmcm9tICduYW5vaWQnO1xuaW1wb3J0IENPTU1BTkQgZnJvbSAnLi9jb21tYW5kJztcbmltcG9ydCBCcm93c2VyQ29ubmVjdGlvblN0YXR1cyBmcm9tICcuL3N0YXR1cyc7XG5pbXBvcnQgSGVhcnRiZWF0U3RhdHVzIGZyb20gJy4vaGVhcnRiZWF0LXN0YXR1cyc7XG5pbXBvcnQgeyBHZW5lcmFsRXJyb3IsIFRpbWVvdXRFcnJvciB9IGZyb20gJy4uLy4uL2Vycm9ycy9ydW50aW1lJztcbmltcG9ydCB7IFJVTlRJTUVfRVJST1JTIH0gZnJvbSAnLi4vLi4vZXJyb3JzL3R5cGVzJztcbmltcG9ydCBCcm93c2VyQ29ubmVjdGlvbkdhdGV3YXkgZnJvbSAnLi9nYXRld2F5JztcbmltcG9ydCBCcm93c2VySm9iIGZyb20gJy4uLy4uL3J1bm5lci9icm93c2VyLWpvYic7XG5pbXBvcnQgV2FybmluZ0xvZyBmcm9tICcuLi8uLi9ub3RpZmljYXRpb25zL3dhcm5pbmctbG9nJztcbmltcG9ydCBCcm93c2VyUHJvdmlkZXIgZnJvbSAnLi4vcHJvdmlkZXInO1xuaW1wb3J0IHsgT1NJbmZvIH0gZnJvbSAnZ2V0LW9zLWluZm8nO1xuaW1wb3J0IFNFUlZJQ0VfUk9VVEVTIGZyb20gJy4vc2VydmljZS1yb3V0ZXMnO1xuaW1wb3J0IHtcbiAgICBCUk9XU0VSX1JFU1RBUlRfVElNRU9VVCxcbiAgICBCUk9XU0VSX0NMT1NFX1RJTUVPVVQsXG4gICAgSEVBUlRCRUFUX1RJTUVPVVQsXG4gICAgTE9DQUxfQlJPV1NFUl9JTklUX1RJTUVPVVQsXG4gICAgUkVNT1RFX0JST1dTRVJfSU5JVF9USU1FT1VULFxufSBmcm9tICcuLi8uLi91dGlscy9icm93c2VyLWNvbm5lY3Rpb24tdGltZW91dHMnO1xuaW1wb3J0IE1lc3NhZ2VCdXMgZnJvbSAnLi4vLi4vdXRpbHMvbWVzc2FnZS1idXMnO1xuaW1wb3J0IEJyb3dzZXJDb25uZWN0aW9uVHJhY2tlciBmcm9tICcuL3RyYWNrZXInO1xuaW1wb3J0IFRlc3RSdW4gZnJvbSAnLi4vLi4vdGVzdC1ydW4nO1xuLy8gQHRzLWlnbm9yZVxuaW1wb3J0IHsgVGVzdFJ1biBhcyBMZWdhY3lUZXN0UnVuIH0gZnJvbSAndGVzdGNhZmUtbGVnYWN5LWFwaSc7XG5pbXBvcnQgeyBQcm94eSB9IGZyb20gJ3Rlc3RjYWZlLWhhbW1lcmhlYWQnO1xuaW1wb3J0IHsgTmV4dFRlc3RSdW5JbmZvLCBPcGVuQnJvd3NlckFkZGl0aW9uYWxPcHRpb25zIH0gZnJvbSAnLi4vLi4vc2hhcmVkL3R5cGVzJztcbmltcG9ydCB7IEV2ZW50VHlwZSB9IGZyb20gJy4uLy4uL3Byb3h5bGVzcy90eXBlcyc7XG5cbmNvbnN0IGdldEJyb3dzZXJDb25uZWN0aW9uRGVidWdTY29wZSA9IChpZDogc3RyaW5nKTogc3RyaW5nID0+IGB0ZXN0Y2FmZTpicm93c2VyOmNvbm5lY3Rpb246JHtpZH1gO1xuXG5jb25zdCBJRExFX1BBR0VfVEVNUExBVEUgPSByZWFkKCcuLi8uLi9jbGllbnQvYnJvd3Nlci9pZGxlLXBhZ2UvaW5kZXguaHRtbC5tdXN0YWNoZScpO1xuXG5cbmludGVyZmFjZSBEaXNjb25uZWN0aW9uUHJvbWlzZTxUPiBleHRlbmRzIFByb21pc2U8VD4ge1xuICAgIHJlc29sdmU6IEZ1bmN0aW9uO1xuICAgIHJlamVjdDogRnVuY3Rpb247XG59XG5cbmludGVyZmFjZSBCcm93c2VyQ29ubmVjdGlvblN0YXR1c1Jlc3VsdCB7XG4gICAgY21kOiBzdHJpbmc7XG4gICAgdXJsOiBzdHJpbmc7XG4gICAgdGVzdFJ1bklkOiBzdHJpbmcgfCBudWxsO1xufVxuXG5pbnRlcmZhY2UgSGVhcnRiZWF0U3RhdHVzUmVzdWx0IHtcbiAgICBjb2RlOiBIZWFydGJlYXRTdGF0dXM7XG4gICAgdXJsOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBJbml0U2NyaXB0IHtcbiAgICBjb2RlOiBzdHJpbmcgfCBudWxsO1xufVxuXG5pbnRlcmZhY2UgSW5pdFNjcmlwdFRhc2sgZXh0ZW5kcyBJbml0U2NyaXB0IHtcbiAgICByZXNvbHZlOiBGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIFByb3ZpZGVyTWV0YUluZm9PcHRpb25zIHtcbiAgICBhcHBlbmRUb1VzZXJBZ2VudD86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQnJvd3NlckNsb3NpbmdJbmZvIHtcbiAgICBpc1Jlc3RhcnRpbmc/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEJyb3dzZXJJbmZvIHtcbiAgICBhbGlhczogc3RyaW5nO1xuICAgIGJyb3dzZXJOYW1lOiBzdHJpbmc7XG4gICAgYnJvd3Nlck9wdGlvbjogdW5rbm93bjtcbiAgICBwcm92aWRlck5hbWU6IHN0cmluZztcbiAgICBwcm92aWRlcjogQnJvd3NlclByb3ZpZGVyO1xuICAgIHVzZXJBZ2VudFByb3ZpZGVyTWV0YUluZm86IHN0cmluZztcbiAgICBwYXJzZWRVc2VyQWdlbnQ6IFBhcnNlZFVzZXJBZ2VudDtcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQnJvd3NlckNvbm5lY3Rpb24gZXh0ZW5kcyBFdmVudEVtaXR0ZXIge1xuICAgIHB1YmxpYyBwZXJtYW5lbnQ6IGJvb2xlYW47XG4gICAgcHVibGljIHByZXZpb3VzQWN0aXZlV2luZG93SWQ6IHN0cmluZyB8IG51bGw7XG4gICAgcHJpdmF0ZSByZWFkb25seSBkaXNhYmxlTXVsdGlwbGVXaW5kb3dzOiBib29sZWFuO1xuICAgIHB1YmxpYyByZWFkb25seSBwcm94eWxlc3M6IGJvb2xlYW47XG4gICAgcHJpdmF0ZSByZWFkb25seSBIRUFSVEJFQVRfVElNRU9VVDogbnVtYmVyO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgQlJPV1NFUl9DTE9TRV9USU1FT1VUOiBudW1iZXI7XG4gICAgcHJpdmF0ZSByZWFkb25seSBCUk9XU0VSX1JFU1RBUlRfVElNRU9VVDogbnVtYmVyO1xuICAgIHB1YmxpYyByZWFkb25seSBpZDogc3RyaW5nO1xuICAgIHByaXZhdGUgX2N1cnJlbnRUZXN0UnVuOiBUZXN0UnVuIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSByZWFkb25seSBqb2JRdWV1ZTogQnJvd3NlckpvYltdO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgaW5pdFNjcmlwdHNRdWV1ZTogSW5pdFNjcmlwdFRhc2tbXTtcbiAgICBwdWJsaWMgYnJvd3NlckNvbm5lY3Rpb25HYXRld2F5OiBCcm93c2VyQ29ubmVjdGlvbkdhdGV3YXk7XG4gICAgcHJpdmF0ZSBkaXNjb25uZWN0aW9uUHJvbWlzZTogRGlzY29ubmVjdGlvblByb21pc2U8dm9pZD4gfCBudWxsO1xuICAgIHByaXZhdGUgdGVzdFJ1bkFib3J0ZWQ6IGJvb2xlYW47XG4gICAgcHVibGljIHN0YXR1czogQnJvd3NlckNvbm5lY3Rpb25TdGF0dXM7XG4gICAgcHJpdmF0ZSBoZWFydGJlYXRUaW1lb3V0OiBOb2RlSlMuVGltZW91dCB8IG51bGw7XG4gICAgcHJpdmF0ZSBwZW5kaW5nVGVzdFJ1bkluZm86IE5leHRUZXN0UnVuSW5mbyB8IG51bGw7XG4gICAgcHVibGljIHVybCA9ICcnO1xuICAgIHB1YmxpYyBpZGxlVXJsID0gJyc7XG4gICAgcHJpdmF0ZSBmb3JjZWRJZGxlVXJsID0gJyc7XG4gICAgcHJpdmF0ZSBpbml0U2NyaXB0VXJsID0gJyc7XG4gICAgcHVibGljIGhlYXJ0YmVhdFVybCA9ICcnO1xuICAgIHB1YmxpYyBzdGF0dXNVcmwgPSAnJztcbiAgICBwdWJsaWMgYWN0aXZlV2luZG93SWRVcmwgPSAnJztcbiAgICBwdWJsaWMgY2xvc2VXaW5kb3dVcmwgPSAnJztcbiAgICBwdWJsaWMgc3RhdHVzRG9uZVVybCA9ICcnO1xuICAgIHB1YmxpYyBoZWFydGJlYXRSZWxhdGl2ZVVybCA9ICcnO1xuICAgIHB1YmxpYyBzdGF0dXNSZWxhdGl2ZVVybCA9ICcnO1xuICAgIHB1YmxpYyBzdGF0dXNEb25lUmVsYXRpdmVVcmwgPSAnJztcbiAgICBwdWJsaWMgaWRsZVJlbGF0aXZlVXJsID0gJyc7XG4gICAgcHVibGljIG9wZW5GaWxlUHJvdG9jb2xSZWxhdGl2ZVVybCA9ICcnO1xuICAgIHB1YmxpYyBvcGVuRmlsZVByb3RvY29sVXJsID0gJyc7XG4gICAgcHVibGljIGRpc3BhdGNoUHJveHlsZXNzRXZlbnRSZWxhdGl2ZVVybCA9ICcnO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgZGVidWdMb2dnZXI6IGRlYnVnLkRlYnVnZ2VyO1xuICAgIHByaXZhdGUgb3NJbmZvOiBPU0luZm8gfCBudWxsID0gbnVsbDtcblxuICAgIHB1YmxpYyByZWFkb25seSB3YXJuaW5nTG9nOiBXYXJuaW5nTG9nO1xuICAgIHByaXZhdGUgX21lc3NhZ2VCdXM/OiBNZXNzYWdlQnVzO1xuXG4gICAgcHVibGljIGlkbGU6IGJvb2xlYW47XG5cbiAgICBwdWJsaWMgYnJvd3NlckluZm86IEJyb3dzZXJJbmZvO1xuICAgIHB1YmxpYyBwcm92aWRlcjogYW55O1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yIChcbiAgICAgICAgZ2F0ZXdheTogQnJvd3NlckNvbm5lY3Rpb25HYXRld2F5LFxuICAgICAgICBicm93c2VySW5mbzogQnJvd3NlckluZm8sXG4gICAgICAgIHBlcm1hbmVudDogYm9vbGVhbixcbiAgICAgICAgZGlzYWJsZU11bHRpcGxlV2luZG93cyA9IGZhbHNlLFxuICAgICAgICBwcm94eWxlc3MgPSBmYWxzZSxcbiAgICAgICAgbWVzc2FnZUJ1cz86IE1lc3NhZ2VCdXMpIHtcbiAgICAgICAgc3VwZXIoKTtcblxuICAgICAgICB0aGlzLkhFQVJUQkVBVF9USU1FT1VUICAgICAgID0gSEVBUlRCRUFUX1RJTUVPVVQ7XG4gICAgICAgIHRoaXMuQlJPV1NFUl9DTE9TRV9USU1FT1VUICAgPSBCUk9XU0VSX0NMT1NFX1RJTUVPVVQ7XG4gICAgICAgIHRoaXMuQlJPV1NFUl9SRVNUQVJUX1RJTUVPVVQgPSBCUk9XU0VSX1JFU1RBUlRfVElNRU9VVDtcblxuICAgICAgICB0aGlzLmlkICAgICAgICAgICAgICAgICAgICAgICA9IEJyb3dzZXJDb25uZWN0aW9uLl9nZW5lcmF0ZUlkKCk7XG4gICAgICAgIHRoaXMuam9iUXVldWUgICAgICAgICAgICAgICAgID0gW107XG4gICAgICAgIHRoaXMuaW5pdFNjcmlwdHNRdWV1ZSAgICAgICAgID0gW107XG4gICAgICAgIHRoaXMuYnJvd3NlckNvbm5lY3Rpb25HYXRld2F5ID0gZ2F0ZXdheTtcbiAgICAgICAgdGhpcy5kaXNjb25uZWN0aW9uUHJvbWlzZSAgICAgPSBudWxsO1xuICAgICAgICB0aGlzLnRlc3RSdW5BYm9ydGVkICAgICAgICAgICA9IGZhbHNlO1xuICAgICAgICB0aGlzLndhcm5pbmdMb2cgICAgICAgICAgICAgICA9IG5ldyBXYXJuaW5nTG9nKG51bGwsIFdhcm5pbmdMb2cuY3JlYXRlQWRkV2FybmluZ0NhbGxiYWNrKG1lc3NhZ2VCdXMpKTtcbiAgICAgICAgdGhpcy5kZWJ1Z0xvZ2dlciAgICAgICAgICAgICAgPSBkZWJ1ZyhnZXRCcm93c2VyQ29ubmVjdGlvbkRlYnVnU2NvcGUodGhpcy5pZCkpO1xuXG4gICAgICAgIGlmIChtZXNzYWdlQnVzKVxuICAgICAgICAgICAgdGhpcy5tZXNzYWdlQnVzID0gbWVzc2FnZUJ1cztcblxuICAgICAgICB0aGlzLmJyb3dzZXJJbmZvICAgICAgICAgICAgICAgICAgICAgICAgICAgPSBicm93c2VySW5mbztcbiAgICAgICAgdGhpcy5icm93c2VySW5mby51c2VyQWdlbnRQcm92aWRlck1ldGFJbmZvID0gJyc7XG5cbiAgICAgICAgdGhpcy5wcm92aWRlciA9IGJyb3dzZXJJbmZvLnByb3ZpZGVyO1xuXG4gICAgICAgIHRoaXMucGVybWFuZW50ICAgICAgICAgICAgICA9IHBlcm1hbmVudDtcbiAgICAgICAgdGhpcy5zdGF0dXMgICAgICAgICAgICAgICAgID0gQnJvd3NlckNvbm5lY3Rpb25TdGF0dXMudW5pbml0aWFsaXplZDtcbiAgICAgICAgdGhpcy5pZGxlICAgICAgICAgICAgICAgICAgID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5oZWFydGJlYXRUaW1lb3V0ICAgICAgID0gbnVsbDtcbiAgICAgICAgdGhpcy5wZW5kaW5nVGVzdFJ1bkluZm8gICAgID0gbnVsbDtcbiAgICAgICAgdGhpcy5kaXNhYmxlTXVsdGlwbGVXaW5kb3dzID0gZGlzYWJsZU11bHRpcGxlV2luZG93cztcbiAgICAgICAgdGhpcy5wcm94eWxlc3MgICAgICAgICAgICAgID0gcHJveHlsZXNzO1xuXG4gICAgICAgIHRoaXMuX2J1aWxkQ29tbXVuaWNhdGlvblVybHMoZ2F0ZXdheS5wcm94eSk7XG4gICAgICAgIHRoaXMuX3NldEV2ZW50SGFuZGxlcnMoKTtcblxuICAgICAgICBCcm93c2VyQ29ubmVjdGlvblRyYWNrZXIuYWRkKHRoaXMpO1xuXG4gICAgICAgIHRoaXMucHJldmlvdXNBY3RpdmVXaW5kb3dJZCA9IG51bGw7XG5cbiAgICAgICAgdGhpcy5icm93c2VyQ29ubmVjdGlvbkdhdGV3YXkuc3RhcnRTZXJ2aW5nQ29ubmVjdGlvbih0aGlzKTtcblxuICAgICAgICAvLyBOT1RFOiBHaXZlIGEgY2FsbGVyIHRpbWUgdG8gYXNzaWduIGV2ZW50IGxpc3RlbmVyc1xuICAgICAgICBwcm9jZXNzLm5leHRUaWNrKCgpID0+IHRoaXMuX3J1bkJyb3dzZXIoKSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfYnVpbGRDb21tdW5pY2F0aW9uVXJscyAocHJveHk6IFByb3h5KTogdm9pZCB7XG4gICAgICAgIHRoaXMudXJsICAgICAgICAgICAgICAgPSBwcm94eS5yZXNvbHZlUmVsYXRpdmVTZXJ2aWNlVXJsKGAke1NFUlZJQ0VfUk9VVEVTLmNvbm5lY3R9LyR7dGhpcy5pZH1gKTtcbiAgICAgICAgdGhpcy5mb3JjZWRJZGxlVXJsICAgICA9IHByb3h5LnJlc29sdmVSZWxhdGl2ZVNlcnZpY2VVcmwoYCR7U0VSVklDRV9ST1VURVMuaWRsZUZvcmNlZH0vJHt0aGlzLmlkfWApO1xuICAgICAgICB0aGlzLmluaXRTY3JpcHRVcmwgICAgID0gcHJveHkucmVzb2x2ZVJlbGF0aXZlU2VydmljZVVybChgJHtTRVJWSUNFX1JPVVRFUy5pbml0U2NyaXB0fS8ke3RoaXMuaWR9YCk7XG5cbiAgICAgICAgdGhpcy5oZWFydGJlYXRSZWxhdGl2ZVVybCAgICAgICAgICAgICAgPSBgJHtTRVJWSUNFX1JPVVRFUy5oZWFydGJlYXR9LyR7dGhpcy5pZH1gO1xuICAgICAgICB0aGlzLnN0YXR1c1JlbGF0aXZlVXJsICAgICAgICAgICAgICAgICA9IGAke1NFUlZJQ0VfUk9VVEVTLnN0YXR1c30vJHt0aGlzLmlkfWA7XG4gICAgICAgIHRoaXMuc3RhdHVzRG9uZVJlbGF0aXZlVXJsICAgICAgICAgICAgID0gYCR7U0VSVklDRV9ST1VURVMuc3RhdHVzRG9uZX0vJHt0aGlzLmlkfWA7XG4gICAgICAgIHRoaXMuaWRsZVJlbGF0aXZlVXJsICAgICAgICAgICAgICAgICAgID0gYCR7U0VSVklDRV9ST1VURVMuaWRsZX0vJHt0aGlzLmlkfWA7XG4gICAgICAgIHRoaXMuYWN0aXZlV2luZG93SWRVcmwgICAgICAgICAgICAgICAgID0gYCR7U0VSVklDRV9ST1VURVMuYWN0aXZlV2luZG93SWR9LyR7dGhpcy5pZH1gO1xuICAgICAgICB0aGlzLmNsb3NlV2luZG93VXJsICAgICAgICAgICAgICAgICAgICA9IGAke1NFUlZJQ0VfUk9VVEVTLmNsb3NlV2luZG93fS8ke3RoaXMuaWR9YDtcbiAgICAgICAgdGhpcy5vcGVuRmlsZVByb3RvY29sUmVsYXRpdmVVcmwgICAgICAgPSBgJHtTRVJWSUNFX1JPVVRFUy5vcGVuRmlsZVByb3RvY29sfS8ke3RoaXMuaWR9YDtcbiAgICAgICAgdGhpcy5kaXNwYXRjaFByb3h5bGVzc0V2ZW50UmVsYXRpdmVVcmwgPSBgJHtTRVJWSUNFX1JPVVRFUy5kaXNwYXRjaFByb3h5bGVzc0V2ZW50fS8ke3RoaXMuaWR9YDtcblxuICAgICAgICB0aGlzLmlkbGVVcmwgICAgICAgICAgICAgPSBwcm94eS5yZXNvbHZlUmVsYXRpdmVTZXJ2aWNlVXJsKHRoaXMuaWRsZVJlbGF0aXZlVXJsKTtcbiAgICAgICAgdGhpcy5oZWFydGJlYXRVcmwgICAgICAgID0gcHJveHkucmVzb2x2ZVJlbGF0aXZlU2VydmljZVVybCh0aGlzLmhlYXJ0YmVhdFJlbGF0aXZlVXJsKTtcbiAgICAgICAgdGhpcy5zdGF0dXNVcmwgICAgICAgICAgID0gcHJveHkucmVzb2x2ZVJlbGF0aXZlU2VydmljZVVybCh0aGlzLnN0YXR1c1JlbGF0aXZlVXJsKTtcbiAgICAgICAgdGhpcy5zdGF0dXNEb25lVXJsICAgICAgID0gcHJveHkucmVzb2x2ZVJlbGF0aXZlU2VydmljZVVybCh0aGlzLnN0YXR1c0RvbmVSZWxhdGl2ZVVybCk7XG4gICAgICAgIHRoaXMub3BlbkZpbGVQcm90b2NvbFVybCA9IHByb3h5LnJlc29sdmVSZWxhdGl2ZVNlcnZpY2VVcmwodGhpcy5vcGVuRmlsZVByb3RvY29sUmVsYXRpdmVVcmwpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXQgbWVzc2FnZUJ1cyAobWVzc2FnZUJ1czogTWVzc2FnZUJ1cyB8IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLl9tZXNzYWdlQnVzICAgICAgICAgPSBtZXNzYWdlQnVzO1xuICAgICAgICB0aGlzLndhcm5pbmdMb2cuY2FsbGJhY2sgPSBXYXJuaW5nTG9nLmNyZWF0ZUFkZFdhcm5pbmdDYWxsYmFjayh0aGlzLl9tZXNzYWdlQnVzKTtcblxuICAgICAgICBpZiAobWVzc2FnZUJ1cykge1xuICAgICAgICAgICAgbWVzc2FnZUJ1cy5vbigndGVzdC1ydW4tc3RhcnQnLCB0ZXN0UnVuID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGVzdFJ1bi5icm93c2VyQ29ubmVjdGlvbi5pZCA9PT0gdGhpcy5pZClcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fY3VycmVudFRlc3RSdW4gPSB0ZXN0UnVuO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmVtaXQoJ21lc3NhZ2UtYnVzLWluaXRpYWxpemVkJywgbWVzc2FnZUJ1cyk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBtZXNzYWdlQnVzICgpOiBNZXNzYWdlQnVzIHwgdW5kZWZpbmVkIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21lc3NhZ2VCdXM7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfc2V0RXZlbnRIYW5kbGVycyAoKTogdm9pZCB7XG4gICAgICAgIHRoaXMub24oJ2Vycm9yJywgZSA9PiB7XG4gICAgICAgICAgICB0aGlzLmRlYnVnTG9nZ2VyKGUpO1xuICAgICAgICAgICAgdGhpcy5fZm9yY2VJZGxlKCk7XG4gICAgICAgICAgICB0aGlzLmNsb3NlKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGZvciAoY29uc3QgbmFtZSBpbiBCcm93c2VyQ29ubmVjdGlvblN0YXR1cykge1xuICAgICAgICAgICAgY29uc3Qgc3RhdHVzID0gQnJvd3NlckNvbm5lY3Rpb25TdGF0dXNbbmFtZSBhcyBrZXlvZiB0eXBlb2YgQnJvd3NlckNvbm5lY3Rpb25TdGF0dXNdO1xuXG4gICAgICAgICAgICB0aGlzLm9uKHN0YXR1cywgKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZGVidWdMb2dnZXIoYHN0YXR1cyBjaGFuZ2VkIHRvICcke3N0YXR1c30nYCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIF9nZW5lcmF0ZUlkICgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gbmFub2lkKDcpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2dldEFkZGl0aW9uYWxCcm93c2VyT3B0aW9ucyAoKTogT3BlbkJyb3dzZXJBZGRpdGlvbmFsT3B0aW9ucyB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgICAgICBkaXNhYmxlTXVsdGlwbGVXaW5kb3dzOiB0aGlzLmRpc2FibGVNdWx0aXBsZVdpbmRvd3MsXG4gICAgICAgIH0gYXMgT3BlbkJyb3dzZXJBZGRpdGlvbmFsT3B0aW9ucztcblxuICAgICAgICBpZiAodGhpcy5wcm94eWxlc3MpIHtcbiAgICAgICAgICAgIG9wdGlvbnMucHJveHlsZXNzID0ge1xuICAgICAgICAgICAgICAgIHNlcnZpY2VEb21haW5zOiBbXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYnJvd3NlckNvbm5lY3Rpb25HYXRld2F5LnByb3h5LnNlcnZlcjFJbmZvLmRvbWFpbixcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5icm93c2VyQ29ubmVjdGlvbkdhdGV3YXkucHJveHkuc2VydmVyMkluZm8uZG9tYWluLFxuICAgICAgICAgICAgICAgIF0sXG5cbiAgICAgICAgICAgICAgICBkZXZlbG9wbWVudE1vZGU6IHRoaXMuYnJvd3NlckNvbm5lY3Rpb25HYXRld2F5LnByb3h5Lm9wdGlvbnMuZGV2ZWxvcG1lbnRNb2RlLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBvcHRpb25zO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX3J1bkJyb3dzZXIgKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgYWRkaXRpb25hbE9wdGlvbnMgPSB0aGlzLl9nZXRBZGRpdGlvbmFsQnJvd3Nlck9wdGlvbnMoKTtcblxuICAgICAgICAgICAgYXdhaXQgdGhpcy5wcm92aWRlci5vcGVuQnJvd3Nlcih0aGlzLmlkLCB0aGlzLnVybCwgdGhpcy5icm93c2VySW5mby5icm93c2VyT3B0aW9uLCBhZGRpdGlvbmFsT3B0aW9ucyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXR1cyAhPT0gQnJvd3NlckNvbm5lY3Rpb25TdGF0dXMucmVhZHkpXG4gICAgICAgICAgICAgICAgYXdhaXQgcHJvbWlzaWZ5RXZlbnQodGhpcywgJ3JlYWR5Jyk7XG5cbiAgICAgICAgICAgIHRoaXMuc3RhdHVzID0gQnJvd3NlckNvbm5lY3Rpb25TdGF0dXMub3BlbmVkO1xuICAgICAgICAgICAgdGhpcy5lbWl0KCdvcGVuZWQnKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgICAgICAgIHRoaXMuZW1pdCgnZXJyb3InLCBuZXcgR2VuZXJhbEVycm9yKFxuICAgICAgICAgICAgICAgIFJVTlRJTUVfRVJST1JTLnVuYWJsZVRvT3BlbkJyb3dzZXIsXG4gICAgICAgICAgICAgICAgdGhpcy5icm93c2VySW5mby5wcm92aWRlck5hbWUgKyAnOicgKyB0aGlzLmJyb3dzZXJJbmZvLmJyb3dzZXJOYW1lLFxuICAgICAgICAgICAgICAgIGVyci5zdGFja1xuICAgICAgICAgICAgKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIF9jbG9zZUJyb3dzZXIgKGRhdGE6IEJyb3dzZXJDbG9zaW5nSW5mbyA9IHt9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICghdGhpcy5pZGxlKVxuICAgICAgICAgICAgYXdhaXQgcHJvbWlzaWZ5RXZlbnQodGhpcywgJ2lkbGUnKTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5wcm92aWRlci5jbG9zZUJyb3dzZXIodGhpcy5pZCwgZGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgLy8gTk9URTogQSB3YXJuaW5nIHdvdWxkIGJlIHJlYWxseSBuaWNlIGhlcmUsIGJ1dCBpdCBjYW4ndCBiZSBkb25lIHdoaWxlIGxvZyBpcyBzdG9yZWQgaW4gYSB0YXNrLlxuICAgICAgICAgICAgdGhpcy5kZWJ1Z0xvZ2dlcihlcnIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfZm9yY2VJZGxlICgpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLmlkbGUpIHtcbiAgICAgICAgICAgIHRoaXMuaWRsZSA9IHRydWU7XG5cbiAgICAgICAgICAgIHRoaXMuZW1pdCgnaWRsZScpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfY3JlYXRlQnJvd3NlckRpc2Nvbm5lY3RlZEVycm9yICgpOiBHZW5lcmFsRXJyb3Ige1xuICAgICAgICByZXR1cm4gbmV3IEdlbmVyYWxFcnJvcihSVU5USU1FX0VSUk9SUy5icm93c2VyRGlzY29ubmVjdGVkLCB0aGlzLnVzZXJBZ2VudCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfd2FpdEZvckhlYXJ0YmVhdCAoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuaGVhcnRiZWF0VGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZXJyID0gdGhpcy5fY3JlYXRlQnJvd3NlckRpc2Nvbm5lY3RlZEVycm9yKCk7XG5cbiAgICAgICAgICAgIHRoaXMuc3RhdHVzICAgICAgICAgPSBCcm93c2VyQ29ubmVjdGlvblN0YXR1cy5kaXNjb25uZWN0ZWQ7XG4gICAgICAgICAgICB0aGlzLnRlc3RSdW5BYm9ydGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgdGhpcy5lbWl0KCdkaXNjb25uZWN0ZWQnLCBlcnIpO1xuXG4gICAgICAgICAgICB0aGlzLl9yZXN0YXJ0QnJvd3Nlck9uRGlzY29ubmVjdChlcnIpO1xuICAgICAgICB9LCB0aGlzLkhFQVJUQkVBVF9USU1FT1VUKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIF9nZXRUZXN0UnVuSW5mbyAobmVlZFBvcE5leHQ6IGJvb2xlYW4pOiBQcm9taXNlPE5leHRUZXN0UnVuSW5mbz4ge1xuICAgICAgICBpZiAobmVlZFBvcE5leHQgfHwgIXRoaXMucGVuZGluZ1Rlc3RSdW5JbmZvKVxuICAgICAgICAgICAgdGhpcy5wZW5kaW5nVGVzdFJ1bkluZm8gPSBhd2FpdCB0aGlzLl9wb3BOZXh0VGVzdFJ1bkluZm8oKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5wZW5kaW5nVGVzdFJ1bkluZm8gYXMgTmV4dFRlc3RSdW5JbmZvO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX3BvcE5leHRUZXN0UnVuSW5mbyAoKTogUHJvbWlzZTxOZXh0VGVzdFJ1bkluZm8gfCBudWxsPiB7XG4gICAgICAgIHdoaWxlICh0aGlzLmhhc1F1ZXVlZEpvYnMgJiYgIXRoaXMuY3VycmVudEpvYi5oYXNRdWV1ZWRUZXN0UnVucylcbiAgICAgICAgICAgIHRoaXMuam9iUXVldWUuc2hpZnQoKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5oYXNRdWV1ZWRKb2JzID8gYXdhaXQgdGhpcy5jdXJyZW50Sm9iLnBvcE5leHRUZXN0UnVuSW5mbyh0aGlzKSA6IG51bGw7XG4gICAgfVxuXG4gICAgcHVibGljIGdldEN1cnJlbnRUZXN0UnVuICgpOiBMZWdhY3lUZXN0UnVuIHwgVGVzdFJ1biB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5fY3VycmVudFRlc3RSdW47XG4gICAgfVxuXG4gICAgcHVibGljIHN0YXRpYyBnZXRCeUlkIChpZDogc3RyaW5nKTogQnJvd3NlckNvbm5lY3Rpb24gfCBudWxsIHtcbiAgICAgICAgcmV0dXJuIEJyb3dzZXJDb25uZWN0aW9uVHJhY2tlci5hY3RpdmVCcm93c2VyQ29ubmVjdGlvbnNbaWRdIHx8IG51bGw7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBfcmVzdGFydEJyb3dzZXIgKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0aGlzLnN0YXR1cyA9IEJyb3dzZXJDb25uZWN0aW9uU3RhdHVzLnVuaW5pdGlhbGl6ZWQ7XG5cbiAgICAgICAgdGhpcy5fZm9yY2VJZGxlKCk7XG5cbiAgICAgICAgbGV0IHJlc29sdmVUaW1lb3V0OiBGdW5jdGlvbiB8IG51bGwgPSBudWxsO1xuICAgICAgICBsZXQgaXNUaW1lb3V0RXhwaXJlZCAgICAgICAgICAgICAgICA9IGZhbHNlO1xuICAgICAgICBsZXQgdGltZW91dDogTm9kZUpTLlRpbWVvdXQgfCBudWxsICA9IG51bGw7XG5cbiAgICAgICAgY29uc3QgcmVzdGFydFByb21pc2UgPSB0aW1lTGltaXQodGhpcy5fY2xvc2VCcm93c2VyKHsgaXNSZXN0YXJ0aW5nOiB0cnVlIH0pLCB0aGlzLkJST1dTRVJfQ0xPU0VfVElNRU9VVCwgeyByZWplY3RXaXRoOiBuZXcgVGltZW91dEVycm9yKCkgfSlcbiAgICAgICAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5kZWJ1Z0xvZ2dlcihlcnIpKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5fcnVuQnJvd3NlcigpKTtcblxuICAgICAgICBjb25zdCB0aW1lb3V0UHJvbWlzZSA9IG5ldyBQcm9taXNlPHZvaWQ+KHJlc29sdmUgPT4ge1xuICAgICAgICAgICAgcmVzb2x2ZVRpbWVvdXQgPSByZXNvbHZlO1xuXG4gICAgICAgICAgICB0aW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgaXNUaW1lb3V0RXhwaXJlZCA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9LCB0aGlzLkJST1dTRVJfUkVTVEFSVF9USU1FT1VUKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIFByb21pc2UucmFjZShbcmVzdGFydFByb21pc2UsIHRpbWVvdXRQcm9taXNlXSlcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dCBhcyBOb2RlSlMuVGltZW91dCk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaW1lb3V0RXhwaXJlZClcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0KCdlcnJvcicsIHRoaXMuX2NyZWF0ZUJyb3dzZXJEaXNjb25uZWN0ZWRFcnJvcigpKTtcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgIChyZXNvbHZlVGltZW91dCBhcyBGdW5jdGlvbikoKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3Jlc3RhcnRCcm93c2VyT25EaXNjb25uZWN0IChlcnI6IEVycm9yKTogdm9pZCB7XG4gICAgICAgIGxldCByZXNvbHZlRm46IEZ1bmN0aW9uIHwgbnVsbCA9IG51bGw7XG4gICAgICAgIGxldCByZWplY3RGbjogRnVuY3Rpb24gfCBudWxsICA9IG51bGw7XG5cbiAgICAgICAgdGhpcy5kaXNjb25uZWN0aW9uUHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHJlc29sdmVGbiA9IHJlc29sdmU7XG5cbiAgICAgICAgICAgIHJlamVjdEZuID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgKHJlamVjdEZuIGFzIEZ1bmN0aW9uKSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3Jlc3RhcnRCcm93c2VyKCk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGUgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdCgnZXJyb3InLCBlKTtcbiAgICAgICAgICAgIH0pIGFzIERpc2Nvbm5lY3Rpb25Qcm9taXNlPHZvaWQ+O1xuXG4gICAgICAgIHRoaXMuZGlzY29ubmVjdGlvblByb21pc2UucmVzb2x2ZSA9IHJlc29sdmVGbiBhcyB1bmtub3duIGFzIEZ1bmN0aW9uO1xuICAgICAgICB0aGlzLmRpc2Nvbm5lY3Rpb25Qcm9taXNlLnJlamVjdCAgPSByZWplY3RGbiBhcyB1bmtub3duIGFzIEZ1bmN0aW9uO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXREZWZhdWx0QnJvd3NlckluaXRUaW1lb3V0ICgpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgICAgICBjb25zdCBpc0xvY2FsQnJvd3NlciA9IGF3YWl0IHRoaXMucHJvdmlkZXIuaXNMb2NhbEJyb3dzZXIodGhpcy5pZCwgdGhpcy5icm93c2VySW5mby5icm93c2VyTmFtZSk7XG5cbiAgICAgICAgcmV0dXJuIGlzTG9jYWxCcm93c2VyID8gTE9DQUxfQlJPV1NFUl9JTklUX1RJTUVPVVQgOiBSRU1PVEVfQlJPV1NFUl9JTklUX1RJTUVPVVQ7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHByb2Nlc3NEaXNjb25uZWN0aW9uIChkaXNjb25uZWN0aW9uVGhyZXNob2xkRXhjZWVkZWQ6IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgeyByZXNvbHZlLCByZWplY3QgfSA9IHRoaXMuZGlzY29ubmVjdGlvblByb21pc2UgYXMgRGlzY29ubmVjdGlvblByb21pc2U8dm9pZD47XG5cbiAgICAgICAgaWYgKGRpc2Nvbm5lY3Rpb25UaHJlc2hvbGRFeGNlZWRlZClcbiAgICAgICAgICAgIHJlamVjdCgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGFkZFdhcm5pbmcgKG1lc3NhZ2U6IHN0cmluZywgLi4uYXJnczogYW55W10pOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuY3VycmVudEpvYilcbiAgICAgICAgICAgIHRoaXMuY3VycmVudEpvYi53YXJuaW5nTG9nLmFkZFdhcm5pbmcobWVzc2FnZSwgLi4uYXJncyk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHRoaXMud2FybmluZ0xvZy5hZGRXYXJuaW5nKG1lc3NhZ2UsIC4uLmFyZ3MpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2FwcGVuZFRvUHJldHR5VXNlckFnZW50IChzdHI6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmJyb3dzZXJJbmZvLnBhcnNlZFVzZXJBZ2VudC5wcmV0dHlVc2VyQWdlbnQgKz0gYCAoJHtzdHJ9KWA7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfbW92ZVdhcm5pbmdMb2dUb0pvYiAoam9iOiBCcm93c2VySm9iKTogdm9pZCB7XG4gICAgICAgIGpvYi53YXJuaW5nTG9nLmNvcHlGcm9tKHRoaXMud2FybmluZ0xvZyk7XG4gICAgICAgIHRoaXMud2FybmluZ0xvZy5jbGVhcigpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRQcm92aWRlck1ldGFJbmZvIChzdHI6IHN0cmluZywgb3B0aW9ucz86IFByb3ZpZGVyTWV0YUluZm9PcHRpb25zKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGFwcGVuZFRvVXNlckFnZW50ID0gb3B0aW9ucz8uYXBwZW5kVG9Vc2VyQWdlbnQgYXMgYm9vbGVhbjtcblxuICAgICAgICBpZiAoYXBwZW5kVG9Vc2VyQWdlbnQpIHtcbiAgICAgICAgICAgIC8vIE5PVEU6XG4gICAgICAgICAgICAvLyBjaGFuZ2UgcHJldHR5VXNlckFnZW50IG9ubHkgd2hlbiBjb25uZWN0aW9uIGFscmVhZHkgd2FzIGVzdGFibGlzaGVkXG4gICAgICAgICAgICBpZiAodGhpcy5pc1JlYWR5KCkpXG4gICAgICAgICAgICAgICAgdGhpcy5fYXBwZW5kVG9QcmV0dHlVc2VyQWdlbnQoc3RyKTtcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICB0aGlzLm9uKCdyZWFkeScsICgpID0+IHRoaXMuX2FwcGVuZFRvUHJldHR5VXNlckFnZW50KHN0cikpO1xuXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmJyb3dzZXJJbmZvLnVzZXJBZ2VudFByb3ZpZGVyTWV0YUluZm8gPSBzdHI7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCB1c2VyQWdlbnQgKCk6IHN0cmluZyB7XG4gICAgICAgIGxldCB1c2VyQWdlbnQgPSB0aGlzLmJyb3dzZXJJbmZvLnBhcnNlZFVzZXJBZ2VudC5wcmV0dHlVc2VyQWdlbnQ7XG5cbiAgICAgICAgaWYgKHRoaXMuYnJvd3NlckluZm8udXNlckFnZW50UHJvdmlkZXJNZXRhSW5mbylcbiAgICAgICAgICAgIHVzZXJBZ2VudCArPSBgICgke3RoaXMuYnJvd3NlckluZm8udXNlckFnZW50UHJvdmlkZXJNZXRhSW5mb30pYDtcblxuICAgICAgICByZXR1cm4gdXNlckFnZW50O1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgY29ubmVjdGlvbkluZm8gKCk6IHN0cmluZyB7XG4gICAgICAgIGlmICghdGhpcy5vc0luZm8pXG4gICAgICAgICAgICByZXR1cm4gdGhpcy51c2VyQWdlbnQ7XG5cbiAgICAgICAgY29uc3QgeyBuYW1lLCB2ZXJzaW9uIH0gPSB0aGlzLmJyb3dzZXJJbmZvLnBhcnNlZFVzZXJBZ2VudDtcbiAgICAgICAgbGV0IGNvbm5lY3Rpb25JbmZvICAgICAgPSBjYWxjdWxhdGVQcmV0dHlVc2VyQWdlbnQoeyBuYW1lLCB2ZXJzaW9uIH0sIHRoaXMub3NJbmZvKTtcbiAgICAgICAgY29uc3QgbWV0YUluZm8gICAgICAgICAgPSB0aGlzLmJyb3dzZXJJbmZvLnVzZXJBZ2VudFByb3ZpZGVyTWV0YUluZm8gfHwgZXh0cmFjdE1ldGFJbmZvKHRoaXMuYnJvd3NlckluZm8ucGFyc2VkVXNlckFnZW50LnByZXR0eVVzZXJBZ2VudCk7XG5cbiAgICAgICAgaWYgKG1ldGFJbmZvKVxuICAgICAgICAgICAgY29ubmVjdGlvbkluZm8gKz0gYCAoJHsgbWV0YUluZm8gfSlgO1xuXG4gICAgICAgIHJldHVybiBjb25uZWN0aW9uSW5mbztcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IHJldHJ5VGVzdFBhZ2VzICgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYnJvd3NlckNvbm5lY3Rpb25HYXRld2F5LnJldHJ5VGVzdFBhZ2VzO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgaGFzUXVldWVkSm9icyAoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuam9iUXVldWUubGVuZ3RoO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgY3VycmVudEpvYiAoKTogQnJvd3NlckpvYiB7XG4gICAgICAgIHJldHVybiB0aGlzLmpvYlF1ZXVlWzBdO1xuICAgIH1cblxuICAgIC8vIEFQSVxuICAgIHB1YmxpYyBydW5Jbml0U2NyaXB0IChjb2RlOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IHVua25vd24+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4gdGhpcy5pbml0U2NyaXB0c1F1ZXVlLnB1c2goeyBjb2RlLCByZXNvbHZlIH0pKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYWRkSm9iIChqb2I6IEJyb3dzZXJKb2IpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5qb2JRdWV1ZS5wdXNoKGpvYik7XG5cbiAgICAgICAgdGhpcy5fbW92ZVdhcm5pbmdMb2dUb0pvYihqb2IpO1xuICAgIH1cblxuICAgIHB1YmxpYyByZW1vdmVKb2IgKGpvYjogQnJvd3NlckpvYik6IHZvaWQge1xuICAgICAgICByZW1vdmUodGhpcy5qb2JRdWV1ZSwgam9iKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgY2xvc2UgKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAodGhpcy5zdGF0dXMgPT09IEJyb3dzZXJDb25uZWN0aW9uU3RhdHVzLmNsb3NpbmcgfHwgdGhpcy5zdGF0dXMgPT09IEJyb3dzZXJDb25uZWN0aW9uU3RhdHVzLmNsb3NlZClcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICB0aGlzLnN0YXR1cyA9IEJyb3dzZXJDb25uZWN0aW9uU3RhdHVzLmNsb3Npbmc7XG4gICAgICAgIHRoaXMuZW1pdChCcm93c2VyQ29ubmVjdGlvblN0YXR1cy5jbG9zaW5nKTtcblxuICAgICAgICBhd2FpdCB0aGlzLl9jbG9zZUJyb3dzZXIoKTtcblxuICAgICAgICB0aGlzLmJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5zdG9wU2VydmluZ0Nvbm5lY3Rpb24odGhpcyk7XG5cbiAgICAgICAgaWYgKHRoaXMuaGVhcnRiZWF0VGltZW91dClcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLmhlYXJ0YmVhdFRpbWVvdXQpO1xuXG4gICAgICAgIEJyb3dzZXJDb25uZWN0aW9uVHJhY2tlci5yZW1vdmUodGhpcyk7XG5cbiAgICAgICAgdGhpcy5zdGF0dXMgPSBCcm93c2VyQ29ubmVjdGlvblN0YXR1cy5jbG9zZWQ7XG4gICAgICAgIHRoaXMuZW1pdChCcm93c2VyQ29ubmVjdGlvblN0YXR1cy5jbG9zZWQpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBlc3RhYmxpc2ggKHVzZXJBZ2VudDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRoaXMuc3RhdHVzICAgICAgICAgICAgICAgICAgICAgID0gQnJvd3NlckNvbm5lY3Rpb25TdGF0dXMucmVhZHk7XG4gICAgICAgIHRoaXMuYnJvd3NlckluZm8ucGFyc2VkVXNlckFnZW50ID0gcGFyc2VVc2VyQWdlbnQodXNlckFnZW50KTtcbiAgICAgICAgdGhpcy5vc0luZm8gICAgICAgICAgICAgICAgICAgICAgPSBhd2FpdCB0aGlzLnByb3ZpZGVyLmdldE9TSW5mbyh0aGlzLmlkKTtcblxuICAgICAgICB0aGlzLl93YWl0Rm9ySGVhcnRiZWF0KCk7XG4gICAgICAgIHRoaXMuZW1pdCgncmVhZHknKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgaGVhcnRiZWF0ICgpOiBIZWFydGJlYXRTdGF0dXNSZXN1bHQge1xuICAgICAgICBpZiAodGhpcy5oZWFydGJlYXRUaW1lb3V0KVxuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuaGVhcnRiZWF0VGltZW91dCk7XG5cbiAgICAgICAgdGhpcy5fd2FpdEZvckhlYXJ0YmVhdCgpO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjb2RlOiB0aGlzLnN0YXR1cyA9PT0gQnJvd3NlckNvbm5lY3Rpb25TdGF0dXMuY2xvc2luZyA/IEhlYXJ0YmVhdFN0YXR1cy5jbG9zaW5nIDogSGVhcnRiZWF0U3RhdHVzLm9rLFxuICAgICAgICAgICAgdXJsOiAgdGhpcy5zdGF0dXMgPT09IEJyb3dzZXJDb25uZWN0aW9uU3RhdHVzLmNsb3NpbmcgPyB0aGlzLmlkbGVVcmwgOiAnJyxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVuZGVySWRsZVBhZ2UgKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiBNdXN0YWNoZS5yZW5kZXIoSURMRV9QQUdFX1RFTVBMQVRFIGFzIHN0cmluZywge1xuICAgICAgICAgICAgdXNlckFnZW50OiAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uSW5mbyxcbiAgICAgICAgICAgIHN0YXR1c1VybDogICAgICAgICAgIHRoaXMuc3RhdHVzVXJsLFxuICAgICAgICAgICAgaGVhcnRiZWF0VXJsOiAgICAgICAgdGhpcy5oZWFydGJlYXRVcmwsXG4gICAgICAgICAgICBpbml0U2NyaXB0VXJsOiAgICAgICB0aGlzLmluaXRTY3JpcHRVcmwsXG4gICAgICAgICAgICBvcGVuRmlsZVByb3RvY29sVXJsOiB0aGlzLm9wZW5GaWxlUHJvdG9jb2xVcmwsXG4gICAgICAgICAgICByZXRyeVRlc3RQYWdlczogICAgICAhIXRoaXMuYnJvd3NlckNvbm5lY3Rpb25HYXRld2F5LnJldHJ5VGVzdFBhZ2VzLFxuICAgICAgICAgICAgcHJveHlsZXNzOiAgICAgICAgICAgdGhpcy5wcm94eWxlc3MsXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRJbml0U2NyaXB0ICgpOiBJbml0U2NyaXB0IHtcbiAgICAgICAgY29uc3QgaW5pdFNjcmlwdFByb21pc2UgPSB0aGlzLmluaXRTY3JpcHRzUXVldWVbMF07XG5cbiAgICAgICAgcmV0dXJuIHsgY29kZTogaW5pdFNjcmlwdFByb21pc2UgPyBpbml0U2NyaXB0UHJvbWlzZS5jb2RlIDogbnVsbCB9O1xuICAgIH1cblxuICAgIHB1YmxpYyBoYW5kbGVJbml0U2NyaXB0UmVzdWx0IChkYXRhOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgaW5pdFNjcmlwdFByb21pc2UgPSB0aGlzLmluaXRTY3JpcHRzUXVldWUuc2hpZnQoKTtcblxuICAgICAgICBpZiAoaW5pdFNjcmlwdFByb21pc2UpXG4gICAgICAgICAgICBpbml0U2NyaXB0UHJvbWlzZS5yZXNvbHZlKEpTT04ucGFyc2UoZGF0YSkpO1xuICAgIH1cblxuICAgIHB1YmxpYyBpc0hlYWRsZXNzQnJvd3NlciAoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLnByb3ZpZGVyLmlzSGVhZGxlc3NCcm93c2VyKHRoaXMuaWQpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyByZXBvcnRKb2JSZXN1bHQgKHN0YXR1czogc3RyaW5nLCBkYXRhOiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICBhd2FpdCB0aGlzLnByb3ZpZGVyLnJlcG9ydEpvYlJlc3VsdCh0aGlzLmlkLCBzdGF0dXMsIGRhdGEpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXRTdGF0dXMgKGlzVGVzdERvbmU6IGJvb2xlYW4pOiBQcm9taXNlPEJyb3dzZXJDb25uZWN0aW9uU3RhdHVzUmVzdWx0PiB7XG4gICAgICAgIGlmICghdGhpcy5pZGxlICYmICFpc1Rlc3REb25lKSB7XG4gICAgICAgICAgICB0aGlzLmlkbGUgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5lbWl0KCdpZGxlJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5zdGF0dXMgPT09IEJyb3dzZXJDb25uZWN0aW9uU3RhdHVzLm9wZW5lZCkge1xuICAgICAgICAgICAgY29uc3QgbmV4dFRlc3RSdW5JbmZvID0gYXdhaXQgdGhpcy5fZ2V0VGVzdFJ1bkluZm8oaXNUZXN0RG9uZSB8fCB0aGlzLnRlc3RSdW5BYm9ydGVkKTtcblxuICAgICAgICAgICAgdGhpcy50ZXN0UnVuQWJvcnRlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICBpZiAobmV4dFRlc3RSdW5JbmZvKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pZGxlID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjbWQ6ICAgICAgIENPTU1BTkQucnVuLFxuICAgICAgICAgICAgICAgICAgICB0ZXN0UnVuSWQ6IG5leHRUZXN0UnVuSW5mby50ZXN0UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgIHVybDogICAgICAgbmV4dFRlc3RSdW5JbmZvLnVybCxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNtZDogICAgICAgQ09NTUFORC5pZGxlLFxuICAgICAgICAgICAgdXJsOiAgICAgICB0aGlzLmlkbGVVcmwsXG4gICAgICAgICAgICB0ZXN0UnVuSWQ6IG51bGwsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBhY3RpdmVXaW5kb3dJZCAoKTogbnVsbCB8IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLnByb3ZpZGVyLmdldEFjdGl2ZVdpbmRvd0lkKHRoaXMuaWQpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXQgYWN0aXZlV2luZG93SWQgKHZhbCkge1xuICAgICAgICB0aGlzLnByZXZpb3VzQWN0aXZlV2luZG93SWQgPSB0aGlzLmFjdGl2ZVdpbmRvd0lkO1xuXG4gICAgICAgIHRoaXMucHJvdmlkZXIuc2V0QWN0aXZlV2luZG93SWQodGhpcy5pZCwgdmFsKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgb3BlbkZpbGVQcm90b2NvbCAodXJsOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucHJvdmlkZXIub3BlbkZpbGVQcm90b2NvbCh0aGlzLmlkLCB1cmwpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBkaXNwYXRjaFByb3h5bGVzc0V2ZW50ICh0eXBlOiBFdmVudFR5cGUsIG9wdGlvbnM6IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpcy5wcm92aWRlci5kaXNwYXRjaFByb3h5bGVzc0V2ZW50KHRoaXMuaWQsIHR5cGUsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBjYW5Vc2VEZWZhdWx0V2luZG93QWN0aW9ucyAoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIHJldHVybiB0aGlzLnByb3ZpZGVyLmNhblVzZURlZmF1bHRXaW5kb3dBY3Rpb25zKHRoaXMuaWQpO1xuICAgIH1cblxuICAgIHB1YmxpYyBpc1JlYWR5ICgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdHVzID09PSBCcm93c2VyQ29ubmVjdGlvblN0YXR1cy5yZWFkeSB8fFxuICAgICAgICAgICAgdGhpcy5zdGF0dXMgPT09IEJyb3dzZXJDb25uZWN0aW9uU3RhdHVzLm9wZW5lZCB8fFxuICAgICAgICAgICAgdGhpcy5zdGF0dXMgPT09IEJyb3dzZXJDb25uZWN0aW9uU3RhdHVzLmNsb3Npbmc7XG4gICAgfVxufVxuIl19