UNPKG

testcafe

Version:

Automated browser testing for the modern web development stack.

278 lines 50.1 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const load_assets_1 = __importDefault(require("../../../load-assets")); const http_1 = require("../../../utils/http"); const remotes_queue_1 = __importDefault(require("../remotes-queue")); const testcafe_hammerhead_1 = require("testcafe-hammerhead"); const service_routes_1 = __importDefault(require("../service-routes")); const empty_page_markup_1 = __importDefault(require("../../../native-automation/empty-page-markup")); const error_route_1 = __importDefault(require("../../../native-automation/error-route")); const initializers_1 = require("../../../test-run/commands/validations/initializers"); const status_1 = __importDefault(require("./status")); const events_1 = require("events"); const DEFAULT_BROWSER_CONNECTION_GATEWAY_OPTIONS = { retryTestPages: false, }; class BrowserConnectionGateway extends events_1.EventEmitter { constructor(proxy, options) { super(); this._connections = {}; this._remotesQueue = new remotes_queue_1.default(); this.connectUrl = ''; this._options = this._calculateResultOptions(options); this.proxy = proxy; this._status = status_1.default.uninitialized; } _calculateResultOptions(options) { return Object.assign({}, DEFAULT_BROWSER_CONNECTION_GATEWAY_OPTIONS, options); } _dispatch(url, proxy, handler, method = 'GET') { // @ts-ignore Need to improve typings of the 'testcafe-hammerhead' module proxy[method](url, (req, res, serverInfo, params) => { const connection = this._connections[params.id]; (0, http_1.preventCaching)(res); (0, testcafe_hammerhead_1.acceptCrossOrigin)(res); if (connection) handler(req, res, connection); else (0, http_1.respond404)(res); }); } _registerRoutes(proxy) { const { idlePageScript, idlePageStyle, idlePageLogo, serviceWorkerScript, } = (0, load_assets_1.default)(); this._dispatch(`${service_routes_1.default.connect}/{id}`, proxy, BrowserConnectionGateway._onConnection); this._dispatch(`${service_routes_1.default.heartbeat}/{id}`, proxy, BrowserConnectionGateway._onHeartbeat, 'GET'); this._dispatch(`${service_routes_1.default.idle}/{id}`, proxy, BrowserConnectionGateway._onIdle); this._dispatch(`${service_routes_1.default.idleForced}/{id}`, proxy, BrowserConnectionGateway._onIdleForced); this._dispatch(`${service_routes_1.default.status}/{id}`, proxy, BrowserConnectionGateway._onStatusRequest); this._dispatch(`${service_routes_1.default.statusDone}/{id}`, proxy, BrowserConnectionGateway._onStatusRequestOnTestDone, 'GET'); this._dispatch(`${service_routes_1.default.initScript}/{id}`, proxy, BrowserConnectionGateway._onInitScriptRequest); this._dispatch(`${service_routes_1.default.initScript}/{id}`, proxy, BrowserConnectionGateway._onInitScriptResponse, 'POST'); this._dispatch(`${service_routes_1.default.activeWindowId}/{id}`, proxy, BrowserConnectionGateway._onGetActiveWindowIdRequest, 'GET'); this._dispatch(`${service_routes_1.default.activeWindowId}/{id}`, proxy, BrowserConnectionGateway._onSetActiveWindowIdRequest, 'POST'); this._dispatch(`${service_routes_1.default.ensureWindowInNativeAutomation}/{id}`, proxy, BrowserConnectionGateway._ensureWindowInNativeAutomation, 'POST'); this._dispatch(`${service_routes_1.default.closeWindow}/{id}`, proxy, BrowserConnectionGateway._onCloseWindowRequest, 'POST'); this._dispatch(`${service_routes_1.default.openFileProtocol}/{id}`, proxy, BrowserConnectionGateway._onOpenFileProtocolRequest, 'POST'); this._dispatch(`${service_routes_1.default.dispatchNativeAutomationEvent}/{id}`, proxy, BrowserConnectionGateway._onDispatchNativeAutomationEvent, 'POST'); this._dispatch(`${service_routes_1.default.parseSelector}/{id}`, proxy, BrowserConnectionGateway._parseSelector, 'POST'); this._dispatch(`${service_routes_1.default.dispatchNativeAutomationEventSequence}/{id}`, proxy, BrowserConnectionGateway._onDispatchNativeAutomationEventSequence, 'POST'); proxy.GET(service_routes_1.default.connect, (req, res) => this._connectNextRemoteBrowser(req, res)); proxy.GET(service_routes_1.default.connectWithTrailingSlash, (req, res) => this._connectNextRemoteBrowser(req, res)); proxy.GET(service_routes_1.default.serviceWorker, { content: serviceWorkerScript, contentType: 'application/x-javascript' }); proxy.GET(service_routes_1.default.assets.index, { content: idlePageScript, contentType: 'application/x-javascript' }); proxy.GET(service_routes_1.default.assets.styles, { content: idlePageStyle, contentType: 'text/css' }); proxy.GET(service_routes_1.default.assets.logo, { content: idlePageLogo, contentType: 'image/svg+xml' }); proxy.GET(error_route_1.default, (req, res) => { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(empty_page_markup_1.default); }); } // Helpers static _ensureConnectionReady(res, connection) { if (!connection.isReady()) { (0, http_1.respond500)(res, 'The connection is not ready yet.'); return false; } return true; } static _fetchRequestData(req, callback) { let data = ''; req.on('data', chunk => { data += chunk; }); req.on('end', () => { callback(data.toString()); }); } // Route handlers static async _onConnection(req, res, connection) { if (connection.isReady()) (0, http_1.respond500)(res, 'The connection is already established.'); else { const userAgent = req.headers['user-agent']; await connection.establish(userAgent); (0, http_1.redirect)(res, connection.idleUrl); } } static _onHeartbeat(req, res, connection) { if (BrowserConnectionGateway._ensureConnectionReady(res, connection)) { const status = connection.heartbeat(); (0, http_1.respondWithJSON)(res, status); } } static _onIdle(req, res, connection) { if (BrowserConnectionGateway._ensureConnectionReady(res, connection)) res.end(connection.renderIdlePage()); } static async _onIdleForced(req, res, connection) { if (BrowserConnectionGateway._ensureConnectionReady(res, connection)) { const status = await connection.getStatus(true); (0, http_1.redirect)(res, status.url); } } static async _onStatusRequest(req, res, connection) { return BrowserConnectionGateway._onStatusRequestCore(req, res, connection, false); } static async _onStatusRequestOnTestDone(req, res, connection) { return BrowserConnectionGateway._onStatusRequestCore(req, res, connection, true); } static async _onStatusRequestCore(req, res, connection, isTestDone) { if (BrowserConnectionGateway._ensureConnectionReady(res, connection)) { const status = await connection.getStatus(isTestDone); (0, http_1.respondWithJSON)(res, status); } } static _onInitScriptRequest(req, res, connection) { if (BrowserConnectionGateway._ensureConnectionReady(res, connection)) { const script = connection.getInitScript(); (0, http_1.respondWithJSON)(res, script); } } static _onInitScriptResponse(req, res, connection) { if (BrowserConnectionGateway._ensureConnectionReady(res, connection)) { BrowserConnectionGateway._fetchRequestData(req, data => { connection.handleInitScriptResult(data); res.end(); }); } } static _onGetActiveWindowIdRequest(req, res, connection) { if (BrowserConnectionGateway._ensureConnectionReady(res, connection)) { (0, http_1.respondWithJSON)(res, { activeWindowId: connection.activeWindowId, }); } } static async _ensureWindowInNativeAutomation(req, res, connection) { if (BrowserConnectionGateway._ensureConnectionReady(res, connection)) { BrowserConnectionGateway._fetchRequestData(req, async (data) => { const windowId = await connection.getNewWindowIdInNativeAutomation(JSON.parse(data).windowId); (0, http_1.respondWithJSON)(res, { windowId }); }); } } static _onSetActiveWindowIdRequest(req, res, connection) { if (BrowserConnectionGateway._ensureConnectionReady(res, connection)) { BrowserConnectionGateway._fetchRequestData(req, data => { const parsedData = JSON.parse(data); connection.activeWindowId = parsedData.windowId; (0, http_1.respondWithJSON)(res); }); } } static _onCloseWindowRequest(req, res, connection) { if (BrowserConnectionGateway._ensureConnectionReady(res, connection)) { connection.provider.closeBrowserChildWindow(connection.id) .then(() => { (0, http_1.respondWithJSON)(res); }); } } static _onOpenFileProtocolRequest(req, res, connection) { if (BrowserConnectionGateway._ensureConnectionReady(res, connection)) { BrowserConnectionGateway._fetchRequestData(req, data => { const parsedData = JSON.parse(data); connection.openFileProtocol(parsedData.url) .then(() => { (0, http_1.respondWithJSON)(res); }); }); } } static _onDispatchNativeAutomationEvent(req, res, connection) { if (BrowserConnectionGateway._ensureConnectionReady(res, connection)) { BrowserConnectionGateway._fetchRequestData(req, data => { const { type, options } = JSON.parse(data); connection.dispatchNativeAutomationEvent(type, options) .then(() => { (0, http_1.respondWithJSON)(res); }); }); } } static _onDispatchNativeAutomationEventSequence(req, res, connection) { if (BrowserConnectionGateway._ensureConnectionReady(res, connection)) { BrowserConnectionGateway._fetchRequestData(req, data => { const eventSequence = JSON.parse(data); connection.dispatchNativeAutomationEventSequence(eventSequence) .then(() => { (0, http_1.respondWithJSON)(res); }); }); } } async _connectNextRemoteBrowser(req, res) { (0, http_1.preventCaching)(res); const remoteConnection = await this._remotesQueue.shift(); if (remoteConnection) (0, http_1.redirect)(res, remoteConnection.url); else (0, http_1.respond500)(res, 'There are no available _connections to establish.'); } static _getParsedSelector(testRun, rawSelector) { const options = { testRun, skipVisibilityCheck: true, collectionMode: true, }; const value = rawSelector.trim().startsWith('Selector(') ? rawSelector : `'${rawSelector}'`; const selector = { type: 'js-expr', value }; return (0, initializers_1.initSelector)('selector', selector, options); } static _parseSelector(req, res, connection) { if (BrowserConnectionGateway._ensureConnectionReady(res, connection)) { BrowserConnectionGateway._fetchRequestData(req, data => { try { const testRun = connection.getCurrentTestRun(); const rawSelector = JSON.parse(data).selector; const parsedSelector = BrowserConnectionGateway._getParsedSelector(testRun, rawSelector); (0, http_1.respondWithJSON)(res, parsedSelector); } catch (error) { (0, http_1.respondWithJSON)(res); } }); } } // API startServingConnection(connection) { this._connections[connection.id] = connection; if (connection.browserInfo.providerName === 'remote') this._remotesQueue.add(connection); } stopServingConnection(connection) { delete this._connections[connection.id]; if (connection.browserInfo.providerName === 'remote') this._remotesQueue.remove(connection); } async close() { for (const id in this._connections) await this._connections[id].close(); this.proxy.close(); } getConnections() { return this._connections; } get status() { return this._status; } get retryTestPages() { return this._options.retryTestPages; } initialize(options) { // NOTE: Initialize only once in case of multiple runners. if (this._status === status_1.default.initialized) return; this.proxy.start(options); this._registerRoutes(this.proxy); this.connectUrl = this.proxy.resolveRelativeServiceUrl(service_routes_1.default.connect); this._status = status_1.default.initialized; this.emit('initialized'); } } exports.default = BrowserConnectionGateway; module.exports = exports.default; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvYnJvd3Nlci9jb25uZWN0aW9uL2dhdGV3YXkvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSx1RUFBOEM7QUFDOUMsOENBTTZCO0FBRTdCLHFFQUE0QztBQUM1Qyw2REFBK0Q7QUFJL0QsdUVBQStDO0FBQy9DLHFHQUE2RTtBQUM3RSx5RkFBbUY7QUFDbkYsc0ZBQW1GO0FBR25GLHNEQUFzRDtBQUN0RCxtQ0FBc0M7QUFNdEMsTUFBTSwwQ0FBMEMsR0FBRztJQUMvQyxjQUFjLEVBQUUsS0FBSztDQUN4QixDQUFDO0FBRUYsTUFBcUIsd0JBQXlCLFNBQVEscUJBQVk7SUFROUQsWUFBb0IsS0FBWSxFQUFFLE9BQXdDO1FBQ3RFLEtBQUssRUFBRSxDQUFDO1FBUkosaUJBQVksR0FBa0MsRUFBRSxDQUFDO1FBVXJELElBQUksQ0FBQyxhQUFhLEdBQUksSUFBSSx1QkFBWSxFQUFFLENBQUM7UUFDekMsSUFBSSxDQUFDLFVBQVUsR0FBTyxFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLFFBQVEsR0FBUyxJQUFJLENBQUMsdUJBQXVCLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDNUQsSUFBSSxDQUFDLEtBQUssR0FBWSxLQUFLLENBQUM7UUFDNUIsSUFBSSxDQUFDLE9BQU8sR0FBVSxnQkFBOEIsQ0FBQyxhQUFhLENBQUM7SUFDdkUsQ0FBQztJQUVPLHVCQUF1QixDQUFFLE9BQXdDO1FBQ3JFLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsMENBQTBDLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDbEYsQ0FBQztJQUVPLFNBQVMsQ0FBRSxHQUFXLEVBQUUsS0FBWSxFQUFFLE9BQWlCLEVBQUUsTUFBTSxHQUFHLEtBQUs7UUFDM0UseUVBQXlFO1FBQ3pFLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFvQixF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TSxVQUFVLENBQUUsT0FBNkI7UUFDNUMsMERBQTBEO1FBQzFELElBQUksSUFBSSxDQUFDLE9BQU8sS0FBSyxnQkFBOEIsQ0FBQyxXQUFXO1lBQzNELE9BQU87UUFFWCxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUUxQixJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUVqQyxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMseUJBQXlCLENBQUMsd0JBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMvRSxJQUFJLENBQUMsT0FBTyxHQUFNLGdCQUE4QixDQUFDLFdBQVcsQ0FBQztRQUU3RCxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQzdCLENBQUM7Q0FDSjtBQTlVRCwyQ0E4VUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgbG9hZEFzc2V0cyBmcm9tICcuLi8uLi8uLi9sb2FkLWFzc2V0cyc7XG5pbXBvcnQge1xuICAgIHJlc3BvbmQ0MDQsXG4gICAgcmVzcG9uZDUwMCxcbiAgICByZXNwb25kV2l0aEpTT04sXG4gICAgcmVkaXJlY3QsXG4gICAgcHJldmVudENhY2hpbmcsXG59IGZyb20gJy4uLy4uLy4uL3V0aWxzL2h0dHAnO1xuXG5pbXBvcnQgUmVtb3Rlc1F1ZXVlIGZyb20gJy4uL3JlbW90ZXMtcXVldWUnO1xuaW1wb3J0IHsgUHJveHksIGFjY2VwdENyb3NzT3JpZ2luIH0gZnJvbSAndGVzdGNhZmUtaGFtbWVyaGVhZCc7XG5pbXBvcnQgeyBEaWN0aW9uYXJ5IH0gZnJvbSAnLi4vLi4vLi4vY29uZmlndXJhdGlvbi9pbnRlcmZhY2VzJztcbmltcG9ydCBCcm93c2VyQ29ubmVjdGlvbiBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgeyBJbmNvbWluZ01lc3NhZ2UsIFNlcnZlclJlc3BvbnNlIH0gZnJvbSAnaHR0cCc7XG5pbXBvcnQgU0VSVklDRV9ST1VURVMgZnJvbSAnLi4vc2VydmljZS1yb3V0ZXMnO1xuaW1wb3J0IEVNUFRZX1BBR0VfTUFSS1VQIGZyb20gJy4uLy4uLy4uL25hdGl2ZS1hdXRvbWF0aW9uL2VtcHR5LXBhZ2UtbWFya3VwJztcbmltcG9ydCBOQVRJVkVfQVVUT01BVElPTl9FUlJPUl9ST1VURSBmcm9tICcuLi8uLi8uLi9uYXRpdmUtYXV0b21hdGlvbi9lcnJvci1yb3V0ZSc7XG5pbXBvcnQgeyBpbml0U2VsZWN0b3IgfSBmcm9tICcuLi8uLi8uLi90ZXN0LXJ1bi9jb21tYW5kcy92YWxpZGF0aW9ucy9pbml0aWFsaXplcnMnO1xuaW1wb3J0IFRlc3RSdW4gZnJvbSAnLi4vLi4vLi4vdGVzdC1ydW4nO1xuaW1wb3J0IHsgVGVzdENhZmVTdGFydE9wdGlvbnMgfSBmcm9tICcuLi8uLi8uLi9jb25maWd1cmF0aW9uL3Rlc3RjYWZlLWNvbmZpZ3VyYXRpb24nO1xuaW1wb3J0IEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheVN0YXR1cyBmcm9tICcuL3N0YXR1cyc7XG5pbXBvcnQgeyBFdmVudEVtaXR0ZXIgfSBmcm9tICdldmVudHMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheU9wdGlvbnMge1xuICAgIHJldHJ5VGVzdFBhZ2VzOiBib29sZWFuO1xufVxuXG5jb25zdCBERUZBVUxUX0JST1dTRVJfQ09OTkVDVElPTl9HQVRFV0FZX09QVElPTlMgPSB7XG4gICAgcmV0cnlUZXN0UGFnZXM6IGZhbHNlLFxufTtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQnJvd3NlckNvbm5lY3Rpb25HYXRld2F5IGV4dGVuZHMgRXZlbnRFbWl0dGVyIHtcbiAgICBwcml2YXRlIF9jb25uZWN0aW9uczogRGljdGlvbmFyeTxCcm93c2VyQ29ubmVjdGlvbj4gPSB7fTtcbiAgICBwcml2YXRlIF9yZW1vdGVzUXVldWU6IFJlbW90ZXNRdWV1ZTtcbiAgICBwdWJsaWMgY29ubmVjdFVybDogc3RyaW5nO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX29wdGlvbnM6IEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheU9wdGlvbnM7XG4gICAgcHVibGljIHJlYWRvbmx5IHByb3h5OiBQcm94eTtcbiAgICBwcml2YXRlIF9zdGF0dXM6IEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheVN0YXR1cztcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3RvciAocHJveHk6IFByb3h5LCBvcHRpb25zOiBCcm93c2VyQ29ubmVjdGlvbkdhdGV3YXlPcHRpb25zKSB7XG4gICAgICAgIHN1cGVyKCk7XG5cbiAgICAgICAgdGhpcy5fcmVtb3Rlc1F1ZXVlICA9IG5ldyBSZW1vdGVzUXVldWUoKTtcbiAgICAgICAgdGhpcy5jb25uZWN0VXJsICAgICA9ICcnO1xuICAgICAgICB0aGlzLl9vcHRpb25zICAgICAgID0gdGhpcy5fY2FsY3VsYXRlUmVzdWx0T3B0aW9ucyhvcHRpb25zKTtcbiAgICAgICAgdGhpcy5wcm94eSAgICAgICAgICA9IHByb3h5O1xuICAgICAgICB0aGlzLl9zdGF0dXMgICAgICAgID0gQnJvd3NlckNvbm5lY3Rpb25HYXRld2F5U3RhdHVzLnVuaW5pdGlhbGl6ZWQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfY2FsY3VsYXRlUmVzdWx0T3B0aW9ucyAob3B0aW9uczogQnJvd3NlckNvbm5lY3Rpb25HYXRld2F5T3B0aW9ucyk6IEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheU9wdGlvbnMge1xuICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgREVGQVVMVF9CUk9XU0VSX0NPTk5FQ1RJT05fR0FURVdBWV9PUFRJT05TLCBvcHRpb25zKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9kaXNwYXRjaCAodXJsOiBzdHJpbmcsIHByb3h5OiBQcm94eSwgaGFuZGxlcjogRnVuY3Rpb24sIG1ldGhvZCA9ICdHRVQnKTogdm9pZCB7XG4gICAgICAgIC8vIEB0cy1pZ25vcmUgTmVlZCB0byBpbXByb3ZlIHR5cGluZ3Mgb2YgdGhlICd0ZXN0Y2FmZS1oYW1tZXJoZWFkJyBtb2R1bGVcbiAgICAgICAgcHJveHlbbWV0aG9kXSh1cmwsIChyZXE6IEluY29taW5nTWVzc2FnZSwgcmVzOiBTZXJ2ZXJSZXNwb25zZSwgc2VydmVySW5mbywgcGFyYW1zOiBEaWN0aW9uYXJ5PHN0cmluZz4pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB0aGlzLl9jb25uZWN0aW9uc1twYXJhbXMuaWRdO1xuXG4gICAgICAgICAgICBwcmV2ZW50Q2FjaGluZyhyZXMpO1xuICAgICAgICAgICAgYWNjZXB0Q3Jvc3NPcmlnaW4ocmVzKTtcblxuICAgICAgICAgICAgaWYgKGNvbm5lY3Rpb24pXG4gICAgICAgICAgICAgICAgaGFuZGxlcihyZXEsIHJlcywgY29ubmVjdGlvbik7XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgcmVzcG9uZDQwNChyZXMpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9yZWdpc3RlclJvdXRlcyAocHJveHk6IFByb3h5KTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAgIGlkbGVQYWdlU2NyaXB0LFxuICAgICAgICAgICAgaWRsZVBhZ2VTdHlsZSxcbiAgICAgICAgICAgIGlkbGVQYWdlTG9nbyxcbiAgICAgICAgICAgIHNlcnZpY2VXb3JrZXJTY3JpcHQsXG4gICAgICAgIH0gPSBsb2FkQXNzZXRzKCk7XG5cbiAgICAgICAgdGhpcy5fZGlzcGF0Y2goYCR7U0VSVklDRV9ST1VURVMuY29ubmVjdH0ve2lkfWAsIHByb3h5LCBCcm93c2VyQ29ubmVjdGlvbkdhdGV3YXkuX29uQ29ubmVjdGlvbik7XG4gICAgICAgIHRoaXMuX2Rpc3BhdGNoKGAke1NFUlZJQ0VfUk9VVEVTLmhlYXJ0YmVhdH0ve2lkfWAsIHByb3h5LCBCcm93c2VyQ29ubmVjdGlvbkdhdGV3YXkuX29uSGVhcnRiZWF0LCAnR0VUJyk7XG4gICAgICAgIHRoaXMuX2Rpc3BhdGNoKGAke1NFUlZJQ0VfUk9VVEVTLmlkbGV9L3tpZH1gLCBwcm94eSwgQnJvd3NlckNvbm5lY3Rpb25HYXRld2F5Ll9vbklkbGUpO1xuICAgICAgICB0aGlzLl9kaXNwYXRjaChgJHtTRVJWSUNFX1JPVVRFUy5pZGxlRm9yY2VkfS97aWR9YCwgcHJveHksIEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5fb25JZGxlRm9yY2VkKTtcbiAgICAgICAgdGhpcy5fZGlzcGF0Y2goYCR7U0VSVklDRV9ST1VURVMuc3RhdHVzfS97aWR9YCwgcHJveHksIEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5fb25TdGF0dXNSZXF1ZXN0KTtcbiAgICAgICAgdGhpcy5fZGlzcGF0Y2goYCR7U0VSVklDRV9ST1VURVMuc3RhdHVzRG9uZX0ve2lkfWAsIHByb3h5LCBCcm93c2VyQ29ubmVjdGlvbkdhdGV3YXkuX29uU3RhdHVzUmVxdWVzdE9uVGVzdERvbmUsICdHRVQnKTtcbiAgICAgICAgdGhpcy5fZGlzcGF0Y2goYCR7U0VSVklDRV9ST1VURVMuaW5pdFNjcmlwdH0ve2lkfWAsIHByb3h5LCBCcm93c2VyQ29ubmVjdGlvbkdhdGV3YXkuX29uSW5pdFNjcmlwdFJlcXVlc3QpO1xuICAgICAgICB0aGlzLl9kaXNwYXRjaChgJHtTRVJWSUNFX1JPVVRFUy5pbml0U2NyaXB0fS97aWR9YCwgcHJveHksIEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5fb25Jbml0U2NyaXB0UmVzcG9uc2UsICdQT1NUJyk7XG4gICAgICAgIHRoaXMuX2Rpc3BhdGNoKGAke1NFUlZJQ0VfUk9VVEVTLmFjdGl2ZVdpbmRvd0lkfS97aWR9YCwgcHJveHksIEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5fb25HZXRBY3RpdmVXaW5kb3dJZFJlcXVlc3QsICdHRVQnKTtcbiAgICAgICAgdGhpcy5fZGlzcGF0Y2goYCR7U0VSVklDRV9ST1VURVMuYWN0aXZlV2luZG93SWR9L3tpZH1gLCBwcm94eSwgQnJvd3NlckNvbm5lY3Rpb25HYXRld2F5Ll9vblNldEFjdGl2ZVdpbmRvd0lkUmVxdWVzdCwgJ1BPU1QnKTtcbiAgICAgICAgdGhpcy5fZGlzcGF0Y2goYCR7U0VSVklDRV9ST1VURVMuZW5zdXJlV2luZG93SW5OYXRpdmVBdXRvbWF0aW9ufS97aWR9YCwgcHJveHksIEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5fZW5zdXJlV2luZG93SW5OYXRpdmVBdXRvbWF0aW9uLCAnUE9TVCcpO1xuICAgICAgICB0aGlzLl9kaXNwYXRjaChgJHtTRVJWSUNFX1JPVVRFUy5jbG9zZVdpbmRvd30ve2lkfWAsIHByb3h5LCBCcm93c2VyQ29ubmVjdGlvbkdhdGV3YXkuX29uQ2xvc2VXaW5kb3dSZXF1ZXN0LCAnUE9TVCcpO1xuICAgICAgICB0aGlzLl9kaXNwYXRjaChgJHtTRVJWSUNFX1JPVVRFUy5vcGVuRmlsZVByb3RvY29sfS97aWR9YCwgcHJveHksIEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5fb25PcGVuRmlsZVByb3RvY29sUmVxdWVzdCwgJ1BPU1QnKTtcbiAgICAgICAgdGhpcy5fZGlzcGF0Y2goYCR7U0VSVklDRV9ST1VURVMuZGlzcGF0Y2hOYXRpdmVBdXRvbWF0aW9uRXZlbnR9L3tpZH1gLCBwcm94eSwgQnJvd3NlckNvbm5lY3Rpb25HYXRld2F5Ll9vbkRpc3BhdGNoTmF0aXZlQXV0b21hdGlvbkV2ZW50LCAnUE9TVCcpO1xuICAgICAgICB0aGlzLl9kaXNwYXRjaChgJHtTRVJWSUNFX1JPVVRFUy5wYXJzZVNlbGVjdG9yfS97aWR9YCwgcHJveHksIEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5fcGFyc2VTZWxlY3RvciwgJ1BPU1QnKTtcbiAgICAgICAgdGhpcy5fZGlzcGF0Y2goYCR7U0VSVklDRV9ST1VURVMuZGlzcGF0Y2hOYXRpdmVBdXRvbWF0aW9uRXZlbnRTZXF1ZW5jZX0ve2lkfWAsIHByb3h5LCBCcm93c2VyQ29ubmVjdGlvbkdhdGV3YXkuX29uRGlzcGF0Y2hOYXRpdmVBdXRvbWF0aW9uRXZlbnRTZXF1ZW5jZSwgJ1BPU1QnKTtcblxuICAgICAgICBwcm94eS5HRVQoU0VSVklDRV9ST1VURVMuY29ubmVjdCwgKHJlcTogSW5jb21pbmdNZXNzYWdlLCByZXM6IFNlcnZlclJlc3BvbnNlKSA9PiB0aGlzLl9jb25uZWN0TmV4dFJlbW90ZUJyb3dzZXIocmVxLCByZXMpKTtcbiAgICAgICAgcHJveHkuR0VUKFNFUlZJQ0VfUk9VVEVTLmNvbm5lY3RXaXRoVHJhaWxpbmdTbGFzaCwgKHJlcTogSW5jb21pbmdNZXNzYWdlLCByZXM6IFNlcnZlclJlc3BvbnNlKSA9PiB0aGlzLl9jb25uZWN0TmV4dFJlbW90ZUJyb3dzZXIocmVxLCByZXMpKTtcblxuICAgICAgICBwcm94eS5HRVQoU0VSVklDRV9ST1VURVMuc2VydmljZVdvcmtlciwgeyBjb250ZW50OiBzZXJ2aWNlV29ya2VyU2NyaXB0LCBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL3gtamF2YXNjcmlwdCcgfSk7XG4gICAgICAgIHByb3h5LkdFVChTRVJWSUNFX1JPVVRFUy5hc3NldHMuaW5kZXgsIHsgY29udGVudDogaWRsZVBhZ2VTY3JpcHQsIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24veC1qYXZhc2NyaXB0JyB9KTtcbiAgICAgICAgcHJveHkuR0VUKFNFUlZJQ0VfUk9VVEVTLmFzc2V0cy5zdHlsZXMsIHsgY29udGVudDogaWRsZVBhZ2VTdHlsZSwgY29udGVudFR5cGU6ICd0ZXh0L2NzcycgfSk7XG4gICAgICAgIHByb3h5LkdFVChTRVJWSUNFX1JPVVRFUy5hc3NldHMubG9nbywgeyBjb250ZW50OiBpZGxlUGFnZUxvZ28sIGNvbnRlbnRUeXBlOiAnaW1hZ2Uvc3ZnK3htbCcgfSk7XG5cbiAgICAgICAgcHJveHkuR0VUKE5BVElWRV9BVVRPTUFUSU9OX0VSUk9SX1JPVVRFLCAocmVxOiBJbmNvbWluZ01lc3NhZ2UsIHJlczogU2VydmVyUmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgIHJlcy53cml0ZUhlYWQoMjAwLCB7ICdDb250ZW50LVR5cGUnOiAndGV4dC9odG1sJyB9KTtcbiAgICAgICAgICAgIHJlcy5lbmQoRU1QVFlfUEFHRV9NQVJLVVApO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBIZWxwZXJzXG4gICAgcHJpdmF0ZSBzdGF0aWMgX2Vuc3VyZUNvbm5lY3Rpb25SZWFkeSAocmVzOiBTZXJ2ZXJSZXNwb25zZSwgY29ubmVjdGlvbjogQnJvd3NlckNvbm5lY3Rpb24pOiBib29sZWFuIHtcbiAgICAgICAgaWYgKCFjb25uZWN0aW9uLmlzUmVhZHkoKSkge1xuICAgICAgICAgICAgcmVzcG9uZDUwMChyZXMsICdUaGUgY29ubmVjdGlvbiBpcyBub3QgcmVhZHkgeWV0LicpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgX2ZldGNoUmVxdWVzdERhdGEgKHJlcTogSW5jb21pbmdNZXNzYWdlLCBjYWxsYmFjazogKGRhdGE6IHN0cmluZykgPT4gdm9pZCk6IHZvaWQge1xuICAgICAgICBsZXQgZGF0YSA9ICcnO1xuXG4gICAgICAgIHJlcS5vbignZGF0YScsIGNodW5rID0+IHtcbiAgICAgICAgICAgIGRhdGEgKz0gY2h1bms7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJlcS5vbignZW5kJywgKCkgPT4ge1xuICAgICAgICAgICAgY2FsbGJhY2soZGF0YS50b1N0cmluZygpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gUm91dGUgaGFuZGxlcnNcbiAgICBwcml2YXRlIHN0YXRpYyBhc3luYyBfb25Db25uZWN0aW9uIChyZXE6IEluY29taW5nTWVzc2FnZSwgcmVzOiBTZXJ2ZXJSZXNwb25zZSwgY29ubmVjdGlvbjogQnJvd3NlckNvbm5lY3Rpb24pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKGNvbm5lY3Rpb24uaXNSZWFkeSgpKVxuICAgICAgICAgICAgcmVzcG9uZDUwMChyZXMsICdUaGUgY29ubmVjdGlvbiBpcyBhbHJlYWR5IGVzdGFibGlzaGVkLicpO1xuXG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgdXNlckFnZW50ID0gcmVxLmhlYWRlcnNbJ3VzZXItYWdlbnQnXSBhcyBzdHJpbmc7XG5cbiAgICAgICAgICAgIGF3YWl0IGNvbm5lY3Rpb24uZXN0YWJsaXNoKHVzZXJBZ2VudCk7XG4gICAgICAgICAgICByZWRpcmVjdChyZXMsIGNvbm5lY3Rpb24uaWRsZVVybCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBfb25IZWFydGJlYXQgKHJlcTogSW5jb21pbmdNZXNzYWdlLCByZXM6IFNlcnZlclJlc3BvbnNlLCBjb25uZWN0aW9uOiBCcm93c2VyQ29ubmVjdGlvbik6IHZvaWQge1xuICAgICAgICBpZiAoQnJvd3NlckNvbm5lY3Rpb25HYXRld2F5Ll9lbnN1cmVDb25uZWN0aW9uUmVhZHkocmVzLCBjb25uZWN0aW9uKSkge1xuICAgICAgICAgICAgY29uc3Qgc3RhdHVzID0gY29ubmVjdGlvbi5oZWFydGJlYXQoKTtcblxuICAgICAgICAgICAgcmVzcG9uZFdpdGhKU09OKHJlcywgc3RhdHVzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIF9vbklkbGUgKHJlcTogSW5jb21pbmdNZXNzYWdlLCByZXM6IFNlcnZlclJlc3BvbnNlLCBjb25uZWN0aW9uOiBCcm93c2VyQ29ubmVjdGlvbik6IHZvaWQge1xuICAgICAgICBpZiAoQnJvd3NlckNvbm5lY3Rpb25HYXRld2F5Ll9lbnN1cmVDb25uZWN0aW9uUmVhZHkocmVzLCBjb25uZWN0aW9uKSlcbiAgICAgICAgICAgIHJlcy5lbmQoY29ubmVjdGlvbi5yZW5kZXJJZGxlUGFnZSgpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBhc3luYyBfb25JZGxlRm9yY2VkIChyZXE6IEluY29taW5nTWVzc2FnZSwgcmVzOiBTZXJ2ZXJSZXNwb25zZSwgY29ubmVjdGlvbjogQnJvd3NlckNvbm5lY3Rpb24pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5fZW5zdXJlQ29ubmVjdGlvblJlYWR5KHJlcywgY29ubmVjdGlvbikpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0YXR1cyA9IGF3YWl0IGNvbm5lY3Rpb24uZ2V0U3RhdHVzKHRydWUpO1xuXG4gICAgICAgICAgICByZWRpcmVjdChyZXMsIHN0YXR1cy51cmwpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgYXN5bmMgX29uU3RhdHVzUmVxdWVzdCAocmVxOiBJbmNvbWluZ01lc3NhZ2UsIHJlczogU2VydmVyUmVzcG9uc2UsIGNvbm5lY3Rpb246IEJyb3dzZXJDb25uZWN0aW9uKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBCcm93c2VyQ29ubmVjdGlvbkdhdGV3YXkuX29uU3RhdHVzUmVxdWVzdENvcmUocmVxLCByZXMsIGNvbm5lY3Rpb24sIGZhbHNlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBhc3luYyBfb25TdGF0dXNSZXF1ZXN0T25UZXN0RG9uZSAocmVxOiBJbmNvbWluZ01lc3NhZ2UsIHJlczogU2VydmVyUmVzcG9uc2UsIGNvbm5lY3Rpb246IEJyb3dzZXJDb25uZWN0aW9uKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBCcm93c2VyQ29ubmVjdGlvbkdhdGV3YXkuX29uU3RhdHVzUmVxdWVzdENvcmUocmVxLCByZXMsIGNvbm5lY3Rpb24sIHRydWUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGFzeW5jIF9vblN0YXR1c1JlcXVlc3RDb3JlIChyZXE6IEluY29taW5nTWVzc2FnZSwgcmVzOiBTZXJ2ZXJSZXNwb25zZSwgY29ubmVjdGlvbjogQnJvd3NlckNvbm5lY3Rpb24sIGlzVGVzdERvbmU6IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5fZW5zdXJlQ29ubmVjdGlvblJlYWR5KHJlcywgY29ubmVjdGlvbikpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0YXR1cyA9IGF3YWl0IGNvbm5lY3Rpb24uZ2V0U3RhdHVzKGlzVGVzdERvbmUpO1xuXG4gICAgICAgICAgICByZXNwb25kV2l0aEpTT04ocmVzLCBzdGF0dXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgX29uSW5pdFNjcmlwdFJlcXVlc3QgKHJlcTogSW5jb21pbmdNZXNzYWdlLCByZXM6IFNlcnZlclJlc3BvbnNlLCBjb25uZWN0aW9uOiBCcm93c2VyQ29ubmVjdGlvbik6IHZvaWQge1xuICAgICAgICBpZiAoQnJvd3NlckNvbm5lY3Rpb25HYXRld2F5Ll9lbnN1cmVDb25uZWN0aW9uUmVhZHkocmVzLCBjb25uZWN0aW9uKSkge1xuICAgICAgICAgICAgY29uc3Qgc2NyaXB0ID0gY29ubmVjdGlvbi5nZXRJbml0U2NyaXB0KCk7XG5cbiAgICAgICAgICAgIHJlc3BvbmRXaXRoSlNPTihyZXMsIHNjcmlwdCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBfb25Jbml0U2NyaXB0UmVzcG9uc2UgKHJlcTogSW5jb21pbmdNZXNzYWdlLCByZXM6IFNlcnZlclJlc3BvbnNlLCBjb25uZWN0aW9uOiBCcm93c2VyQ29ubmVjdGlvbik6IHZvaWQge1xuICAgICAgICBpZiAoQnJvd3NlckNvbm5lY3Rpb25HYXRld2F5Ll9lbnN1cmVDb25uZWN0aW9uUmVhZHkocmVzLCBjb25uZWN0aW9uKSkge1xuICAgICAgICAgICAgQnJvd3NlckNvbm5lY3Rpb25HYXRld2F5Ll9mZXRjaFJlcXVlc3REYXRhKHJlcSwgZGF0YSA9PiB7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5oYW5kbGVJbml0U2NyaXB0UmVzdWx0KGRhdGEpO1xuXG4gICAgICAgICAgICAgICAgcmVzLmVuZCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBfb25HZXRBY3RpdmVXaW5kb3dJZFJlcXVlc3QgKHJlcTogSW5jb21pbmdNZXNzYWdlLCByZXM6IFNlcnZlclJlc3BvbnNlLCBjb25uZWN0aW9uOiBCcm93c2VyQ29ubmVjdGlvbik6IHZvaWQge1xuICAgICAgICBpZiAoQnJvd3NlckNvbm5lY3Rpb25HYXRld2F5Ll9lbnN1cmVDb25uZWN0aW9uUmVhZHkocmVzLCBjb25uZWN0aW9uKSkge1xuICAgICAgICAgICAgcmVzcG9uZFdpdGhKU09OKHJlcywge1xuICAgICAgICAgICAgICAgIGFjdGl2ZVdpbmRvd0lkOiBjb25uZWN0aW9uLmFjdGl2ZVdpbmRvd0lkLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBhc3luYyBfZW5zdXJlV2luZG93SW5OYXRpdmVBdXRvbWF0aW9uIChyZXE6IEluY29taW5nTWVzc2FnZSwgcmVzOiBTZXJ2ZXJSZXNwb25zZSwgY29ubmVjdGlvbjogQnJvd3NlckNvbm5lY3Rpb24pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5fZW5zdXJlQ29ubmVjdGlvblJlYWR5KHJlcywgY29ubmVjdGlvbikpIHtcbiAgICAgICAgICAgIEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5fZmV0Y2hSZXF1ZXN0RGF0YShyZXEsIGFzeW5jIGRhdGEgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHdpbmRvd0lkID0gYXdhaXQgY29ubmVjdGlvbi5nZXROZXdXaW5kb3dJZEluTmF0aXZlQXV0b21hdGlvbihKU09OLnBhcnNlKGRhdGEpLndpbmRvd0lkKTtcblxuICAgICAgICAgICAgICAgIHJlc3BvbmRXaXRoSlNPTihyZXMsIHsgd2luZG93SWQgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIF9vblNldEFjdGl2ZVdpbmRvd0lkUmVxdWVzdCAocmVxOiBJbmNvbWluZ01lc3NhZ2UsIHJlczogU2VydmVyUmVzcG9uc2UsIGNvbm5lY3Rpb246IEJyb3dzZXJDb25uZWN0aW9uKTogdm9pZCB7XG4gICAgICAgIGlmIChCcm93c2VyQ29ubmVjdGlvbkdhdGV3YXkuX2Vuc3VyZUNvbm5lY3Rpb25SZWFkeShyZXMsIGNvbm5lY3Rpb24pKSB7XG4gICAgICAgICAgICBCcm93c2VyQ29ubmVjdGlvbkdhdGV3YXkuX2ZldGNoUmVxdWVzdERhdGEocmVxLCBkYXRhID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXJzZWREYXRhID0gSlNPTi5wYXJzZShkYXRhKTtcblxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24uYWN0aXZlV2luZG93SWQgPSBwYXJzZWREYXRhLndpbmRvd0lkO1xuXG4gICAgICAgICAgICAgICAgcmVzcG9uZFdpdGhKU09OKHJlcyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIF9vbkNsb3NlV2luZG93UmVxdWVzdCAocmVxOiBJbmNvbWluZ01lc3NhZ2UsIHJlczogU2VydmVyUmVzcG9uc2UsIGNvbm5lY3Rpb246IEJyb3dzZXJDb25uZWN0aW9uKTogdm9pZCB7XG4gICAgICAgIGlmIChCcm93c2VyQ29ubmVjdGlvbkdhdGV3YXkuX2Vuc3VyZUNvbm5lY3Rpb25SZWFkeShyZXMsIGNvbm5lY3Rpb24pKSB7XG4gICAgICAgICAgICBjb25uZWN0aW9uLnByb3ZpZGVyLmNsb3NlQnJvd3NlckNoaWxkV2luZG93KGNvbm5lY3Rpb24uaWQpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXNwb25kV2l0aEpTT04ocmVzKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIF9vbk9wZW5GaWxlUHJvdG9jb2xSZXF1ZXN0IChyZXE6IEluY29taW5nTWVzc2FnZSwgcmVzOiBTZXJ2ZXJSZXNwb25zZSwgY29ubmVjdGlvbjogQnJvd3NlckNvbm5lY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgaWYgKEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5fZW5zdXJlQ29ubmVjdGlvblJlYWR5KHJlcywgY29ubmVjdGlvbikpIHtcbiAgICAgICAgICAgIEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5fZmV0Y2hSZXF1ZXN0RGF0YShyZXEsIGRhdGEgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhcnNlZERhdGEgPSBKU09OLnBhcnNlKGRhdGEpO1xuXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5vcGVuRmlsZVByb3RvY29sKHBhcnNlZERhdGEudXJsKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNwb25kV2l0aEpTT04ocmVzKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIF9vbkRpc3BhdGNoTmF0aXZlQXV0b21hdGlvbkV2ZW50IChyZXE6IEluY29taW5nTWVzc2FnZSwgcmVzOiBTZXJ2ZXJSZXNwb25zZSwgY29ubmVjdGlvbjogQnJvd3NlckNvbm5lY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgaWYgKEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5fZW5zdXJlQ29ubmVjdGlvblJlYWR5KHJlcywgY29ubmVjdGlvbikpIHtcbiAgICAgICAgICAgIEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5fZmV0Y2hSZXF1ZXN0RGF0YShyZXEsIGRhdGEgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHsgdHlwZSwgb3B0aW9ucyB9ID0gSlNPTi5wYXJzZShkYXRhKTtcblxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24uZGlzcGF0Y2hOYXRpdmVBdXRvbWF0aW9uRXZlbnQodHlwZSwgb3B0aW9ucylcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzcG9uZFdpdGhKU09OKHJlcyk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBfb25EaXNwYXRjaE5hdGl2ZUF1dG9tYXRpb25FdmVudFNlcXVlbmNlIChyZXE6IEluY29taW5nTWVzc2FnZSwgcmVzOiBTZXJ2ZXJSZXNwb25zZSwgY29ubmVjdGlvbjogQnJvd3NlckNvbm5lY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgaWYgKEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5fZW5zdXJlQ29ubmVjdGlvblJlYWR5KHJlcywgY29ubmVjdGlvbikpIHtcbiAgICAgICAgICAgIEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5fZmV0Y2hSZXF1ZXN0RGF0YShyZXEsIGRhdGEgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50U2VxdWVuY2UgPSBKU09OLnBhcnNlKGRhdGEpO1xuXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5kaXNwYXRjaE5hdGl2ZUF1dG9tYXRpb25FdmVudFNlcXVlbmNlKGV2ZW50U2VxdWVuY2UpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbmRXaXRoSlNPTihyZXMpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBfY29ubmVjdE5leHRSZW1vdGVCcm93c2VyIChyZXE6IEluY29taW5nTWVzc2FnZSwgcmVzOiBTZXJ2ZXJSZXNwb25zZSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBwcmV2ZW50Q2FjaGluZyhyZXMpO1xuXG4gICAgICAgIGNvbnN0IHJlbW90ZUNvbm5lY3Rpb24gPSBhd2FpdCB0aGlzLl9yZW1vdGVzUXVldWUuc2hpZnQoKTtcblxuICAgICAgICBpZiAocmVtb3RlQ29ubmVjdGlvbilcbiAgICAgICAgICAgIHJlZGlyZWN0KHJlcywgcmVtb3RlQ29ubmVjdGlvbi51cmwpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICByZXNwb25kNTAwKHJlcywgJ1RoZXJlIGFyZSBubyBhdmFpbGFibGUgX2Nvbm5lY3Rpb25zIHRvIGVzdGFibGlzaC4nKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBfZ2V0UGFyc2VkU2VsZWN0b3IgKHRlc3RSdW46IFRlc3RSdW4sIHJhd1NlbGVjdG9yOiBzdHJpbmcpOiBhbnkge1xuICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgdGVzdFJ1bixcblxuICAgICAgICAgICAgc2tpcFZpc2liaWxpdHlDaGVjazogdHJ1ZSxcbiAgICAgICAgICAgIGNvbGxlY3Rpb25Nb2RlOiAgICAgIHRydWUsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgdmFsdWUgICAgPSByYXdTZWxlY3Rvci50cmltKCkuc3RhcnRzV2l0aCgnU2VsZWN0b3IoJykgPyByYXdTZWxlY3RvciA6IGAnJHtyYXdTZWxlY3Rvcn0nYDtcbiAgICAgICAgY29uc3Qgc2VsZWN0b3IgPSB7IHR5cGU6ICdqcy1leHByJywgdmFsdWUgfTtcblxuICAgICAgICByZXR1cm4gaW5pdFNlbGVjdG9yKCdzZWxlY3RvcicsIHNlbGVjdG9yLCBvcHRpb25zKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBfcGFyc2VTZWxlY3RvciAocmVxOiBJbmNvbWluZ01lc3NhZ2UsIHJlczogU2VydmVyUmVzcG9uc2UsIGNvbm5lY3Rpb246IEJyb3dzZXJDb25uZWN0aW9uKTogdm9pZCB7XG4gICAgICAgIGlmIChCcm93c2VyQ29ubmVjdGlvbkdhdGV3YXkuX2Vuc3VyZUNvbm5lY3Rpb25SZWFkeShyZXMsIGNvbm5lY3Rpb24pKSB7XG4gICAgICAgICAgICBCcm93c2VyQ29ubmVjdGlvbkdhdGV3YXkuX2ZldGNoUmVxdWVzdERhdGEocmVxLCBkYXRhID0+IHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZXN0UnVuICAgICAgICA9IGNvbm5lY3Rpb24uZ2V0Q3VycmVudFRlc3RSdW4oKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmF3U2VsZWN0b3IgICAgPSBKU09OLnBhcnNlKGRhdGEpLnNlbGVjdG9yO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXJzZWRTZWxlY3RvciA9IEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5fZ2V0UGFyc2VkU2VsZWN0b3IodGVzdFJ1biwgcmF3U2VsZWN0b3IpO1xuXG4gICAgICAgICAgICAgICAgICAgIHJlc3BvbmRXaXRoSlNPTihyZXMsIHBhcnNlZFNlbGVjdG9yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3BvbmRXaXRoSlNPTihyZXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gQVBJXG4gICAgcHVibGljIHN0YXJ0U2VydmluZ0Nvbm5lY3Rpb24gKGNvbm5lY3Rpb246IEJyb3dzZXJDb25uZWN0aW9uKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX2Nvbm5lY3Rpb25zW2Nvbm5lY3Rpb24uaWRdID0gY29ubmVjdGlvbjtcblxuICAgICAgICBpZiAoY29ubmVjdGlvbi5icm93c2VySW5mby5wcm92aWRlck5hbWUgPT09ICdyZW1vdGUnKVxuICAgICAgICAgICAgdGhpcy5fcmVtb3Rlc1F1ZXVlLmFkZChjb25uZWN0aW9uKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc3RvcFNlcnZpbmdDb25uZWN0aW9uIChjb25uZWN0aW9uOiBCcm93c2VyQ29ubmVjdGlvbik6IHZvaWQge1xuICAgICAgICBkZWxldGUgdGhpcy5fY29ubmVjdGlvbnNbY29ubmVjdGlvbi5pZF07XG5cbiAgICAgICAgaWYgKGNvbm5lY3Rpb24uYnJvd3NlckluZm8ucHJvdmlkZXJOYW1lID09PSAncmVtb3RlJylcbiAgICAgICAgICAgIHRoaXMuX3JlbW90ZXNRdWV1ZS5yZW1vdmUoY29ubmVjdGlvbik7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGNsb3NlICgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgZm9yIChjb25zdCBpZCBpbiB0aGlzLl9jb25uZWN0aW9ucylcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuX2Nvbm5lY3Rpb25zW2lkXS5jbG9zZSgpO1xuXG4gICAgICAgIHRoaXMucHJveHkuY2xvc2UoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0Q29ubmVjdGlvbnMgKCk6IERpY3Rpb25hcnk8QnJvd3NlckNvbm5lY3Rpb24+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Nvbm5lY3Rpb25zO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgc3RhdHVzICgpOiBCcm93c2VyQ29ubmVjdGlvbkdhdGV3YXlTdGF0dXMge1xuICAgICAgICByZXR1cm4gdGhpcy5fc3RhdHVzO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgcmV0cnlUZXN0UGFnZXMgKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5yZXRyeVRlc3RQYWdlcztcbiAgICB9XG5cbiAgICBwdWJsaWMgaW5pdGlhbGl6ZSAob3B0aW9uczogVGVzdENhZmVTdGFydE9wdGlvbnMpOiB2b2lkIHtcbiAgICAgICAgLy8gTk9URTogSW5pdGlhbGl6ZSBvbmx5IG9uY2UgaW4gY2FzZSBvZiBtdWx0aXBsZSBydW5uZXJzLlxuICAgICAgICBpZiAodGhpcy5fc3RhdHVzID09PSBCcm93c2VyQ29ubmVjdGlvbkdhdGV3YXlTdGF0dXMuaW5pdGlhbGl6ZWQpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgdGhpcy5wcm94eS5zdGFydChvcHRpb25zKTtcblxuICAgICAgICB0aGlzLl9yZWdpc3RlclJvdXRlcyh0aGlzLnByb3h5KTtcblxuICAgICAgICB0aGlzLmNvbm5lY3RVcmwgPSB0aGlzLnByb3h5LnJlc29sdmVSZWxhdGl2ZVNlcnZpY2VVcmwoU0VSVklDRV9ST1VURVMuY29ubmVjdCk7XG4gICAgICAgIHRoaXMuX3N0YXR1cyAgICA9IEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheVN0YXR1cy